blob: 61a30f4872a5583d4193a896854601b33bd8b8ea [file] [log] [blame]
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001/* vi: set sw=4 ts=4: */
2/*
3 * e2fsck
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 * Copyright (C) 2006 Garrett Kajmowicz
7 *
8 * Dictionary Abstract Data Type
9 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10 * Free Software License:
11 * All rights are reserved by the author, with the following exceptions:
12 * Permission is granted to freely reproduce and distribute this software,
13 * possibly in exchange for a fee, provided that this copyright notice appears
14 * intact. Permission is also granted to adapt this software to produce
15 * derivative works, as long as the modified versions carry this copyright
16 * notice and additional notices stating that the work has been modified.
17 * This source code may be translated into executable form and incorporated
18 * into proprietary software; there is no requirement for such software to
19 * contain a copyright notice related to this source.
20 *
21 * linux/fs/recovery and linux/fs/revoke
22 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23 *
24 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25 *
26 * Journal recovery routines for the generic filesystem journaling code;
27 * part of the ext2fs journaling system.
28 *
29 * Licensed under GPLv2 or later, see file License in this tarball for details.
30 */
31
32#ifndef _GNU_SOURCE
33#define _GNU_SOURCE 1 /* get strnlen() */
34#endif
35
36#include "e2fsck.h" /*Put all of our defines here to clean things up*/
37
38#define _(x) x
39#define N_(x) x
40
41/*
42 * Procedure declarations
43 */
44
45static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
46
47/* pass1.c */
48static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
49
50/* pass2.c */
51static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
52 ext2_ino_t ino, char *buf);
53
54/* pass3.c */
55static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
56static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
57 int num, int gauranteed_size);
58static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
59static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
60 int adj);
61
62/* rehash.c */
63static void e2fsck_rehash_directories(e2fsck_t ctx);
64
65/* util.c */
66static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
67 const char *description);
68static int ask(e2fsck_t ctx, const char * string, int def);
69static void e2fsck_read_bitmaps(e2fsck_t ctx);
70static void preenhalt(e2fsck_t ctx);
71static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
72 struct ext2_inode * inode, const char * proc);
73static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
74 struct ext2_inode * inode, const char * proc);
75static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
76 const char *name, io_manager manager);
77
78/* unix.c */
79static void e2fsck_clear_progbar(e2fsck_t ctx);
80static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
81 float percent, unsigned int dpynum);
82
83
84/*
85 * problem.h --- e2fsck problem error codes
86 */
87
88typedef __u32 problem_t;
89
90struct problem_context {
91 errcode_t errcode;
92 ext2_ino_t ino, ino2, dir;
93 struct ext2_inode *inode;
94 struct ext2_dir_entry *dirent;
95 blk_t blk, blk2;
96 e2_blkcnt_t blkcount;
97 int group;
98 __u64 num;
99 const char *str;
100};
101
102
103/*
104 * Function declarations
105 */
106static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
107static int end_problem_latch(e2fsck_t ctx, int mask);
108static int set_latch_flags(int mask, int setflags, int clearflags);
109static void clear_problem_context(struct problem_context *ctx);
110
111/*
112 * Dictionary Abstract Data Type
113 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
114 *
115 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
116 * kazlib_1_20
117 */
118
119#ifndef DICT_H
120#define DICT_H
121
122/*
123 * Blurb for inclusion into C++ translation units
124 */
125
126typedef unsigned long dictcount_t;
127#define DICTCOUNT_T_MAX ULONG_MAX
128
129/*
130 * The dictionary is implemented as a red-black tree
131 */
132
133typedef enum { dnode_red, dnode_black } dnode_color_t;
134
135typedef struct dnode_t {
136 struct dnode_t *dict_left;
137 struct dnode_t *dict_right;
138 struct dnode_t *dict_parent;
139 dnode_color_t dict_color;
140 const void *dict_key;
141 void *dict_data;
142} dnode_t;
143
144typedef int (*dict_comp_t)(const void *, const void *);
145typedef void (*dnode_free_t)(dnode_t *);
146
147typedef struct dict_t {
148 dnode_t dict_nilnode;
149 dictcount_t dict_nodecount;
150 dictcount_t dict_maxcount;
151 dict_comp_t dict_compare;
152 dnode_free_t dict_freenode;
153 int dict_dupes;
154} dict_t;
155
156typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
157
158typedef struct dict_load_t {
159 dict_t *dict_dictptr;
160 dnode_t dict_nilnode;
161} dict_load_t;
162
163#define dict_count(D) ((D)->dict_nodecount)
164#define dnode_get(N) ((N)->dict_data)
165#define dnode_getkey(N) ((N)->dict_key)
166
167#endif
168
169/*
170 * Compatibility header file for e2fsck which should be included
171 * instead of linux/jfs.h
172 *
173 * Copyright (C) 2000 Stephen C. Tweedie
174 */
175
176/*
177 * Pull in the definition of the e2fsck context structure
178 */
179
180struct buffer_head {
181 char b_data[8192];
182 e2fsck_t b_ctx;
183 io_channel b_io;
184 int b_size;
185 blk_t b_blocknr;
186 int b_dirty;
187 int b_uptodate;
188 int b_err;
189};
190
191
192#define K_DEV_FS 1
193#define K_DEV_JOURNAL 2
194
Denis Vlasenkobb045062008-09-27 14:06:06 +0000195#define lock_buffer(bh) do {} while (0)
196#define unlock_buffer(bh) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000197#define buffer_req(bh) 1
Denis Vlasenkobb045062008-09-27 14:06:06 +0000198#define do_readahead(journal, start) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000199
200static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
201
202typedef struct {
203 int object_length;
204} kmem_cache_t;
205
206#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
207
208/*
209 * We use the standard libext2fs portability tricks for inline
210 * functions.
211 */
212
213static kmem_cache_t * do_cache_create(int len)
214{
215 kmem_cache_t *new_cache;
216
217 new_cache = malloc(sizeof(*new_cache));
218 if (new_cache)
219 new_cache->object_length = len;
220 return new_cache;
221}
222
223static void do_cache_destroy(kmem_cache_t *cache)
224{
225 free(cache);
226}
227
228
229/*
230 * Dictionary Abstract Data Type
231 */
232
233
234/*
235 * These macros provide short convenient names for structure members,
236 * which are embellished with dict_ prefixes so that they are
237 * properly confined to the documented namespace. It's legal for a
238 * program which uses dict to define, for instance, a macro called ``parent''.
239 * Such a macro would interfere with the dnode_t struct definition.
240 * In general, highly portable and reusable C modules which expose their
241 * structures need to confine structure member names to well-defined spaces.
242 * The resulting identifiers aren't necessarily convenient to use, nor
243 * readable, in the implementation, however!
244 */
245
246#define left dict_left
247#define right dict_right
248#define parent dict_parent
249#define color dict_color
250#define key dict_key
251#define data dict_data
252
253#define nilnode dict_nilnode
254#define maxcount dict_maxcount
255#define compare dict_compare
256#define dupes dict_dupes
257
258#define dict_root(D) ((D)->nilnode.left)
259#define dict_nil(D) (&(D)->nilnode)
260
261static void dnode_free(dnode_t *node);
262
263/*
264 * Perform a ``left rotation'' adjustment on the tree. The given node P and
265 * its right child C are rearranged so that the P instead becomes the left
266 * child of C. The left subtree of C is inherited as the new right subtree
267 * for P. The ordering of the keys within the tree is thus preserved.
268 */
269
270static void rotate_left(dnode_t *upper)
271{
272 dnode_t *lower, *lowleft, *upparent;
273
274 lower = upper->right;
275 upper->right = lowleft = lower->left;
276 lowleft->parent = upper;
277
278 lower->parent = upparent = upper->parent;
279
280 /* don't need to check for root node here because root->parent is
281 the sentinel nil node, and root->parent->left points back to root */
282
283 if (upper == upparent->left) {
284 upparent->left = lower;
285 } else {
286 assert (upper == upparent->right);
287 upparent->right = lower;
288 }
289
290 lower->left = upper;
291 upper->parent = lower;
292}
293
294/*
295 * This operation is the ``mirror'' image of rotate_left. It is
296 * the same procedure, but with left and right interchanged.
297 */
298
299static void rotate_right(dnode_t *upper)
300{
301 dnode_t *lower, *lowright, *upparent;
302
303 lower = upper->left;
304 upper->left = lowright = lower->right;
305 lowright->parent = upper;
306
307 lower->parent = upparent = upper->parent;
308
309 if (upper == upparent->right) {
310 upparent->right = lower;
311 } else {
312 assert (upper == upparent->left);
313 upparent->left = lower;
314 }
315
316 lower->right = upper;
317 upper->parent = lower;
318}
319
320/*
321 * Do a postorder traversal of the tree rooted at the specified
322 * node and free everything under it. Used by dict_free().
323 */
324
325static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
326{
327 if (node == nil)
328 return;
329 free_nodes(dict, node->left, nil);
330 free_nodes(dict, node->right, nil);
331 dict->dict_freenode(node);
332}
333
334/*
335 * Verify that the tree contains the given node. This is done by
336 * traversing all of the nodes and comparing their pointers to the
337 * given pointer. Returns 1 if the node is found, otherwise
338 * returns zero. It is intended for debugging purposes.
339 */
340
341static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
342{
343 if (root != nil) {
344 return root == node
345 || verify_dict_has_node(nil, root->left, node)
346 || verify_dict_has_node(nil, root->right, node);
347 }
348 return 0;
349}
350
351
352/*
353 * Select a different set of node allocator routines.
354 */
355
356static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
357{
358 assert (dict_count(dict) == 0);
359 dict->dict_freenode = fr;
360}
361
362/*
363 * Free all the nodes in the dictionary by using the dictionary's
364 * installed free routine. The dictionary is emptied.
365 */
366
367static void dict_free_nodes(dict_t *dict)
368{
369 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
370 free_nodes(dict, root, nil);
371 dict->dict_nodecount = 0;
372 dict->nilnode.left = &dict->nilnode;
373 dict->nilnode.right = &dict->nilnode;
374}
375
376/*
377 * Initialize a user-supplied dictionary object.
378 */
379
380static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
381{
382 dict->compare = comp;
383 dict->dict_freenode = dnode_free;
384 dict->dict_nodecount = 0;
385 dict->maxcount = maxcount;
386 dict->nilnode.left = &dict->nilnode;
387 dict->nilnode.right = &dict->nilnode;
388 dict->nilnode.parent = &dict->nilnode;
389 dict->nilnode.color = dnode_black;
390 dict->dupes = 0;
391 return dict;
392}
393
394/*
395 * Locate a node in the dictionary having the given key.
396 * If the node is not found, a null a pointer is returned (rather than
397 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
398 * located node is returned.
399 */
400
401static dnode_t *dict_lookup(dict_t *dict, const void *key)
402{
403 dnode_t *root = dict_root(dict);
404 dnode_t *nil = dict_nil(dict);
405 dnode_t *saved;
406 int result;
407
408 /* simple binary search adapted for trees that contain duplicate keys */
409
410 while (root != nil) {
411 result = dict->compare(key, root->key);
412 if (result < 0)
413 root = root->left;
414 else if (result > 0)
415 root = root->right;
416 else {
417 if (!dict->dupes) { /* no duplicates, return match */
418 return root;
419 } else { /* could be dupes, find leftmost one */
420 do {
421 saved = root;
422 root = root->left;
423 while (root != nil && dict->compare(key, root->key))
424 root = root->right;
425 } while (root != nil);
426 return saved;
427 }
428 }
429 }
430
431 return NULL;
432}
433
434/*
435 * Insert a node into the dictionary. The node should have been
436 * initialized with a data field. All other fields are ignored.
437 * The behavior is undefined if the user attempts to insert into
438 * a dictionary that is already full (for which the dict_isfull()
439 * function returns true).
440 */
441
442static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
443{
444 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
445 dnode_t *parent = nil, *uncle, *grandpa;
446 int result = -1;
447
448 node->key = key;
449
450 /* basic binary tree insert */
451
452 while (where != nil) {
453 parent = where;
454 result = dict->compare(key, where->key);
455 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
456 assert (dict->dupes || result != 0);
457 if (result < 0)
458 where = where->left;
459 else
460 where = where->right;
461 }
462
463 assert (where == nil);
464
465 if (result < 0)
466 parent->left = node;
467 else
468 parent->right = node;
469
470 node->parent = parent;
471 node->left = nil;
472 node->right = nil;
473
474 dict->dict_nodecount++;
475
476 /* red black adjustments */
477
478 node->color = dnode_red;
479
480 while (parent->color == dnode_red) {
481 grandpa = parent->parent;
482 if (parent == grandpa->left) {
483 uncle = grandpa->right;
484 if (uncle->color == dnode_red) { /* red parent, red uncle */
485 parent->color = dnode_black;
486 uncle->color = dnode_black;
487 grandpa->color = dnode_red;
488 node = grandpa;
489 parent = grandpa->parent;
490 } else { /* red parent, black uncle */
491 if (node == parent->right) {
492 rotate_left(parent);
493 parent = node;
494 assert (grandpa == parent->parent);
495 /* rotation between parent and child preserves grandpa */
496 }
497 parent->color = dnode_black;
498 grandpa->color = dnode_red;
499 rotate_right(grandpa);
500 break;
501 }
502 } else { /* symmetric cases: parent == parent->parent->right */
503 uncle = grandpa->left;
504 if (uncle->color == dnode_red) {
505 parent->color = dnode_black;
506 uncle->color = dnode_black;
507 grandpa->color = dnode_red;
508 node = grandpa;
509 parent = grandpa->parent;
510 } else {
511 if (node == parent->left) {
512 rotate_right(parent);
513 parent = node;
514 assert (grandpa == parent->parent);
515 }
516 parent->color = dnode_black;
517 grandpa->color = dnode_red;
518 rotate_left(grandpa);
519 break;
520 }
521 }
522 }
523
524 dict_root(dict)->color = dnode_black;
525
526}
527
528/*
529 * Allocate a node using the dictionary's allocator routine, give it
530 * the data item.
531 */
532
533static dnode_t *dnode_init(dnode_t *dnode, void *data)
534{
535 dnode->data = data;
536 dnode->parent = NULL;
537 dnode->left = NULL;
538 dnode->right = NULL;
539 return dnode;
540}
541
542static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
543{
544 dnode_t *node = malloc(sizeof(dnode_t));
545
546 if (node) {
547 dnode_init(node, data);
548 dict_insert(dict, node, key);
549 return 1;
550 }
551 return 0;
552}
553
554/*
555 * Return the node with the lowest (leftmost) key. If the dictionary is empty
556 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
557 */
558
559static dnode_t *dict_first(dict_t *dict)
560{
561 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
562
563 if (root != nil)
564 while ((left = root->left) != nil)
565 root = left;
566
567 return (root == nil) ? NULL : root;
568}
569
570/*
571 * Return the given node's successor node---the node which has the
572 * next key in the the left to right ordering. If the node has
573 * no successor, a null pointer is returned rather than a pointer to
574 * the nil node.
575 */
576
577static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
578{
579 dnode_t *nil = dict_nil(dict), *parent, *left;
580
581 if (curr->right != nil) {
582 curr = curr->right;
583 while ((left = curr->left) != nil)
584 curr = left;
585 return curr;
586 }
587
588 parent = curr->parent;
589
590 while (parent != nil && curr == parent->right) {
591 curr = parent;
592 parent = curr->parent;
593 }
594
595 return (parent == nil) ? NULL : parent;
596}
597
598
599static void dnode_free(dnode_t *node)
600{
601 free(node);
602}
603
604
605#undef left
606#undef right
607#undef parent
608#undef color
609#undef key
610#undef data
611
612#undef nilnode
613#undef maxcount
614#undef compare
615#undef dupes
616
617
618/*
619 * dirinfo.c --- maintains the directory information table for e2fsck.
620 */
621
622/*
623 * This subroutine is called during pass1 to create a directory info
624 * entry. During pass1, the passed-in parent is 0; it will get filled
625 * in during pass2.
626 */
627static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
628{
629 struct dir_info *dir;
630 int i, j;
631 ext2_ino_t num_dirs;
632 errcode_t retval;
633 unsigned long old_size;
634
635 if (!ctx->dir_info) {
636 ctx->dir_info_count = 0;
637 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
638 if (retval)
639 num_dirs = 1024; /* Guess */
640 ctx->dir_info_size = num_dirs + 10;
641 ctx->dir_info = (struct dir_info *)
642 e2fsck_allocate_memory(ctx, ctx->dir_info_size
643 * sizeof (struct dir_info),
644 "directory map");
645 }
646
647 if (ctx->dir_info_count >= ctx->dir_info_size) {
648 old_size = ctx->dir_info_size * sizeof(struct dir_info);
649 ctx->dir_info_size += 10;
650 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
651 sizeof(struct dir_info),
652 &ctx->dir_info);
653 if (retval) {
654 ctx->dir_info_size -= 10;
655 return;
656 }
657 }
658
659 /*
660 * Normally, add_dir_info is called with each inode in
661 * sequential order; but once in a while (like when pass 3
662 * needs to recreate the root directory or lost+found
663 * directory) it is called out of order. In those cases, we
664 * need to move the dir_info entries down to make room, since
665 * the dir_info array needs to be sorted by inode number for
666 * get_dir_info()'s sake.
667 */
668 if (ctx->dir_info_count &&
669 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
670 for (i = ctx->dir_info_count-1; i > 0; i--)
671 if (ctx->dir_info[i-1].ino < ino)
672 break;
673 dir = &ctx->dir_info[i];
674 if (dir->ino != ino)
675 for (j = ctx->dir_info_count++; j > i; j--)
676 ctx->dir_info[j] = ctx->dir_info[j-1];
677 } else
678 dir = &ctx->dir_info[ctx->dir_info_count++];
679
680 dir->ino = ino;
681 dir->dotdot = parent;
682 dir->parent = parent;
683}
684
685/*
686 * get_dir_info() --- given an inode number, try to find the directory
687 * information entry for it.
688 */
689static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
690{
691 int low, high, mid;
692
693 low = 0;
694 high = ctx->dir_info_count-1;
695 if (!ctx->dir_info)
696 return 0;
697 if (ino == ctx->dir_info[low].ino)
698 return &ctx->dir_info[low];
699 if (ino == ctx->dir_info[high].ino)
700 return &ctx->dir_info[high];
701
702 while (low < high) {
703 mid = (low+high)/2;
704 if (mid == low || mid == high)
705 break;
706 if (ino == ctx->dir_info[mid].ino)
707 return &ctx->dir_info[mid];
708 if (ino < ctx->dir_info[mid].ino)
709 high = mid;
710 else
711 low = mid;
712 }
713 return 0;
714}
715
716/*
717 * Free the dir_info structure when it isn't needed any more.
718 */
719static void e2fsck_free_dir_info(e2fsck_t ctx)
720{
721 ext2fs_free_mem(&ctx->dir_info);
722 ctx->dir_info_size = 0;
723 ctx->dir_info_count = 0;
724}
725
726/*
727 * Return the count of number of directories in the dir_info structure
728 */
729static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
730{
731 return ctx->dir_info_count;
732}
733
734/*
735 * A simple interator function
736 */
737static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
738{
739 if (*control >= ctx->dir_info_count)
740 return 0;
741
742 return ctx->dir_info + (*control)++;
743}
744
745/*
746 * dirinfo.c --- maintains the directory information table for e2fsck.
747 *
748 */
749
750#ifdef ENABLE_HTREE
751
752/*
753 * This subroutine is called during pass1 to create a directory info
754 * entry. During pass1, the passed-in parent is 0; it will get filled
755 * in during pass2.
756 */
757static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
758{
759 struct dx_dir_info *dir;
760 int i, j;
761 errcode_t retval;
762 unsigned long old_size;
763
764 if (!ctx->dx_dir_info) {
765 ctx->dx_dir_info_count = 0;
766 ctx->dx_dir_info_size = 100; /* Guess */
767 ctx->dx_dir_info = (struct dx_dir_info *)
768 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
769 * sizeof (struct dx_dir_info),
770 "directory map");
771 }
772
773 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
774 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
775 ctx->dx_dir_info_size += 10;
776 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
777 sizeof(struct dx_dir_info),
778 &ctx->dx_dir_info);
779 if (retval) {
780 ctx->dx_dir_info_size -= 10;
781 return;
782 }
783 }
784
785 /*
786 * Normally, add_dx_dir_info is called with each inode in
787 * sequential order; but once in a while (like when pass 3
788 * needs to recreate the root directory or lost+found
789 * directory) it is called out of order. In those cases, we
790 * need to move the dx_dir_info entries down to make room, since
791 * the dx_dir_info array needs to be sorted by inode number for
792 * get_dx_dir_info()'s sake.
793 */
794 if (ctx->dx_dir_info_count &&
795 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
796 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
797 if (ctx->dx_dir_info[i-1].ino < ino)
798 break;
799 dir = &ctx->dx_dir_info[i];
800 if (dir->ino != ino)
801 for (j = ctx->dx_dir_info_count++; j > i; j--)
802 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
803 } else
804 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
805
806 dir->ino = ino;
807 dir->numblocks = num_blocks;
808 dir->hashversion = 0;
809 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
810 * sizeof (struct dx_dirblock_info),
811 "dx_block info array");
812
813}
814
815/*
816 * get_dx_dir_info() --- given an inode number, try to find the directory
817 * information entry for it.
818 */
819static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
820{
821 int low, high, mid;
822
823 low = 0;
824 high = ctx->dx_dir_info_count-1;
825 if (!ctx->dx_dir_info)
826 return 0;
827 if (ino == ctx->dx_dir_info[low].ino)
828 return &ctx->dx_dir_info[low];
829 if (ino == ctx->dx_dir_info[high].ino)
830 return &ctx->dx_dir_info[high];
831
832 while (low < high) {
833 mid = (low+high)/2;
834 if (mid == low || mid == high)
835 break;
836 if (ino == ctx->dx_dir_info[mid].ino)
837 return &ctx->dx_dir_info[mid];
838 if (ino < ctx->dx_dir_info[mid].ino)
839 high = mid;
840 else
841 low = mid;
842 }
843 return 0;
844}
845
846/*
847 * Free the dx_dir_info structure when it isn't needed any more.
848 */
849static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
850{
851 int i;
852 struct dx_dir_info *dir;
853
854 if (ctx->dx_dir_info) {
855 dir = ctx->dx_dir_info;
856 for (i=0; i < ctx->dx_dir_info_count; i++) {
857 ext2fs_free_mem(&dir->dx_block);
858 }
859 ext2fs_free_mem(&ctx->dx_dir_info);
860 }
861 ctx->dx_dir_info_size = 0;
862 ctx->dx_dir_info_count = 0;
863}
864
865/*
866 * A simple interator function
867 */
868static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
869{
870 if (*control >= ctx->dx_dir_info_count)
871 return 0;
872
873 return ctx->dx_dir_info + (*control)++;
874}
875
876#endif /* ENABLE_HTREE */
877/*
878 * e2fsck.c - a consistency checker for the new extended file system.
879 *
880 */
881
882/*
883 * This function allocates an e2fsck context
884 */
885static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
886{
887 e2fsck_t context;
888 errcode_t retval;
889
890 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
891 if (retval)
892 return retval;
893
894 memset(context, 0, sizeof(struct e2fsck_struct));
895
896 context->process_inode_size = 256;
897 context->ext_attr_ver = 2;
898
899 *ret = context;
900 return 0;
901}
902
903struct ea_refcount_el {
904 blk_t ea_blk;
905 int ea_count;
906};
907
908struct ea_refcount {
909 blk_t count;
910 blk_t size;
911 blk_t cursor;
912 struct ea_refcount_el *list;
913};
914
915static void ea_refcount_free(ext2_refcount_t refcount)
916{
917 if (!refcount)
918 return;
919
920 ext2fs_free_mem(&refcount->list);
921 ext2fs_free_mem(&refcount);
922}
923
924/*
925 * This function resets an e2fsck context; it is called when e2fsck
926 * needs to be restarted.
927 */
928static errcode_t e2fsck_reset_context(e2fsck_t ctx)
929{
930 ctx->flags = 0;
931 ctx->lost_and_found = 0;
932 ctx->bad_lost_and_found = 0;
933 ext2fs_free_inode_bitmap(ctx->inode_used_map);
934 ctx->inode_used_map = 0;
935 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
936 ctx->inode_dir_map = 0;
937 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
938 ctx->inode_reg_map = 0;
939 ext2fs_free_block_bitmap(ctx->block_found_map);
940 ctx->block_found_map = 0;
941 ext2fs_free_icount(ctx->inode_link_info);
942 ctx->inode_link_info = 0;
943 if (ctx->journal_io) {
944 if (ctx->fs && ctx->fs->io != ctx->journal_io)
945 io_channel_close(ctx->journal_io);
946 ctx->journal_io = 0;
947 }
948 if (ctx->fs) {
949 ext2fs_free_dblist(ctx->fs->dblist);
950 ctx->fs->dblist = 0;
951 }
952 e2fsck_free_dir_info(ctx);
953#ifdef ENABLE_HTREE
954 e2fsck_free_dx_dir_info(ctx);
955#endif
956 ea_refcount_free(ctx->refcount);
957 ctx->refcount = 0;
958 ea_refcount_free(ctx->refcount_extra);
959 ctx->refcount_extra = 0;
960 ext2fs_free_block_bitmap(ctx->block_dup_map);
961 ctx->block_dup_map = 0;
962 ext2fs_free_block_bitmap(ctx->block_ea_map);
963 ctx->block_ea_map = 0;
964 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
965 ctx->inode_bad_map = 0;
966 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
967 ctx->inode_imagic_map = 0;
968 ext2fs_u32_list_free(ctx->dirs_to_hash);
969 ctx->dirs_to_hash = 0;
970
971 /*
972 * Clear the array of invalid meta-data flags
973 */
974 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
975 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
976 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
977
978 /* Clear statistic counters */
979 ctx->fs_directory_count = 0;
980 ctx->fs_regular_count = 0;
981 ctx->fs_blockdev_count = 0;
982 ctx->fs_chardev_count = 0;
983 ctx->fs_links_count = 0;
984 ctx->fs_symlinks_count = 0;
985 ctx->fs_fast_symlinks_count = 0;
986 ctx->fs_fifo_count = 0;
987 ctx->fs_total_count = 0;
988 ctx->fs_sockets_count = 0;
989 ctx->fs_ind_count = 0;
990 ctx->fs_dind_count = 0;
991 ctx->fs_tind_count = 0;
992 ctx->fs_fragmented = 0;
993 ctx->large_files = 0;
994
995 /* Reset the superblock to the user's requested value */
996 ctx->superblock = ctx->use_superblock;
997
998 return 0;
999}
1000
1001static void e2fsck_free_context(e2fsck_t ctx)
1002{
1003 if (!ctx)
1004 return;
1005
1006 e2fsck_reset_context(ctx);
1007 if (ctx->blkid)
1008 blkid_put_cache(ctx->blkid);
1009
1010 ext2fs_free_mem(&ctx);
1011}
1012
1013/*
1014 * ea_refcount.c
1015 */
1016
1017/*
1018 * The strategy we use for keeping track of EA refcounts is as
1019 * follows. We keep a sorted array of first EA blocks and its
1020 * reference counts. Once the refcount has dropped to zero, it is
1021 * removed from the array to save memory space. Once the EA block is
1022 * checked, its bit is set in the block_ea_map bitmap.
1023 */
1024
1025
1026static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1027{
1028 ext2_refcount_t refcount;
1029 errcode_t retval;
1030 size_t bytes;
1031
1032 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1033 if (retval)
1034 return retval;
1035 memset(refcount, 0, sizeof(struct ea_refcount));
1036
1037 if (!size)
1038 size = 500;
1039 refcount->size = size;
1040 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1041#ifdef DEBUG
1042 printf("Refcount allocated %d entries, %d bytes.\n",
1043 refcount->size, bytes);
1044#endif
1045 retval = ext2fs_get_mem(bytes, &refcount->list);
1046 if (retval)
1047 goto errout;
1048 memset(refcount->list, 0, bytes);
1049
1050 refcount->count = 0;
1051 refcount->cursor = 0;
1052
1053 *ret = refcount;
1054 return 0;
1055
1056errout:
1057 ea_refcount_free(refcount);
1058 return retval;
1059}
1060
1061/*
1062 * collapse_refcount() --- go through the refcount array, and get rid
1063 * of any count == zero entries
1064 */
1065static void refcount_collapse(ext2_refcount_t refcount)
1066{
1067 unsigned int i, j;
1068 struct ea_refcount_el *list;
1069
1070 list = refcount->list;
1071 for (i = 0, j = 0; i < refcount->count; i++) {
1072 if (list[i].ea_count) {
1073 if (i != j)
1074 list[j] = list[i];
1075 j++;
1076 }
1077 }
1078#if defined(DEBUG) || defined(TEST_PROGRAM)
1079 printf("Refcount_collapse: size was %d, now %d\n",
1080 refcount->count, j);
1081#endif
1082 refcount->count = j;
1083}
1084
1085
1086/*
1087 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1088 * specified position.
1089 */
1090static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1091 blk_t blk, int pos)
1092{
1093 struct ea_refcount_el *el;
1094 errcode_t retval;
1095 blk_t new_size = 0;
1096 int num;
1097
1098 if (refcount->count >= refcount->size) {
1099 new_size = refcount->size + 100;
1100#ifdef DEBUG
1101 printf("Reallocating refcount %d entries...\n", new_size);
1102#endif
1103 retval = ext2fs_resize_mem((size_t) refcount->size *
1104 sizeof(struct ea_refcount_el),
1105 (size_t) new_size *
1106 sizeof(struct ea_refcount_el),
1107 &refcount->list);
1108 if (retval)
1109 return 0;
1110 refcount->size = new_size;
1111 }
1112 num = (int) refcount->count - pos;
1113 if (num < 0)
1114 return 0; /* should never happen */
1115 if (num) {
1116 memmove(&refcount->list[pos+1], &refcount->list[pos],
1117 sizeof(struct ea_refcount_el) * num);
1118 }
1119 refcount->count++;
1120 el = &refcount->list[pos];
1121 el->ea_count = 0;
1122 el->ea_blk = blk;
1123 return el;
1124}
1125
1126
1127/*
1128 * get_refcount_el() --- given an block number, try to find refcount
1129 * information in the sorted list. If the create flag is set,
1130 * and we can't find an entry, create one in the sorted list.
1131 */
1132static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1133 blk_t blk, int create)
1134{
1135 float range;
1136 int low, high, mid;
1137 blk_t lowval, highval;
1138
1139 if (!refcount || !refcount->list)
1140 return 0;
1141retry:
1142 low = 0;
1143 high = (int) refcount->count-1;
1144 if (create && ((refcount->count == 0) ||
1145 (blk > refcount->list[high].ea_blk))) {
1146 if (refcount->count >= refcount->size)
1147 refcount_collapse(refcount);
1148
1149 return insert_refcount_el(refcount, blk,
1150 (unsigned) refcount->count);
1151 }
1152 if (refcount->count == 0)
1153 return 0;
1154
1155 if (refcount->cursor >= refcount->count)
1156 refcount->cursor = 0;
1157 if (blk == refcount->list[refcount->cursor].ea_blk)
1158 return &refcount->list[refcount->cursor++];
1159#ifdef DEBUG
1160 printf("Non-cursor get_refcount_el: %u\n", blk);
1161#endif
1162 while (low <= high) {
1163 if (low == high)
1164 mid = low;
1165 else {
1166 /* Interpolate for efficiency */
1167 lowval = refcount->list[low].ea_blk;
1168 highval = refcount->list[high].ea_blk;
1169
1170 if (blk < lowval)
1171 range = 0;
1172 else if (blk > highval)
1173 range = 1;
1174 else
1175 range = ((float) (blk - lowval)) /
1176 (highval - lowval);
1177 mid = low + ((int) (range * (high-low)));
1178 }
1179
1180 if (blk == refcount->list[mid].ea_blk) {
1181 refcount->cursor = mid+1;
1182 return &refcount->list[mid];
1183 }
1184 if (blk < refcount->list[mid].ea_blk)
1185 high = mid-1;
1186 else
1187 low = mid+1;
1188 }
1189 /*
1190 * If we need to create a new entry, it should be right at
1191 * low (where high will be left at low-1).
1192 */
1193 if (create) {
1194 if (refcount->count >= refcount->size) {
1195 refcount_collapse(refcount);
1196 if (refcount->count < refcount->size)
1197 goto retry;
1198 }
1199 return insert_refcount_el(refcount, blk, low);
1200 }
1201 return 0;
1202}
1203
1204static errcode_t
1205ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1206{
1207 struct ea_refcount_el *el;
1208
1209 el = get_refcount_el(refcount, blk, 1);
1210 if (!el)
1211 return EXT2_ET_NO_MEMORY;
1212 el->ea_count++;
1213
1214 if (ret)
1215 *ret = el->ea_count;
1216 return 0;
1217}
1218
1219static errcode_t
1220ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1221{
1222 struct ea_refcount_el *el;
1223
1224 el = get_refcount_el(refcount, blk, 0);
1225 if (!el || el->ea_count == 0)
1226 return EXT2_ET_INVALID_ARGUMENT;
1227
1228 el->ea_count--;
1229
1230 if (ret)
1231 *ret = el->ea_count;
1232 return 0;
1233}
1234
1235static errcode_t
1236ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1237{
1238 struct ea_refcount_el *el;
1239
1240 /*
1241 * Get the refcount element
1242 */
1243 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1244 if (!el)
1245 return count ? EXT2_ET_NO_MEMORY : 0;
1246 el->ea_count = count;
1247 return 0;
1248}
1249
1250static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1251{
1252 refcount->cursor = 0;
1253}
1254
1255
1256static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1257{
1258 struct ea_refcount_el *list;
1259
1260 while (1) {
1261 if (refcount->cursor >= refcount->count)
1262 return 0;
1263 list = refcount->list;
1264 if (list[refcount->cursor].ea_count) {
1265 if (ret)
1266 *ret = list[refcount->cursor].ea_count;
1267 return list[refcount->cursor++].ea_blk;
1268 }
1269 refcount->cursor++;
1270 }
1271}
1272
1273
1274/*
1275 * ehandler.c --- handle bad block errors which come up during the
1276 * course of an e2fsck session.
1277 */
1278
1279
1280static const char *operation;
1281
1282static errcode_t
1283e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1284 void *data, size_t size FSCK_ATTR((unused)),
1285 int actual FSCK_ATTR((unused)), errcode_t error)
1286{
1287 int i;
1288 char *p;
1289 ext2_filsys fs = (ext2_filsys) channel->app_data;
1290 e2fsck_t ctx;
1291
1292 ctx = (e2fsck_t) fs->priv_data;
1293
1294 /*
1295 * If more than one block was read, try reading each block
1296 * separately. We could use the actual bytes read to figure
1297 * out where to start, but we don't bother.
1298 */
1299 if (count > 1) {
1300 p = (char *) data;
1301 for (i=0; i < count; i++, p += channel->block_size, block++) {
1302 error = io_channel_read_blk(channel, block,
1303 1, p);
1304 if (error)
1305 return error;
1306 }
1307 return 0;
1308 }
1309 if (operation)
1310 printf(_("Error reading block %lu (%s) while %s. "), block,
1311 error_message(error), operation);
1312 else
1313 printf(_("Error reading block %lu (%s). "), block,
1314 error_message(error));
1315 preenhalt(ctx);
1316 if (ask(ctx, _("Ignore error"), 1)) {
1317 if (ask(ctx, _("Force rewrite"), 1))
1318 io_channel_write_blk(channel, block, 1, data);
1319 return 0;
1320 }
1321
1322 return error;
1323}
1324
1325static errcode_t
1326e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1327 const void *data, size_t size FSCK_ATTR((unused)),
1328 int actual FSCK_ATTR((unused)), errcode_t error)
1329{
1330 int i;
1331 const char *p;
1332 ext2_filsys fs = (ext2_filsys) channel->app_data;
1333 e2fsck_t ctx;
1334
1335 ctx = (e2fsck_t) fs->priv_data;
1336
1337 /*
1338 * If more than one block was written, try writing each block
1339 * separately. We could use the actual bytes read to figure
1340 * out where to start, but we don't bother.
1341 */
1342 if (count > 1) {
1343 p = (const char *) data;
1344 for (i=0; i < count; i++, p += channel->block_size, block++) {
1345 error = io_channel_write_blk(channel, block,
1346 1, p);
1347 if (error)
1348 return error;
1349 }
1350 return 0;
1351 }
1352
1353 if (operation)
1354 printf(_("Error writing block %lu (%s) while %s. "), block,
1355 error_message(error), operation);
1356 else
1357 printf(_("Error writing block %lu (%s). "), block,
1358 error_message(error));
1359 preenhalt(ctx);
1360 if (ask(ctx, _("Ignore error"), 1))
1361 return 0;
1362
1363 return error;
1364}
1365
1366static const char *ehandler_operation(const char *op)
1367{
1368 const char *ret = operation;
1369
1370 operation = op;
1371 return ret;
1372}
1373
1374static void ehandler_init(io_channel channel)
1375{
1376 channel->read_error = e2fsck_handle_read_error;
1377 channel->write_error = e2fsck_handle_write_error;
1378}
1379
1380/*
1381 * journal.c --- code for handling the "ext3" journal
1382 *
1383 * Copyright (C) 2000 Andreas Dilger
1384 * Copyright (C) 2000 Theodore Ts'o
1385 *
1386 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1387 * Copyright (C) 1999 Red Hat Software
1388 *
1389 * This file may be redistributed under the terms of the
1390 * GNU General Public License version 2 or at your discretion
1391 * any later version.
1392 */
1393
1394/*
1395 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1396 * This creates a larger static binary, and a smaller binary using
1397 * shared libraries. It's also probably slightly less CPU-efficient,
1398 * which is why it's not on by default. But, it's a good way of
1399 * testing the functions in inode_io.c and fileio.c.
1400 */
1401#undef USE_INODE_IO
1402
1403/* Kernel compatibility functions for handling the journal. These allow us
1404 * to use the recovery.c file virtually unchanged from the kernel, so we
1405 * don't have to do much to keep kernel and user recovery in sync.
1406 */
1407static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1408{
1409#ifdef USE_INODE_IO
1410 *phys = block;
1411 return 0;
1412#else
1413 struct inode *inode = journal->j_inode;
1414 errcode_t retval;
1415 blk_t pblk;
1416
1417 if (!inode) {
1418 *phys = block;
1419 return 0;
1420 }
1421
1422 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1423 &inode->i_ext2, NULL, 0, block, &pblk);
1424 *phys = pblk;
1425 return retval;
1426#endif
1427}
1428
1429static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1430{
1431 struct buffer_head *bh;
1432
1433 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1434 if (!bh)
1435 return NULL;
1436
1437 bh->b_ctx = kdev->k_ctx;
1438 if (kdev->k_dev == K_DEV_FS)
1439 bh->b_io = kdev->k_ctx->fs->io;
1440 else
1441 bh->b_io = kdev->k_ctx->journal_io;
1442 bh->b_size = blocksize;
1443 bh->b_blocknr = blocknr;
1444
1445 return bh;
1446}
1447
1448static void sync_blockdev(kdev_t kdev)
1449{
1450 io_channel io;
1451
1452 if (kdev->k_dev == K_DEV_FS)
1453 io = kdev->k_ctx->fs->io;
1454 else
1455 io = kdev->k_ctx->journal_io;
1456
1457 io_channel_flush(io);
1458}
1459
1460static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1461{
1462 int retval;
1463 struct buffer_head *bh;
1464
1465 for (; nr > 0; --nr) {
1466 bh = *bhp++;
1467 if (rw == READ && !bh->b_uptodate) {
1468 retval = io_channel_read_blk(bh->b_io,
1469 bh->b_blocknr,
1470 1, bh->b_data);
1471 if (retval) {
1472 bb_error_msg("while reading block %lu",
1473 (unsigned long) bh->b_blocknr);
1474 bh->b_err = retval;
1475 continue;
1476 }
1477 bh->b_uptodate = 1;
1478 } else if (rw == WRITE && bh->b_dirty) {
1479 retval = io_channel_write_blk(bh->b_io,
1480 bh->b_blocknr,
1481 1, bh->b_data);
1482 if (retval) {
1483 bb_error_msg("while writing block %lu",
1484 (unsigned long) bh->b_blocknr);
1485 bh->b_err = retval;
1486 continue;
1487 }
1488 bh->b_dirty = 0;
1489 bh->b_uptodate = 1;
1490 }
1491 }
1492}
1493
1494static void mark_buffer_dirty(struct buffer_head *bh)
1495{
1496 bh->b_dirty = 1;
1497}
1498
1499static inline void mark_buffer_clean(struct buffer_head * bh)
1500{
1501 bh->b_dirty = 0;
1502}
1503
1504static void brelse(struct buffer_head *bh)
1505{
1506 if (bh->b_dirty)
1507 ll_rw_block(WRITE, 1, &bh);
1508 ext2fs_free_mem(&bh);
1509}
1510
1511static int buffer_uptodate(struct buffer_head *bh)
1512{
1513 return bh->b_uptodate;
1514}
1515
1516static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1517{
1518 bh->b_uptodate = val;
1519}
1520
1521static void wait_on_buffer(struct buffer_head *bh)
1522{
1523 if (!bh->b_uptodate)
1524 ll_rw_block(READ, 1, &bh);
1525}
1526
1527
1528static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1529{
1530 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1531
1532 /* if we had an error doing journal recovery, we need a full fsck */
1533 if (error)
1534 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1535 ext2fs_mark_super_dirty(ctx->fs);
1536}
1537
1538static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1539{
1540 struct ext2_super_block *sb = ctx->fs->super;
1541 struct ext2_super_block jsuper;
1542 struct problem_context pctx;
1543 struct buffer_head *bh;
1544 struct inode *j_inode = NULL;
1545 struct kdev_s *dev_fs = NULL, *dev_journal;
1546 const char *journal_name = 0;
1547 journal_t *journal = NULL;
1548 errcode_t retval = 0;
1549 io_manager io_ptr = 0;
1550 unsigned long start = 0;
1551 blk_t blk;
1552 int ext_journal = 0;
1553 int tried_backup_jnl = 0;
1554 int i;
1555
1556 clear_problem_context(&pctx);
1557
1558 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1559 if (!journal) {
1560 return EXT2_ET_NO_MEMORY;
1561 }
1562
1563 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1564 if (!dev_fs) {
1565 retval = EXT2_ET_NO_MEMORY;
1566 goto errout;
1567 }
1568 dev_journal = dev_fs+1;
1569
1570 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1571 dev_fs->k_dev = K_DEV_FS;
1572 dev_journal->k_dev = K_DEV_JOURNAL;
1573
1574 journal->j_dev = dev_journal;
1575 journal->j_fs_dev = dev_fs;
1576 journal->j_inode = NULL;
1577 journal->j_blocksize = ctx->fs->blocksize;
1578
1579 if (uuid_is_null(sb->s_journal_uuid)) {
1580 if (!sb->s_journal_inum)
1581 return EXT2_ET_BAD_INODE_NUM;
1582 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1583 "journal inode");
1584 if (!j_inode) {
1585 retval = EXT2_ET_NO_MEMORY;
1586 goto errout;
1587 }
1588
1589 j_inode->i_ctx = ctx;
1590 j_inode->i_ino = sb->s_journal_inum;
1591
1592 if ((retval = ext2fs_read_inode(ctx->fs,
1593 sb->s_journal_inum,
1594 &j_inode->i_ext2))) {
1595 try_backup_journal:
1596 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1597 tried_backup_jnl)
1598 goto errout;
1599 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1600 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1601 EXT2_N_BLOCKS*4);
1602 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1603 j_inode->i_ext2.i_links_count = 1;
1604 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1605 tried_backup_jnl++;
1606 }
1607 if (!j_inode->i_ext2.i_links_count ||
1608 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1609 retval = EXT2_ET_NO_JOURNAL;
1610 goto try_backup_journal;
1611 }
1612 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1613 JFS_MIN_JOURNAL_BLOCKS) {
1614 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1615 goto try_backup_journal;
1616 }
1617 for (i=0; i < EXT2_N_BLOCKS; i++) {
1618 blk = j_inode->i_ext2.i_block[i];
1619 if (!blk) {
1620 if (i < EXT2_NDIR_BLOCKS) {
1621 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1622 goto try_backup_journal;
1623 }
1624 continue;
1625 }
1626 if (blk < sb->s_first_data_block ||
1627 blk >= sb->s_blocks_count) {
1628 retval = EXT2_ET_BAD_BLOCK_NUM;
1629 goto try_backup_journal;
1630 }
1631 }
1632 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1633
1634#ifdef USE_INODE_IO
1635 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1636 &j_inode->i_ext2,
1637 &journal_name);
1638 if (retval)
1639 goto errout;
1640
1641 io_ptr = inode_io_manager;
1642#else
1643 journal->j_inode = j_inode;
1644 ctx->journal_io = ctx->fs->io;
1645 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1646 goto errout;
1647#endif
1648 } else {
1649 ext_journal = 1;
1650 if (!ctx->journal_name) {
1651 char uuid[37];
1652
1653 uuid_unparse(sb->s_journal_uuid, uuid);
1654 ctx->journal_name = blkid_get_devname(ctx->blkid,
1655 "UUID", uuid);
1656 if (!ctx->journal_name)
1657 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1658 }
1659 journal_name = ctx->journal_name;
1660
1661 if (!journal_name) {
1662 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1663 return EXT2_ET_LOAD_EXT_JOURNAL;
1664 }
1665
1666 io_ptr = unix_io_manager;
1667 }
1668
1669#ifndef USE_INODE_IO
1670 if (ext_journal)
1671#endif
1672 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1673 &ctx->journal_io);
1674 if (retval)
1675 goto errout;
1676
1677 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1678
1679 if (ext_journal) {
1680 if (ctx->fs->blocksize == 1024)
1681 start = 1;
1682 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1683 if (!bh) {
1684 retval = EXT2_ET_NO_MEMORY;
1685 goto errout;
1686 }
1687 ll_rw_block(READ, 1, &bh);
1688 if ((retval = bh->b_err) != 0)
1689 goto errout;
1690 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1691 sizeof(jsuper));
1692 brelse(bh);
1693#if BB_BIG_ENDIAN
1694 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1695 ext2fs_swap_super(&jsuper);
1696#endif
1697 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1698 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1699 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1700 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1701 goto errout;
1702 }
1703 /* Make sure the journal UUID is correct */
1704 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1705 sizeof(jsuper.s_uuid))) {
1706 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1707 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1708 goto errout;
1709 }
1710
1711 journal->j_maxlen = jsuper.s_blocks_count;
1712 start++;
1713 }
1714
1715 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1716 retval = EXT2_ET_NO_MEMORY;
1717 goto errout;
1718 }
1719
1720 journal->j_sb_buffer = bh;
1721 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1722
1723#ifdef USE_INODE_IO
1724 ext2fs_free_mem(&j_inode);
1725#endif
1726
1727 *ret_journal = journal;
1728 return 0;
1729
1730errout:
1731 ext2fs_free_mem(&dev_fs);
1732 ext2fs_free_mem(&j_inode);
1733 ext2fs_free_mem(&journal);
1734 return retval;
1735
1736}
1737
1738static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1739 struct problem_context *pctx)
1740{
1741 struct ext2_super_block *sb = ctx->fs->super;
1742 int recover = ctx->fs->super->s_feature_incompat &
1743 EXT3_FEATURE_INCOMPAT_RECOVER;
1744 int has_journal = ctx->fs->super->s_feature_compat &
1745 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1746
1747 if (has_journal || sb->s_journal_inum) {
1748 /* The journal inode is bogus, remove and force full fsck */
1749 pctx->ino = sb->s_journal_inum;
1750 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1751 if (has_journal && sb->s_journal_inum)
1752 printf("*** ext3 journal has been deleted - "
1753 "filesystem is now ext2 only ***\n\n");
1754 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1755 sb->s_journal_inum = 0;
1756 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1757 e2fsck_clear_recover(ctx, 1);
1758 return 0;
1759 }
1760 return EXT2_ET_BAD_INODE_NUM;
1761 } else if (recover) {
1762 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1763 e2fsck_clear_recover(ctx, 1);
1764 return 0;
1765 }
1766 return EXT2_ET_UNSUPP_FEATURE;
1767 }
1768 return 0;
1769}
1770
1771#define V1_SB_SIZE 0x0024
1772static void clear_v2_journal_fields(journal_t *journal)
1773{
1774 e2fsck_t ctx = journal->j_dev->k_ctx;
1775 struct problem_context pctx;
1776
1777 clear_problem_context(&pctx);
1778
1779 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1780 return;
1781
1782 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1783 ctx->fs->blocksize-V1_SB_SIZE);
1784 mark_buffer_dirty(journal->j_sb_buffer);
1785}
1786
1787
1788static errcode_t e2fsck_journal_load(journal_t *journal)
1789{
1790 e2fsck_t ctx = journal->j_dev->k_ctx;
1791 journal_superblock_t *jsb;
1792 struct buffer_head *jbh = journal->j_sb_buffer;
1793 struct problem_context pctx;
1794
1795 clear_problem_context(&pctx);
1796
1797 ll_rw_block(READ, 1, &jbh);
1798 if (jbh->b_err) {
1799 bb_error_msg(_("reading journal superblock"));
1800 return jbh->b_err;
1801 }
1802
1803 jsb = journal->j_superblock;
1804 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1805 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1806 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1807
1808 switch (ntohl(jsb->s_header.h_blocktype)) {
1809 case JFS_SUPERBLOCK_V1:
1810 journal->j_format_version = 1;
1811 if (jsb->s_feature_compat ||
1812 jsb->s_feature_incompat ||
1813 jsb->s_feature_ro_compat ||
1814 jsb->s_nr_users)
1815 clear_v2_journal_fields(journal);
1816 break;
1817
1818 case JFS_SUPERBLOCK_V2:
1819 journal->j_format_version = 2;
1820 if (ntohl(jsb->s_nr_users) > 1 &&
1821 uuid_is_null(ctx->fs->super->s_journal_uuid))
1822 clear_v2_journal_fields(journal);
1823 if (ntohl(jsb->s_nr_users) > 1) {
1824 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1825 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1826 }
1827 break;
1828
1829 /*
1830 * These should never appear in a journal super block, so if
1831 * they do, the journal is badly corrupted.
1832 */
1833 case JFS_DESCRIPTOR_BLOCK:
1834 case JFS_COMMIT_BLOCK:
1835 case JFS_REVOKE_BLOCK:
1836 return EXT2_ET_CORRUPT_SUPERBLOCK;
1837
1838 /* If we don't understand the superblock major type, but there
1839 * is a magic number, then it is likely to be a new format we
1840 * just don't understand, so leave it alone. */
1841 default:
1842 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1843 }
1844
1845 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1846 return EXT2_ET_UNSUPP_FEATURE;
1847
1848 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1849 return EXT2_ET_RO_UNSUPP_FEATURE;
1850
1851 /* We have now checked whether we know enough about the journal
1852 * format to be able to proceed safely, so any other checks that
1853 * fail we should attempt to recover from. */
1854 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1855 bb_error_msg(_("%s: no valid journal superblock found"),
1856 ctx->device_name);
1857 return EXT2_ET_CORRUPT_SUPERBLOCK;
1858 }
1859
1860 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1861 journal->j_maxlen = ntohl(jsb->s_maxlen);
1862 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1863 bb_error_msg(_("%s: journal too short"),
1864 ctx->device_name);
1865 return EXT2_ET_CORRUPT_SUPERBLOCK;
1866 }
1867
1868 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1869 journal->j_transaction_sequence = journal->j_tail_sequence;
1870 journal->j_tail = ntohl(jsb->s_start);
1871 journal->j_first = ntohl(jsb->s_first);
1872 journal->j_last = ntohl(jsb->s_maxlen);
1873
1874 return 0;
1875}
1876
1877static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1878 journal_t *journal)
1879{
1880 char *p;
1881 union {
1882 uuid_t uuid;
1883 __u32 val[4];
1884 } u;
1885 __u32 new_seq = 0;
1886 int i;
1887
1888 /* Leave a valid existing V1 superblock signature alone.
1889 * Anything unrecognisable we overwrite with a new V2
1890 * signature. */
1891
1892 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1893 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1894 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1895 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1896 }
1897
1898 /* Zero out everything else beyond the superblock header */
1899
1900 p = ((char *) jsb) + sizeof(journal_header_t);
1901 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1902
1903 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1904 jsb->s_maxlen = htonl(journal->j_maxlen);
1905 jsb->s_first = htonl(1);
1906
1907 /* Initialize the journal sequence number so that there is "no"
1908 * chance we will find old "valid" transactions in the journal.
1909 * This avoids the need to zero the whole journal (slow to do,
1910 * and risky when we are just recovering the filesystem).
1911 */
1912 uuid_generate(u.uuid);
1913 for (i = 0; i < 4; i ++)
1914 new_seq ^= u.val[i];
1915 jsb->s_sequence = htonl(new_seq);
1916
1917 mark_buffer_dirty(journal->j_sb_buffer);
1918 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1919}
1920
1921static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1922 journal_t *journal,
1923 struct problem_context *pctx)
1924{
1925 struct ext2_super_block *sb = ctx->fs->super;
1926 int recover = ctx->fs->super->s_feature_incompat &
1927 EXT3_FEATURE_INCOMPAT_RECOVER;
1928
1929 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1930 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1931 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1932 journal);
1933 journal->j_transaction_sequence = 1;
1934 e2fsck_clear_recover(ctx, recover);
1935 return 0;
1936 }
1937 return EXT2_ET_CORRUPT_SUPERBLOCK;
1938 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1939 return EXT2_ET_CORRUPT_SUPERBLOCK;
1940
1941 return 0;
1942}
1943
1944static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1945 int reset, int drop)
1946{
1947 journal_superblock_t *jsb;
1948
1949 if (drop)
1950 mark_buffer_clean(journal->j_sb_buffer);
1951 else if (!(ctx->options & E2F_OPT_READONLY)) {
1952 jsb = journal->j_superblock;
1953 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1954 if (reset)
1955 jsb->s_start = 0; /* this marks the journal as empty */
1956 mark_buffer_dirty(journal->j_sb_buffer);
1957 }
1958 brelse(journal->j_sb_buffer);
1959
1960 if (ctx->journal_io) {
1961 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1962 io_channel_close(ctx->journal_io);
1963 ctx->journal_io = 0;
1964 }
1965
1966#ifndef USE_INODE_IO
1967 ext2fs_free_mem(&journal->j_inode);
1968#endif
1969 ext2fs_free_mem(&journal->j_fs_dev);
1970 ext2fs_free_mem(&journal);
1971}
1972
1973/*
1974 * This function makes sure that the superblock fields regarding the
1975 * journal are consistent.
1976 */
1977static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1978{
1979 struct ext2_super_block *sb = ctx->fs->super;
1980 journal_t *journal;
1981 int recover = ctx->fs->super->s_feature_incompat &
1982 EXT3_FEATURE_INCOMPAT_RECOVER;
1983 struct problem_context pctx;
1984 problem_t problem;
1985 int reset = 0, force_fsck = 0;
1986 int retval;
1987
1988 /* If we don't have any journal features, don't do anything more */
1989 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1990 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1991 uuid_is_null(sb->s_journal_uuid))
1992 return 0;
1993
1994 clear_problem_context(&pctx);
1995 pctx.num = sb->s_journal_inum;
1996
1997 retval = e2fsck_get_journal(ctx, &journal);
1998 if (retval) {
1999 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2000 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2001 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2002 (retval == EXT2_ET_NO_JOURNAL))
2003 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2004 return retval;
2005 }
2006
2007 retval = e2fsck_journal_load(journal);
2008 if (retval) {
2009 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2010 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2011 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2012 &pctx))) ||
2013 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2014 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2015 &pctx))) ||
2016 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2017 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2018 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2019 &pctx);
2020 e2fsck_journal_release(ctx, journal, 0, 1);
2021 return retval;
2022 }
2023
2024 /*
2025 * We want to make the flags consistent here. We will not leave with
2026 * needs_recovery set but has_journal clear. We can't get in a loop
2027 * with -y, -n, or -p, only if a user isn't making up their mind.
2028 */
2029no_has_journal:
2030 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2031 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2032 pctx.str = "inode";
2033 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2034 if (recover &&
2035 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2036 goto no_has_journal;
2037 /*
2038 * Need a full fsck if we are releasing a
2039 * journal stored on a reserved inode.
2040 */
2041 force_fsck = recover ||
2042 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2043 /* Clear all of the journal fields */
2044 sb->s_journal_inum = 0;
2045 sb->s_journal_dev = 0;
2046 memset(sb->s_journal_uuid, 0,
2047 sizeof(sb->s_journal_uuid));
2048 e2fsck_clear_recover(ctx, force_fsck);
2049 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2050 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2051 ext2fs_mark_super_dirty(ctx->fs);
2052 }
2053 }
2054
2055 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2056 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2057 journal->j_superblock->s_start != 0) {
2058 /* Print status information */
2059 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2060 if (ctx->superblock)
2061 problem = PR_0_JOURNAL_RUN_DEFAULT;
2062 else
2063 problem = PR_0_JOURNAL_RUN;
2064 if (fix_problem(ctx, problem, &pctx)) {
2065 ctx->options |= E2F_OPT_FORCE;
2066 sb->s_feature_incompat |=
2067 EXT3_FEATURE_INCOMPAT_RECOVER;
2068 ext2fs_mark_super_dirty(ctx->fs);
2069 } else if (fix_problem(ctx,
2070 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2071 reset = 1;
2072 sb->s_state &= ~EXT2_VALID_FS;
2073 ext2fs_mark_super_dirty(ctx->fs);
2074 }
2075 /*
2076 * If the user answers no to the above question, we
2077 * ignore the fact that journal apparently has data;
2078 * accidentally replaying over valid data would be far
2079 * worse than skipping a questionable recovery.
2080 *
2081 * XXX should we abort with a fatal error here? What
2082 * will the ext3 kernel code do if a filesystem with
2083 * !NEEDS_RECOVERY but with a non-zero
2084 * journal->j_superblock->s_start is mounted?
2085 */
2086 }
2087
2088 e2fsck_journal_release(ctx, journal, reset, 0);
2089 return retval;
2090}
2091
2092static errcode_t recover_ext3_journal(e2fsck_t ctx)
2093{
2094 journal_t *journal;
2095 int retval;
2096
2097 journal_init_revoke_caches();
2098 retval = e2fsck_get_journal(ctx, &journal);
2099 if (retval)
2100 return retval;
2101
2102 retval = e2fsck_journal_load(journal);
2103 if (retval)
2104 goto errout;
2105
2106 retval = journal_init_revoke(journal, 1024);
2107 if (retval)
2108 goto errout;
2109
2110 retval = -journal_recover(journal);
2111 if (retval)
2112 goto errout;
2113
2114 if (journal->j_superblock->s_errno) {
2115 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2116 ext2fs_mark_super_dirty(ctx->fs);
2117 journal->j_superblock->s_errno = 0;
2118 mark_buffer_dirty(journal->j_sb_buffer);
2119 }
2120
2121errout:
2122 journal_destroy_revoke(journal);
2123 journal_destroy_revoke_caches();
2124 e2fsck_journal_release(ctx, journal, 1, 0);
2125 return retval;
2126}
2127
2128static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2129{
2130 io_manager io_ptr = ctx->fs->io->manager;
2131 int blocksize = ctx->fs->blocksize;
2132 errcode_t retval, recover_retval;
2133
2134 printf(_("%s: recovering journal\n"), ctx->device_name);
2135 if (ctx->options & E2F_OPT_READONLY) {
2136 printf(_("%s: won't do journal recovery while read-only\n"),
2137 ctx->device_name);
2138 return EXT2_ET_FILE_RO;
2139 }
2140
2141 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2142 ext2fs_flush(ctx->fs); /* Force out any modifications */
2143
2144 recover_retval = recover_ext3_journal(ctx);
2145
2146 /*
2147 * Reload the filesystem context to get up-to-date data from disk
2148 * because journal recovery will change the filesystem under us.
2149 */
2150 ext2fs_close(ctx->fs);
2151 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2152 ctx->superblock, blocksize, io_ptr,
2153 &ctx->fs);
2154
2155 if (retval) {
2156 bb_error_msg(_("while trying to re-open %s"),
2157 ctx->device_name);
2158 bb_error_msg_and_die(0);
2159 }
2160 ctx->fs->priv_data = ctx;
2161
2162 /* Set the superblock flags */
2163 e2fsck_clear_recover(ctx, recover_retval);
2164 return recover_retval;
2165}
2166
2167/*
2168 * This function will move the journal inode from a visible file in
2169 * the filesystem directory hierarchy to the reserved inode if necessary.
2170 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002171static const char *const journal_names[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002172 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2173
2174static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2175{
2176 struct ext2_super_block *sb = ctx->fs->super;
2177 struct problem_context pctx;
2178 struct ext2_inode inode;
2179 ext2_filsys fs = ctx->fs;
2180 ext2_ino_t ino;
2181 errcode_t retval;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002182 const char *const * cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002183 int group, mount_flags;
2184
2185 clear_problem_context(&pctx);
2186
2187 /*
2188 * If the filesystem is opened read-only, or there is no
2189 * journal, then do nothing.
2190 */
2191 if ((ctx->options & E2F_OPT_READONLY) ||
2192 (sb->s_journal_inum == 0) ||
2193 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2194 return;
2195
2196 /*
2197 * Read in the journal inode
2198 */
2199 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2200 return;
2201
2202 /*
2203 * If it's necessary to backup the journal inode, do so.
2204 */
2205 if ((sb->s_jnl_backup_type == 0) ||
2206 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2207 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2208 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2209 memcpy(sb->s_jnl_blocks, inode.i_block,
2210 EXT2_N_BLOCKS*4);
2211 sb->s_jnl_blocks[16] = inode.i_size;
2212 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2213 ext2fs_mark_super_dirty(fs);
2214 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2215 }
2216 }
2217
2218 /*
2219 * If the journal is already the hidden inode, then do nothing
2220 */
2221 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2222 return;
2223
2224 /*
2225 * The journal inode had better have only one link and not be readable.
2226 */
2227 if (inode.i_links_count != 1)
2228 return;
2229
2230 /*
2231 * If the filesystem is mounted, or we can't tell whether
2232 * or not it's mounted, do nothing.
2233 */
2234 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2235 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2236 return;
2237
2238 /*
2239 * If we can't find the name of the journal inode, then do
2240 * nothing.
2241 */
2242 for (cpp = journal_names; *cpp; cpp++) {
2243 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2244 strlen(*cpp), 0, &ino);
2245 if ((retval == 0) && (ino == sb->s_journal_inum))
2246 break;
2247 }
2248 if (*cpp == 0)
2249 return;
2250
2251 /* We need the inode bitmap to be loaded */
2252 retval = ext2fs_read_bitmaps(fs);
2253 if (retval)
2254 return;
2255
2256 pctx.str = *cpp;
2257 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2258 return;
2259
2260 /*
2261 * OK, we've done all the checks, let's actually move the
2262 * journal inode. Errors at this point mean we need to force
2263 * an ext2 filesystem check.
2264 */
2265 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2266 goto err_out;
2267 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2268 goto err_out;
2269 sb->s_journal_inum = EXT2_JOURNAL_INO;
2270 ext2fs_mark_super_dirty(fs);
2271 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2272 inode.i_links_count = 0;
2273 inode.i_dtime = time(0);
2274 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2275 goto err_out;
2276
2277 group = ext2fs_group_of_ino(fs, ino);
2278 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2279 ext2fs_mark_ib_dirty(fs);
2280 fs->group_desc[group].bg_free_inodes_count++;
2281 fs->super->s_free_inodes_count++;
2282 return;
2283
2284err_out:
2285 pctx.errcode = retval;
2286 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2287 fs->super->s_state &= ~EXT2_VALID_FS;
2288 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002289}
2290
2291/*
2292 * message.c --- print e2fsck messages (with compression)
2293 *
2294 * print_e2fsck_message() prints a message to the user, using
2295 * compression techniques and expansions of abbreviations.
2296 *
2297 * The following % expansions are supported:
2298 *
2299 * %b <blk> block number
2300 * %B <blkcount> integer
2301 * %c <blk2> block number
2302 * %Di <dirent>->ino inode number
2303 * %Dn <dirent>->name string
2304 * %Dr <dirent>->rec_len
2305 * %Dl <dirent>->name_len
2306 * %Dt <dirent>->filetype
2307 * %d <dir> inode number
2308 * %g <group> integer
2309 * %i <ino> inode number
2310 * %Is <inode> -> i_size
2311 * %IS <inode> -> i_extra_isize
2312 * %Ib <inode> -> i_blocks
2313 * %Il <inode> -> i_links_count
2314 * %Im <inode> -> i_mode
2315 * %IM <inode> -> i_mtime
2316 * %IF <inode> -> i_faddr
2317 * %If <inode> -> i_file_acl
2318 * %Id <inode> -> i_dir_acl
2319 * %Iu <inode> -> i_uid
2320 * %Ig <inode> -> i_gid
2321 * %j <ino2> inode number
2322 * %m <com_err error message>
2323 * %N <num>
2324 * %p ext2fs_get_pathname of directory <ino>
2325 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2326 * the containing directory. (If dirent is NULL
2327 * then return the pathname of directory <ino2>)
2328 * %q ext2fs_get_pathname of directory <dir>
2329 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2330 * the containing directory.
2331 * %s <str> miscellaneous string
2332 * %S backup superblock
2333 * %X <num> hexadecimal format
2334 *
2335 * The following '@' expansions are supported:
2336 *
2337 * @a extended attribute
2338 * @A error allocating
2339 * @b block
2340 * @B bitmap
2341 * @c compress
2342 * @C conflicts with some other fs block
2343 * @D deleted
2344 * @d directory
2345 * @e entry
2346 * @E Entry '%Dn' in %p (%i)
2347 * @f filesystem
2348 * @F for @i %i (%Q) is
2349 * @g group
2350 * @h HTREE directory inode
2351 * @i inode
2352 * @I illegal
2353 * @j journal
2354 * @l lost+found
2355 * @L is a link
2356 * @m multiply-claimed
2357 * @n invalid
2358 * @o orphaned
2359 * @p problem in
2360 * @r root inode
2361 * @s should be
2362 * @S superblock
2363 * @u unattached
2364 * @v device
2365 * @z zero-length
2366 */
2367
2368
2369/*
2370 * This structure defines the abbreviations used by the text strings
2371 * below. The first character in the string is the index letter. An
2372 * abbreviation of the form '@<i>' is expanded by looking up the index
2373 * letter <i> in the table below.
2374 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002375static const char *const abbrevs[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002376 N_("aextended attribute"),
2377 N_("Aerror allocating"),
2378 N_("bblock"),
2379 N_("Bbitmap"),
2380 N_("ccompress"),
2381 N_("Cconflicts with some other fs @b"),
2382 N_("iinode"),
2383 N_("Iillegal"),
2384 N_("jjournal"),
2385 N_("Ddeleted"),
2386 N_("ddirectory"),
2387 N_("eentry"),
2388 N_("E@e '%Dn' in %p (%i)"),
2389 N_("ffilesystem"),
2390 N_("Ffor @i %i (%Q) is"),
2391 N_("ggroup"),
2392 N_("hHTREE @d @i"),
2393 N_("llost+found"),
2394 N_("Lis a link"),
2395 N_("mmultiply-claimed"),
2396 N_("ninvalid"),
2397 N_("oorphaned"),
2398 N_("pproblem in"),
2399 N_("rroot @i"),
2400 N_("sshould be"),
2401 N_("Ssuper@b"),
2402 N_("uunattached"),
2403 N_("vdevice"),
2404 N_("zzero-length"),
2405 "@@",
2406 0
2407 };
2408
2409/*
2410 * Give more user friendly names to the "special" inodes.
2411 */
2412#define num_special_inodes 11
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002413static const char *const special_inode_name[] =
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002414{
2415 N_("<The NULL inode>"), /* 0 */
2416 N_("<The bad blocks inode>"), /* 1 */
2417 "/", /* 2 */
2418 N_("<The ACL index inode>"), /* 3 */
2419 N_("<The ACL data inode>"), /* 4 */
2420 N_("<The boot loader inode>"), /* 5 */
2421 N_("<The undelete directory inode>"), /* 6 */
2422 N_("<The group descriptor inode>"), /* 7 */
2423 N_("<The journal inode>"), /* 8 */
2424 N_("<Reserved inode 9>"), /* 9 */
2425 N_("<Reserved inode 10>"), /* 10 */
2426};
2427
2428/*
2429 * This function does "safe" printing. It will convert non-printable
2430 * ASCII characters using '^' and M- notation.
2431 */
2432static void safe_print(const char *cp, int len)
2433{
2434 unsigned char ch;
2435
2436 if (len < 0)
2437 len = strlen(cp);
2438
2439 while (len--) {
2440 ch = *cp++;
2441 if (ch > 128) {
2442 fputs("M-", stdout);
2443 ch -= 128;
2444 }
2445 if ((ch < 32) || (ch == 0x7f)) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002446 bb_putchar('^');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002447 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2448 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00002449 bb_putchar(ch);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002450 }
2451}
2452
2453
2454/*
2455 * This function prints a pathname, using the ext2fs_get_pathname
2456 * function
2457 */
2458static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2459{
2460 errcode_t retval;
2461 char *path;
2462
2463 if (!dir && (ino < num_special_inodes)) {
2464 fputs(_(special_inode_name[ino]), stdout);
2465 return;
2466 }
2467
2468 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2469 if (retval)
2470 fputs("???", stdout);
2471 else {
2472 safe_print(path, -1);
2473 ext2fs_free_mem(&path);
2474 }
2475}
2476
2477static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2478 struct problem_context *pctx, int first);
2479/*
2480 * This function handles the '@' expansion. We allow recursive
2481 * expansion; an @ expression can contain further '@' and '%'
2482 * expressions.
2483 */
2484static void expand_at_expression(e2fsck_t ctx, char ch,
2485 struct problem_context *pctx,
2486 int *first)
2487{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002488 const char *const *cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002489 const char *str;
2490
2491 /* Search for the abbreviation */
2492 for (cpp = abbrevs; *cpp; cpp++) {
2493 if (ch == *cpp[0])
2494 break;
2495 }
2496 if (*cpp) {
2497 str = _(*cpp) + 1;
2498 if (*first && islower(*str)) {
2499 *first = 0;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002500 bb_putchar(toupper(*str++));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002501 }
2502 print_e2fsck_message(ctx, str, pctx, *first);
2503 } else
2504 printf("@%c", ch);
2505}
2506
2507/*
2508 * This function expands '%IX' expressions
2509 */
2510static void expand_inode_expression(char ch,
2511 struct problem_context *ctx)
2512{
2513 struct ext2_inode *inode;
2514 struct ext2_inode_large *large_inode;
2515 char * time_str;
2516 time_t t;
2517 int do_gmt = -1;
2518
2519 if (!ctx || !ctx->inode)
2520 goto no_inode;
2521
2522 inode = ctx->inode;
2523 large_inode = (struct ext2_inode_large *) inode;
2524
2525 switch (ch) {
2526 case 's':
2527 if (LINUX_S_ISDIR(inode->i_mode))
2528 printf("%u", inode->i_size);
2529 else {
2530 printf("%"PRIu64, (inode->i_size |
2531 ((uint64_t) inode->i_size_high << 32)));
2532 }
2533 break;
2534 case 'S':
2535 printf("%u", large_inode->i_extra_isize);
2536 break;
2537 case 'b':
2538 printf("%u", inode->i_blocks);
2539 break;
2540 case 'l':
2541 printf("%d", inode->i_links_count);
2542 break;
2543 case 'm':
2544 printf("0%o", inode->i_mode);
2545 break;
2546 case 'M':
2547 /* The diet libc doesn't respect the TZ environemnt variable */
2548 if (do_gmt == -1) {
2549 time_str = getenv("TZ");
2550 if (!time_str)
2551 time_str = "";
2552 do_gmt = !strcmp(time_str, "GMT");
2553 }
2554 t = inode->i_mtime;
2555 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2556 printf("%.24s", time_str);
2557 break;
2558 case 'F':
2559 printf("%u", inode->i_faddr);
2560 break;
2561 case 'f':
2562 printf("%u", inode->i_file_acl);
2563 break;
2564 case 'd':
2565 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2566 inode->i_dir_acl : 0));
2567 break;
2568 case 'u':
2569 printf("%d", (inode->i_uid |
2570 (inode->osd2.linux2.l_i_uid_high << 16)));
2571 break;
2572 case 'g':
2573 printf("%d", (inode->i_gid |
2574 (inode->osd2.linux2.l_i_gid_high << 16)));
2575 break;
2576 default:
2577 no_inode:
2578 printf("%%I%c", ch);
2579 break;
2580 }
2581}
2582
2583/*
2584 * This function expands '%dX' expressions
2585 */
2586static void expand_dirent_expression(char ch,
2587 struct problem_context *ctx)
2588{
2589 struct ext2_dir_entry *dirent;
2590 int len;
2591
2592 if (!ctx || !ctx->dirent)
2593 goto no_dirent;
2594
2595 dirent = ctx->dirent;
2596
2597 switch (ch) {
2598 case 'i':
2599 printf("%u", dirent->inode);
2600 break;
2601 case 'n':
2602 len = dirent->name_len & 0xFF;
2603 if (len > EXT2_NAME_LEN)
2604 len = EXT2_NAME_LEN;
2605 if (len > dirent->rec_len)
2606 len = dirent->rec_len;
2607 safe_print(dirent->name, len);
2608 break;
2609 case 'r':
2610 printf("%u", dirent->rec_len);
2611 break;
2612 case 'l':
2613 printf("%u", dirent->name_len & 0xFF);
2614 break;
2615 case 't':
2616 printf("%u", dirent->name_len >> 8);
2617 break;
2618 default:
2619 no_dirent:
2620 printf("%%D%c", ch);
2621 break;
2622 }
2623}
2624
2625static void expand_percent_expression(ext2_filsys fs, char ch,
2626 struct problem_context *ctx)
2627{
2628 if (!ctx)
2629 goto no_context;
2630
2631 switch (ch) {
2632 case '%':
Denis Vlasenko4daad902007-09-27 10:20:47 +00002633 bb_putchar('%');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002634 break;
2635 case 'b':
2636 printf("%u", ctx->blk);
2637 break;
2638 case 'B':
2639 printf("%"PRIi64, ctx->blkcount);
2640 break;
2641 case 'c':
2642 printf("%u", ctx->blk2);
2643 break;
2644 case 'd':
2645 printf("%u", ctx->dir);
2646 break;
2647 case 'g':
2648 printf("%d", ctx->group);
2649 break;
2650 case 'i':
2651 printf("%u", ctx->ino);
2652 break;
2653 case 'j':
2654 printf("%u", ctx->ino2);
2655 break;
2656 case 'm':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002657 fputs(error_message(ctx->errcode), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002658 break;
2659 case 'N':
2660 printf("%"PRIi64, ctx->num);
2661 break;
2662 case 'p':
2663 print_pathname(fs, ctx->ino, 0);
2664 break;
2665 case 'P':
2666 print_pathname(fs, ctx->ino2,
2667 ctx->dirent ? ctx->dirent->inode : 0);
2668 break;
2669 case 'q':
2670 print_pathname(fs, ctx->dir, 0);
2671 break;
2672 case 'Q':
2673 print_pathname(fs, ctx->dir, ctx->ino);
2674 break;
2675 case 'S':
2676 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2677 break;
2678 case 's':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002679 fputs((ctx->str ? ctx->str : "NULL"), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002680 break;
2681 case 'X':
2682 printf("0x%"PRIi64, ctx->num);
2683 break;
2684 default:
2685 no_context:
2686 printf("%%%c", ch);
2687 break;
2688 }
2689}
2690
2691
2692static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2693 struct problem_context *pctx, int first)
2694{
2695 ext2_filsys fs = ctx->fs;
2696 const char * cp;
2697 int i;
2698
2699 e2fsck_clear_progbar(ctx);
2700 for (cp = msg; *cp; cp++) {
2701 if (cp[0] == '@') {
2702 cp++;
2703 expand_at_expression(ctx, *cp, pctx, &first);
2704 } else if (cp[0] == '%' && cp[1] == 'I') {
2705 cp += 2;
2706 expand_inode_expression(*cp, pctx);
2707 } else if (cp[0] == '%' && cp[1] == 'D') {
2708 cp += 2;
2709 expand_dirent_expression(*cp, pctx);
2710 } else if ((cp[0] == '%')) {
2711 cp++;
2712 expand_percent_expression(fs, *cp, pctx);
2713 } else {
2714 for (i=0; cp[i]; i++)
2715 if ((cp[i] == '@') || cp[i] == '%')
2716 break;
2717 printf("%.*s", i, cp);
2718 cp += i-1;
2719 }
2720 first = 0;
2721 }
2722}
2723
2724
2725/*
2726 * region.c --- code which manages allocations within a region.
2727 */
2728
2729struct region_el {
2730 region_addr_t start;
2731 region_addr_t end;
2732 struct region_el *next;
2733};
2734
2735struct region_struct {
2736 region_addr_t min;
2737 region_addr_t max;
2738 struct region_el *allocated;
2739};
2740
2741static region_t region_create(region_addr_t min, region_addr_t max)
2742{
2743 region_t region;
2744
2745 region = malloc(sizeof(struct region_struct));
2746 if (!region)
2747 return NULL;
2748 memset(region, 0, sizeof(struct region_struct));
2749 region->min = min;
2750 region->max = max;
2751 return region;
2752}
2753
2754static void region_free(region_t region)
2755{
2756 struct region_el *r, *next;
2757
2758 for (r = region->allocated; r; r = next) {
2759 next = r->next;
2760 free(r);
2761 }
2762 memset(region, 0, sizeof(struct region_struct));
2763 free(region);
2764}
2765
2766static int region_allocate(region_t region, region_addr_t start, int n)
2767{
2768 struct region_el *r, *new_region, *prev, *next;
2769 region_addr_t end;
2770
2771 end = start+n;
2772 if ((start < region->min) || (end > region->max))
2773 return -1;
2774 if (n == 0)
2775 return 1;
2776
2777 /*
2778 * Search through the linked list. If we find that it
2779 * conflicts witih something that's already allocated, return
2780 * 1; if we can find an existing region which we can grow, do
2781 * so. Otherwise, stop when we find the appropriate place
2782 * insert a new region element into the linked list.
2783 */
2784 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2785 if (((start >= r->start) && (start < r->end)) ||
2786 ((end > r->start) && (end <= r->end)) ||
2787 ((start <= r->start) && (end >= r->end)))
2788 return 1;
2789 if (end == r->start) {
2790 r->start = start;
2791 return 0;
2792 }
2793 if (start == r->end) {
2794 if ((next = r->next)) {
2795 if (end > next->start)
2796 return 1;
2797 if (end == next->start) {
2798 r->end = next->end;
2799 r->next = next->next;
2800 free(next);
2801 return 0;
2802 }
2803 }
2804 r->end = end;
2805 return 0;
2806 }
2807 if (start < r->start)
2808 break;
2809 }
2810 /*
2811 * Insert a new region element structure into the linked list
2812 */
2813 new_region = malloc(sizeof(struct region_el));
2814 if (!new_region)
2815 return -1;
2816 new_region->start = start;
2817 new_region->end = start + n;
2818 new_region->next = r;
2819 if (prev)
2820 prev->next = new_region;
2821 else
2822 region->allocated = new_region;
2823 return 0;
2824}
2825
2826/*
2827 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2828 *
2829 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2830 * and applies the following tests to each inode:
2831 *
2832 * - The mode field of the inode must be legal.
2833 * - The size and block count fields of the inode are correct.
2834 * - A data block must not be used by another inode
2835 *
2836 * Pass 1 also gathers the collects the following information:
2837 *
2838 * - A bitmap of which inodes are in use. (inode_used_map)
2839 * - A bitmap of which inodes are directories. (inode_dir_map)
2840 * - A bitmap of which inodes are regular files. (inode_reg_map)
2841 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2842 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2843 * - A bitmap of which blocks are in use. (block_found_map)
2844 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2845 * - The data blocks of the directory inodes. (dir_map)
2846 *
2847 * Pass 1 is designed to stash away enough information so that the
2848 * other passes should not need to read in the inode information
2849 * during the normal course of a filesystem check. (Althogh if an
2850 * inconsistency is detected, other passes may need to read in an
2851 * inode to fix it.)
2852 *
2853 * Note that pass 1B will be invoked if there are any duplicate blocks
2854 * found.
2855 */
2856
2857
2858static int process_block(ext2_filsys fs, blk_t *blocknr,
2859 e2_blkcnt_t blockcnt, blk_t ref_blk,
2860 int ref_offset, void *priv_data);
2861static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2862 e2_blkcnt_t blockcnt, blk_t ref_blk,
2863 int ref_offset, void *priv_data);
2864static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2865 char *block_buf);
2866static void mark_table_blocks(e2fsck_t ctx);
2867static void alloc_imagic_map(e2fsck_t ctx);
2868static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2869static void handle_fs_bad_blocks(e2fsck_t ctx);
2870static void process_inodes(e2fsck_t ctx, char *block_buf);
2871static int process_inode_cmp(const void *a, const void *b);
2872static errcode_t scan_callback(ext2_filsys fs,
2873 dgrp_t group, void * priv_data);
2874static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2875 char *block_buf, int adjust_sign);
2876/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2877
2878static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2879 struct ext2_inode * inode, int bufsize,
2880 const char *proc);
2881
2882struct process_block_struct_1 {
2883 ext2_ino_t ino;
2884 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2885 fragmented:1, compressed:1, bbcheck:1;
2886 blk_t num_blocks;
2887 blk_t max_blocks;
2888 e2_blkcnt_t last_block;
2889 int num_illegal_blocks;
2890 blk_t previous_block;
2891 struct ext2_inode *inode;
2892 struct problem_context *pctx;
2893 ext2fs_block_bitmap fs_meta_blocks;
2894 e2fsck_t ctx;
2895};
2896
2897struct process_inode_block {
2898 ext2_ino_t ino;
2899 struct ext2_inode inode;
2900};
2901
2902struct scan_callback_struct {
2903 e2fsck_t ctx;
2904 char *block_buf;
2905};
2906
2907/*
2908 * For the inodes to process list.
2909 */
2910static struct process_inode_block *inodes_to_process;
2911static int process_inode_count;
2912
2913static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2914 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2915
2916/*
2917 * Free all memory allocated by pass1 in preparation for restarting
2918 * things.
2919 */
2920static void unwind_pass1(void)
2921{
2922 ext2fs_free_mem(&inodes_to_process);
2923}
2924
2925/*
2926 * Check to make sure a device inode is real. Returns 1 if the device
2927 * checks out, 0 if not.
2928 *
2929 * Note: this routine is now also used to check FIFO's and Sockets,
2930 * since they have the same requirement; the i_block fields should be
2931 * zero.
2932 */
2933static int
2934e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2935{
2936 int i;
2937
2938 /*
2939 * If i_blocks is non-zero, or the index flag is set, then
2940 * this is a bogus device/fifo/socket
2941 */
2942 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2943 (inode->i_flags & EXT2_INDEX_FL))
2944 return 0;
2945
2946 /*
2947 * We should be able to do the test below all the time, but
2948 * because the kernel doesn't forcibly clear the device
2949 * inode's additional i_block fields, there are some rare
2950 * occasions when a legitimate device inode will have non-zero
2951 * additional i_block fields. So for now, we only complain
2952 * when the immutable flag is set, which should never happen
2953 * for devices. (And that's when the problem is caused, since
2954 * you can't set or clear immutable flags for devices.) Once
2955 * the kernel has been fixed we can change this...
2956 */
2957 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2958 for (i=4; i < EXT2_N_BLOCKS; i++)
2959 if (inode->i_block[i])
2960 return 0;
2961 }
2962 return 1;
2963}
2964
2965/*
2966 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2967 * checks out, 0 if not.
2968 */
2969static int
2970e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2971{
2972 unsigned int len;
2973 int i;
2974 blk_t blocks;
2975
2976 if ((inode->i_size_high || inode->i_size == 0) ||
2977 (inode->i_flags & EXT2_INDEX_FL))
2978 return 0;
2979
2980 blocks = ext2fs_inode_data_blocks(fs, inode);
2981 if (blocks) {
2982 if ((inode->i_size >= fs->blocksize) ||
2983 (blocks != fs->blocksize >> 9) ||
2984 (inode->i_block[0] < fs->super->s_first_data_block) ||
2985 (inode->i_block[0] >= fs->super->s_blocks_count))
2986 return 0;
2987
2988 for (i = 1; i < EXT2_N_BLOCKS; i++)
2989 if (inode->i_block[i])
2990 return 0;
2991
2992 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2993 return 0;
2994
2995 len = strnlen(buf, fs->blocksize);
2996 if (len == fs->blocksize)
2997 return 0;
2998 } else {
2999 if (inode->i_size >= sizeof(inode->i_block))
3000 return 0;
3001
3002 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3003 if (len == sizeof(inode->i_block))
3004 return 0;
3005 }
3006 if (len != inode->i_size)
3007 return 0;
3008 return 1;
3009}
3010
3011/*
3012 * If the immutable (or append-only) flag is set on the inode, offer
3013 * to clear it.
3014 */
3015#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3016static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3017{
3018 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3019 return;
3020
3021 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3022 return;
3023
3024 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3025 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3026}
3027
3028/*
3029 * If device, fifo or socket, check size is zero -- if not offer to
3030 * clear it
3031 */
3032static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3033{
3034 struct ext2_inode *inode = pctx->inode;
3035
3036 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3037 return;
3038
3039 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3040 return;
3041
3042 inode->i_size = 0;
3043 inode->i_size_high = 0;
3044 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3045}
3046
3047static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3048{
3049 struct ext2_super_block *sb = ctx->fs->super;
3050 struct ext2_inode_large *inode;
3051 struct ext2_ext_attr_entry *entry;
3052 char *start, *end;
3053 int storage_size, remain, offs;
3054 int problem = 0;
3055
3056 inode = (struct ext2_inode_large *) pctx->inode;
3057 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3058 inode->i_extra_isize;
3059 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3060 inode->i_extra_isize + sizeof(__u32);
3061 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3062 entry = (struct ext2_ext_attr_entry *) start;
3063
3064 /* scan all entry's headers first */
3065
3066 /* take finish entry 0UL into account */
3067 remain = storage_size - sizeof(__u32);
3068 offs = end - start;
3069
3070 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3071
3072 /* header eats this space */
3073 remain -= sizeof(struct ext2_ext_attr_entry);
3074
3075 /* is attribute name valid? */
3076 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3077 pctx->num = entry->e_name_len;
3078 problem = PR_1_ATTR_NAME_LEN;
3079 goto fix;
3080 }
3081
3082 /* attribute len eats this space */
3083 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3084
3085 /* check value size */
3086 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3087 pctx->num = entry->e_value_size;
3088 problem = PR_1_ATTR_VALUE_SIZE;
3089 goto fix;
3090 }
3091
3092 /* check value placement */
3093 if (entry->e_value_offs +
3094 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3095 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3096 pctx->num = entry->e_value_offs;
3097 problem = PR_1_ATTR_VALUE_OFFSET;
3098 goto fix;
3099 }
3100
3101 /* e_value_block must be 0 in inode's ea */
3102 if (entry->e_value_block != 0) {
3103 pctx->num = entry->e_value_block;
3104 problem = PR_1_ATTR_VALUE_BLOCK;
3105 goto fix;
3106 }
3107
3108 /* e_hash must be 0 in inode's ea */
3109 if (entry->e_hash != 0) {
3110 pctx->num = entry->e_hash;
3111 problem = PR_1_ATTR_HASH;
3112 goto fix;
3113 }
3114
3115 remain -= entry->e_value_size;
3116 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3117
3118 entry = EXT2_EXT_ATTR_NEXT(entry);
3119 }
3120fix:
3121 /*
3122 * it seems like a corruption. it's very unlikely we could repair
3123 * EA(s) in automatic fashion -bzzz
3124 */
3125 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3126 return;
3127
3128 /* simple remove all possible EA(s) */
3129 *((__u32 *)start) = 0UL;
3130 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3131 EXT2_INODE_SIZE(sb), "pass1");
3132}
3133
3134static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3135{
3136 struct ext2_super_block *sb = ctx->fs->super;
3137 struct ext2_inode_large *inode;
3138 __u32 *eamagic;
3139 int min, max;
3140
3141 inode = (struct ext2_inode_large *) pctx->inode;
3142 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3143 /* this isn't large inode. so, nothing to check */
3144 return;
3145 }
3146
3147 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3148 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3149 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3150 /*
3151 * For now we will allow i_extra_isize to be 0, but really
3152 * implementations should never allow i_extra_isize to be 0
3153 */
3154 if (inode->i_extra_isize &&
3155 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3156 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3157 return;
3158 inode->i_extra_isize = min;
3159 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3160 EXT2_INODE_SIZE(sb), "pass1");
3161 return;
3162 }
3163
3164 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3165 inode->i_extra_isize);
3166 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3167 /* it seems inode has an extended attribute(s) in body */
3168 check_ea_in_inode(ctx, pctx);
3169 }
3170}
3171
3172static void e2fsck_pass1(e2fsck_t ctx)
3173{
3174 int i;
3175 __u64 max_sizes;
3176 ext2_filsys fs = ctx->fs;
3177 ext2_ino_t ino;
3178 struct ext2_inode *inode;
3179 ext2_inode_scan scan;
3180 char *block_buf;
3181 unsigned char frag, fsize;
3182 struct problem_context pctx;
3183 struct scan_callback_struct scan_struct;
3184 struct ext2_super_block *sb = ctx->fs->super;
3185 int imagic_fs;
3186 int busted_fs_time = 0;
3187 int inode_size;
3188
3189 clear_problem_context(&pctx);
3190
3191 if (!(ctx->options & E2F_OPT_PREEN))
3192 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3193
3194 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3195 !(ctx->options & E2F_OPT_NO)) {
3196 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3197 ctx->dirs_to_hash = 0;
3198 }
3199
3200 /* Pass 1 */
3201
3202#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3203
3204 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3205 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3206 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3207 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3208 max_sizes = (max_sizes * (1UL << i)) - 1;
3209 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3210 }
3211#undef EXT2_BPP
3212
3213 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3214
3215 /*
3216 * Allocate bitmaps structures
3217 */
3218 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3219 &ctx->inode_used_map);
3220 if (pctx.errcode) {
3221 pctx.num = 1;
3222 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3223 ctx->flags |= E2F_FLAG_ABORT;
3224 return;
3225 }
3226 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3227 _("directory inode map"), &ctx->inode_dir_map);
3228 if (pctx.errcode) {
3229 pctx.num = 2;
3230 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3231 ctx->flags |= E2F_FLAG_ABORT;
3232 return;
3233 }
3234 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3235 _("regular file inode map"), &ctx->inode_reg_map);
3236 if (pctx.errcode) {
3237 pctx.num = 6;
3238 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3239 ctx->flags |= E2F_FLAG_ABORT;
3240 return;
3241 }
3242 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3243 &ctx->block_found_map);
3244 if (pctx.errcode) {
3245 pctx.num = 1;
3246 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3247 ctx->flags |= E2F_FLAG_ABORT;
3248 return;
3249 }
3250 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3251 &ctx->inode_link_info);
3252 if (pctx.errcode) {
3253 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3254 ctx->flags |= E2F_FLAG_ABORT;
3255 return;
3256 }
3257 inode_size = EXT2_INODE_SIZE(fs->super);
3258 inode = (struct ext2_inode *)
3259 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3260
3261 inodes_to_process = (struct process_inode_block *)
3262 e2fsck_allocate_memory(ctx,
3263 (ctx->process_inode_size *
3264 sizeof(struct process_inode_block)),
3265 "array of inodes to process");
3266 process_inode_count = 0;
3267
3268 pctx.errcode = ext2fs_init_dblist(fs, 0);
3269 if (pctx.errcode) {
3270 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3271 ctx->flags |= E2F_FLAG_ABORT;
3272 return;
3273 }
3274
3275 /*
3276 * If the last orphan field is set, clear it, since the pass1
3277 * processing will automatically find and clear the orphans.
3278 * In the future, we may want to try using the last_orphan
3279 * linked list ourselves, but for now, we clear it so that the
3280 * ext3 mount code won't get confused.
3281 */
3282 if (!(ctx->options & E2F_OPT_READONLY)) {
3283 if (fs->super->s_last_orphan) {
3284 fs->super->s_last_orphan = 0;
3285 ext2fs_mark_super_dirty(fs);
3286 }
3287 }
3288
3289 mark_table_blocks(ctx);
3290 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3291 "block interate buffer");
3292 e2fsck_use_inode_shortcuts(ctx, 1);
3293 ehandler_operation(_("doing inode scan"));
3294 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3295 &scan);
3296 if (pctx.errcode) {
3297 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3298 ctx->flags |= E2F_FLAG_ABORT;
3299 return;
3300 }
3301 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3302 ctx->stashed_inode = inode;
3303 scan_struct.ctx = ctx;
3304 scan_struct.block_buf = block_buf;
3305 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3306 if (ctx->progress)
3307 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3308 return;
3309 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3310 (fs->super->s_mtime < fs->super->s_inodes_count))
3311 busted_fs_time = 1;
3312
3313 while (1) {
3314 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3315 inode, inode_size);
3316 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3317 return;
3318 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3319 continue;
3320 }
3321 if (pctx.errcode) {
3322 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3323 ctx->flags |= E2F_FLAG_ABORT;
3324 return;
3325 }
3326 if (!ino)
3327 break;
3328 pctx.ino = ino;
3329 pctx.inode = inode;
3330 ctx->stashed_ino = ino;
3331 if (inode->i_links_count) {
3332 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3333 ino, inode->i_links_count);
3334 if (pctx.errcode) {
3335 pctx.num = inode->i_links_count;
3336 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3337 ctx->flags |= E2F_FLAG_ABORT;
3338 return;
3339 }
3340 }
3341 if (ino == EXT2_BAD_INO) {
3342 struct process_block_struct_1 pb;
3343
3344 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3345 &pb.fs_meta_blocks);
3346 if (pctx.errcode) {
3347 pctx.num = 4;
3348 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3349 ctx->flags |= E2F_FLAG_ABORT;
3350 return;
3351 }
3352 pb.ino = EXT2_BAD_INO;
3353 pb.num_blocks = pb.last_block = 0;
3354 pb.num_illegal_blocks = 0;
3355 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3356 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3357 pb.inode = inode;
3358 pb.pctx = &pctx;
3359 pb.ctx = ctx;
3360 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3361 block_buf, process_bad_block, &pb);
3362 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3363 if (pctx.errcode) {
3364 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3365 ctx->flags |= E2F_FLAG_ABORT;
3366 return;
3367 }
3368 if (pb.bbcheck)
3369 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3370 ctx->flags |= E2F_FLAG_ABORT;
3371 return;
3372 }
3373 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3374 clear_problem_context(&pctx);
3375 continue;
3376 } else if (ino == EXT2_ROOT_INO) {
3377 /*
3378 * Make sure the root inode is a directory; if
3379 * not, offer to clear it. It will be
3380 * regnerated in pass #3.
3381 */
3382 if (!LINUX_S_ISDIR(inode->i_mode)) {
3383 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3384 inode->i_dtime = time(0);
3385 inode->i_links_count = 0;
3386 ext2fs_icount_store(ctx->inode_link_info,
3387 ino, 0);
3388 e2fsck_write_inode(ctx, ino, inode,
3389 "pass1");
3390 }
3391
3392 }
3393 /*
3394 * If dtime is set, offer to clear it. mke2fs
3395 * version 0.2b created filesystems with the
3396 * dtime field set for the root and lost+found
3397 * directories. We won't worry about
3398 * /lost+found, since that can be regenerated
3399 * easily. But we will fix the root directory
3400 * as a special case.
3401 */
3402 if (inode->i_dtime && inode->i_links_count) {
3403 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3404 inode->i_dtime = 0;
3405 e2fsck_write_inode(ctx, ino, inode,
3406 "pass1");
3407 }
3408 }
3409 } else if (ino == EXT2_JOURNAL_INO) {
3410 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3411 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3412 if (!LINUX_S_ISREG(inode->i_mode) &&
3413 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3414 &pctx)) {
3415 inode->i_mode = LINUX_S_IFREG;
3416 e2fsck_write_inode(ctx, ino, inode,
3417 "pass1");
3418 }
3419 check_blocks(ctx, &pctx, block_buf);
3420 continue;
3421 }
3422 if ((inode->i_links_count || inode->i_blocks ||
3423 inode->i_blocks || inode->i_block[0]) &&
3424 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3425 &pctx)) {
3426 memset(inode, 0, inode_size);
3427 ext2fs_icount_store(ctx->inode_link_info,
3428 ino, 0);
3429 e2fsck_write_inode_full(ctx, ino, inode,
3430 inode_size, "pass1");
3431 }
3432 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3433 int problem = 0;
3434
3435 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3436 if (ino == EXT2_BOOT_LOADER_INO) {
3437 if (LINUX_S_ISDIR(inode->i_mode))
3438 problem = PR_1_RESERVED_BAD_MODE;
3439 } else if (ino == EXT2_RESIZE_INO) {
3440 if (inode->i_mode &&
3441 !LINUX_S_ISREG(inode->i_mode))
3442 problem = PR_1_RESERVED_BAD_MODE;
3443 } else {
3444 if (inode->i_mode != 0)
3445 problem = PR_1_RESERVED_BAD_MODE;
3446 }
3447 if (problem) {
3448 if (fix_problem(ctx, problem, &pctx)) {
3449 inode->i_mode = 0;
3450 e2fsck_write_inode(ctx, ino, inode,
3451 "pass1");
3452 }
3453 }
3454 check_blocks(ctx, &pctx, block_buf);
3455 continue;
3456 }
3457 /*
3458 * Check for inodes who might have been part of the
3459 * orphaned list linked list. They should have gotten
3460 * dealt with by now, unless the list had somehow been
3461 * corrupted.
3462 *
3463 * FIXME: In the future, inodes which are still in use
3464 * (and which are therefore) pending truncation should
3465 * be handled specially. Right now we just clear the
3466 * dtime field, and the normal e2fsck handling of
3467 * inodes where i_size and the inode blocks are
3468 * inconsistent is to fix i_size, instead of releasing
3469 * the extra blocks. This won't catch the inodes that
3470 * was at the end of the orphan list, but it's better
3471 * than nothing. The right answer is that there
3472 * shouldn't be any bugs in the orphan list handling. :-)
3473 */
3474 if (inode->i_dtime && !busted_fs_time &&
3475 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3476 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3477 inode->i_dtime = inode->i_links_count ?
3478 0 : time(0);
3479 e2fsck_write_inode(ctx, ino, inode,
3480 "pass1");
3481 }
3482 }
3483
3484 /*
3485 * This code assumes that deleted inodes have
3486 * i_links_count set to 0.
3487 */
3488 if (!inode->i_links_count) {
3489 if (!inode->i_dtime && inode->i_mode) {
3490 if (fix_problem(ctx,
3491 PR_1_ZERO_DTIME, &pctx)) {
3492 inode->i_dtime = time(0);
3493 e2fsck_write_inode(ctx, ino, inode,
3494 "pass1");
3495 }
3496 }
3497 continue;
3498 }
3499 /*
3500 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3501 * deleted files. Oops.
3502 *
3503 * Since all new ext2 implementations get this right,
3504 * we now assume that the case of non-zero
3505 * i_links_count and non-zero dtime means that we
3506 * should keep the file, not delete it.
3507 *
3508 */
3509 if (inode->i_dtime) {
3510 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3511 inode->i_dtime = 0;
3512 e2fsck_write_inode(ctx, ino, inode, "pass1");
3513 }
3514 }
3515
3516 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3517 switch (fs->super->s_creator_os) {
3518 case EXT2_OS_LINUX:
3519 frag = inode->osd2.linux2.l_i_frag;
3520 fsize = inode->osd2.linux2.l_i_fsize;
3521 break;
3522 case EXT2_OS_HURD:
3523 frag = inode->osd2.hurd2.h_i_frag;
3524 fsize = inode->osd2.hurd2.h_i_fsize;
3525 break;
3526 case EXT2_OS_MASIX:
3527 frag = inode->osd2.masix2.m_i_frag;
3528 fsize = inode->osd2.masix2.m_i_fsize;
3529 break;
3530 default:
3531 frag = fsize = 0;
3532 }
3533
3534 if (inode->i_faddr || frag || fsize ||
3535 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3536 mark_inode_bad(ctx, ino);
3537 if (inode->i_flags & EXT2_IMAGIC_FL) {
3538 if (imagic_fs) {
3539 if (!ctx->inode_imagic_map)
3540 alloc_imagic_map(ctx);
3541 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3542 ino);
3543 } else {
3544 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3545 inode->i_flags &= ~EXT2_IMAGIC_FL;
3546 e2fsck_write_inode(ctx, ino,
3547 inode, "pass1");
3548 }
3549 }
3550 }
3551
3552 check_inode_extra_space(ctx, &pctx);
3553
3554 if (LINUX_S_ISDIR(inode->i_mode)) {
3555 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3556 e2fsck_add_dir_info(ctx, ino, 0);
3557 ctx->fs_directory_count++;
3558 } else if (LINUX_S_ISREG (inode->i_mode)) {
3559 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3560 ctx->fs_regular_count++;
3561 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3562 e2fsck_pass1_check_device_inode(fs, inode)) {
3563 check_immutable(ctx, &pctx);
3564 check_size(ctx, &pctx);
3565 ctx->fs_chardev_count++;
3566 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3567 e2fsck_pass1_check_device_inode(fs, inode)) {
3568 check_immutable(ctx, &pctx);
3569 check_size(ctx, &pctx);
3570 ctx->fs_blockdev_count++;
3571 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3572 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3573 check_immutable(ctx, &pctx);
3574 ctx->fs_symlinks_count++;
3575 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3576 ctx->fs_fast_symlinks_count++;
3577 check_blocks(ctx, &pctx, block_buf);
3578 continue;
3579 }
3580 }
3581 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3582 e2fsck_pass1_check_device_inode(fs, inode)) {
3583 check_immutable(ctx, &pctx);
3584 check_size(ctx, &pctx);
3585 ctx->fs_fifo_count++;
3586 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3587 e2fsck_pass1_check_device_inode(fs, inode)) {
3588 check_immutable(ctx, &pctx);
3589 check_size(ctx, &pctx);
3590 ctx->fs_sockets_count++;
3591 } else
3592 mark_inode_bad(ctx, ino);
3593 if (inode->i_block[EXT2_IND_BLOCK])
3594 ctx->fs_ind_count++;
3595 if (inode->i_block[EXT2_DIND_BLOCK])
3596 ctx->fs_dind_count++;
3597 if (inode->i_block[EXT2_TIND_BLOCK])
3598 ctx->fs_tind_count++;
3599 if (inode->i_block[EXT2_IND_BLOCK] ||
3600 inode->i_block[EXT2_DIND_BLOCK] ||
3601 inode->i_block[EXT2_TIND_BLOCK] ||
3602 inode->i_file_acl) {
3603 inodes_to_process[process_inode_count].ino = ino;
3604 inodes_to_process[process_inode_count].inode = *inode;
3605 process_inode_count++;
3606 } else
3607 check_blocks(ctx, &pctx, block_buf);
3608
3609 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3610 return;
3611
3612 if (process_inode_count >= ctx->process_inode_size) {
3613 process_inodes(ctx, block_buf);
3614
3615 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3616 return;
3617 }
3618 }
3619 process_inodes(ctx, block_buf);
3620 ext2fs_close_inode_scan(scan);
3621 ehandler_operation(0);
3622
3623 /*
3624 * If any extended attribute blocks' reference counts need to
3625 * be adjusted, either up (ctx->refcount_extra), or down
3626 * (ctx->refcount), then fix them.
3627 */
3628 if (ctx->refcount) {
3629 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3630 ea_refcount_free(ctx->refcount);
3631 ctx->refcount = 0;
3632 }
3633 if (ctx->refcount_extra) {
3634 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3635 block_buf, +1);
3636 ea_refcount_free(ctx->refcount_extra);
3637 ctx->refcount_extra = 0;
3638 }
3639
3640 if (ctx->invalid_bitmaps)
3641 handle_fs_bad_blocks(ctx);
3642
3643 /* We don't need the block_ea_map any more */
3644 ext2fs_free_block_bitmap(ctx->block_ea_map);
3645 ctx->block_ea_map = 0;
3646
3647 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3648 ext2fs_block_bitmap save_bmap;
3649
3650 save_bmap = fs->block_map;
3651 fs->block_map = ctx->block_found_map;
3652 clear_problem_context(&pctx);
3653 pctx.errcode = ext2fs_create_resize_inode(fs);
3654 if (pctx.errcode) {
3655 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3656 /* Should never get here */
3657 ctx->flags |= E2F_FLAG_ABORT;
3658 return;
3659 }
3660 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3661 "recreate inode");
3662 inode->i_mtime = time(0);
3663 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3664 "recreate inode");
3665 fs->block_map = save_bmap;
3666 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3667 }
3668
3669 if (ctx->flags & E2F_FLAG_RESTART) {
3670 /*
3671 * Only the master copy of the superblock and block
3672 * group descriptors are going to be written during a
3673 * restart, so set the superblock to be used to be the
3674 * master superblock.
3675 */
3676 ctx->use_superblock = 0;
3677 unwind_pass1();
3678 goto endit;
3679 }
3680
3681 if (ctx->block_dup_map) {
3682 if (ctx->options & E2F_OPT_PREEN) {
3683 clear_problem_context(&pctx);
3684 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3685 }
3686 e2fsck_pass1_dupblocks(ctx, block_buf);
3687 }
3688 ext2fs_free_mem(&inodes_to_process);
3689endit:
3690 e2fsck_use_inode_shortcuts(ctx, 0);
3691
3692 ext2fs_free_mem(&block_buf);
3693 ext2fs_free_mem(&inode);
3694
3695}
3696
3697/*
3698 * When the inode_scan routines call this callback at the end of the
3699 * glock group, call process_inodes.
3700 */
3701static errcode_t scan_callback(ext2_filsys fs,
3702 dgrp_t group, void * priv_data)
3703{
3704 struct scan_callback_struct *scan_struct;
3705 e2fsck_t ctx;
3706
3707 scan_struct = (struct scan_callback_struct *) priv_data;
3708 ctx = scan_struct->ctx;
3709
3710 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3711
3712 if (ctx->progress)
3713 if ((ctx->progress)(ctx, 1, group+1,
3714 ctx->fs->group_desc_count))
3715 return EXT2_ET_CANCEL_REQUESTED;
3716
3717 return 0;
3718}
3719
3720/*
3721 * Process the inodes in the "inodes to process" list.
3722 */
3723static void process_inodes(e2fsck_t ctx, char *block_buf)
3724{
3725 int i;
3726 struct ext2_inode *old_stashed_inode;
3727 ext2_ino_t old_stashed_ino;
3728 const char *old_operation;
3729 char buf[80];
3730 struct problem_context pctx;
3731
3732 /* begin process_inodes */
3733 if (process_inode_count == 0)
3734 return;
3735 old_operation = ehandler_operation(0);
3736 old_stashed_inode = ctx->stashed_inode;
3737 old_stashed_ino = ctx->stashed_ino;
3738 qsort(inodes_to_process, process_inode_count,
3739 sizeof(struct process_inode_block), process_inode_cmp);
3740 clear_problem_context(&pctx);
3741 for (i=0; i < process_inode_count; i++) {
3742 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3743 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3744 sprintf(buf, _("reading indirect blocks of inode %u"),
3745 pctx.ino);
3746 ehandler_operation(buf);
3747 check_blocks(ctx, &pctx, block_buf);
3748 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3749 break;
3750 }
3751 ctx->stashed_inode = old_stashed_inode;
3752 ctx->stashed_ino = old_stashed_ino;
3753 process_inode_count = 0;
3754 /* end process inodes */
3755
3756 ehandler_operation(old_operation);
3757}
3758
3759static int process_inode_cmp(const void *a, const void *b)
3760{
3761 const struct process_inode_block *ib_a =
3762 (const struct process_inode_block *) a;
3763 const struct process_inode_block *ib_b =
3764 (const struct process_inode_block *) b;
3765 int ret;
3766
3767 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3768 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3769 if (ret == 0)
3770 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3771 return ret;
3772}
3773
3774/*
3775 * Mark an inode as being bad in some what
3776 */
3777static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3778{
3779 struct problem_context pctx;
3780
3781 if (!ctx->inode_bad_map) {
3782 clear_problem_context(&pctx);
3783
3784 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3785 _("bad inode map"), &ctx->inode_bad_map);
3786 if (pctx.errcode) {
3787 pctx.num = 3;
3788 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3789 /* Should never get here */
3790 ctx->flags |= E2F_FLAG_ABORT;
3791 return;
3792 }
3793 }
3794 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3795}
3796
3797
3798/*
3799 * This procedure will allocate the inode imagic table
3800 */
3801static void alloc_imagic_map(e2fsck_t ctx)
3802{
3803 struct problem_context pctx;
3804
3805 clear_problem_context(&pctx);
3806 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3807 _("imagic inode map"),
3808 &ctx->inode_imagic_map);
3809 if (pctx.errcode) {
3810 pctx.num = 5;
3811 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3812 /* Should never get here */
3813 ctx->flags |= E2F_FLAG_ABORT;
3814 return;
3815 }
3816}
3817
3818/*
3819 * Marks a block as in use, setting the dup_map if it's been set
3820 * already. Called by process_block and process_bad_block.
3821 *
3822 * WARNING: Assumes checks have already been done to make sure block
3823 * is valid. This is true in both process_block and process_bad_block.
3824 */
3825static void mark_block_used(e2fsck_t ctx, blk_t block)
3826{
3827 struct problem_context pctx;
3828
3829 clear_problem_context(&pctx);
3830
3831 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3832 if (!ctx->block_dup_map) {
3833 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3834 _("multiply claimed block map"),
3835 &ctx->block_dup_map);
3836 if (pctx.errcode) {
3837 pctx.num = 3;
3838 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3839 &pctx);
3840 /* Should never get here */
3841 ctx->flags |= E2F_FLAG_ABORT;
3842 return;
3843 }
3844 }
3845 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3846 } else {
3847 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3848 }
3849}
3850
3851/*
3852 * Adjust the extended attribute block's reference counts at the end
3853 * of pass 1, either by subtracting out references for EA blocks that
3854 * are still referenced in ctx->refcount, or by adding references for
3855 * EA blocks that had extra references as accounted for in
3856 * ctx->refcount_extra.
3857 */
3858static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3859 char *block_buf, int adjust_sign)
3860{
3861 struct ext2_ext_attr_header *header;
3862 struct problem_context pctx;
3863 ext2_filsys fs = ctx->fs;
3864 blk_t blk;
3865 __u32 should_be;
3866 int count;
3867
3868 clear_problem_context(&pctx);
3869
3870 ea_refcount_intr_begin(refcount);
3871 while (1) {
3872 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3873 break;
3874 pctx.blk = blk;
3875 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3876 if (pctx.errcode) {
3877 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3878 return;
3879 }
3880 header = (struct ext2_ext_attr_header *) block_buf;
3881 pctx.blkcount = header->h_refcount;
3882 should_be = header->h_refcount + adjust_sign * count;
3883 pctx.num = should_be;
3884 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3885 header->h_refcount = should_be;
3886 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3887 block_buf);
3888 if (pctx.errcode) {
3889 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3890 continue;
3891 }
3892 }
3893 }
3894}
3895
3896/*
3897 * Handle processing the extended attribute blocks
3898 */
3899static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3900 char *block_buf)
3901{
3902 ext2_filsys fs = ctx->fs;
3903 ext2_ino_t ino = pctx->ino;
3904 struct ext2_inode *inode = pctx->inode;
3905 blk_t blk;
3906 char * end;
3907 struct ext2_ext_attr_header *header;
3908 struct ext2_ext_attr_entry *entry;
3909 int count;
3910 region_t region;
3911
3912 blk = inode->i_file_acl;
3913 if (blk == 0)
3914 return 0;
3915
3916 /*
3917 * If the Extended attribute flag isn't set, then a non-zero
3918 * file acl means that the inode is corrupted.
3919 *
3920 * Or if the extended attribute block is an invalid block,
3921 * then the inode is also corrupted.
3922 */
3923 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3924 (blk < fs->super->s_first_data_block) ||
3925 (blk >= fs->super->s_blocks_count)) {
3926 mark_inode_bad(ctx, ino);
3927 return 0;
3928 }
3929
3930 /* If ea bitmap hasn't been allocated, create it */
3931 if (!ctx->block_ea_map) {
3932 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3933 _("ext attr block map"),
3934 &ctx->block_ea_map);
3935 if (pctx->errcode) {
3936 pctx->num = 2;
3937 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3938 ctx->flags |= E2F_FLAG_ABORT;
3939 return 0;
3940 }
3941 }
3942
3943 /* Create the EA refcount structure if necessary */
3944 if (!ctx->refcount) {
3945 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3946 if (pctx->errcode) {
3947 pctx->num = 1;
3948 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3949 ctx->flags |= E2F_FLAG_ABORT;
3950 return 0;
3951 }
3952 }
3953
3954 /* Have we seen this EA block before? */
3955 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3956 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3957 return 1;
3958 /* Ooops, this EA was referenced more than it stated */
3959 if (!ctx->refcount_extra) {
3960 pctx->errcode = ea_refcount_create(0,
3961 &ctx->refcount_extra);
3962 if (pctx->errcode) {
3963 pctx->num = 2;
3964 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3965 ctx->flags |= E2F_FLAG_ABORT;
3966 return 0;
3967 }
3968 }
3969 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3970 return 1;
3971 }
3972
3973 /*
3974 * OK, we haven't seen this EA block yet. So we need to
3975 * validate it
3976 */
3977 pctx->blk = blk;
3978 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3979 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3980 goto clear_extattr;
3981 header = (struct ext2_ext_attr_header *) block_buf;
3982 pctx->blk = inode->i_file_acl;
3983 if (((ctx->ext_attr_ver == 1) &&
3984 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3985 ((ctx->ext_attr_ver == 2) &&
3986 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3987 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3988 goto clear_extattr;
3989 }
3990
3991 if (header->h_blocks != 1) {
3992 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3993 goto clear_extattr;
3994 }
3995
3996 region = region_create(0, fs->blocksize);
3997 if (!region) {
3998 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3999 ctx->flags |= E2F_FLAG_ABORT;
4000 return 0;
4001 }
4002 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4003 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4004 goto clear_extattr;
4005 }
4006
4007 entry = (struct ext2_ext_attr_entry *)(header+1);
4008 end = block_buf + fs->blocksize;
4009 while ((char *)entry < end && *(__u32 *)entry) {
4010 if (region_allocate(region, (char *)entry - (char *)header,
4011 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4012 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4013 goto clear_extattr;
4014 }
4015 if ((ctx->ext_attr_ver == 1 &&
4016 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4017 (ctx->ext_attr_ver == 2 &&
4018 entry->e_name_index == 0)) {
4019 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4020 goto clear_extattr;
4021 }
4022 if (entry->e_value_block != 0) {
4023 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4024 goto clear_extattr;
4025 }
4026 if (entry->e_value_size &&
4027 region_allocate(region, entry->e_value_offs,
4028 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4029 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4030 goto clear_extattr;
4031 }
4032 entry = EXT2_EXT_ATTR_NEXT(entry);
4033 }
4034 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4035 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4036 goto clear_extattr;
4037 }
4038 region_free(region);
4039
4040 count = header->h_refcount - 1;
4041 if (count)
4042 ea_refcount_store(ctx->refcount, blk, count);
4043 mark_block_used(ctx, blk);
4044 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4045
4046 return 1;
4047
4048clear_extattr:
4049 inode->i_file_acl = 0;
4050 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4051 return 0;
4052}
4053
4054/* Returns 1 if bad htree, 0 if OK */
4055static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4056 ext2_ino_t ino FSCK_ATTR((unused)),
4057 struct ext2_inode *inode,
4058 char *block_buf)
4059{
4060 struct ext2_dx_root_info *root;
4061 ext2_filsys fs = ctx->fs;
4062 errcode_t retval;
4063 blk_t blk;
4064
4065 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4066 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4067 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4068 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4069 return 1;
4070
4071 blk = inode->i_block[0];
4072 if (((blk == 0) ||
4073 (blk < fs->super->s_first_data_block) ||
4074 (blk >= fs->super->s_blocks_count)) &&
4075 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4076 return 1;
4077
4078 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4079 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4080 return 1;
4081
4082 /* XXX should check that beginning matches a directory */
4083 root = (struct ext2_dx_root_info *) (block_buf + 24);
4084
4085 if ((root->reserved_zero || root->info_length < 8) &&
4086 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4087 return 1;
4088
4089 pctx->num = root->hash_version;
4090 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4091 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4092 (root->hash_version != EXT2_HASH_TEA) &&
4093 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4094 return 1;
4095
4096 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4097 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4098 return 1;
4099
4100 pctx->num = root->indirect_levels;
4101 if ((root->indirect_levels > 1) &&
4102 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4103 return 1;
4104
4105 return 0;
4106}
4107
4108/*
4109 * This subroutine is called on each inode to account for all of the
4110 * blocks used by that inode.
4111 */
4112static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4113 char *block_buf)
4114{
4115 ext2_filsys fs = ctx->fs;
4116 struct process_block_struct_1 pb;
4117 ext2_ino_t ino = pctx->ino;
4118 struct ext2_inode *inode = pctx->inode;
4119 int bad_size = 0;
4120 int dirty_inode = 0;
4121 __u64 size;
4122
4123 pb.ino = ino;
4124 pb.num_blocks = 0;
4125 pb.last_block = -1;
4126 pb.num_illegal_blocks = 0;
4127 pb.suppress = 0; pb.clear = 0;
4128 pb.fragmented = 0;
4129 pb.compressed = 0;
4130 pb.previous_block = 0;
4131 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4132 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4133 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4134 pb.inode = inode;
4135 pb.pctx = pctx;
4136 pb.ctx = ctx;
4137 pctx->ino = ino;
4138 pctx->errcode = 0;
4139
4140 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4141 if (fs->super->s_feature_incompat &
4142 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4143 pb.compressed = 1;
4144 else {
4145 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4146 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4147 dirty_inode++;
4148 }
4149 }
4150 }
4151
4152 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4153 pb.num_blocks++;
4154
4155 if (ext2fs_inode_has_valid_blocks(inode))
4156 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4157 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4158 block_buf, process_block, &pb);
4159 end_problem_latch(ctx, PR_LATCH_BLOCK);
4160 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4161 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4162 goto out;
4163 if (pctx->errcode)
4164 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4165
4166 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4167 ctx->fs_fragmented++;
4168
4169 if (pb.clear) {
4170 inode->i_links_count = 0;
4171 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4172 inode->i_dtime = time(0);
4173 dirty_inode++;
4174 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4175 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4176 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4177 /*
4178 * The inode was probably partially accounted for
4179 * before processing was aborted, so we need to
4180 * restart the pass 1 scan.
4181 */
4182 ctx->flags |= E2F_FLAG_RESTART;
4183 goto out;
4184 }
4185
4186 if (inode->i_flags & EXT2_INDEX_FL) {
4187 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4188 inode->i_flags &= ~EXT2_INDEX_FL;
4189 dirty_inode++;
4190 } else {
4191#ifdef ENABLE_HTREE
4192 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4193#endif
4194 }
4195 }
4196 if (ctx->dirs_to_hash && pb.is_dir &&
4197 !(inode->i_flags & EXT2_INDEX_FL) &&
4198 ((inode->i_size / fs->blocksize) >= 3))
4199 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4200
4201 if (!pb.num_blocks && pb.is_dir) {
4202 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4203 inode->i_links_count = 0;
4204 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4205 inode->i_dtime = time(0);
4206 dirty_inode++;
4207 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4208 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4209 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4210 ctx->fs_directory_count--;
4211 goto out;
4212 }
4213 }
4214
4215 pb.num_blocks *= (fs->blocksize / 512);
4216
4217 if (pb.is_dir) {
4218 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4219 if (nblock > (pb.last_block + 1))
4220 bad_size = 1;
4221 else if (nblock < (pb.last_block + 1)) {
4222 if (((pb.last_block + 1) - nblock) >
4223 fs->super->s_prealloc_dir_blocks)
4224 bad_size = 2;
4225 }
4226 } else {
4227 size = EXT2_I_SIZE(inode);
4228 if ((pb.last_block >= 0) &&
4229 (size < (__u64) pb.last_block * fs->blocksize))
4230 bad_size = 3;
4231 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4232 bad_size = 4;
4233 }
4234 /* i_size for symlinks is checked elsewhere */
4235 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4236 pctx->num = (pb.last_block+1) * fs->blocksize;
4237 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4238 inode->i_size = pctx->num;
4239 if (!LINUX_S_ISDIR(inode->i_mode))
4240 inode->i_size_high = pctx->num >> 32;
4241 dirty_inode++;
4242 }
4243 pctx->num = 0;
4244 }
4245 if (LINUX_S_ISREG(inode->i_mode) &&
4246 (inode->i_size_high || inode->i_size & 0x80000000UL))
4247 ctx->large_files++;
4248 if (pb.num_blocks != inode->i_blocks) {
4249 pctx->num = pb.num_blocks;
4250 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4251 inode->i_blocks = pb.num_blocks;
4252 dirty_inode++;
4253 }
4254 pctx->num = 0;
4255 }
4256out:
4257 if (dirty_inode)
4258 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4259}
4260
4261
4262/*
4263 * This is a helper function for check_blocks().
4264 */
4265static int process_block(ext2_filsys fs,
4266 blk_t *block_nr,
4267 e2_blkcnt_t blockcnt,
4268 blk_t ref_block FSCK_ATTR((unused)),
4269 int ref_offset FSCK_ATTR((unused)),
4270 void *priv_data)
4271{
4272 struct process_block_struct_1 *p;
4273 struct problem_context *pctx;
4274 blk_t blk = *block_nr;
4275 int ret_code = 0;
4276 int problem = 0;
4277 e2fsck_t ctx;
4278
4279 p = (struct process_block_struct_1 *) priv_data;
4280 pctx = p->pctx;
4281 ctx = p->ctx;
4282
4283 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4284 /* todo: Check that the comprblk_fl is high, that the
4285 blkaddr pattern looks right (all non-holes up to
4286 first EXT2FS_COMPRESSED_BLKADDR, then all
4287 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4288 that the feature_incompat bit is high, and that the
4289 inode is a regular file. If we're doing a "full
4290 check" (a concept introduced to e2fsck by e2compr,
4291 meaning that we look at data blocks as well as
4292 metadata) then call some library routine that
4293 checks the compressed data. I'll have to think
4294 about this, because one particularly important
4295 problem to be able to fix is to recalculate the
4296 cluster size if necessary. I think that perhaps
4297 we'd better do most/all e2compr-specific checks
4298 separately, after the non-e2compr checks. If not
4299 doing a full check, it may be useful to test that
4300 the personality is linux; e.g. if it isn't then
4301 perhaps this really is just an illegal block. */
4302 return 0;
4303 }
4304
4305 if (blk == 0) {
4306 if (p->is_dir == 0) {
4307 /*
4308 * Should never happen, since only directories
4309 * get called with BLOCK_FLAG_HOLE
4310 */
4311#ifdef DEBUG_E2FSCK
4312 printf("process_block() called with blk == 0, "
4313 "blockcnt=%d, inode %lu???\n",
4314 blockcnt, p->ino);
4315#endif
4316 return 0;
4317 }
4318 if (blockcnt < 0)
4319 return 0;
4320 if (blockcnt * fs->blocksize < p->inode->i_size) {
4321 goto mark_dir;
4322 }
4323 return 0;
4324 }
4325
4326 /*
4327 * Simplistic fragmentation check. We merely require that the
4328 * file be contiguous. (Which can never be true for really
4329 * big files that are greater than a block group.)
4330 */
4331 if (!HOLE_BLKADDR(p->previous_block)) {
4332 if (p->previous_block+1 != blk)
4333 p->fragmented = 1;
4334 }
4335 p->previous_block = blk;
4336
4337 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4338 problem = PR_1_TOOBIG_DIR;
4339 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4340 problem = PR_1_TOOBIG_REG;
4341 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4342 problem = PR_1_TOOBIG_SYMLINK;
4343
4344 if (blk < fs->super->s_first_data_block ||
4345 blk >= fs->super->s_blocks_count)
4346 problem = PR_1_ILLEGAL_BLOCK_NUM;
4347
4348 if (problem) {
4349 p->num_illegal_blocks++;
4350 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4351 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4352 p->clear = 1;
4353 return BLOCK_ABORT;
4354 }
4355 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4356 p->suppress = 1;
4357 set_latch_flags(PR_LATCH_BLOCK,
4358 PRL_SUPPRESS, 0);
4359 }
4360 }
4361 pctx->blk = blk;
4362 pctx->blkcount = blockcnt;
4363 if (fix_problem(ctx, problem, pctx)) {
4364 blk = *block_nr = 0;
4365 ret_code = BLOCK_CHANGED;
4366 goto mark_dir;
4367 } else
4368 return 0;
4369 }
4370
4371 if (p->ino == EXT2_RESIZE_INO) {
4372 /*
4373 * The resize inode has already be sanity checked
4374 * during pass #0 (the superblock checks). All we
4375 * have to do is mark the double indirect block as
4376 * being in use; all of the other blocks are handled
4377 * by mark_table_blocks()).
4378 */
4379 if (blockcnt == BLOCK_COUNT_DIND)
4380 mark_block_used(ctx, blk);
4381 } else
4382 mark_block_used(ctx, blk);
4383 p->num_blocks++;
4384 if (blockcnt >= 0)
4385 p->last_block = blockcnt;
4386mark_dir:
4387 if (p->is_dir && (blockcnt >= 0)) {
4388 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4389 blk, blockcnt);
4390 if (pctx->errcode) {
4391 pctx->blk = blk;
4392 pctx->num = blockcnt;
4393 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4394 /* Should never get here */
4395 ctx->flags |= E2F_FLAG_ABORT;
4396 return BLOCK_ABORT;
4397 }
4398 }
4399 return ret_code;
4400}
4401
4402static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4403 blk_t *block_nr,
4404 e2_blkcnt_t blockcnt,
4405 blk_t ref_block FSCK_ATTR((unused)),
4406 int ref_offset FSCK_ATTR((unused)),
4407 void *priv_data EXT2FS_ATTR((unused)))
4408{
4409 /*
4410 * Note: This function processes blocks for the bad blocks
4411 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4412 */
4413
4414 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4415 return BLOCK_ERROR;
4416}
4417
4418/*
4419 * This routine gets called at the end of pass 1 if bad blocks are
4420 * detected in the superblock, group descriptors, inode_bitmaps, or
4421 * block bitmaps. At this point, all of the blocks have been mapped
4422 * out, so we can try to allocate new block(s) to replace the bad
4423 * blocks.
4424 */
4425static void handle_fs_bad_blocks(e2fsck_t ctx)
4426{
4427 printf("Bad blocks detected on your filesystem\n"
4428 "You should get your data off as the device will soon die\n");
4429}
4430
4431/*
4432 * This routine marks all blocks which are used by the superblock,
4433 * group descriptors, inode bitmaps, and block bitmaps.
4434 */
4435static void mark_table_blocks(e2fsck_t ctx)
4436{
4437 ext2_filsys fs = ctx->fs;
4438 blk_t block, b;
4439 dgrp_t i;
4440 int j;
4441 struct problem_context pctx;
4442
4443 clear_problem_context(&pctx);
4444
4445 block = fs->super->s_first_data_block;
4446 for (i = 0; i < fs->group_desc_count; i++) {
4447 pctx.group = i;
4448
4449 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4450
4451 /*
4452 * Mark the blocks used for the inode table
4453 */
4454 if (fs->group_desc[i].bg_inode_table) {
4455 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4456 j < fs->inode_blocks_per_group;
4457 j++, b++) {
4458 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4459 b)) {
4460 pctx.blk = b;
4461 if (fix_problem(ctx,
4462 PR_1_ITABLE_CONFLICT, &pctx)) {
4463 ctx->invalid_inode_table_flag[i]++;
4464 ctx->invalid_bitmaps++;
4465 }
4466 } else {
4467 ext2fs_mark_block_bitmap(ctx->block_found_map,
4468 b);
4469 }
4470 }
4471 }
4472
4473 /*
4474 * Mark block used for the block bitmap
4475 */
4476 if (fs->group_desc[i].bg_block_bitmap) {
4477 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4478 fs->group_desc[i].bg_block_bitmap)) {
4479 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4480 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4481 ctx->invalid_block_bitmap_flag[i]++;
4482 ctx->invalid_bitmaps++;
4483 }
4484 } else {
4485 ext2fs_mark_block_bitmap(ctx->block_found_map,
4486 fs->group_desc[i].bg_block_bitmap);
4487 }
4488
4489 }
4490 /*
4491 * Mark block used for the inode bitmap
4492 */
4493 if (fs->group_desc[i].bg_inode_bitmap) {
4494 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4495 fs->group_desc[i].bg_inode_bitmap)) {
4496 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4497 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4498 ctx->invalid_inode_bitmap_flag[i]++;
4499 ctx->invalid_bitmaps++;
4500 }
4501 } else {
4502 ext2fs_mark_block_bitmap(ctx->block_found_map,
4503 fs->group_desc[i].bg_inode_bitmap);
4504 }
4505 }
4506 block += fs->super->s_blocks_per_group;
4507 }
4508}
4509
4510/*
4511 * Thes subroutines short circuits ext2fs_get_blocks and
4512 * ext2fs_check_directory; we use them since we already have the inode
4513 * structure, so there's no point in letting the ext2fs library read
4514 * the inode again.
4515 */
4516static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4517 blk_t *blocks)
4518{
4519 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4520 int i;
4521
4522 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4523 return EXT2_ET_CALLBACK_NOTHANDLED;
4524
4525 for (i=0; i < EXT2_N_BLOCKS; i++)
4526 blocks[i] = ctx->stashed_inode->i_block[i];
4527 return 0;
4528}
4529
4530static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4531 struct ext2_inode *inode)
4532{
4533 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4534
4535 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4536 return EXT2_ET_CALLBACK_NOTHANDLED;
4537 *inode = *ctx->stashed_inode;
4538 return 0;
4539}
4540
4541static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4542 struct ext2_inode *inode)
4543{
4544 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545
4546 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4547 *ctx->stashed_inode = *inode;
4548 return EXT2_ET_CALLBACK_NOTHANDLED;
4549}
4550
4551static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4552{
4553 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4554
4555 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4556 return EXT2_ET_CALLBACK_NOTHANDLED;
4557
4558 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4559 return EXT2_ET_NO_DIRECTORY;
4560 return 0;
4561}
4562
4563void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4564{
4565 ext2_filsys fs = ctx->fs;
4566
4567 if (bool) {
4568 fs->get_blocks = pass1_get_blocks;
4569 fs->check_directory = pass1_check_directory;
4570 fs->read_inode = pass1_read_inode;
4571 fs->write_inode = pass1_write_inode;
4572 ctx->stashed_ino = 0;
4573 } else {
4574 fs->get_blocks = 0;
4575 fs->check_directory = 0;
4576 fs->read_inode = 0;
4577 fs->write_inode = 0;
4578 }
4579}
4580
4581/*
4582 * pass1b.c --- Pass #1b of e2fsck
4583 *
4584 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4585 * only invoked if pass 1 discovered blocks which are in use by more
4586 * than one inode.
4587 *
4588 * Pass1B scans the data blocks of all the inodes again, generating a
4589 * complete list of duplicate blocks and which inodes have claimed
4590 * them.
4591 *
4592 * Pass1C does a tree-traversal of the filesystem, to determine the
4593 * parent directories of these inodes. This step is necessary so that
4594 * e2fsck can print out the pathnames of affected inodes.
4595 *
4596 * Pass1D is a reconciliation pass. For each inode with duplicate
4597 * blocks, the user is prompted if s/he would like to clone the file
4598 * (so that the file gets a fresh copy of the duplicated blocks) or
4599 * simply to delete the file.
4600 *
4601 */
4602
4603
4604/* Needed for architectures where sizeof(int) != sizeof(void *) */
4605#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4606#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4607
4608/* Define an extension to the ext2 library's block count information */
4609#define BLOCK_COUNT_EXTATTR (-5)
4610
4611struct block_el {
4612 blk_t block;
4613 struct block_el *next;
4614};
4615
4616struct inode_el {
4617 ext2_ino_t inode;
4618 struct inode_el *next;
4619};
4620
4621struct dup_block {
4622 int num_bad;
4623 struct inode_el *inode_list;
4624};
4625
4626/*
4627 * This structure stores information about a particular inode which
4628 * is sharing blocks with other inodes. This information is collected
4629 * to display to the user, so that the user knows what files he or she
4630 * is dealing with, when trying to decide how to resolve the conflict
4631 * of multiply-claimed blocks.
4632 */
4633struct dup_inode {
4634 ext2_ino_t dir;
4635 int num_dupblocks;
4636 struct ext2_inode inode;
4637 struct block_el *block_list;
4638};
4639
4640static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4641 e2_blkcnt_t blockcnt, blk_t ref_blk,
4642 int ref_offset, void *priv_data);
4643static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4644 struct dup_inode *dp, char *block_buf);
4645static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4646 struct dup_inode *dp, char* block_buf);
4647static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4648
4649static void pass1b(e2fsck_t ctx, char *block_buf);
4650static void pass1c(e2fsck_t ctx, char *block_buf);
4651static void pass1d(e2fsck_t ctx, char *block_buf);
4652
4653static int dup_inode_count = 0;
4654
4655static dict_t blk_dict, ino_dict;
4656
4657static ext2fs_inode_bitmap inode_dup_map;
4658
4659static int dict_int_cmp(const void *a, const void *b)
4660{
4661 intptr_t ia, ib;
4662
4663 ia = (intptr_t)a;
4664 ib = (intptr_t)b;
4665
4666 return (ia-ib);
4667}
4668
4669/*
4670 * Add a duplicate block record
4671 */
4672static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4673 struct ext2_inode *inode)
4674{
4675 dnode_t *n;
4676 struct dup_block *db;
4677 struct dup_inode *di;
4678 struct block_el *blk_el;
4679 struct inode_el *ino_el;
4680
4681 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4682 if (n)
4683 db = (struct dup_block *) dnode_get(n);
4684 else {
4685 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4686 sizeof(struct dup_block), "duplicate block header");
4687 db->num_bad = 0;
4688 db->inode_list = 0;
4689 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4690 }
4691 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4692 sizeof(struct inode_el), "inode element");
4693 ino_el->inode = ino;
4694 ino_el->next = db->inode_list;
4695 db->inode_list = ino_el;
4696 db->num_bad++;
4697
4698 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4699 if (n)
4700 di = (struct dup_inode *) dnode_get(n);
4701 else {
4702 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4703 sizeof(struct dup_inode), "duplicate inode header");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00004704 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004705 di->num_dupblocks = 0;
4706 di->block_list = 0;
4707 di->inode = *inode;
4708 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4709 }
4710 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4711 sizeof(struct block_el), "block element");
4712 blk_el->block = blk;
4713 blk_el->next = di->block_list;
4714 di->block_list = blk_el;
4715 di->num_dupblocks++;
4716}
4717
4718/*
4719 * Free a duplicate inode record
4720 */
4721static void inode_dnode_free(dnode_t *node)
4722{
4723 struct dup_inode *di;
4724 struct block_el *p, *next;
4725
4726 di = (struct dup_inode *) dnode_get(node);
4727 for (p = di->block_list; p; p = next) {
4728 next = p->next;
4729 free(p);
4730 }
4731 free(node);
4732}
4733
4734/*
4735 * Free a duplicate block record
4736 */
4737static void block_dnode_free(dnode_t *node)
4738{
4739 struct dup_block *db;
4740 struct inode_el *p, *next;
4741
4742 db = (struct dup_block *) dnode_get(node);
4743 for (p = db->inode_list; p; p = next) {
4744 next = p->next;
4745 free(p);
4746 }
4747 free(node);
4748}
4749
4750
4751/*
4752 * Main procedure for handling duplicate blocks
4753 */
4754void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4755{
4756 ext2_filsys fs = ctx->fs;
4757 struct problem_context pctx;
4758
4759 clear_problem_context(&pctx);
4760
4761 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4762 _("multiply claimed inode map"), &inode_dup_map);
4763 if (pctx.errcode) {
4764 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4765 ctx->flags |= E2F_FLAG_ABORT;
4766 return;
4767 }
4768
4769 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4770 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771 dict_set_allocator(&ino_dict, inode_dnode_free);
4772 dict_set_allocator(&blk_dict, block_dnode_free);
4773
4774 pass1b(ctx, block_buf);
4775 pass1c(ctx, block_buf);
4776 pass1d(ctx, block_buf);
4777
4778 /*
4779 * Time to free all of the accumulated data structures that we
4780 * don't need anymore.
4781 */
4782 dict_free_nodes(&ino_dict);
4783 dict_free_nodes(&blk_dict);
4784}
4785
4786/*
4787 * Scan the inodes looking for inodes that contain duplicate blocks.
4788 */
4789struct process_block_struct_1b {
4790 e2fsck_t ctx;
4791 ext2_ino_t ino;
4792 int dup_blocks;
4793 struct ext2_inode *inode;
4794 struct problem_context *pctx;
4795};
4796
4797static void pass1b(e2fsck_t ctx, char *block_buf)
4798{
4799 ext2_filsys fs = ctx->fs;
4800 ext2_ino_t ino;
4801 struct ext2_inode inode;
4802 ext2_inode_scan scan;
4803 struct process_block_struct_1b pb;
4804 struct problem_context pctx;
4805
4806 clear_problem_context(&pctx);
4807
4808 if (!(ctx->options & E2F_OPT_PREEN))
4809 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4810 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4811 &scan);
4812 if (pctx.errcode) {
4813 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4814 ctx->flags |= E2F_FLAG_ABORT;
4815 return;
4816 }
4817 ctx->stashed_inode = &inode;
4818 pb.ctx = ctx;
4819 pb.pctx = &pctx;
4820 pctx.str = "pass1b";
4821 while (1) {
4822 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4823 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4824 continue;
4825 if (pctx.errcode) {
4826 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4827 ctx->flags |= E2F_FLAG_ABORT;
4828 return;
4829 }
4830 if (!ino)
4831 break;
4832 pctx.ino = ctx->stashed_ino = ino;
4833 if ((ino != EXT2_BAD_INO) &&
4834 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4835 continue;
4836
4837 pb.ino = ino;
4838 pb.dup_blocks = 0;
4839 pb.inode = &inode;
4840
4841 if (ext2fs_inode_has_valid_blocks(&inode) ||
4842 (ino == EXT2_BAD_INO))
4843 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4844 0, block_buf, process_pass1b_block, &pb);
4845 if (inode.i_file_acl)
4846 process_pass1b_block(fs, &inode.i_file_acl,
4847 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4848 if (pb.dup_blocks) {
4849 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4850 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4851 ino == EXT2_ROOT_INO)
4852 dup_inode_count++;
4853 }
4854 if (pctx.errcode)
4855 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4856 }
4857 ext2fs_close_inode_scan(scan);
4858 e2fsck_use_inode_shortcuts(ctx, 0);
4859}
4860
4861static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4862 blk_t *block_nr,
4863 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4864 blk_t ref_blk FSCK_ATTR((unused)),
4865 int ref_offset FSCK_ATTR((unused)),
4866 void *priv_data)
4867{
4868 struct process_block_struct_1b *p;
4869 e2fsck_t ctx;
4870
4871 if (HOLE_BLKADDR(*block_nr))
4872 return 0;
4873 p = (struct process_block_struct_1b *) priv_data;
4874 ctx = p->ctx;
4875
4876 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4877 return 0;
4878
4879 /* OK, this is a duplicate block */
4880 if (p->ino != EXT2_BAD_INO) {
4881 p->pctx->blk = *block_nr;
4882 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4883 }
4884 p->dup_blocks++;
4885 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4886
4887 add_dupe(ctx, p->ino, *block_nr, p->inode);
4888
4889 return 0;
4890}
4891
4892/*
4893 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4894 * is used so that we can print pathnames when prompting the user for
4895 * what to do.
4896 */
4897struct search_dir_struct {
4898 int count;
4899 ext2_ino_t first_inode;
4900 ext2_ino_t max_inode;
4901};
4902
4903static int search_dirent_proc(ext2_ino_t dir, int entry,
4904 struct ext2_dir_entry *dirent,
4905 int offset FSCK_ATTR((unused)),
4906 int blocksize FSCK_ATTR((unused)),
4907 char *buf FSCK_ATTR((unused)),
4908 void *priv_data)
4909{
4910 struct search_dir_struct *sd;
4911 struct dup_inode *p;
4912 dnode_t *n;
4913
4914 sd = (struct search_dir_struct *) priv_data;
4915
4916 if (dirent->inode > sd->max_inode)
4917 /* Should abort this inode, but not everything */
4918 return 0;
4919
4920 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4921 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4922 return 0;
4923
4924 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4925 if (!n)
4926 return 0;
4927 p = (struct dup_inode *) dnode_get(n);
4928 p->dir = dir;
4929 sd->count--;
4930
4931 return sd->count ? 0 : DIRENT_ABORT;
4932}
4933
4934
4935static void pass1c(e2fsck_t ctx, char *block_buf)
4936{
4937 ext2_filsys fs = ctx->fs;
4938 struct search_dir_struct sd;
4939 struct problem_context pctx;
4940
4941 clear_problem_context(&pctx);
4942
4943 if (!(ctx->options & E2F_OPT_PREEN))
4944 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4945
4946 /*
4947 * Search through all directories to translate inodes to names
4948 * (by searching for the containing directory for that inode.)
4949 */
4950 sd.count = dup_inode_count;
4951 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4952 sd.max_inode = fs->super->s_inodes_count;
4953 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4954 search_dirent_proc, &sd);
4955}
4956
4957static void pass1d(e2fsck_t ctx, char *block_buf)
4958{
4959 ext2_filsys fs = ctx->fs;
4960 struct dup_inode *p, *t;
4961 struct dup_block *q;
4962 ext2_ino_t *shared, ino;
4963 int shared_len;
4964 int i;
4965 int file_ok;
4966 int meta_data = 0;
4967 struct problem_context pctx;
4968 dnode_t *n, *m;
4969 struct block_el *s;
4970 struct inode_el *r;
4971
4972 clear_problem_context(&pctx);
4973
4974 if (!(ctx->options & E2F_OPT_PREEN))
4975 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4976 e2fsck_read_bitmaps(ctx);
4977
4978 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4979 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4980 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4981 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4982 "Shared inode list");
4983 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4984 p = (struct dup_inode *) dnode_get(n);
4985 shared_len = 0;
4986 file_ok = 1;
4987 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4988 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4989 continue;
4990
4991 /*
4992 * Find all of the inodes which share blocks with this
4993 * one. First we find all of the duplicate blocks
4994 * belonging to this inode, and then search each block
4995 * get the list of inodes, and merge them together.
4996 */
4997 for (s = p->block_list; s; s = s->next) {
4998 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4999 if (!m)
5000 continue; /* Should never happen... */
5001 q = (struct dup_block *) dnode_get(m);
5002 if (q->num_bad > 1)
5003 file_ok = 0;
5004 if (check_if_fs_block(ctx, s->block)) {
5005 file_ok = 0;
5006 meta_data = 1;
5007 }
5008
5009 /*
5010 * Add all inodes used by this block to the
5011 * shared[] --- which is a unique list, so
5012 * if an inode is already in shared[], don't
5013 * add it again.
5014 */
5015 for (r = q->inode_list; r; r = r->next) {
5016 if (r->inode == ino)
5017 continue;
5018 for (i = 0; i < shared_len; i++)
5019 if (shared[i] == r->inode)
5020 break;
5021 if (i == shared_len) {
5022 shared[shared_len++] = r->inode;
5023 }
5024 }
5025 }
5026
5027 /*
5028 * Report the inode that we are working on
5029 */
5030 pctx.inode = &p->inode;
5031 pctx.ino = ino;
5032 pctx.dir = p->dir;
5033 pctx.blkcount = p->num_dupblocks;
5034 pctx.num = meta_data ? shared_len+1 : shared_len;
5035 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5036 pctx.blkcount = 0;
5037 pctx.num = 0;
5038
5039 if (meta_data)
5040 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5041
5042 for (i = 0; i < shared_len; i++) {
5043 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5044 if (!m)
5045 continue; /* should never happen */
5046 t = (struct dup_inode *) dnode_get(m);
5047 /*
5048 * Report the inode that we are sharing with
5049 */
5050 pctx.inode = &t->inode;
5051 pctx.ino = shared[i];
5052 pctx.dir = t->dir;
5053 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5054 }
5055 if (file_ok) {
5056 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5057 continue;
5058 }
5059 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5060 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5061 if (pctx.errcode)
5062 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5063 else
5064 continue;
5065 }
5066 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5067 delete_file(ctx, ino, p, block_buf);
5068 else
5069 ext2fs_unmark_valid(fs);
5070 }
5071 ext2fs_free_mem(&shared);
5072}
5073
5074/*
5075 * Drop the refcount on the dup_block structure, and clear the entry
5076 * in the block_dup_map if appropriate.
5077 */
5078static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5079{
5080 p->num_bad--;
5081 if (p->num_bad <= 0 ||
5082 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5083 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5084}
5085
5086static int delete_file_block(ext2_filsys fs,
5087 blk_t *block_nr,
5088 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5089 blk_t ref_block FSCK_ATTR((unused)),
5090 int ref_offset FSCK_ATTR((unused)),
5091 void *priv_data)
5092{
5093 struct process_block_struct_1b *pb;
5094 struct dup_block *p;
5095 dnode_t *n;
5096 e2fsck_t ctx;
5097
5098 pb = (struct process_block_struct_1b *) priv_data;
5099 ctx = pb->ctx;
5100
5101 if (HOLE_BLKADDR(*block_nr))
5102 return 0;
5103
5104 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5105 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5106 if (n) {
5107 p = (struct dup_block *) dnode_get(n);
5108 decrement_badcount(ctx, *block_nr, p);
5109 } else
5110 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5111 *block_nr);
5112 } else {
5113 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5114 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5115 }
5116
5117 return 0;
5118}
5119
5120static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5121 struct dup_inode *dp, char* block_buf)
5122{
5123 ext2_filsys fs = ctx->fs;
5124 struct process_block_struct_1b pb;
5125 struct ext2_inode inode;
5126 struct problem_context pctx;
5127 unsigned int count;
5128
5129 clear_problem_context(&pctx);
5130 pctx.ino = pb.ino = ino;
5131 pb.dup_blocks = dp->num_dupblocks;
5132 pb.ctx = ctx;
5133 pctx.str = "delete_file";
5134
5135 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5136 if (ext2fs_inode_has_valid_blocks(&inode))
5137 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5138 delete_file_block, &pb);
5139 if (pctx.errcode)
5140 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5141 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5142 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5143 if (ctx->inode_bad_map)
5144 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5145 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5146
5147 /* Inode may have changed by block_iterate, so reread it */
5148 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5149 inode.i_links_count = 0;
5150 inode.i_dtime = time(0);
5151 if (inode.i_file_acl &&
5152 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5153 count = 1;
5154 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5155 block_buf, -1, &count);
5156 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5157 pctx.errcode = 0;
5158 count = 1;
5159 }
5160 if (pctx.errcode) {
5161 pctx.blk = inode.i_file_acl;
5162 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5163 }
5164 /*
5165 * If the count is zero, then arrange to have the
5166 * block deleted. If the block is in the block_dup_map,
5167 * also call delete_file_block since it will take care
5168 * of keeping the accounting straight.
5169 */
5170 if ((count == 0) ||
5171 ext2fs_test_block_bitmap(ctx->block_dup_map,
5172 inode.i_file_acl))
5173 delete_file_block(fs, &inode.i_file_acl,
5174 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5175 }
5176 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5177}
5178
5179struct clone_struct {
5180 errcode_t errcode;
5181 ext2_ino_t dir;
5182 char *buf;
5183 e2fsck_t ctx;
5184};
5185
5186static int clone_file_block(ext2_filsys fs,
5187 blk_t *block_nr,
5188 e2_blkcnt_t blockcnt,
5189 blk_t ref_block FSCK_ATTR((unused)),
5190 int ref_offset FSCK_ATTR((unused)),
5191 void *priv_data)
5192{
5193 struct dup_block *p;
5194 blk_t new_block;
5195 errcode_t retval;
5196 struct clone_struct *cs = (struct clone_struct *) priv_data;
5197 dnode_t *n;
5198 e2fsck_t ctx;
5199
5200 ctx = cs->ctx;
5201
5202 if (HOLE_BLKADDR(*block_nr))
5203 return 0;
5204
5205 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5206 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5207 if (n) {
5208 p = (struct dup_block *) dnode_get(n);
5209 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5210 &new_block);
5211 if (retval) {
5212 cs->errcode = retval;
5213 return BLOCK_ABORT;
5214 }
5215 if (cs->dir && (blockcnt >= 0)) {
5216 retval = ext2fs_set_dir_block(fs->dblist,
5217 cs->dir, new_block, blockcnt);
5218 if (retval) {
5219 cs->errcode = retval;
5220 return BLOCK_ABORT;
5221 }
5222 }
5223
5224 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5225 cs->buf);
5226 if (retval) {
5227 cs->errcode = retval;
5228 return BLOCK_ABORT;
5229 }
5230 retval = io_channel_write_blk(fs->io, new_block, 1,
5231 cs->buf);
5232 if (retval) {
5233 cs->errcode = retval;
5234 return BLOCK_ABORT;
5235 }
5236 decrement_badcount(ctx, *block_nr, p);
5237 *block_nr = new_block;
5238 ext2fs_mark_block_bitmap(ctx->block_found_map,
5239 new_block);
5240 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5241 return BLOCK_CHANGED;
5242 } else
5243 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5244 *block_nr);
5245 }
5246 return 0;
5247}
5248
5249static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5250 struct dup_inode *dp, char* block_buf)
5251{
5252 ext2_filsys fs = ctx->fs;
5253 errcode_t retval;
5254 struct clone_struct cs;
5255 struct problem_context pctx;
5256 blk_t blk;
5257 dnode_t *n;
5258 struct inode_el *ino_el;
5259 struct dup_block *db;
5260 struct dup_inode *di;
5261
5262 clear_problem_context(&pctx);
5263 cs.errcode = 0;
5264 cs.dir = 0;
5265 cs.ctx = ctx;
5266 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5267 if (retval)
5268 return retval;
5269
5270 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5271 cs.dir = ino;
5272
5273 pctx.ino = ino;
5274 pctx.str = "clone_file";
5275 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5276 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5277 clone_file_block, &cs);
5278 ext2fs_mark_bb_dirty(fs);
5279 if (pctx.errcode) {
5280 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5281 retval = pctx.errcode;
5282 goto errout;
5283 }
5284 if (cs.errcode) {
5285 bb_error_msg(_("returned from clone_file_block"));
5286 retval = cs.errcode;
5287 goto errout;
5288 }
5289 /* The inode may have changed on disk, so we have to re-read it */
5290 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5291 blk = dp->inode.i_file_acl;
5292 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5293 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5294 BLOCK_CHANGED)) {
5295 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5296 /*
5297 * If we cloned the EA block, find all other inodes
5298 * which refered to that EA block, and modify
5299 * them to point to the new EA block.
5300 */
5301 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5302 db = (struct dup_block *) dnode_get(n);
5303 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5304 if (ino_el->inode == ino)
5305 continue;
5306 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5307 di = (struct dup_inode *) dnode_get(n);
5308 if (di->inode.i_file_acl == blk) {
5309 di->inode.i_file_acl = dp->inode.i_file_acl;
5310 e2fsck_write_inode(ctx, ino_el->inode,
5311 &di->inode, "clone file EA");
5312 decrement_badcount(ctx, blk, db);
5313 }
5314 }
5315 }
5316 retval = 0;
5317errout:
5318 ext2fs_free_mem(&cs.buf);
5319 return retval;
5320}
5321
5322/*
5323 * This routine returns 1 if a block overlaps with one of the superblocks,
5324 * group descriptors, inode bitmaps, or block bitmaps.
5325 */
5326static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5327{
5328 ext2_filsys fs = ctx->fs;
5329 blk_t block;
5330 dgrp_t i;
5331
5332 block = fs->super->s_first_data_block;
5333 for (i = 0; i < fs->group_desc_count; i++) {
5334
5335 /* Check superblocks/block group descriptros */
5336 if (ext2fs_bg_has_super(fs, i)) {
5337 if (test_block >= block &&
5338 (test_block <= block + fs->desc_blocks))
5339 return 1;
5340 }
5341
5342 /* Check the inode table */
5343 if ((fs->group_desc[i].bg_inode_table) &&
5344 (test_block >= fs->group_desc[i].bg_inode_table) &&
5345 (test_block < (fs->group_desc[i].bg_inode_table +
5346 fs->inode_blocks_per_group)))
5347 return 1;
5348
5349 /* Check the bitmap blocks */
5350 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5351 (test_block == fs->group_desc[i].bg_inode_bitmap))
5352 return 1;
5353
5354 block += fs->super->s_blocks_per_group;
5355 }
5356 return 0;
5357}
5358/*
5359 * pass2.c --- check directory structure
5360 *
5361 * Pass 2 of e2fsck iterates through all active directory inodes, and
5362 * applies to following tests to each directory entry in the directory
5363 * blocks in the inodes:
5364 *
5365 * - The length of the directory entry (rec_len) should be at
5366 * least 8 bytes, and no more than the remaining space
5367 * left in the directory block.
5368 * - The length of the name in the directory entry (name_len)
5369 * should be less than (rec_len - 8).
5370 * - The inode number in the directory entry should be within
5371 * legal bounds.
5372 * - The inode number should refer to a in-use inode.
5373 * - The first entry should be '.', and its inode should be
5374 * the inode of the directory.
5375 * - The second entry should be '..'.
5376 *
5377 * To minimize disk seek time, the directory blocks are processed in
5378 * sorted order of block numbers.
5379 *
5380 * Pass 2 also collects the following information:
5381 * - The inode numbers of the subdirectories for each directory.
5382 *
5383 * Pass 2 relies on the following information from previous passes:
5384 * - The directory information collected in pass 1.
5385 * - The inode_used_map bitmap
5386 * - The inode_bad_map bitmap
5387 * - The inode_dir_map bitmap
5388 *
5389 * Pass 2 frees the following data structures
5390 * - The inode_bad_map bitmap
5391 * - The inode_reg_map bitmap
5392 */
5393
5394/*
5395 * Keeps track of how many times an inode is referenced.
5396 */
5397static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5398static int check_dir_block(ext2_filsys fs,
5399 struct ext2_db_entry *dir_blocks_info,
5400 void *priv_data);
5401static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5402 struct problem_context *pctx);
5403static int update_dir_block(ext2_filsys fs,
5404 blk_t *block_nr,
5405 e2_blkcnt_t blockcnt,
5406 blk_t ref_block,
5407 int ref_offset,
5408 void *priv_data);
5409static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5410static int htree_depth(struct dx_dir_info *dx_dir,
5411 struct dx_dirblock_info *dx_db);
5412static int special_dir_block_cmp(const void *a, const void *b);
5413
5414struct check_dir_struct {
5415 char *buf;
5416 struct problem_context pctx;
5417 int count, max;
5418 e2fsck_t ctx;
5419};
5420
5421static void e2fsck_pass2(e2fsck_t ctx)
5422{
5423 struct ext2_super_block *sb = ctx->fs->super;
5424 struct problem_context pctx;
5425 ext2_filsys fs = ctx->fs;
5426 char *buf;
5427 struct dir_info *dir;
5428 struct check_dir_struct cd;
5429 struct dx_dir_info *dx_dir;
5430 struct dx_dirblock_info *dx_db, *dx_parent;
5431 int b;
5432 int i, depth;
5433 problem_t code;
5434 int bad_dir;
5435
5436 clear_problem_context(&cd.pctx);
5437
5438 /* Pass 2 */
5439
5440 if (!(ctx->options & E2F_OPT_PREEN))
5441 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5442
5443 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5444 0, ctx->inode_link_info,
5445 &ctx->inode_count);
5446 if (cd.pctx.errcode) {
5447 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5448 ctx->flags |= E2F_FLAG_ABORT;
5449 return;
5450 }
5451 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5452 "directory scan buffer");
5453
5454 /*
5455 * Set up the parent pointer for the root directory, if
5456 * present. (If the root directory is not present, we will
5457 * create it in pass 3.)
5458 */
5459 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5460 if (dir)
5461 dir->parent = EXT2_ROOT_INO;
5462
5463 cd.buf = buf;
5464 cd.ctx = ctx;
5465 cd.count = 1;
5466 cd.max = ext2fs_dblist_count(fs->dblist);
5467
5468 if (ctx->progress)
5469 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5470
5471 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5472 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5473
5474 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5475 &cd);
5476 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5477 return;
5478 if (cd.pctx.errcode) {
5479 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5480 ctx->flags |= E2F_FLAG_ABORT;
5481 return;
5482 }
5483
5484#ifdef ENABLE_HTREE
5485 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5486 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5487 return;
5488 if (dx_dir->numblocks == 0)
5489 continue;
5490 clear_problem_context(&pctx);
5491 bad_dir = 0;
5492 pctx.dir = dx_dir->ino;
5493 dx_db = dx_dir->dx_block;
5494 if (dx_db->flags & DX_FLAG_REFERENCED)
5495 dx_db->flags |= DX_FLAG_DUP_REF;
5496 else
5497 dx_db->flags |= DX_FLAG_REFERENCED;
5498 /*
5499 * Find all of the first and last leaf blocks, and
5500 * update their parent's min and max hash values
5501 */
5502 for (b=0, dx_db = dx_dir->dx_block;
5503 b < dx_dir->numblocks;
5504 b++, dx_db++) {
5505 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5506 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5507 continue;
5508 dx_parent = &dx_dir->dx_block[dx_db->parent];
5509 /*
5510 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5511 */
5512 if (dx_db->flags & DX_FLAG_FIRST)
5513 dx_parent->min_hash = dx_db->min_hash;
5514 /*
5515 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5516 */
5517 if (dx_db->flags & DX_FLAG_LAST)
5518 dx_parent->max_hash = dx_db->max_hash;
5519 }
5520
5521 for (b=0, dx_db = dx_dir->dx_block;
5522 b < dx_dir->numblocks;
5523 b++, dx_db++) {
5524 pctx.blkcount = b;
5525 pctx.group = dx_db->parent;
5526 code = 0;
5527 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5528 (dx_db->min_hash < dx_db->node_min_hash)) {
5529 pctx.blk = dx_db->min_hash;
5530 pctx.blk2 = dx_db->node_min_hash;
5531 code = PR_2_HTREE_MIN_HASH;
5532 fix_problem(ctx, code, &pctx);
5533 bad_dir++;
5534 }
5535 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5536 depth = htree_depth(dx_dir, dx_db);
5537 if (depth != dx_dir->depth) {
5538 code = PR_2_HTREE_BAD_DEPTH;
5539 fix_problem(ctx, code, &pctx);
5540 bad_dir++;
5541 }
5542 }
5543 /*
5544 * This test doesn't apply for the root block
5545 * at block #0
5546 */
5547 if (b &&
5548 (dx_db->max_hash > dx_db->node_max_hash)) {
5549 pctx.blk = dx_db->max_hash;
5550 pctx.blk2 = dx_db->node_max_hash;
5551 code = PR_2_HTREE_MAX_HASH;
5552 fix_problem(ctx, code, &pctx);
5553 bad_dir++;
5554 }
5555 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5556 code = PR_2_HTREE_NOTREF;
5557 fix_problem(ctx, code, &pctx);
5558 bad_dir++;
5559 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5560 code = PR_2_HTREE_DUPREF;
5561 fix_problem(ctx, code, &pctx);
5562 bad_dir++;
5563 }
5564 if (code == 0)
5565 continue;
5566 }
5567 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5568 clear_htree(ctx, dx_dir->ino);
5569 dx_dir->numblocks = 0;
5570 }
5571 }
5572#endif
5573 ext2fs_free_mem(&buf);
5574 ext2fs_free_dblist(fs->dblist);
5575
5576 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5577 ctx->inode_bad_map = 0;
5578 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5579 ctx->inode_reg_map = 0;
5580
5581 clear_problem_context(&pctx);
5582 if (ctx->large_files) {
5583 if (!(sb->s_feature_ro_compat &
5584 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5585 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5586 sb->s_feature_ro_compat |=
5587 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5588 ext2fs_mark_super_dirty(fs);
5589 }
5590 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5591 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5592 ext2fs_update_dynamic_rev(fs);
5593 ext2fs_mark_super_dirty(fs);
5594 }
5595 } else if (!ctx->large_files &&
5596 (sb->s_feature_ro_compat &
5597 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5598 if (fs->flags & EXT2_FLAG_RW) {
5599 sb->s_feature_ro_compat &=
5600 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5601 ext2fs_mark_super_dirty(fs);
5602 }
5603 }
5604
5605}
5606
5607#define MAX_DEPTH 32000
5608static int htree_depth(struct dx_dir_info *dx_dir,
5609 struct dx_dirblock_info *dx_db)
5610{
5611 int depth = 0;
5612
5613 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614 dx_db = &dx_dir->dx_block[dx_db->parent];
5615 depth++;
5616 }
5617 return depth;
5618}
5619
5620static int dict_de_cmp(const void *a, const void *b)
5621{
5622 const struct ext2_dir_entry *de_a, *de_b;
5623 int a_len, b_len;
5624
5625 de_a = (const struct ext2_dir_entry *) a;
5626 a_len = de_a->name_len & 0xFF;
5627 de_b = (const struct ext2_dir_entry *) b;
5628 b_len = de_b->name_len & 0xFF;
5629
5630 if (a_len != b_len)
5631 return (a_len - b_len);
5632
5633 return strncmp(de_a->name, de_b->name, a_len);
5634}
5635
5636/*
5637 * This is special sort function that makes sure that directory blocks
5638 * with a dirblock of zero are sorted to the beginning of the list.
5639 * This guarantees that the root node of the htree directories are
5640 * processed first, so we know what hash version to use.
5641 */
5642static int special_dir_block_cmp(const void *a, const void *b)
5643{
5644 const struct ext2_db_entry *db_a =
5645 (const struct ext2_db_entry *) a;
5646 const struct ext2_db_entry *db_b =
5647 (const struct ext2_db_entry *) b;
5648
5649 if (db_a->blockcnt && !db_b->blockcnt)
5650 return 1;
5651
5652 if (!db_a->blockcnt && db_b->blockcnt)
5653 return -1;
5654
5655 if (db_a->blk != db_b->blk)
5656 return (int) (db_a->blk - db_b->blk);
5657
5658 if (db_a->ino != db_b->ino)
5659 return (int) (db_a->ino - db_b->ino);
5660
5661 return (int) (db_a->blockcnt - db_b->blockcnt);
5662}
5663
5664
5665/*
5666 * Make sure the first entry in the directory is '.', and that the
5667 * directory entry is sane.
5668 */
5669static int check_dot(e2fsck_t ctx,
5670 struct ext2_dir_entry *dirent,
5671 ext2_ino_t ino, struct problem_context *pctx)
5672{
5673 struct ext2_dir_entry *nextdir;
5674 int status = 0;
5675 int created = 0;
5676 int new_len;
5677 int problem = 0;
5678
5679 if (!dirent->inode)
5680 problem = PR_2_MISSING_DOT;
5681 else if (((dirent->name_len & 0xFF) != 1) ||
5682 (dirent->name[0] != '.'))
5683 problem = PR_2_1ST_NOT_DOT;
5684 else if (dirent->name[1] != '\0')
5685 problem = PR_2_DOT_NULL_TERM;
5686
5687 if (problem) {
5688 if (fix_problem(ctx, problem, pctx)) {
5689 if (dirent->rec_len < 12)
5690 dirent->rec_len = 12;
5691 dirent->inode = ino;
5692 dirent->name_len = 1;
5693 dirent->name[0] = '.';
5694 dirent->name[1] = '\0';
5695 status = 1;
5696 created = 1;
5697 }
5698 }
5699 if (dirent->inode != ino) {
5700 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701 dirent->inode = ino;
5702 status = 1;
5703 }
5704 }
5705 if (dirent->rec_len > 12) {
5706 new_len = dirent->rec_len - 12;
5707 if (new_len > 12) {
5708 if (created ||
5709 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710 nextdir = (struct ext2_dir_entry *)
5711 ((char *) dirent + 12);
5712 dirent->rec_len = 12;
5713 nextdir->rec_len = new_len;
5714 nextdir->inode = 0;
5715 nextdir->name_len = 0;
5716 status = 1;
5717 }
5718 }
5719 }
5720 return status;
5721}
5722
5723/*
5724 * Make sure the second entry in the directory is '..', and that the
5725 * directory entry is sane. We do not check the inode number of '..'
5726 * here; this gets done in pass 3.
5727 */
5728static int check_dotdot(e2fsck_t ctx,
5729 struct ext2_dir_entry *dirent,
5730 struct dir_info *dir, struct problem_context *pctx)
5731{
5732 int problem = 0;
5733
5734 if (!dirent->inode)
5735 problem = PR_2_MISSING_DOT_DOT;
5736 else if (((dirent->name_len & 0xFF) != 2) ||
5737 (dirent->name[0] != '.') ||
5738 (dirent->name[1] != '.'))
5739 problem = PR_2_2ND_NOT_DOT_DOT;
5740 else if (dirent->name[2] != '\0')
5741 problem = PR_2_DOT_DOT_NULL_TERM;
5742
5743 if (problem) {
5744 if (fix_problem(ctx, problem, pctx)) {
5745 if (dirent->rec_len < 12)
5746 dirent->rec_len = 12;
5747 /*
5748 * Note: we don't have the parent inode just
5749 * yet, so we will fill it in with the root
5750 * inode. This will get fixed in pass 3.
5751 */
5752 dirent->inode = EXT2_ROOT_INO;
5753 dirent->name_len = 2;
5754 dirent->name[0] = '.';
5755 dirent->name[1] = '.';
5756 dirent->name[2] = '\0';
5757 return 1;
5758 }
5759 return 0;
5760 }
5761 dir->dotdot = dirent->inode;
5762 return 0;
5763}
5764
5765/*
5766 * Check to make sure a directory entry doesn't contain any illegal
5767 * characters.
5768 */
5769static int check_name(e2fsck_t ctx,
5770 struct ext2_dir_entry *dirent,
5771 struct problem_context *pctx)
5772{
5773 int i;
5774 int fixup = -1;
5775 int ret = 0;
5776
5777 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779 if (fixup < 0) {
5780 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5781 }
5782 if (fixup) {
5783 dirent->name[i] = '.';
5784 ret = 1;
5785 }
5786 }
5787 }
5788 return ret;
5789}
5790
5791/*
5792 * Check the directory filetype (if present)
5793 */
5794
5795/*
5796 * Given a mode, return the ext2 file type
5797 */
5798static int ext2_file_type(unsigned int mode)
5799{
5800 if (LINUX_S_ISREG(mode))
5801 return EXT2_FT_REG_FILE;
5802
5803 if (LINUX_S_ISDIR(mode))
5804 return EXT2_FT_DIR;
5805
5806 if (LINUX_S_ISCHR(mode))
5807 return EXT2_FT_CHRDEV;
5808
5809 if (LINUX_S_ISBLK(mode))
5810 return EXT2_FT_BLKDEV;
5811
5812 if (LINUX_S_ISLNK(mode))
5813 return EXT2_FT_SYMLINK;
5814
5815 if (LINUX_S_ISFIFO(mode))
5816 return EXT2_FT_FIFO;
5817
5818 if (LINUX_S_ISSOCK(mode))
5819 return EXT2_FT_SOCK;
5820
5821 return 0;
5822}
5823
5824static int check_filetype(e2fsck_t ctx,
5825 struct ext2_dir_entry *dirent,
5826 struct problem_context *pctx)
5827{
5828 int filetype = dirent->name_len >> 8;
5829 int should_be = EXT2_FT_UNKNOWN;
5830 struct ext2_inode inode;
5831
5832 if (!(ctx->fs->super->s_feature_incompat &
5833 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834 if (filetype == 0 ||
5835 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836 return 0;
5837 dirent->name_len = dirent->name_len & 0xFF;
5838 return 1;
5839 }
5840
5841 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842 should_be = EXT2_FT_DIR;
5843 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844 dirent->inode)) {
5845 should_be = EXT2_FT_REG_FILE;
5846 } else if (ctx->inode_bad_map &&
5847 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848 dirent->inode))
5849 should_be = 0;
5850 else {
5851 e2fsck_read_inode(ctx, dirent->inode, &inode,
5852 "check_filetype");
5853 should_be = ext2_file_type(inode.i_mode);
5854 }
5855 if (filetype == should_be)
5856 return 0;
5857 pctx->num = should_be;
5858
5859 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860 pctx) == 0)
5861 return 0;
5862
5863 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864 return 1;
5865}
5866
5867#ifdef ENABLE_HTREE
5868static void parse_int_node(ext2_filsys fs,
5869 struct ext2_db_entry *db,
5870 struct check_dir_struct *cd,
5871 struct dx_dir_info *dx_dir,
5872 char *block_buf)
5873{
5874 struct ext2_dx_root_info *root;
5875 struct ext2_dx_entry *ent;
5876 struct ext2_dx_countlimit *limit;
5877 struct dx_dirblock_info *dx_db;
5878 int i, expect_limit, count;
5879 blk_t blk;
5880 ext2_dirhash_t min_hash = 0xffffffff;
5881 ext2_dirhash_t max_hash = 0;
5882 ext2_dirhash_t hash = 0, prev_hash;
5883
5884 if (db->blockcnt == 0) {
5885 root = (struct ext2_dx_root_info *) (block_buf + 24);
5886 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887 } else {
5888 ent = (struct ext2_dx_entry *) (block_buf+8);
5889 }
5890 limit = (struct ext2_dx_countlimit *) ent;
5891
5892 count = ext2fs_le16_to_cpu(limit->count);
5893 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894 sizeof(struct ext2_dx_entry);
5895 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898 goto clear_and_exit;
5899 }
5900 if (count > expect_limit) {
5901 cd->pctx.num = count;
5902 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903 goto clear_and_exit;
5904 count = expect_limit;
5905 }
5906
5907 for (i=0; i < count; i++) {
5908 prev_hash = hash;
5909 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911 /* Check to make sure the block is valid */
5912 if (blk > (blk_t) dx_dir->numblocks) {
5913 cd->pctx.blk = blk;
5914 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915 &cd->pctx))
5916 goto clear_and_exit;
5917 }
5918 if (hash < prev_hash &&
5919 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920 goto clear_and_exit;
5921 dx_db = &dx_dir->dx_block[blk];
5922 if (dx_db->flags & DX_FLAG_REFERENCED) {
5923 dx_db->flags |= DX_FLAG_DUP_REF;
5924 } else {
5925 dx_db->flags |= DX_FLAG_REFERENCED;
5926 dx_db->parent = db->blockcnt;
5927 }
5928 if (hash < min_hash)
5929 min_hash = hash;
5930 if (hash > max_hash)
5931 max_hash = hash;
5932 dx_db->node_min_hash = hash;
5933 if ((i+1) < count)
5934 dx_db->node_max_hash =
5935 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936 else {
5937 dx_db->node_max_hash = 0xfffffffe;
5938 dx_db->flags |= DX_FLAG_LAST;
5939 }
5940 if (i == 0)
5941 dx_db->flags |= DX_FLAG_FIRST;
5942 }
5943 dx_db = &dx_dir->dx_block[db->blockcnt];
5944 dx_db->min_hash = min_hash;
5945 dx_db->max_hash = max_hash;
5946 return;
5947
5948clear_and_exit:
5949 clear_htree(cd->ctx, cd->pctx.ino);
5950 dx_dir->numblocks = 0;
5951}
5952#endif /* ENABLE_HTREE */
5953
5954/*
5955 * Given a busted directory, try to salvage it somehow.
5956 *
5957 */
5958static void salvage_directory(ext2_filsys fs,
5959 struct ext2_dir_entry *dirent,
5960 struct ext2_dir_entry *prev,
5961 unsigned int *offset)
5962{
5963 char *cp = (char *) dirent;
5964 int left = fs->blocksize - *offset - dirent->rec_len;
5965 int name_len = dirent->name_len & 0xFF;
5966
5967 /*
5968 * Special case of directory entry of size 8: copy what's left
5969 * of the directory block up to cover up the invalid hole.
5970 */
5971 if ((left >= 12) && (dirent->rec_len == 8)) {
5972 memmove(cp, cp+8, left);
5973 memset(cp + left, 0, 8);
5974 return;
5975 }
5976 /*
5977 * If the directory entry overruns the end of the directory
5978 * block, and the name is small enough to fit, then adjust the
5979 * record length.
5980 */
5981 if ((left < 0) &&
5982 (name_len + 8 <= dirent->rec_len + left) &&
5983 dirent->inode <= fs->super->s_inodes_count &&
5984 strnlen(dirent->name, name_len) == name_len) {
5985 dirent->rec_len += left;
5986 return;
5987 }
5988 /*
5989 * If the directory entry is a multiple of four, so it is
5990 * valid, let the previous directory entry absorb the invalid
5991 * one.
5992 */
5993 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994 prev->rec_len += dirent->rec_len;
5995 *offset += dirent->rec_len;
5996 return;
5997 }
5998 /*
5999 * Default salvage method --- kill all of the directory
6000 * entries for the rest of the block. We will either try to
6001 * absorb it into the previous directory entry, or create a
6002 * new empty directory entry the rest of the directory block.
6003 */
6004 if (prev) {
6005 prev->rec_len += fs->blocksize - *offset;
6006 *offset = fs->blocksize;
6007 } else {
6008 dirent->rec_len = fs->blocksize - *offset;
6009 dirent->name_len = 0;
6010 dirent->inode = 0;
6011 }
6012}
6013
6014static int check_dir_block(ext2_filsys fs,
6015 struct ext2_db_entry *db,
6016 void *priv_data)
6017{
6018 struct dir_info *subdir, *dir;
6019 struct dx_dir_info *dx_dir;
6020#ifdef ENABLE_HTREE
6021 struct dx_dirblock_info *dx_db = 0;
6022#endif /* ENABLE_HTREE */
6023 struct ext2_dir_entry *dirent, *prev;
6024 ext2_dirhash_t hash;
6025 unsigned int offset = 0;
6026 int dir_modified = 0;
6027 int dot_state;
6028 blk_t block_nr = db->blk;
6029 ext2_ino_t ino = db->ino;
6030 __u16 links;
6031 struct check_dir_struct *cd;
6032 char *buf;
6033 e2fsck_t ctx;
6034 int problem;
6035 struct ext2_dx_root_info *root;
6036 struct ext2_dx_countlimit *limit;
6037 static dict_t de_dict;
6038 struct problem_context pctx;
6039 int dups_found = 0;
6040
6041 cd = (struct check_dir_struct *) priv_data;
6042 buf = cd->buf;
6043 ctx = cd->ctx;
6044
6045 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046 return DIRENT_ABORT;
6047
6048 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049 return DIRENT_ABORT;
6050
6051 /*
6052 * Make sure the inode is still in use (could have been
6053 * deleted in the duplicate/bad blocks pass.
6054 */
6055 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056 return 0;
6057
6058 cd->pctx.ino = ino;
6059 cd->pctx.blk = block_nr;
6060 cd->pctx.blkcount = db->blockcnt;
6061 cd->pctx.ino2 = 0;
6062 cd->pctx.dirent = 0;
6063 cd->pctx.num = 0;
6064
6065 if (db->blk == 0) {
6066 if (allocate_dir_block(ctx, db, &cd->pctx))
6067 return 0;
6068 block_nr = db->blk;
6069 }
6070
6071 if (db->blockcnt)
6072 dot_state = 2;
6073 else
6074 dot_state = 0;
6075
6076 if (ctx->dirs_to_hash &&
6077 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078 dups_found++;
6079
6080 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083 if (cd->pctx.errcode) {
6084 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085 ctx->flags |= E2F_FLAG_ABORT;
6086 return DIRENT_ABORT;
6087 }
6088 memset(buf, 0, fs->blocksize);
6089 }
6090#ifdef ENABLE_HTREE
6091 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092 if (dx_dir && dx_dir->numblocks) {
6093 if (db->blockcnt >= dx_dir->numblocks) {
6094 printf("XXX should never happen!!!\n");
6095 abort();
6096 }
6097 dx_db = &dx_dir->dx_block[db->blockcnt];
6098 dx_db->type = DX_DIRBLOCK_LEAF;
6099 dx_db->phys = block_nr;
6100 dx_db->min_hash = ~0;
6101 dx_db->max_hash = 0;
6102
6103 dirent = (struct ext2_dir_entry *) buf;
6104 limit = (struct ext2_dx_countlimit *) (buf+8);
6105 if (db->blockcnt == 0) {
6106 root = (struct ext2_dx_root_info *) (buf + 24);
6107 dx_db->type = DX_DIRBLOCK_ROOT;
6108 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109 if ((root->reserved_zero ||
6110 root->info_length < 8 ||
6111 root->indirect_levels > 1) &&
6112 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113 clear_htree(ctx, ino);
6114 dx_dir->numblocks = 0;
6115 dx_db = 0;
6116 }
6117 dx_dir->hashversion = root->hash_version;
6118 dx_dir->depth = root->indirect_levels + 1;
6119 } else if ((dirent->inode == 0) &&
6120 (dirent->rec_len == fs->blocksize) &&
6121 (dirent->name_len == 0) &&
6122 (ext2fs_le16_to_cpu(limit->limit) ==
6123 ((fs->blocksize-8) /
6124 sizeof(struct ext2_dx_entry))))
6125 dx_db->type = DX_DIRBLOCK_NODE;
6126 }
6127#endif /* ENABLE_HTREE */
6128
6129 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130 prev = 0;
6131 do {
6132 problem = 0;
6133 dirent = (struct ext2_dir_entry *) (buf + offset);
6134 cd->pctx.dirent = dirent;
6135 cd->pctx.num = offset;
6136 if (((offset + dirent->rec_len) > fs->blocksize) ||
6137 (dirent->rec_len < 12) ||
6138 ((dirent->rec_len % 4) != 0) ||
6139 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141 salvage_directory(fs, dirent, prev, &offset);
6142 dir_modified++;
6143 continue;
6144 } else
6145 goto abort_free_dict;
6146 }
6147 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149 dirent->name_len = EXT2_NAME_LEN;
6150 dir_modified++;
6151 }
6152 }
6153
6154 if (dot_state == 0) {
6155 if (check_dot(ctx, dirent, ino, &cd->pctx))
6156 dir_modified++;
6157 } else if (dot_state == 1) {
6158 dir = e2fsck_get_dir_info(ctx, ino);
6159 if (!dir) {
6160 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161 goto abort_free_dict;
6162 }
6163 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164 dir_modified++;
6165 } else if (dirent->inode == ino) {
6166 problem = PR_2_LINK_DOT;
6167 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168 dirent->inode = 0;
6169 dir_modified++;
6170 goto next;
6171 }
6172 }
6173 if (!dirent->inode)
6174 goto next;
6175
6176 /*
6177 * Make sure the inode listed is a legal one.
6178 */
6179 if (((dirent->inode != EXT2_ROOT_INO) &&
6180 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181 (dirent->inode > fs->super->s_inodes_count)) {
6182 problem = PR_2_BAD_INO;
6183 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184 dirent->inode))) {
6185 /*
6186 * If the inode is unused, offer to clear it.
6187 */
6188 problem = PR_2_UNUSED_INODE;
6189 } else if ((dot_state > 1) &&
6190 ((dirent->name_len & 0xFF) == 1) &&
6191 (dirent->name[0] == '.')) {
6192 /*
6193 * If there's a '.' entry in anything other
6194 * than the first directory entry, it's a
6195 * duplicate entry that should be removed.
6196 */
6197 problem = PR_2_DUP_DOT;
6198 } else if ((dot_state > 1) &&
6199 ((dirent->name_len & 0xFF) == 2) &&
6200 (dirent->name[0] == '.') &&
6201 (dirent->name[1] == '.')) {
6202 /*
6203 * If there's a '..' entry in anything other
6204 * than the second directory entry, it's a
6205 * duplicate entry that should be removed.
6206 */
6207 problem = PR_2_DUP_DOT_DOT;
6208 } else if ((dot_state > 1) &&
6209 (dirent->inode == EXT2_ROOT_INO)) {
6210 /*
6211 * Don't allow links to the root directory.
6212 * We check this specially to make sure we
6213 * catch this error case even if the root
6214 * directory hasn't been created yet.
6215 */
6216 problem = PR_2_LINK_ROOT;
6217 } else if ((dot_state > 1) &&
6218 (dirent->name_len & 0xFF) == 0) {
6219 /*
6220 * Don't allow zero-length directory names.
6221 */
6222 problem = PR_2_NULL_NAME;
6223 }
6224
6225 if (problem) {
6226 if (fix_problem(ctx, problem, &cd->pctx)) {
6227 dirent->inode = 0;
6228 dir_modified++;
6229 goto next;
6230 } else {
6231 ext2fs_unmark_valid(fs);
6232 if (problem == PR_2_BAD_INO)
6233 goto next;
6234 }
6235 }
6236
6237 /*
6238 * If the inode was marked as having bad fields in
6239 * pass1, process it and offer to fix/clear it.
6240 * (We wait until now so that we can display the
6241 * pathname to the user.)
6242 */
6243 if (ctx->inode_bad_map &&
6244 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245 dirent->inode)) {
6246 if (e2fsck_process_bad_inode(ctx, ino,
6247 dirent->inode,
6248 buf + fs->blocksize)) {
6249 dirent->inode = 0;
6250 dir_modified++;
6251 goto next;
6252 }
6253 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254 return DIRENT_ABORT;
6255 }
6256
6257 if (check_name(ctx, dirent, &cd->pctx))
6258 dir_modified++;
6259
6260 if (check_filetype(ctx, dirent, &cd->pctx))
6261 dir_modified++;
6262
6263#ifdef ENABLE_HTREE
6264 if (dx_db) {
6265 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266 (dirent->name_len & 0xFF),
6267 fs->super->s_hash_seed, &hash, 0);
6268 if (hash < dx_db->min_hash)
6269 dx_db->min_hash = hash;
6270 if (hash > dx_db->max_hash)
6271 dx_db->max_hash = hash;
6272 }
6273#endif
6274
6275 /*
6276 * If this is a directory, then mark its parent in its
6277 * dir_info structure. If the parent field is already
6278 * filled in, then this directory has more than one
6279 * hard link. We assume the first link is correct,
6280 * and ask the user if he/she wants to clear this one.
6281 */
6282 if ((dot_state > 1) &&
6283 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284 dirent->inode))) {
6285 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286 if (!subdir) {
6287 cd->pctx.ino = dirent->inode;
6288 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289 goto abort_free_dict;
6290 }
6291 if (subdir->parent) {
6292 cd->pctx.ino2 = subdir->parent;
6293 if (fix_problem(ctx, PR_2_LINK_DIR,
6294 &cd->pctx)) {
6295 dirent->inode = 0;
6296 dir_modified++;
6297 goto next;
6298 }
6299 cd->pctx.ino2 = 0;
6300 } else
6301 subdir->parent = ino;
6302 }
6303
6304 if (dups_found) {
6305 ;
6306 } else if (dict_lookup(&de_dict, dirent)) {
6307 clear_problem_context(&pctx);
6308 pctx.ino = ino;
6309 pctx.dirent = dirent;
6310 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311 if (!ctx->dirs_to_hash)
6312 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313 if (ctx->dirs_to_hash)
6314 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315 dups_found++;
6316 } else
6317 dict_alloc_insert(&de_dict, dirent, dirent);
6318
6319 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320 &links);
6321 if (links > 1)
6322 ctx->fs_links_count++;
6323 ctx->fs_total_count++;
6324 next:
6325 prev = dirent;
6326 offset += dirent->rec_len;
6327 dot_state++;
6328 } while (offset < fs->blocksize);
6329#ifdef ENABLE_HTREE
6330 if (dx_db) {
6331 cd->pctx.dir = cd->pctx.ino;
6332 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333 (dx_db->type == DX_DIRBLOCK_NODE))
6334 parse_int_node(fs, db, cd, dx_dir, buf);
6335 }
6336#endif /* ENABLE_HTREE */
6337 if (offset != fs->blocksize) {
6338 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340 dirent->rec_len = cd->pctx.num;
6341 dir_modified++;
6342 }
6343 }
6344 if (dir_modified) {
6345 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346 if (cd->pctx.errcode) {
6347 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348 &cd->pctx))
6349 goto abort_free_dict;
6350 }
6351 ext2fs_mark_changed(fs);
6352 }
6353 dict_free_nodes(&de_dict);
6354 return 0;
6355abort_free_dict:
6356 dict_free_nodes(&de_dict);
6357 ctx->flags |= E2F_FLAG_ABORT;
6358 return DIRENT_ABORT;
6359}
6360
6361/*
6362 * This function is called to deallocate a block, and is an interator
6363 * functioned called by deallocate inode via ext2fs_iterate_block().
6364 */
6365static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367 blk_t ref_block FSCK_ATTR((unused)),
6368 int ref_offset FSCK_ATTR((unused)),
6369 void *priv_data)
6370{
6371 e2fsck_t ctx = (e2fsck_t) priv_data;
6372
6373 if (HOLE_BLKADDR(*block_nr))
6374 return 0;
6375 if ((*block_nr < fs->super->s_first_data_block) ||
6376 (*block_nr >= fs->super->s_blocks_count))
6377 return 0;
6378 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380 return 0;
6381}
6382
6383/*
6384 * This fuction deallocates an inode
6385 */
6386static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6387{
6388 ext2_filsys fs = ctx->fs;
6389 struct ext2_inode inode;
6390 struct problem_context pctx;
6391 __u32 count;
6392
6393 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395 inode.i_links_count = 0;
6396 inode.i_dtime = time(0);
6397 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398 clear_problem_context(&pctx);
6399 pctx.ino = ino;
6400
6401 /*
6402 * Fix up the bitmaps...
6403 */
6404 e2fsck_read_bitmaps(ctx);
6405 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407 if (ctx->inode_bad_map)
6408 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6410
6411 if (inode.i_file_acl &&
6412 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414 block_buf, -1, &count);
6415 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416 pctx.errcode = 0;
6417 count = 1;
6418 }
6419 if (pctx.errcode) {
6420 pctx.blk = inode.i_file_acl;
6421 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422 ctx->flags |= E2F_FLAG_ABORT;
6423 return;
6424 }
6425 if (count == 0) {
6426 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427 inode.i_file_acl);
6428 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6429 }
6430 inode.i_file_acl = 0;
6431 }
6432
6433 if (!ext2fs_inode_has_valid_blocks(&inode))
6434 return;
6435
6436 if (LINUX_S_ISREG(inode.i_mode) &&
6437 (inode.i_size_high || inode.i_size & 0x80000000UL))
6438 ctx->large_files--;
6439
6440 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441 deallocate_inode_block, ctx);
6442 if (pctx.errcode) {
6443 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444 ctx->flags |= E2F_FLAG_ABORT;
6445 return;
6446 }
6447}
6448
6449/*
6450 * This fuction clears the htree flag on an inode
6451 */
6452static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6453{
6454 struct ext2_inode inode;
6455
6456 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459 if (ctx->dirs_to_hash)
6460 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6461}
6462
6463
6464static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465 ext2_ino_t ino, char *buf)
6466{
6467 ext2_filsys fs = ctx->fs;
6468 struct ext2_inode inode;
6469 int inode_modified = 0;
6470 int not_fixed = 0;
6471 unsigned char *frag, *fsize;
6472 struct problem_context pctx;
6473 int problem = 0;
6474
6475 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6476
6477 clear_problem_context(&pctx);
6478 pctx.ino = ino;
6479 pctx.dir = dir;
6480 pctx.inode = &inode;
6481
6482 if (inode.i_file_acl &&
6483 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485 inode.i_file_acl = 0;
6486#if BB_BIG_ENDIAN
6487 /*
6488 * This is a special kludge to deal with long symlinks
6489 * on big endian systems. i_blocks had already been
6490 * decremented earlier in pass 1, but since i_file_acl
6491 * hadn't yet been cleared, ext2fs_read_inode()
6492 * assumed that the file was short symlink and would
6493 * not have byte swapped i_block[0]. Hence, we have
6494 * to byte-swap it here.
6495 */
6496 if (LINUX_S_ISLNK(inode.i_mode) &&
6497 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498 (inode.i_blocks == fs->blocksize >> 9))
6499 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500#endif
6501 inode_modified++;
6502 } else
6503 not_fixed++;
6504
6505 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508 !(LINUX_S_ISSOCK(inode.i_mode)))
6509 problem = PR_2_BAD_MODE;
6510 else if (LINUX_S_ISCHR(inode.i_mode)
6511 && !e2fsck_pass1_check_device_inode(fs, &inode))
6512 problem = PR_2_BAD_CHAR_DEV;
6513 else if (LINUX_S_ISBLK(inode.i_mode)
6514 && !e2fsck_pass1_check_device_inode(fs, &inode))
6515 problem = PR_2_BAD_BLOCK_DEV;
6516 else if (LINUX_S_ISFIFO(inode.i_mode)
6517 && !e2fsck_pass1_check_device_inode(fs, &inode))
6518 problem = PR_2_BAD_FIFO;
6519 else if (LINUX_S_ISSOCK(inode.i_mode)
6520 && !e2fsck_pass1_check_device_inode(fs, &inode))
6521 problem = PR_2_BAD_SOCKET;
6522 else if (LINUX_S_ISLNK(inode.i_mode)
6523 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524 problem = PR_2_INVALID_SYMLINK;
6525 }
6526
6527 if (problem) {
6528 if (fix_problem(ctx, problem, &pctx)) {
6529 deallocate_inode(ctx, ino, 0);
6530 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531 return 0;
6532 return 1;
6533 } else
6534 not_fixed++;
6535 problem = 0;
6536 }
6537
6538 if (inode.i_faddr) {
6539 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540 inode.i_faddr = 0;
6541 inode_modified++;
6542 } else
6543 not_fixed++;
6544 }
6545
6546 switch (fs->super->s_creator_os) {
6547 case EXT2_OS_LINUX:
6548 frag = &inode.osd2.linux2.l_i_frag;
6549 fsize = &inode.osd2.linux2.l_i_fsize;
6550 break;
6551 case EXT2_OS_HURD:
6552 frag = &inode.osd2.hurd2.h_i_frag;
6553 fsize = &inode.osd2.hurd2.h_i_fsize;
6554 break;
6555 case EXT2_OS_MASIX:
6556 frag = &inode.osd2.masix2.m_i_frag;
6557 fsize = &inode.osd2.masix2.m_i_fsize;
6558 break;
6559 default:
6560 frag = fsize = 0;
6561 }
6562 if (frag && *frag) {
6563 pctx.num = *frag;
6564 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565 *frag = 0;
6566 inode_modified++;
6567 } else
6568 not_fixed++;
6569 pctx.num = 0;
6570 }
6571 if (fsize && *fsize) {
6572 pctx.num = *fsize;
6573 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574 *fsize = 0;
6575 inode_modified++;
6576 } else
6577 not_fixed++;
6578 pctx.num = 0;
6579 }
6580
6581 if (inode.i_file_acl &&
6582 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585 inode.i_file_acl = 0;
6586 inode_modified++;
6587 } else
6588 not_fixed++;
6589 }
6590 if (inode.i_dir_acl &&
6591 LINUX_S_ISDIR(inode.i_mode)) {
6592 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593 inode.i_dir_acl = 0;
6594 inode_modified++;
6595 } else
6596 not_fixed++;
6597 }
6598
6599 if (inode_modified)
6600 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601 if (!not_fixed)
6602 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603 return 0;
6604}
6605
6606
6607/*
6608 * allocate_dir_block --- this function allocates a new directory
6609 * block for a particular inode; this is done if a directory has
6610 * a "hole" in it, or if a directory has a illegal block number
6611 * that was zeroed out and now needs to be replaced.
6612 */
6613static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614 struct problem_context *pctx)
6615{
6616 ext2_filsys fs = ctx->fs;
6617 blk_t blk;
6618 char *block;
6619 struct ext2_inode inode;
6620
6621 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622 return 1;
6623
6624 /*
6625 * Read the inode and block bitmaps in; we'll be messing with
6626 * them.
6627 */
6628 e2fsck_read_bitmaps(ctx);
6629
6630 /*
6631 * First, find a free block
6632 */
6633 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634 if (pctx->errcode) {
6635 pctx->str = "ext2fs_new_block";
6636 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637 return 1;
6638 }
6639 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640 ext2fs_mark_block_bitmap(fs->block_map, blk);
6641 ext2fs_mark_bb_dirty(fs);
6642
6643 /*
6644 * Now let's create the actual data block for the inode
6645 */
6646 if (db->blockcnt)
6647 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648 else
6649 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650 EXT2_ROOT_INO, &block);
6651
6652 if (pctx->errcode) {
6653 pctx->str = "ext2fs_new_dir_block";
6654 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655 return 1;
6656 }
6657
6658 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659 ext2fs_free_mem(&block);
6660 if (pctx->errcode) {
6661 pctx->str = "ext2fs_write_dir_block";
6662 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663 return 1;
6664 }
6665
6666 /*
6667 * Update the inode block count
6668 */
6669 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670 inode.i_blocks += fs->blocksize / 512;
6671 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6674
6675 /*
6676 * Finally, update the block pointers for the inode
6677 */
6678 db->blk = blk;
6679 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680 0, update_dir_block, db);
6681 if (pctx->errcode) {
6682 pctx->str = "ext2fs_block_iterate";
6683 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684 return 1;
6685 }
6686
6687 return 0;
6688}
6689
6690/*
6691 * This is a helper function for allocate_dir_block().
6692 */
6693static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694 blk_t *block_nr,
6695 e2_blkcnt_t blockcnt,
6696 blk_t ref_block FSCK_ATTR((unused)),
6697 int ref_offset FSCK_ATTR((unused)),
6698 void *priv_data)
6699{
6700 struct ext2_db_entry *db;
6701
6702 db = (struct ext2_db_entry *) priv_data;
6703 if (db->blockcnt == (int) blockcnt) {
6704 *block_nr = db->blk;
6705 return BLOCK_CHANGED;
6706 }
6707 return 0;
6708}
6709
6710/*
6711 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6712 *
6713 * Pass #3 assures that all directories are connected to the
6714 * filesystem tree, using the following algorithm:
6715 *
6716 * First, the root directory is checked to make sure it exists; if
6717 * not, e2fsck will offer to create a new one. It is then marked as
6718 * "done".
6719 *
6720 * Then, pass3 interates over all directory inodes; for each directory
6721 * it attempts to trace up the filesystem tree, using dirinfo.parent
6722 * until it reaches a directory which has been marked "done". If it
6723 * cannot do so, then the directory must be disconnected, and e2fsck
6724 * will offer to reconnect it to /lost+found. While it is chasing
6725 * parent pointers up the filesystem tree, if pass3 sees a directory
6726 * twice, then it has detected a filesystem loop, and it will again
6727 * offer to reconnect the directory to /lost+found in to break the
6728 * filesystem loop.
6729 *
6730 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731 * reconnect inodes to /lost+found; this subroutine is also used by
6732 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6733 * is responsible for creating /lost+found if it does not exist.
6734 *
6735 * Pass 3 frees the following data structures:
6736 * - The dirinfo directory information cache.
6737 */
6738
6739static void check_root(e2fsck_t ctx);
6740static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741 struct problem_context *pctx);
6742static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6743
6744static ext2fs_inode_bitmap inode_loop_detect;
6745static ext2fs_inode_bitmap inode_done_map;
6746
6747static void e2fsck_pass3(e2fsck_t ctx)
6748{
6749 ext2_filsys fs = ctx->fs;
6750 int i;
6751 struct problem_context pctx;
6752 struct dir_info *dir;
6753 unsigned long maxdirs, count;
6754
6755 clear_problem_context(&pctx);
6756
6757 /* Pass 3 */
6758
6759 if (!(ctx->options & E2F_OPT_PREEN))
6760 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6761
6762 /*
6763 * Allocate some bitmaps to do loop detection.
6764 */
6765 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766 &inode_done_map);
6767 if (pctx.errcode) {
6768 pctx.num = 2;
6769 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770 ctx->flags |= E2F_FLAG_ABORT;
6771 goto abort_exit;
6772 }
6773 check_root(ctx);
6774 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775 goto abort_exit;
6776
6777 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6778
6779 maxdirs = e2fsck_get_num_dirinfo(ctx);
6780 count = 1;
6781
6782 if (ctx->progress)
6783 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784 goto abort_exit;
6785
6786 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788 goto abort_exit;
6789 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790 goto abort_exit;
6791 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792 if (check_directory(ctx, dir, &pctx))
6793 goto abort_exit;
6794 }
6795
6796 /*
6797 * Force the creation of /lost+found if not present
6798 */
6799 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800 e2fsck_get_lost_and_found(ctx, 1);
6801
6802 /*
6803 * If there are any directories that need to be indexed or
6804 * optimized, do it here.
6805 */
6806 e2fsck_rehash_directories(ctx);
6807
6808abort_exit:
6809 e2fsck_free_dir_info(ctx);
6810 ext2fs_free_inode_bitmap(inode_loop_detect);
6811 inode_loop_detect = 0;
6812 ext2fs_free_inode_bitmap(inode_done_map);
6813 inode_done_map = 0;
6814}
6815
6816/*
6817 * This makes sure the root inode is present; if not, we ask if the
6818 * user wants us to create it. Not creating it is a fatal error.
6819 */
6820static void check_root(e2fsck_t ctx)
6821{
6822 ext2_filsys fs = ctx->fs;
6823 blk_t blk;
6824 struct ext2_inode inode;
6825 char * block;
6826 struct problem_context pctx;
6827
6828 clear_problem_context(&pctx);
6829
6830 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6831 /*
6832 * If the root inode is not a directory, die here. The
6833 * user must have answered 'no' in pass1 when we
6834 * offered to clear it.
6835 */
6836 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837 EXT2_ROOT_INO))) {
6838 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839 ctx->flags |= E2F_FLAG_ABORT;
6840 }
6841 return;
6842 }
6843
6844 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846 ctx->flags |= E2F_FLAG_ABORT;
6847 return;
6848 }
6849
6850 e2fsck_read_bitmaps(ctx);
6851
6852 /*
6853 * First, find a free block
6854 */
6855 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856 if (pctx.errcode) {
6857 pctx.str = "ext2fs_new_block";
6858 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859 ctx->flags |= E2F_FLAG_ABORT;
6860 return;
6861 }
6862 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863 ext2fs_mark_block_bitmap(fs->block_map, blk);
6864 ext2fs_mark_bb_dirty(fs);
6865
6866 /*
6867 * Now let's create the actual data block for the inode
6868 */
6869 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870 &block);
6871 if (pctx.errcode) {
6872 pctx.str = "ext2fs_new_dir_block";
6873 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874 ctx->flags |= E2F_FLAG_ABORT;
6875 return;
6876 }
6877
6878 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879 if (pctx.errcode) {
6880 pctx.str = "ext2fs_write_dir_block";
6881 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882 ctx->flags |= E2F_FLAG_ABORT;
6883 return;
6884 }
6885 ext2fs_free_mem(&block);
6886
6887 /*
6888 * Set up the inode structure
6889 */
6890 memset(&inode, 0, sizeof(inode));
6891 inode.i_mode = 040755;
6892 inode.i_size = fs->blocksize;
6893 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
6894 inode.i_links_count = 2;
6895 inode.i_blocks = fs->blocksize / 512;
6896 inode.i_block[0] = blk;
6897
6898 /*
6899 * Write out the inode.
6900 */
6901 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902 if (pctx.errcode) {
6903 pctx.str = "ext2fs_write_inode";
6904 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905 ctx->flags |= E2F_FLAG_ABORT;
6906 return;
6907 }
6908
6909 /*
6910 * Miscellaneous bookkeeping...
6911 */
6912 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6915
6916 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919 ext2fs_mark_ib_dirty(fs);
6920}
6921
6922/*
6923 * This subroutine is responsible for making sure that a particular
6924 * directory is connected to the root; if it isn't we trace it up as
6925 * far as we can go, and then offer to connect the resulting parent to
6926 * the lost+found. We have to do loop detection; if we ever discover
6927 * a loop, we treat that as a disconnected directory and offer to
6928 * reparent it to lost+found.
6929 *
6930 * However, loop detection is expensive, because for very large
6931 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932 * is non-trivial. Loops in filesystems are also a rare error case,
6933 * and we shouldn't optimize for error cases. So we try two passes of
6934 * the algorithm. The first time, we ignore loop detection and merely
6935 * increment a counter; if the counter exceeds some extreme threshold,
6936 * then we try again with the loop detection bitmap enabled.
6937 */
6938static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939 struct problem_context *pctx)
6940{
6941 ext2_filsys fs = ctx->fs;
6942 struct dir_info *p = dir;
6943 int loop_pass = 0, parent_count = 0;
6944
6945 if (!p)
6946 return 0;
6947
6948 while (1) {
6949 /*
6950 * Mark this inode as being "done"; by the time we
6951 * return from this function, the inode we either be
6952 * verified as being connected to the directory tree,
6953 * or we will have offered to reconnect this to
6954 * lost+found.
6955 *
6956 * If it was marked done already, then we've reached a
6957 * parent we've already checked.
6958 */
6959 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960 break;
6961
6962 /*
6963 * If this directory doesn't have a parent, or we've
6964 * seen the parent once already, then offer to
6965 * reparent it to lost+found
6966 */
6967 if (!p->parent ||
6968 (loop_pass &&
6969 (ext2fs_test_inode_bitmap(inode_loop_detect,
6970 p->parent)))) {
6971 pctx->ino = p->ino;
6972 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973 if (e2fsck_reconnect_file(ctx, pctx->ino))
6974 ext2fs_unmark_valid(fs);
6975 else {
6976 p = e2fsck_get_dir_info(ctx, pctx->ino);
6977 p->parent = ctx->lost_and_found;
6978 fix_dotdot(ctx, p, ctx->lost_and_found);
6979 }
6980 }
6981 break;
6982 }
6983 p = e2fsck_get_dir_info(ctx, p->parent);
6984 if (!p) {
6985 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986 return 0;
6987 }
6988 if (loop_pass) {
6989 ext2fs_mark_inode_bitmap(inode_loop_detect,
6990 p->ino);
6991 } else if (parent_count++ > 2048) {
6992 /*
6993 * If we've run into a path depth that's
6994 * greater than 2048, try again with the inode
6995 * loop bitmap turned on and start from the
6996 * top.
6997 */
6998 loop_pass = 1;
6999 if (inode_loop_detect)
7000 ext2fs_clear_inode_bitmap(inode_loop_detect);
7001 else {
7002 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003 if (pctx->errcode) {
7004 pctx->num = 1;
7005 fix_problem(ctx,
7006 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007 ctx->flags |= E2F_FLAG_ABORT;
7008 return -1;
7009 }
7010 }
7011 p = dir;
7012 }
7013 }
7014
7015 /*
7016 * Make sure that .. and the parent directory are the same;
7017 * offer to fix it if not.
7018 */
7019 if (dir->parent != dir->dotdot) {
7020 pctx->ino = dir->ino;
7021 pctx->ino2 = dir->dotdot;
7022 pctx->dir = dir->parent;
7023 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024 fix_dotdot(ctx, dir, dir->parent);
7025 }
7026 return 0;
7027}
7028
7029/*
7030 * This routine gets the lost_and_found inode, making it a directory
7031 * if necessary
7032 */
7033ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7034{
7035 ext2_filsys fs = ctx->fs;
7036 ext2_ino_t ino;
7037 blk_t blk;
7038 errcode_t retval;
7039 struct ext2_inode inode;
7040 char * block;
7041 static const char name[] = "lost+found";
7042 struct problem_context pctx;
7043 struct dir_info *dirinfo;
7044
7045 if (ctx->lost_and_found)
7046 return ctx->lost_and_found;
7047
7048 clear_problem_context(&pctx);
7049
7050 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051 sizeof(name)-1, 0, &ino);
7052 if (retval && !fix)
7053 return 0;
7054 if (!retval) {
7055 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056 ctx->lost_and_found = ino;
7057 return ino;
7058 }
7059
7060 /* Lost+found isn't a directory! */
7061 if (!fix)
7062 return 0;
7063 pctx.ino = ino;
7064 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065 return 0;
7066
7067 /* OK, unlink the old /lost+found file. */
7068 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069 if (pctx.errcode) {
7070 pctx.str = "ext2fs_unlink";
7071 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072 return 0;
7073 }
7074 dirinfo = e2fsck_get_dir_info(ctx, ino);
7075 if (dirinfo)
7076 dirinfo->parent = 0;
7077 e2fsck_adjust_inode_count(ctx, ino, -1);
7078 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079 pctx.errcode = retval;
7080 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7081 }
7082 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083 return 0;
7084
7085 /*
7086 * Read the inode and block bitmaps in; we'll be messing with
7087 * them.
7088 */
7089 e2fsck_read_bitmaps(ctx);
7090
7091 /*
7092 * First, find a free block
7093 */
7094 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095 if (retval) {
7096 pctx.errcode = retval;
7097 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098 return 0;
7099 }
7100 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101 ext2fs_block_alloc_stats(fs, blk, +1);
7102
7103 /*
7104 * Next find a free inode.
7105 */
7106 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107 ctx->inode_used_map, &ino);
7108 if (retval) {
7109 pctx.errcode = retval;
7110 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111 return 0;
7112 }
7113 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7116
7117 /*
7118 * Now let's create the actual data block for the inode
7119 */
7120 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121 if (retval) {
7122 pctx.errcode = retval;
7123 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124 return 0;
7125 }
7126
7127 retval = ext2fs_write_dir_block(fs, blk, block);
7128 ext2fs_free_mem(&block);
7129 if (retval) {
7130 pctx.errcode = retval;
7131 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132 return 0;
7133 }
7134
7135 /*
7136 * Set up the inode structure
7137 */
7138 memset(&inode, 0, sizeof(inode));
7139 inode.i_mode = 040700;
7140 inode.i_size = fs->blocksize;
7141 inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
7142 inode.i_links_count = 2;
7143 inode.i_blocks = fs->blocksize / 512;
7144 inode.i_block[0] = blk;
7145
7146 /*
7147 * Next, write out the inode.
7148 */
7149 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150 if (pctx.errcode) {
7151 pctx.str = "ext2fs_write_inode";
7152 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153 return 0;
7154 }
7155 /*
7156 * Finally, create the directory link
7157 */
7158 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159 if (pctx.errcode) {
7160 pctx.str = "ext2fs_link";
7161 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162 return 0;
7163 }
7164
7165 /*
7166 * Miscellaneous bookkeeping that needs to be kept straight.
7167 */
7168 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170 ext2fs_icount_store(ctx->inode_count, ino, 2);
7171 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172 ctx->lost_and_found = ino;
7173 return ino;
7174}
7175
7176/*
7177 * This routine will connect a file to lost+found
7178 */
7179int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7180{
7181 ext2_filsys fs = ctx->fs;
7182 errcode_t retval;
7183 char name[80];
7184 struct problem_context pctx;
7185 struct ext2_inode inode;
7186 int file_type = 0;
7187
7188 clear_problem_context(&pctx);
7189 pctx.ino = ino;
7190
7191 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193 ctx->bad_lost_and_found++;
7194 }
7195 if (ctx->bad_lost_and_found) {
7196 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197 return 1;
7198 }
7199
7200 sprintf(name, "#%u", ino);
7201 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202 file_type = ext2_file_type(inode.i_mode);
7203 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204 if (retval == EXT2_ET_DIR_NO_SPACE) {
7205 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206 return 1;
7207 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208 1, 0);
7209 if (retval) {
7210 pctx.errcode = retval;
7211 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212 return 1;
7213 }
7214 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215 ino, file_type);
7216 }
7217 if (retval) {
7218 pctx.errcode = retval;
7219 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220 return 1;
7221 }
7222 e2fsck_adjust_inode_count(ctx, ino, 1);
7223
7224 return 0;
7225}
7226
7227/*
7228 * Utility routine to adjust the inode counts on an inode.
7229 */
7230errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7231{
7232 ext2_filsys fs = ctx->fs;
7233 errcode_t retval;
7234 struct ext2_inode inode;
7235
7236 if (!ino)
7237 return 0;
7238
7239 retval = ext2fs_read_inode(fs, ino, &inode);
7240 if (retval)
7241 return retval;
7242
7243 if (adj == 1) {
7244 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245 if (inode.i_links_count == (__u16) ~0)
7246 return 0;
7247 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248 inode.i_links_count++;
7249 } else if (adj == -1) {
7250 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251 if (inode.i_links_count == 0)
7252 return 0;
7253 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254 inode.i_links_count--;
7255 }
7256
7257 retval = ext2fs_write_inode(fs, ino, &inode);
7258 if (retval)
7259 return retval;
7260
7261 return 0;
7262}
7263
7264/*
7265 * Fix parent --- this routine fixes up the parent of a directory.
7266 */
7267struct fix_dotdot_struct {
7268 ext2_filsys fs;
7269 ext2_ino_t parent;
7270 int done;
7271 e2fsck_t ctx;
7272};
7273
7274static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275 int offset FSCK_ATTR((unused)),
7276 int blocksize FSCK_ATTR((unused)),
7277 char *buf FSCK_ATTR((unused)),
7278 void *priv_data)
7279{
7280 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281 errcode_t retval;
7282 struct problem_context pctx;
7283
7284 if ((dirent->name_len & 0xFF) != 2)
7285 return 0;
7286 if (strncmp(dirent->name, "..", 2))
7287 return 0;
7288
7289 clear_problem_context(&pctx);
7290
7291 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292 if (retval) {
7293 pctx.errcode = retval;
7294 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7295 }
7296 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297 if (retval) {
7298 pctx.errcode = retval;
7299 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7300 }
7301 dirent->inode = fp->parent;
7302
7303 fp->done++;
7304 return DIRENT_ABORT | DIRENT_CHANGED;
7305}
7306
7307static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7308{
7309 ext2_filsys fs = ctx->fs;
7310 errcode_t retval;
7311 struct fix_dotdot_struct fp;
7312 struct problem_context pctx;
7313
7314 fp.fs = fs;
7315 fp.parent = parent;
7316 fp.done = 0;
7317 fp.ctx = ctx;
7318
7319 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320 0, fix_dotdot_proc, &fp);
7321 if (retval || !fp.done) {
7322 clear_problem_context(&pctx);
7323 pctx.ino = dir->ino;
7324 pctx.errcode = retval;
7325 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326 PR_3_FIX_PARENT_NOFIND, &pctx);
7327 ext2fs_unmark_valid(fs);
7328 }
7329 dir->dotdot = parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007330}
7331
7332/*
7333 * These routines are responsible for expanding a /lost+found if it is
7334 * too small.
7335 */
7336
7337struct expand_dir_struct {
7338 int num;
7339 int guaranteed_size;
7340 int newblocks;
7341 int last_block;
7342 errcode_t err;
7343 e2fsck_t ctx;
7344};
7345
7346static int expand_dir_proc(ext2_filsys fs,
7347 blk_t *blocknr,
7348 e2_blkcnt_t blockcnt,
7349 blk_t ref_block FSCK_ATTR((unused)),
7350 int ref_offset FSCK_ATTR((unused)),
7351 void *priv_data)
7352{
7353 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354 blk_t new_blk;
7355 static blk_t last_blk = 0;
7356 char *block;
7357 errcode_t retval;
7358 e2fsck_t ctx;
7359
7360 ctx = es->ctx;
7361
7362 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363 return BLOCK_ABORT;
7364
7365 if (blockcnt > 0)
7366 es->last_block = blockcnt;
7367 if (*blocknr) {
7368 last_blk = *blocknr;
7369 return 0;
7370 }
7371 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372 &new_blk);
7373 if (retval) {
7374 es->err = retval;
7375 return BLOCK_ABORT;
7376 }
7377 if (blockcnt > 0) {
7378 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379 if (retval) {
7380 es->err = retval;
7381 return BLOCK_ABORT;
7382 }
7383 es->num--;
7384 retval = ext2fs_write_dir_block(fs, new_blk, block);
7385 } else {
7386 retval = ext2fs_get_mem(fs->blocksize, &block);
7387 if (retval) {
7388 es->err = retval;
7389 return BLOCK_ABORT;
7390 }
7391 memset(block, 0, fs->blocksize);
7392 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7393 }
7394 if (retval) {
7395 es->err = retval;
7396 return BLOCK_ABORT;
7397 }
7398 ext2fs_free_mem(&block);
7399 *blocknr = new_blk;
7400 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401 ext2fs_block_alloc_stats(fs, new_blk, +1);
7402 es->newblocks++;
7403
7404 if (es->num == 0)
7405 return (BLOCK_CHANGED | BLOCK_ABORT);
7406 else
7407 return BLOCK_CHANGED;
7408}
7409
7410errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411 int num, int guaranteed_size)
7412{
7413 ext2_filsys fs = ctx->fs;
7414 errcode_t retval;
7415 struct expand_dir_struct es;
7416 struct ext2_inode inode;
7417
7418 if (!(fs->flags & EXT2_FLAG_RW))
7419 return EXT2_ET_RO_FILSYS;
7420
7421 /*
7422 * Read the inode and block bitmaps in; we'll be messing with
7423 * them.
7424 */
7425 e2fsck_read_bitmaps(ctx);
7426
7427 retval = ext2fs_check_directory(fs, dir);
7428 if (retval)
7429 return retval;
7430
7431 es.num = num;
7432 es.guaranteed_size = guaranteed_size;
7433 es.last_block = 0;
7434 es.err = 0;
7435 es.newblocks = 0;
7436 es.ctx = ctx;
7437
7438 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439 0, expand_dir_proc, &es);
7440
7441 if (es.err)
7442 return es.err;
7443
7444 /*
7445 * Update the size and block count fields in the inode.
7446 */
7447 retval = ext2fs_read_inode(fs, dir, &inode);
7448 if (retval)
7449 return retval;
7450
7451 inode.i_size = (es.last_block + 1) * fs->blocksize;
7452 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7453
7454 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7455
7456 return 0;
7457}
7458
7459/*
7460 * pass4.c -- pass #4 of e2fsck: Check reference counts
7461 *
7462 * Pass 4 frees the following data structures:
7463 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7464 */
7465
7466/*
7467 * This routine is called when an inode is not connected to the
7468 * directory tree.
7469 *
7470 * This subroutine returns 1 then the caller shouldn't bother with the
7471 * rest of the pass 4 tests.
7472 */
7473static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7474{
7475 ext2_filsys fs = ctx->fs;
7476 struct ext2_inode inode;
7477 struct problem_context pctx;
7478
7479 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480 clear_problem_context(&pctx);
7481 pctx.ino = i;
7482 pctx.inode = &inode;
7483
7484 /*
7485 * Offer to delete any zero-length files that does not have
7486 * blocks. If there is an EA block, it might have useful
7487 * information, so we won't prompt to delete it, but let it be
7488 * reconnected to lost+found.
7489 */
7490 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491 LINUX_S_ISDIR(inode.i_mode))) {
7492 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494 inode.i_links_count = 0;
7495 inode.i_dtime = time(0);
7496 e2fsck_write_inode(ctx, i, &inode,
7497 "disconnect_inode");
7498 /*
7499 * Fix up the bitmaps...
7500 */
7501 e2fsck_read_bitmaps(ctx);
7502 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504 ext2fs_inode_alloc_stats2(fs, i, -1,
7505 LINUX_S_ISDIR(inode.i_mode));
7506 return 0;
7507 }
7508 }
7509
7510 /*
7511 * Prompt to reconnect.
7512 */
7513 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514 if (e2fsck_reconnect_file(ctx, i))
7515 ext2fs_unmark_valid(fs);
7516 } else {
7517 /*
7518 * If we don't attach the inode, then skip the
7519 * i_links_test since there's no point in trying to
7520 * force i_links_count to zero.
7521 */
7522 ext2fs_unmark_valid(fs);
7523 return 1;
7524 }
7525 return 0;
7526}
7527
7528
7529static void e2fsck_pass4(e2fsck_t ctx)
7530{
7531 ext2_filsys fs = ctx->fs;
7532 ext2_ino_t i;
7533 struct ext2_inode inode;
7534 struct problem_context pctx;
7535 __u16 link_count, link_counted;
7536 char *buf = 0;
7537 int group, maxgroup;
7538
7539 /* Pass 4 */
7540
7541 clear_problem_context(&pctx);
7542
7543 if (!(ctx->options & E2F_OPT_PREEN))
7544 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7545
7546 group = 0;
7547 maxgroup = fs->group_desc_count;
7548 if (ctx->progress)
7549 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550 return;
7551
7552 for (i=1; i <= fs->super->s_inodes_count; i++) {
7553 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554 return;
7555 if ((i % fs->super->s_inodes_per_group) == 0) {
7556 group++;
7557 if (ctx->progress)
7558 if ((ctx->progress)(ctx, 4, group, maxgroup))
7559 return;
7560 }
7561 if (i == EXT2_BAD_INO ||
7562 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563 continue;
7564 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565 (ctx->inode_imagic_map &&
7566 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567 continue;
7568 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570 if (link_counted == 0) {
7571 if (!buf)
7572 buf = e2fsck_allocate_memory(ctx,
7573 fs->blocksize, "bad_inode buffer");
7574 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575 continue;
7576 if (disconnect_inode(ctx, i))
7577 continue;
7578 ext2fs_icount_fetch(ctx->inode_link_info, i,
7579 &link_count);
7580 ext2fs_icount_fetch(ctx->inode_count, i,
7581 &link_counted);
7582 }
7583 if (link_counted != link_count) {
7584 e2fsck_read_inode(ctx, i, &inode, "pass4");
7585 pctx.ino = i;
7586 pctx.inode = &inode;
7587 if (link_count != inode.i_links_count) {
7588 pctx.num = link_count;
7589 fix_problem(ctx,
7590 PR_4_INCONSISTENT_COUNT, &pctx);
7591 }
7592 pctx.num = link_counted;
7593 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594 inode.i_links_count = link_counted;
7595 e2fsck_write_inode(ctx, i, &inode, "pass4");
7596 }
7597 }
7598 }
7599 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602 ctx->inode_imagic_map = 0;
7603 ext2fs_free_mem(&buf);
7604}
7605
7606/*
7607 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7608 */
7609
7610#define NO_BLK ((blk_t) -1)
7611
7612static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613 struct problem_context *pctx)
7614{
7615 switch (problem) {
7616 case PR_5_BLOCK_UNUSED:
7617 if (pctx->blk == pctx->blk2)
7618 pctx->blk2 = 0;
7619 else
7620 problem = PR_5_BLOCK_RANGE_UNUSED;
7621 break;
7622 case PR_5_BLOCK_USED:
7623 if (pctx->blk == pctx->blk2)
7624 pctx->blk2 = 0;
7625 else
7626 problem = PR_5_BLOCK_RANGE_USED;
7627 break;
7628 case PR_5_INODE_UNUSED:
7629 if (pctx->ino == pctx->ino2)
7630 pctx->ino2 = 0;
7631 else
7632 problem = PR_5_INODE_RANGE_UNUSED;
7633 break;
7634 case PR_5_INODE_USED:
7635 if (pctx->ino == pctx->ino2)
7636 pctx->ino2 = 0;
7637 else
7638 problem = PR_5_INODE_RANGE_USED;
7639 break;
7640 }
7641 fix_problem(ctx, problem, pctx);
7642 pctx->blk = pctx->blk2 = NO_BLK;
7643 pctx->ino = pctx->ino2 = 0;
7644}
7645
7646static void check_block_bitmaps(e2fsck_t ctx)
7647{
7648 ext2_filsys fs = ctx->fs;
7649 blk_t i;
7650 int *free_array;
7651 int group = 0;
7652 unsigned int blocks = 0;
7653 unsigned int free_blocks = 0;
7654 int group_free = 0;
7655 int actual, bitmap;
7656 struct problem_context pctx;
7657 int problem, save_problem, fixit, had_problem;
7658 errcode_t retval;
7659
7660 clear_problem_context(&pctx);
7661 free_array = (int *) e2fsck_allocate_memory(ctx,
7662 fs->group_desc_count * sizeof(int), "free block count array");
7663
7664 if ((fs->super->s_first_data_block <
7665 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666 (fs->super->s_blocks_count-1 >
7667 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668 pctx.num = 1;
7669 pctx.blk = fs->super->s_first_data_block;
7670 pctx.blk2 = fs->super->s_blocks_count -1;
7671 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7674
7675 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676 return;
7677 }
7678
7679 if ((fs->super->s_first_data_block <
7680 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681 (fs->super->s_blocks_count-1 >
7682 ext2fs_get_block_bitmap_end(fs->block_map))) {
7683 pctx.num = 2;
7684 pctx.blk = fs->super->s_first_data_block;
7685 pctx.blk2 = fs->super->s_blocks_count -1;
7686 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7689
7690 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691 return;
7692 }
7693
7694redo_counts:
7695 had_problem = 0;
7696 save_problem = 0;
7697 pctx.blk = pctx.blk2 = NO_BLK;
7698 for (i = fs->super->s_first_data_block;
7699 i < fs->super->s_blocks_count;
7700 i++) {
7701 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7703
7704 if (actual == bitmap)
7705 goto do_counts;
7706
7707 if (!actual && bitmap) {
7708 /*
7709 * Block not used, but marked in use in the bitmap.
7710 */
7711 problem = PR_5_BLOCK_UNUSED;
7712 } else {
7713 /*
7714 * Block used, but not marked in use in the bitmap.
7715 */
7716 problem = PR_5_BLOCK_USED;
7717 }
7718 if (pctx.blk == NO_BLK) {
7719 pctx.blk = pctx.blk2 = i;
7720 save_problem = problem;
7721 } else {
7722 if ((problem == save_problem) &&
7723 (pctx.blk2 == i-1))
7724 pctx.blk2++;
7725 else {
7726 print_bitmap_problem(ctx, save_problem, &pctx);
7727 pctx.blk = pctx.blk2 = i;
7728 save_problem = problem;
7729 }
7730 }
7731 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732 had_problem++;
7733
7734 do_counts:
7735 if (!bitmap) {
7736 group_free++;
7737 free_blocks++;
7738 }
7739 blocks ++;
7740 if ((blocks == fs->super->s_blocks_per_group) ||
7741 (i == fs->super->s_blocks_count-1)) {
7742 free_array[group] = group_free;
7743 group ++;
7744 blocks = 0;
7745 group_free = 0;
7746 if (ctx->progress)
7747 if ((ctx->progress)(ctx, 5, group,
7748 fs->group_desc_count*2))
7749 return;
7750 }
7751 }
7752 if (pctx.blk != NO_BLK)
7753 print_bitmap_problem(ctx, save_problem, &pctx);
7754 if (had_problem)
7755 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756 else
7757 fixit = -1;
7758 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7759
7760 if (fixit == 1) {
7761 ext2fs_free_block_bitmap(fs->block_map);
7762 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763 &fs->block_map);
7764 if (retval) {
7765 clear_problem_context(&pctx);
7766 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767 ctx->flags |= E2F_FLAG_ABORT;
7768 return;
7769 }
7770 ext2fs_set_bitmap_padding(fs->block_map);
7771 ext2fs_mark_bb_dirty(fs);
7772
7773 /* Redo the counts */
7774 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776 goto redo_counts;
7777 } else if (fixit == 0)
7778 ext2fs_unmark_valid(fs);
7779
7780 for (i = 0; i < fs->group_desc_count; i++) {
7781 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782 pctx.group = i;
7783 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784 pctx.blk2 = free_array[i];
7785
7786 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787 &pctx)) {
7788 fs->group_desc[i].bg_free_blocks_count =
7789 free_array[i];
7790 ext2fs_mark_super_dirty(fs);
7791 } else
7792 ext2fs_unmark_valid(fs);
7793 }
7794 }
7795 if (free_blocks != fs->super->s_free_blocks_count) {
7796 pctx.group = 0;
7797 pctx.blk = fs->super->s_free_blocks_count;
7798 pctx.blk2 = free_blocks;
7799
7800 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801 fs->super->s_free_blocks_count = free_blocks;
7802 ext2fs_mark_super_dirty(fs);
7803 } else
7804 ext2fs_unmark_valid(fs);
7805 }
7806 ext2fs_free_mem(&free_array);
7807}
7808
7809static void check_inode_bitmaps(e2fsck_t ctx)
7810{
7811 ext2_filsys fs = ctx->fs;
7812 ext2_ino_t i;
7813 unsigned int free_inodes = 0;
7814 int group_free = 0;
7815 int dirs_count = 0;
7816 int group = 0;
7817 unsigned int inodes = 0;
7818 int *free_array;
7819 int *dir_array;
7820 int actual, bitmap;
7821 errcode_t retval;
7822 struct problem_context pctx;
7823 int problem, save_problem, fixit, had_problem;
7824
7825 clear_problem_context(&pctx);
7826 free_array = (int *) e2fsck_allocate_memory(ctx,
7827 fs->group_desc_count * sizeof(int), "free inode count array");
7828
7829 dir_array = (int *) e2fsck_allocate_memory(ctx,
7830 fs->group_desc_count * sizeof(int), "directory count array");
7831
7832 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833 (fs->super->s_inodes_count >
7834 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835 pctx.num = 3;
7836 pctx.blk = 1;
7837 pctx.blk2 = fs->super->s_inodes_count;
7838 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843 return;
7844 }
7845 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846 (fs->super->s_inodes_count >
7847 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848 pctx.num = 4;
7849 pctx.blk = 1;
7850 pctx.blk2 = fs->super->s_inodes_count;
7851 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7854
7855 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856 return;
7857 }
7858
7859redo_counts:
7860 had_problem = 0;
7861 save_problem = 0;
7862 pctx.ino = pctx.ino2 = 0;
7863 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7866
7867 if (actual == bitmap)
7868 goto do_counts;
7869
7870 if (!actual && bitmap) {
7871 /*
7872 * Inode wasn't used, but marked in bitmap
7873 */
7874 problem = PR_5_INODE_UNUSED;
7875 } else /* if (actual && !bitmap) */ {
7876 /*
7877 * Inode used, but not in bitmap
7878 */
7879 problem = PR_5_INODE_USED;
7880 }
7881 if (pctx.ino == 0) {
7882 pctx.ino = pctx.ino2 = i;
7883 save_problem = problem;
7884 } else {
7885 if ((problem == save_problem) &&
7886 (pctx.ino2 == i-1))
7887 pctx.ino2++;
7888 else {
7889 print_bitmap_problem(ctx, save_problem, &pctx);
7890 pctx.ino = pctx.ino2 = i;
7891 save_problem = problem;
7892 }
7893 }
7894 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895 had_problem++;
7896
7897do_counts:
7898 if (!bitmap) {
7899 group_free++;
7900 free_inodes++;
7901 } else {
7902 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903 dirs_count++;
7904 }
7905 inodes++;
7906 if ((inodes == fs->super->s_inodes_per_group) ||
7907 (i == fs->super->s_inodes_count)) {
7908 free_array[group] = group_free;
7909 dir_array[group] = dirs_count;
7910 group ++;
7911 inodes = 0;
7912 group_free = 0;
7913 dirs_count = 0;
7914 if (ctx->progress)
7915 if ((ctx->progress)(ctx, 5,
7916 group + fs->group_desc_count,
7917 fs->group_desc_count*2))
7918 return;
7919 }
7920 }
7921 if (pctx.ino)
7922 print_bitmap_problem(ctx, save_problem, &pctx);
7923
7924 if (had_problem)
7925 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926 else
7927 fixit = -1;
7928 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7929
7930 if (fixit == 1) {
7931 ext2fs_free_inode_bitmap(fs->inode_map);
7932 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933 &fs->inode_map);
7934 if (retval) {
7935 clear_problem_context(&pctx);
7936 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937 ctx->flags |= E2F_FLAG_ABORT;
7938 return;
7939 }
7940 ext2fs_set_bitmap_padding(fs->inode_map);
7941 ext2fs_mark_ib_dirty(fs);
7942
7943 /* redo counts */
7944 inodes = 0; free_inodes = 0; group_free = 0;
7945 dirs_count = 0; group = 0;
7946 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948 goto redo_counts;
7949 } else if (fixit == 0)
7950 ext2fs_unmark_valid(fs);
7951
7952 for (i = 0; i < fs->group_desc_count; i++) {
7953 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954 pctx.group = i;
7955 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956 pctx.ino2 = free_array[i];
7957 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958 &pctx)) {
7959 fs->group_desc[i].bg_free_inodes_count =
7960 free_array[i];
7961 ext2fs_mark_super_dirty(fs);
7962 } else
7963 ext2fs_unmark_valid(fs);
7964 }
7965 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966 pctx.group = i;
7967 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968 pctx.ino2 = dir_array[i];
7969
7970 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971 &pctx)) {
7972 fs->group_desc[i].bg_used_dirs_count =
7973 dir_array[i];
7974 ext2fs_mark_super_dirty(fs);
7975 } else
7976 ext2fs_unmark_valid(fs);
7977 }
7978 }
7979 if (free_inodes != fs->super->s_free_inodes_count) {
7980 pctx.group = -1;
7981 pctx.ino = fs->super->s_free_inodes_count;
7982 pctx.ino2 = free_inodes;
7983
7984 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985 fs->super->s_free_inodes_count = free_inodes;
7986 ext2fs_mark_super_dirty(fs);
7987 } else
7988 ext2fs_unmark_valid(fs);
7989 }
7990 ext2fs_free_mem(&free_array);
7991 ext2fs_free_mem(&dir_array);
7992}
7993
7994static void check_inode_end(e2fsck_t ctx)
7995{
7996 ext2_filsys fs = ctx->fs;
7997 ext2_ino_t end, save_inodes_count, i;
7998 struct problem_context pctx;
7999
8000 clear_problem_context(&pctx);
8001
8002 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004 &save_inodes_count);
8005 if (pctx.errcode) {
8006 pctx.num = 1;
8007 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009 return;
8010 }
8011 if (save_inodes_count == end)
8012 return;
8013
8014 for (i = save_inodes_count + 1; i <= end; i++) {
8015 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017 for (i = save_inodes_count + 1; i <= end; i++)
8018 ext2fs_mark_inode_bitmap(fs->inode_map,
8019 i);
8020 ext2fs_mark_ib_dirty(fs);
8021 } else
8022 ext2fs_unmark_valid(fs);
8023 break;
8024 }
8025 }
8026
8027 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028 save_inodes_count, 0);
8029 if (pctx.errcode) {
8030 pctx.num = 2;
8031 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033 return;
8034 }
8035}
8036
8037static void check_block_end(e2fsck_t ctx)
8038{
8039 ext2_filsys fs = ctx->fs;
8040 blk_t end, save_blocks_count, i;
8041 struct problem_context pctx;
8042
8043 clear_problem_context(&pctx);
8044
8045 end = fs->block_map->start +
8046 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048 &save_blocks_count);
8049 if (pctx.errcode) {
8050 pctx.num = 3;
8051 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053 return;
8054 }
8055 if (save_blocks_count == end)
8056 return;
8057
8058 for (i = save_blocks_count + 1; i <= end; i++) {
8059 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061 for (i = save_blocks_count + 1; i <= end; i++)
8062 ext2fs_mark_block_bitmap(fs->block_map,
8063 i);
8064 ext2fs_mark_bb_dirty(fs);
8065 } else
8066 ext2fs_unmark_valid(fs);
8067 break;
8068 }
8069 }
8070
8071 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072 save_blocks_count, 0);
8073 if (pctx.errcode) {
8074 pctx.num = 4;
8075 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077 return;
8078 }
8079}
8080
8081static void e2fsck_pass5(e2fsck_t ctx)
8082{
8083 struct problem_context pctx;
8084
8085 /* Pass 5 */
8086
8087 clear_problem_context(&pctx);
8088
8089 if (!(ctx->options & E2F_OPT_PREEN))
8090 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8091
8092 if (ctx->progress)
8093 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094 return;
8095
8096 e2fsck_read_bitmaps(ctx);
8097
8098 check_block_bitmaps(ctx);
8099 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100 return;
8101 check_inode_bitmaps(ctx);
8102 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103 return;
8104 check_inode_end(ctx);
8105 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106 return;
8107 check_block_end(ctx);
8108 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109 return;
8110
8111 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112 ctx->inode_used_map = 0;
8113 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114 ctx->inode_dir_map = 0;
8115 ext2fs_free_block_bitmap(ctx->block_found_map);
8116 ctx->block_found_map = 0;
8117}
8118
8119/*
8120 * problem.c --- report filesystem problems to the user
8121 */
8122
8123#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8124#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8125#define PR_NO_DEFAULT 0x000004 /* Default to no */
8126#define PR_MSG_ONLY 0x000008 /* Print message only */
8127
8128/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8129
8130#define PR_FATAL 0x001000 /* Fatal error */
8131#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8132 /* ask another */
8133#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8134#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8135#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8136#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8137#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8138
8139
8140#define PROMPT_NONE 0
8141#define PROMPT_FIX 1
8142#define PROMPT_CLEAR 2
8143#define PROMPT_RELOCATE 3
8144#define PROMPT_ALLOCATE 4
8145#define PROMPT_EXPAND 5
8146#define PROMPT_CONNECT 6
8147#define PROMPT_CREATE 7
8148#define PROMPT_SALVAGE 8
8149#define PROMPT_TRUNCATE 9
8150#define PROMPT_CLEAR_INODE 10
8151#define PROMPT_ABORT 11
8152#define PROMPT_SPLIT 12
8153#define PROMPT_CONTINUE 13
8154#define PROMPT_CLONE 14
8155#define PROMPT_DELETE 15
8156#define PROMPT_SUPPRESS 16
8157#define PROMPT_UNLINK 17
8158#define PROMPT_CLEAR_HTREE 18
8159#define PROMPT_RECREATE 19
8160#define PROMPT_NULL 20
8161
8162struct e2fsck_problem {
8163 problem_t e2p_code;
8164 const char * e2p_description;
8165 char prompt;
8166 int flags;
8167 problem_t second_code;
8168};
8169
8170struct latch_descr {
8171 int latch_code;
8172 problem_t question;
8173 problem_t end_message;
8174 int flags;
8175};
8176
8177/*
8178 * These are the prompts which are used to ask the user if they want
8179 * to fix a problem.
8180 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008181static const char *const prompt[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008182 N_("(no prompt)"), /* 0 */
8183 N_("Fix"), /* 1 */
8184 N_("Clear"), /* 2 */
8185 N_("Relocate"), /* 3 */
8186 N_("Allocate"), /* 4 */
8187 N_("Expand"), /* 5 */
8188 N_("Connect to /lost+found"), /* 6 */
8189 N_("Create"), /* 7 */
8190 N_("Salvage"), /* 8 */
8191 N_("Truncate"), /* 9 */
8192 N_("Clear inode"), /* 10 */
8193 N_("Abort"), /* 11 */
8194 N_("Split"), /* 12 */
8195 N_("Continue"), /* 13 */
8196 N_("Clone multiply-claimed blocks"), /* 14 */
8197 N_("Delete file"), /* 15 */
8198 N_("Suppress messages"),/* 16 */
8199 N_("Unlink"), /* 17 */
8200 N_("Clear HTree index"),/* 18 */
8201 N_("Recreate"), /* 19 */
8202 "", /* 20 */
8203};
8204
8205/*
8206 * These messages are printed when we are preen mode and we will be
8207 * automatically fixing the problem.
8208 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008209static const char *const preen_msg[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008210 N_("(NONE)"), /* 0 */
8211 N_("FIXED"), /* 1 */
8212 N_("CLEARED"), /* 2 */
8213 N_("RELOCATED"), /* 3 */
8214 N_("ALLOCATED"), /* 4 */
8215 N_("EXPANDED"), /* 5 */
8216 N_("RECONNECTED"), /* 6 */
8217 N_("CREATED"), /* 7 */
8218 N_("SALVAGED"), /* 8 */
8219 N_("TRUNCATED"), /* 9 */
8220 N_("INODE CLEARED"), /* 10 */
8221 N_("ABORTED"), /* 11 */
8222 N_("SPLIT"), /* 12 */
8223 N_("CONTINUING"), /* 13 */
8224 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225 N_("FILE DELETED"), /* 15 */
8226 N_("SUPPRESSED"), /* 16 */
8227 N_("UNLINKED"), /* 17 */
8228 N_("HTREE INDEX CLEARED"),/* 18 */
8229 N_("WILL RECREATE"), /* 19 */
8230 "", /* 20 */
8231};
8232
8233static const struct e2fsck_problem problem_table[] = {
8234
8235 /* Pre-Pass 1 errors */
8236
8237 /* Block bitmap not in group */
8238 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8239 PROMPT_RELOCATE, PR_LATCH_RELOC },
8240
8241 /* Inode bitmap not in group */
8242 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8243 PROMPT_RELOCATE, PR_LATCH_RELOC },
8244
8245 /* Inode table not in group */
8246 { PR_0_ITABLE_NOT_GROUP,
8247 N_("@i table for @g %g is not in @g. (@b %b)\n"
8248 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249 PROMPT_RELOCATE, PR_LATCH_RELOC },
8250
8251 /* Superblock corrupt */
8252 { PR_0_SB_CORRUPT,
8253 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254 "@f. If the @v is valid and it really contains an ext2\n"
8255 "@f (and not swap or ufs or something else), then the @S\n"
8256 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257 " e2fsck -b %S <@v>\n\n"),
8258 PROMPT_NONE, PR_FATAL },
8259
8260 /* Filesystem size is wrong */
8261 { PR_0_FS_SIZE_WRONG,
8262 N_("The @f size (according to the @S) is %b @bs\n"
8263 "The physical size of the @v is %c @bs\n"
8264 "Either the @S or the partition table is likely to be corrupt!\n"),
8265 PROMPT_ABORT, 0 },
8266
8267 /* Fragments not supported */
8268 { PR_0_NO_FRAGMENTS,
8269 N_("@S @b_size = %b, fragsize = %c.\n"
8270 "This version of e2fsck does not support fragment sizes different\n"
8271 "from the @b size.\n"),
8272 PROMPT_NONE, PR_FATAL },
8273
8274 /* Bad blocks_per_group */
8275 { PR_0_BLOCKS_PER_GROUP,
8276 N_("@S @bs_per_group = %b, should have been %c\n"),
8277 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8278
8279 /* Bad first_data_block */
8280 { PR_0_FIRST_DATA_BLOCK,
8281 N_("@S first_data_@b = %b, should have been %c\n"),
8282 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8283
8284 /* Adding UUID to filesystem */
8285 { PR_0_ADD_UUID,
8286 N_("@f did not have a UUID; generating one.\n\n"),
8287 PROMPT_NONE, 0 },
8288
8289 /* Relocate hint */
8290 { PR_0_RELOCATE_HINT,
8291 N_("Note: if several inode or block bitmap blocks or part\n"
8292 "of the inode table require relocation, you may wish to try\n"
8293 "running e2fsck with the '-b %S' option first. The problem\n"
8294 "may lie only with the primary block group descriptors, and\n"
8295 "the backup block group descriptors may be OK.\n\n"),
8296 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8297
8298 /* Miscellaneous superblock corruption */
8299 { PR_0_MISC_CORRUPT_SUPER,
8300 N_("Corruption found in @S. (%s = %N).\n"),
8301 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8302
8303 /* Error determing physical device size of filesystem */
8304 { PR_0_GETSIZE_ERROR,
8305 N_("Error determining size of the physical @v: %m\n"),
8306 PROMPT_NONE, PR_FATAL },
8307
8308 /* Inode count in superblock is incorrect */
8309 { PR_0_INODE_COUNT_WRONG,
8310 N_("@i count in @S is %i, @s %j.\n"),
8311 PROMPT_FIX, 0 },
8312
8313 { PR_0_HURD_CLEAR_FILETYPE,
8314 N_("The Hurd does not support the filetype feature.\n"),
8315 PROMPT_CLEAR, 0 },
8316
8317 /* Journal inode is invalid */
8318 { PR_0_JOURNAL_BAD_INODE,
8319 N_("@S has an @n ext3 @j (@i %i).\n"),
8320 PROMPT_CLEAR, PR_PREEN_OK },
8321
8322 /* The external journal has (unsupported) multiple filesystems */
8323 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324 N_("External @j has multiple @f users (unsupported).\n"),
8325 PROMPT_NONE, PR_FATAL },
8326
8327 /* Can't find external journal */
8328 { PR_0_CANT_FIND_JOURNAL,
8329 N_("Can't find external @j\n"),
8330 PROMPT_NONE, PR_FATAL },
8331
8332 /* External journal has bad superblock */
8333 { PR_0_EXT_JOURNAL_BAD_SUPER,
8334 N_("External @j has bad @S\n"),
8335 PROMPT_NONE, PR_FATAL },
8336
8337 /* Superblock has a bad journal UUID */
8338 { PR_0_JOURNAL_BAD_UUID,
8339 N_("External @j does not support this @f\n"),
8340 PROMPT_NONE, PR_FATAL },
8341
8342 /* Journal has an unknown superblock type */
8343 { PR_0_JOURNAL_UNSUPP_SUPER,
8344 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345 "It is likely that your copy of e2fsck is old and/or doesn't "
8346 "support this @j format.\n"
8347 "It is also possible the @j @S is corrupt.\n"),
8348 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8349
8350 /* Journal superblock is corrupt */
8351 { PR_0_JOURNAL_BAD_SUPER,
8352 N_("Ext3 @j @S is corrupt.\n"),
8353 PROMPT_FIX, PR_PREEN_OK },
8354
8355 /* Superblock flag should be cleared */
8356 { PR_0_JOURNAL_HAS_JOURNAL,
8357 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358 PROMPT_CLEAR, PR_PREEN_OK },
8359
8360 /* Superblock flag is incorrect */
8361 { PR_0_JOURNAL_RECOVER_SET,
8362 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363 PROMPT_CLEAR, PR_PREEN_OK },
8364
8365 /* Journal has data, but recovery flag is clear */
8366 { PR_0_JOURNAL_RECOVERY_CLEAR,
8367 N_("ext3 recovery flag is clear, but @j has data.\n"),
8368 PROMPT_NONE, 0 },
8369
8370 /* Ask if we should clear the journal */
8371 { PR_0_JOURNAL_RESET_JOURNAL,
8372 N_("Clear @j"),
8373 PROMPT_NULL, PR_PREEN_NOMSG },
8374
8375 /* Ask if we should run the journal anyway */
8376 { PR_0_JOURNAL_RUN,
8377 N_("Run @j anyway"),
8378 PROMPT_NULL, 0 },
8379
8380 /* Run the journal by default */
8381 { PR_0_JOURNAL_RUN_DEFAULT,
8382 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383 PROMPT_NONE, 0 },
8384
8385 /* Clearing orphan inode */
8386 { PR_0_ORPHAN_CLEAR_INODE,
8387 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388 PROMPT_NONE, 0 },
8389
8390 /* Illegal block found in orphaned inode */
8391 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393 PROMPT_NONE, 0 },
8394
8395 /* Already cleared block found in orphaned inode */
8396 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398 PROMPT_NONE, 0 },
8399
8400 /* Illegal orphan inode in superblock */
8401 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402 N_("@I @o @i %i in @S.\n"),
8403 PROMPT_NONE, 0 },
8404
8405 /* Illegal inode in orphaned inode list */
8406 { PR_0_ORPHAN_ILLEGAL_INODE,
8407 N_("@I @i %i in @o @i list.\n"),
8408 PROMPT_NONE, 0 },
8409
8410 /* Filesystem revision is 0, but feature flags are set */
8411 { PR_0_FS_REV_LEVEL,
8412 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8413 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8414
8415 /* Journal superblock has an unknown read-only feature flag set */
8416 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418 PROMPT_ABORT, 0 },
8419
8420 /* Journal superblock has an unknown incompatible feature flag set */
8421 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423 PROMPT_ABORT, 0 },
8424
8425 /* Journal has unsupported version number */
8426 { PR_0_JOURNAL_UNSUPP_VERSION,
8427 N_("@j version not supported by this e2fsck.\n"),
8428 PROMPT_ABORT, 0 },
8429
8430 /* Moving journal to hidden file */
8431 { PR_0_MOVE_JOURNAL,
8432 N_("Moving @j from /%s to hidden @i.\n\n"),
8433 PROMPT_NONE, 0 },
8434
8435 /* Error moving journal to hidden file */
8436 { PR_0_ERR_MOVE_JOURNAL,
8437 N_("Error moving @j: %m\n\n"),
8438 PROMPT_NONE, 0 },
8439
8440 /* Clearing V2 journal superblock */
8441 { PR_0_CLEAR_V2_JOURNAL,
8442 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443 "Clearing fields beyond the V1 @j @S...\n\n"),
8444 PROMPT_NONE, 0 },
8445
8446 /* Backup journal inode blocks */
8447 { PR_0_BACKUP_JNL,
8448 N_("Backing up @j @i @b information.\n\n"),
8449 PROMPT_NONE, 0 },
8450
8451 /* Reserved blocks w/o resize_inode */
8452 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454 "is %N; @s zero. "),
8455 PROMPT_FIX, 0 },
8456
8457 /* Resize_inode not enabled, but resize inode is non-zero */
8458 { PR_0_CLEAR_RESIZE_INODE,
8459 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8460 PROMPT_CLEAR, 0 },
8461
8462 /* Resize inode invalid */
8463 { PR_0_RESIZE_INODE_INVALID,
8464 N_("Resize @i not valid. "),
8465 PROMPT_RECREATE, 0 },
8466
8467 /* Pass 1 errors */
8468
8469 /* Pass 1: Checking inodes, blocks, and sizes */
8470 { PR_1_PASS_HEADER,
8471 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472 PROMPT_NONE, 0 },
8473
8474 /* Root directory is not an inode */
8475 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8476 PROMPT_CLEAR, 0 },
8477
8478 /* Root directory has dtime set */
8479 { PR_1_ROOT_DTIME,
8480 N_("@r has dtime set (probably due to old mke2fs). "),
8481 PROMPT_FIX, PR_PREEN_OK },
8482
8483 /* Reserved inode has bad mode */
8484 { PR_1_RESERVED_BAD_MODE,
8485 N_("Reserved @i %i (%Q) has @n mode. "),
8486 PROMPT_CLEAR, PR_PREEN_OK },
8487
8488 /* Deleted inode has zero dtime */
8489 { PR_1_ZERO_DTIME,
8490 N_("@D @i %i has zero dtime. "),
8491 PROMPT_FIX, PR_PREEN_OK },
8492
8493 /* Inode in use, but dtime set */
8494 { PR_1_SET_DTIME,
8495 N_("@i %i is in use, but has dtime set. "),
8496 PROMPT_FIX, PR_PREEN_OK },
8497
8498 /* Zero-length directory */
8499 { PR_1_ZERO_LENGTH_DIR,
8500 N_("@i %i is a @z @d. "),
8501 PROMPT_CLEAR, PR_PREEN_OK },
8502
8503 /* Block bitmap conflicts with some other fs block */
8504 { PR_1_BB_CONFLICT,
8505 N_("@g %g's @b @B at %b @C.\n"),
8506 PROMPT_RELOCATE, 0 },
8507
8508 /* Inode bitmap conflicts with some other fs block */
8509 { PR_1_IB_CONFLICT,
8510 N_("@g %g's @i @B at %b @C.\n"),
8511 PROMPT_RELOCATE, 0 },
8512
8513 /* Inode table conflicts with some other fs block */
8514 { PR_1_ITABLE_CONFLICT,
8515 N_("@g %g's @i table at %b @C.\n"),
8516 PROMPT_RELOCATE, 0 },
8517
8518 /* Block bitmap is on a bad block */
8519 { PR_1_BB_BAD_BLOCK,
8520 N_("@g %g's @b @B (%b) is bad. "),
8521 PROMPT_RELOCATE, 0 },
8522
8523 /* Inode bitmap is on a bad block */
8524 { PR_1_IB_BAD_BLOCK,
8525 N_("@g %g's @i @B (%b) is bad. "),
8526 PROMPT_RELOCATE, 0 },
8527
8528 /* Inode has incorrect i_size */
8529 { PR_1_BAD_I_SIZE,
8530 N_("@i %i, i_size is %Is, @s %N. "),
8531 PROMPT_FIX, PR_PREEN_OK },
8532
8533 /* Inode has incorrect i_blocks */
8534 { PR_1_BAD_I_BLOCKS,
8535 N_("@i %i, i_@bs is %Ib, @s %N. "),
8536 PROMPT_FIX, PR_PREEN_OK },
8537
8538 /* Illegal blocknumber in inode */
8539 { PR_1_ILLEGAL_BLOCK_NUM,
8540 N_("@I @b #%B (%b) in @i %i. "),
8541 PROMPT_CLEAR, PR_LATCH_BLOCK },
8542
8543 /* Block number overlaps fs metadata */
8544 { PR_1_BLOCK_OVERLAPS_METADATA,
8545 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8546 PROMPT_CLEAR, PR_LATCH_BLOCK },
8547
8548 /* Inode has illegal blocks (latch question) */
8549 { PR_1_INODE_BLOCK_LATCH,
8550 N_("@i %i has illegal @b(s). "),
8551 PROMPT_CLEAR, 0 },
8552
8553 /* Too many bad blocks in inode */
8554 { PR_1_TOO_MANY_BAD_BLOCKS,
8555 N_("Too many illegal @bs in @i %i.\n"),
8556 PROMPT_CLEAR_INODE, PR_NO_OK },
8557
8558 /* Illegal block number in bad block inode */
8559 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560 N_("@I @b #%B (%b) in bad @b @i. "),
8561 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8562
8563 /* Bad block inode has illegal blocks (latch question) */
8564 { PR_1_INODE_BBLOCK_LATCH,
8565 N_("Bad @b @i has illegal @b(s). "),
8566 PROMPT_CLEAR, 0 },
8567
8568 /* Duplicate or bad blocks in use! */
8569 { PR_1_DUP_BLOCKS_PREENSTOP,
8570 N_("Duplicate or bad @b in use!\n"),
8571 PROMPT_NONE, 0 },
8572
8573 /* Bad block used as bad block indirect block */
8574 { PR_1_BBINODE_BAD_METABLOCK,
8575 N_("Bad @b %b used as bad @b @i indirect @b. "),
8576 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8577
8578 /* Inconsistency can't be fixed prompt */
8579 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8581 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582 "in the @f.\n"),
8583 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8584
8585 /* Bad primary block */
8586 { PR_1_BAD_PRIMARY_BLOCK,
8587 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8589
8590 /* Bad primary block prompt */
8591 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592 N_("You can remove this @b from the bad @b list and hope\n"
8593 "that the @b is really OK. But there are no guarantees.\n\n"),
8594 PROMPT_CLEAR, PR_PREEN_NOMSG },
8595
8596 /* Bad primary superblock */
8597 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598 N_("The primary @S (%b) is on the bad @b list.\n"),
8599 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8600
8601 /* Bad primary block group descriptors */
8602 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603 N_("Block %b in the primary @g descriptors "
8604 "is on the bad @b list\n"),
8605 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8606
8607 /* Bad superblock in group */
8608 { PR_1_BAD_SUPERBLOCK,
8609 N_("Warning: Group %g's @S (%b) is bad.\n"),
8610 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8611
8612 /* Bad block group descriptors in group */
8613 { PR_1_BAD_GROUP_DESCRIPTORS,
8614 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615 "@b (%b).\n"),
8616 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8617
8618 /* Block claimed for no reason */
8619 { PR_1_PROGERR_CLAIMED_BLOCK,
8620 N_("Programming error? @b #%b claimed for no reason in "
8621 "process_bad_@b.\n"),
8622 PROMPT_NONE, PR_PREEN_OK },
8623
8624 /* Error allocating blocks for relocating metadata */
8625 { PR_1_RELOC_BLOCK_ALLOCATE,
8626 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627 PROMPT_NONE, PR_PREEN_OK },
8628
8629 /* Error allocating block buffer during relocation process */
8630 { PR_1_RELOC_MEMORY_ALLOCATE,
8631 N_("@A @b buffer for relocating %s\n"),
8632 PROMPT_NONE, PR_PREEN_OK },
8633
8634 /* Relocating metadata group information from X to Y */
8635 { PR_1_RELOC_FROM_TO,
8636 N_("Relocating @g %g's %s from %b to %c...\n"),
8637 PROMPT_NONE, PR_PREEN_OK },
8638
8639 /* Relocating metatdata group information to X */
8640 { PR_1_RELOC_TO,
8641 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642 PROMPT_NONE, PR_PREEN_OK },
8643
8644 /* Block read error during relocation process */
8645 { PR_1_RELOC_READ_ERR,
8646 N_("Warning: could not read @b %b of %s: %m\n"),
8647 PROMPT_NONE, PR_PREEN_OK },
8648
8649 /* Block write error during relocation process */
8650 { PR_1_RELOC_WRITE_ERR,
8651 N_("Warning: could not write @b %b for %s: %m\n"),
8652 PROMPT_NONE, PR_PREEN_OK },
8653
8654 /* Error allocating inode bitmap */
8655 { PR_1_ALLOCATE_IBITMAP_ERROR,
8656 N_("@A @i @B (%N): %m\n"),
8657 PROMPT_NONE, PR_FATAL },
8658
8659 /* Error allocating block bitmap */
8660 { PR_1_ALLOCATE_BBITMAP_ERROR,
8661 N_("@A @b @B (%N): %m\n"),
8662 PROMPT_NONE, PR_FATAL },
8663
8664 /* Error allocating icount structure */
8665 { PR_1_ALLOCATE_ICOUNT,
8666 N_("@A icount link information: %m\n"),
8667 PROMPT_NONE, PR_FATAL },
8668
8669 /* Error allocating dbcount */
8670 { PR_1_ALLOCATE_DBCOUNT,
8671 N_("@A @d @b array: %m\n"),
8672 PROMPT_NONE, PR_FATAL },
8673
8674 /* Error while scanning inodes */
8675 { PR_1_ISCAN_ERROR,
8676 N_("Error while scanning @is (%i): %m\n"),
8677 PROMPT_NONE, PR_FATAL },
8678
8679 /* Error while iterating over blocks */
8680 { PR_1_BLOCK_ITERATE,
8681 N_("Error while iterating over @bs in @i %i: %m\n"),
8682 PROMPT_NONE, PR_FATAL },
8683
8684 /* Error while storing inode count information */
8685 { PR_1_ICOUNT_STORE,
8686 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687 PROMPT_NONE, PR_FATAL },
8688
8689 /* Error while storing directory block information */
8690 { PR_1_ADD_DBLOCK,
8691 N_("Error storing @d @b information "
8692 "(@i=%i, @b=%b, num=%N): %m\n"),
8693 PROMPT_NONE, PR_FATAL },
8694
8695 /* Error while reading inode (for clearing) */
8696 { PR_1_READ_INODE,
8697 N_("Error reading @i %i: %m\n"),
8698 PROMPT_NONE, PR_FATAL },
8699
8700 /* Suppress messages prompt */
8701 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8702
8703 /* Imagic flag set on an inode when filesystem doesn't support it */
8704 { PR_1_SET_IMAGIC,
8705 N_("@i %i has imagic flag set. "),
8706 PROMPT_CLEAR, 0 },
8707
8708 /* Immutable flag set on a device or socket inode */
8709 { PR_1_SET_IMMUTABLE,
8710 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711 "or append-only flag set. "),
8712 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8713
8714 /* Compression flag set on an inode when filesystem doesn't support it */
8715 { PR_1_COMPR_SET,
8716 N_("@i %i has @cion flag set on @f without @cion support. "),
8717 PROMPT_CLEAR, 0 },
8718
8719 /* Non-zero size for device, fifo or socket inode */
8720 { PR_1_SET_NONZSIZE,
8721 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8722 PROMPT_FIX, PR_PREEN_OK },
8723
8724 /* Filesystem revision is 0, but feature flags are set */
8725 { PR_1_FS_REV_LEVEL,
8726 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8727 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8728
8729 /* Journal inode is not in use, but contains data */
8730 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731 N_("@j @i is not in use, but contains data. "),
8732 PROMPT_CLEAR, PR_PREEN_OK },
8733
8734 /* Journal has bad mode */
8735 { PR_1_JOURNAL_BAD_MODE,
8736 N_("@j is not regular file. "),
8737 PROMPT_FIX, PR_PREEN_OK },
8738
8739 /* Deal with inodes that were part of orphan linked list */
8740 { PR_1_LOW_DTIME,
8741 N_("@i %i was part of the @o @i list. "),
8742 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8743
8744 /* Deal with inodes that were part of corrupted orphan linked
8745 list (latch question) */
8746 { PR_1_ORPHAN_LIST_REFUGEES,
8747 N_("@is that were part of a corrupted orphan linked list found. "),
8748 PROMPT_FIX, 0 },
8749
8750 /* Error allocating refcount structure */
8751 { PR_1_ALLOCATE_REFCOUNT,
8752 N_("@A refcount structure (%N): %m\n"),
8753 PROMPT_NONE, PR_FATAL },
8754
8755 /* Error reading extended attribute block */
8756 { PR_1_READ_EA_BLOCK,
8757 N_("Error reading @a @b %b for @i %i. "),
8758 PROMPT_CLEAR, 0 },
8759
8760 /* Invalid extended attribute block */
8761 { PR_1_BAD_EA_BLOCK,
8762 N_("@i %i has a bad @a @b %b. "),
8763 PROMPT_CLEAR, 0 },
8764
8765 /* Error reading Extended Attribute block while fixing refcount */
8766 { PR_1_EXTATTR_READ_ABORT,
8767 N_("Error reading @a @b %b (%m). "),
8768 PROMPT_ABORT, 0 },
8769
8770 /* Extended attribute reference count incorrect */
8771 { PR_1_EXTATTR_REFCOUNT,
8772 N_("@a @b %b has reference count %B, @s %N. "),
8773 PROMPT_FIX, 0 },
8774
8775 /* Error writing Extended Attribute block while fixing refcount */
8776 { PR_1_EXTATTR_WRITE,
8777 N_("Error writing @a @b %b (%m). "),
8778 PROMPT_ABORT, 0 },
8779
8780 /* Multiple EA blocks not supported */
8781 { PR_1_EA_MULTI_BLOCK,
8782 N_("@a @b %b has h_@bs > 1. "),
8783 PROMPT_CLEAR, 0},
8784
8785 /* Error allocating EA region allocation structure */
8786 { PR_1_EA_ALLOC_REGION,
8787 N_("@A @a @b %b. "),
8788 PROMPT_ABORT, 0},
8789
8790 /* Error EA allocation collision */
8791 { PR_1_EA_ALLOC_COLLISION,
8792 N_("@a @b %b is corrupt (allocation collision). "),
8793 PROMPT_CLEAR, 0},
8794
8795 /* Bad extended attribute name */
8796 { PR_1_EA_BAD_NAME,
8797 N_("@a @b %b is corrupt (@n name). "),
8798 PROMPT_CLEAR, 0},
8799
8800 /* Bad extended attribute value */
8801 { PR_1_EA_BAD_VALUE,
8802 N_("@a @b %b is corrupt (@n value). "),
8803 PROMPT_CLEAR, 0},
8804
8805 /* Inode too big (latch question) */
8806 { PR_1_INODE_TOOBIG,
8807 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8808
8809 /* Directory too big */
8810 { PR_1_TOOBIG_DIR,
8811 N_("@b #%B (%b) causes @d to be too big. "),
8812 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8813
8814 /* Regular file too big */
8815 { PR_1_TOOBIG_REG,
8816 N_("@b #%B (%b) causes file to be too big. "),
8817 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8818
8819 /* Symlink too big */
8820 { PR_1_TOOBIG_SYMLINK,
8821 N_("@b #%B (%b) causes symlink to be too big. "),
8822 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8823
8824 /* INDEX_FL flag set on a non-HTREE filesystem */
8825 { PR_1_HTREE_SET,
8826 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8828
8829 /* INDEX_FL flag set on a non-directory */
8830 { PR_1_HTREE_NODIR,
8831 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8833
8834 /* Invalid root node in HTREE directory */
8835 { PR_1_HTREE_BADROOT,
8836 N_("@h %i has an @n root node.\n"),
8837 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8838
8839 /* Unsupported hash version in HTREE directory */
8840 { PR_1_HTREE_HASHV,
8841 N_("@h %i has an unsupported hash version (%N)\n"),
8842 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8843
8844 /* Incompatible flag in HTREE root node */
8845 { PR_1_HTREE_INCOMPAT,
8846 N_("@h %i uses an incompatible htree root node flag.\n"),
8847 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8848
8849 /* HTREE too deep */
8850 { PR_1_HTREE_DEPTH,
8851 N_("@h %i has a tree depth (%N) which is too big\n"),
8852 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853
8854 /* Bad block has indirect block that conflicts with filesystem block */
8855 { PR_1_BB_FS_BLOCK,
8856 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857 "@f metadata. "),
8858 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8859
8860 /* Resize inode failed */
8861 { PR_1_RESIZE_INODE_CREATE,
8862 N_("Resize @i (re)creation failed: %m."),
8863 PROMPT_ABORT, 0 },
8864
8865 /* invalid inode->i_extra_isize */
8866 { PR_1_EXTRA_ISIZE,
8867 N_("@i %i has a extra size (%IS) which is @n\n"),
8868 PROMPT_FIX, PR_PREEN_OK },
8869
8870 /* invalid ea entry->e_name_len */
8871 { PR_1_ATTR_NAME_LEN,
8872 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873 PROMPT_CLEAR, PR_PREEN_OK },
8874
8875 /* invalid ea entry->e_value_size */
8876 { PR_1_ATTR_VALUE_SIZE,
8877 N_("@a in @i %i has a value size (%N) which is @n\n"),
8878 PROMPT_CLEAR, PR_PREEN_OK },
8879
8880 /* invalid ea entry->e_value_offs */
8881 { PR_1_ATTR_VALUE_OFFSET,
8882 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883 PROMPT_CLEAR, PR_PREEN_OK },
8884
8885 /* invalid ea entry->e_value_block */
8886 { PR_1_ATTR_VALUE_BLOCK,
8887 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888 PROMPT_CLEAR, PR_PREEN_OK },
8889
8890 /* invalid ea entry->e_hash */
8891 { PR_1_ATTR_HASH,
8892 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893 PROMPT_CLEAR, PR_PREEN_OK },
8894
8895 /* Pass 1b errors */
8896
8897 /* Pass 1B: Rescan for duplicate/bad blocks */
8898 { PR_1B_PASS_HEADER,
8899 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900 "Pass 1B: Rescanning for @m @bs\n"),
8901 PROMPT_NONE, 0 },
8902
8903 /* Duplicate/bad block(s) header */
8904 { PR_1B_DUP_BLOCK_HEADER,
8905 N_("@m @b(s) in @i %i:"),
8906 PROMPT_NONE, 0 },
8907
8908 /* Duplicate/bad block(s) in inode */
8909 { PR_1B_DUP_BLOCK,
8910 " %b",
8911 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8912
8913 /* Duplicate/bad block(s) end */
8914 { PR_1B_DUP_BLOCK_END,
8915 "\n",
8916 PROMPT_NONE, PR_PREEN_NOHDR },
8917
8918 /* Error while scanning inodes */
8919 { PR_1B_ISCAN_ERROR,
8920 N_("Error while scanning inodes (%i): %m\n"),
8921 PROMPT_NONE, PR_FATAL },
8922
8923 /* Error allocating inode bitmap */
8924 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925 N_("@A @i @B (@i_dup_map): %m\n"),
8926 PROMPT_NONE, PR_FATAL },
8927
8928 /* Error while iterating over blocks */
8929 { PR_1B_BLOCK_ITERATE,
8930 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931 PROMPT_NONE, 0 },
8932
8933 /* Error adjusting EA refcount */
8934 { PR_1B_ADJ_EA_REFCOUNT,
8935 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936 PROMPT_NONE, 0 },
8937
8938
8939 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940 { PR_1C_PASS_HEADER,
8941 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942 PROMPT_NONE, 0 },
8943
8944
8945 /* Pass 1D: Reconciling multiply-claimed blocks */
8946 { PR_1D_PASS_HEADER,
8947 N_("Pass 1D: Reconciling @m @bs\n"),
8948 PROMPT_NONE, 0 },
8949
8950 /* File has duplicate blocks */
8951 { PR_1D_DUP_FILE,
8952 N_("File %Q (@i #%i, mod time %IM)\n"
8953 " has %B @m @b(s), shared with %N file(s):\n"),
8954 PROMPT_NONE, 0 },
8955
8956 /* List of files sharing duplicate blocks */
8957 { PR_1D_DUP_FILE_LIST,
8958 N_("\t%Q (@i #%i, mod time %IM)\n"),
8959 PROMPT_NONE, 0 },
8960
8961 /* File sharing blocks with filesystem metadata */
8962 { PR_1D_SHARE_METADATA,
8963 N_("\t<@f metadata>\n"),
8964 PROMPT_NONE, 0 },
8965
8966 /* Report of how many duplicate/bad inodes */
8967 { PR_1D_NUM_DUP_INODES,
8968 N_("(There are %N @is containing @m @bs.)\n\n"),
8969 PROMPT_NONE, 0 },
8970
8971 /* Duplicated blocks already reassigned or cloned. */
8972 { PR_1D_DUP_BLOCKS_DEALT,
8973 N_("@m @bs already reassigned or cloned.\n\n"),
8974 PROMPT_NONE, 0 },
8975
8976 /* Clone duplicate/bad blocks? */
8977 { PR_1D_CLONE_QUESTION,
8978 "", PROMPT_CLONE, PR_NO_OK },
8979
8980 /* Delete file? */
8981 { PR_1D_DELETE_QUESTION,
8982 "", PROMPT_DELETE, 0 },
8983
8984 /* Couldn't clone file (error) */
8985 { PR_1D_CLONE_ERROR,
8986 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8987
8988 /* Pass 2 errors */
8989
8990 /* Pass 2: Checking directory structure */
8991 { PR_2_PASS_HEADER,
8992 N_("Pass 2: Checking @d structure\n"),
8993 PROMPT_NONE, 0 },
8994
8995 /* Bad inode number for '.' */
8996 { PR_2_BAD_INODE_DOT,
8997 N_("@n @i number for '.' in @d @i %i.\n"),
8998 PROMPT_FIX, 0 },
8999
9000 /* Directory entry has bad inode number */
9001 { PR_2_BAD_INO,
9002 N_("@E has @n @i #: %Di.\n"),
9003 PROMPT_CLEAR, 0 },
9004
9005 /* Directory entry has deleted or unused inode */
9006 { PR_2_UNUSED_INODE,
9007 N_("@E has @D/unused @i %Di. "),
9008 PROMPT_CLEAR, PR_PREEN_OK },
9009
9010 /* Directry entry is link to '.' */
9011 { PR_2_LINK_DOT,
9012 N_("@E @L to '.' "),
9013 PROMPT_CLEAR, 0 },
9014
9015 /* Directory entry points to inode now located in a bad block */
9016 { PR_2_BB_INODE,
9017 N_("@E points to @i (%Di) located in a bad @b.\n"),
9018 PROMPT_CLEAR, 0 },
9019
9020 /* Directory entry contains a link to a directory */
9021 { PR_2_LINK_DIR,
9022 N_("@E @L to @d %P (%Di).\n"),
9023 PROMPT_CLEAR, 0 },
9024
9025 /* Directory entry contains a link to the root directry */
9026 { PR_2_LINK_ROOT,
9027 N_("@E @L to the @r.\n"),
9028 PROMPT_CLEAR, 0 },
9029
9030 /* Directory entry has illegal characters in its name */
9031 { PR_2_BAD_NAME,
9032 N_("@E has illegal characters in its name.\n"),
9033 PROMPT_FIX, 0 },
9034
9035 /* Missing '.' in directory inode */
9036 { PR_2_MISSING_DOT,
9037 N_("Missing '.' in @d @i %i.\n"),
9038 PROMPT_FIX, 0 },
9039
9040 /* Missing '..' in directory inode */
9041 { PR_2_MISSING_DOT_DOT,
9042 N_("Missing '..' in @d @i %i.\n"),
9043 PROMPT_FIX, 0 },
9044
9045 /* First entry in directory inode doesn't contain '.' */
9046 { PR_2_1ST_NOT_DOT,
9047 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048 PROMPT_FIX, 0 },
9049
9050 /* Second entry in directory inode doesn't contain '..' */
9051 { PR_2_2ND_NOT_DOT_DOT,
9052 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053 PROMPT_FIX, 0 },
9054
9055 /* i_faddr should be zero */
9056 { PR_2_FADDR_ZERO,
9057 N_("i_faddr @F %IF, @s zero.\n"),
9058 PROMPT_CLEAR, 0 },
9059
9060 /* i_file_acl should be zero */
9061 { PR_2_FILE_ACL_ZERO,
9062 N_("i_file_acl @F %If, @s zero.\n"),
9063 PROMPT_CLEAR, 0 },
9064
9065 /* i_dir_acl should be zero */
9066 { PR_2_DIR_ACL_ZERO,
9067 N_("i_dir_acl @F %Id, @s zero.\n"),
9068 PROMPT_CLEAR, 0 },
9069
9070 /* i_frag should be zero */
9071 { PR_2_FRAG_ZERO,
9072 N_("i_frag @F %N, @s zero.\n"),
9073 PROMPT_CLEAR, 0 },
9074
9075 /* i_fsize should be zero */
9076 { PR_2_FSIZE_ZERO,
9077 N_("i_fsize @F %N, @s zero.\n"),
9078 PROMPT_CLEAR, 0 },
9079
9080 /* inode has bad mode */
9081 { PR_2_BAD_MODE,
9082 N_("@i %i (%Q) has @n mode (%Im).\n"),
9083 PROMPT_CLEAR, 0 },
9084
9085 /* directory corrupted */
9086 { PR_2_DIR_CORRUPTED,
9087 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088 PROMPT_SALVAGE, 0 },
9089
9090 /* filename too long */
9091 { PR_2_FILENAME_LONG,
9092 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093 PROMPT_TRUNCATE, 0 },
9094
9095 /* Directory inode has a missing block (hole) */
9096 { PR_2_DIRECTORY_HOLE,
9097 N_("@d @i %i has an unallocated @b #%B. "),
9098 PROMPT_ALLOCATE, 0 },
9099
9100 /* '.' is not NULL terminated */
9101 { PR_2_DOT_NULL_TERM,
9102 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103 PROMPT_FIX, 0 },
9104
9105 /* '..' is not NULL terminated */
9106 { PR_2_DOT_DOT_NULL_TERM,
9107 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108 PROMPT_FIX, 0 },
9109
9110 /* Illegal character device inode */
9111 { PR_2_BAD_CHAR_DEV,
9112 N_("@i %i (%Q) is an @I character @v.\n"),
9113 PROMPT_CLEAR, 0 },
9114
9115 /* Illegal block device inode */
9116 { PR_2_BAD_BLOCK_DEV,
9117 N_("@i %i (%Q) is an @I @b @v.\n"),
9118 PROMPT_CLEAR, 0 },
9119
9120 /* Duplicate '.' entry */
9121 { PR_2_DUP_DOT,
9122 N_("@E is duplicate '.' @e.\n"),
9123 PROMPT_FIX, 0 },
9124
9125 /* Duplicate '..' entry */
9126 { PR_2_DUP_DOT_DOT,
9127 N_("@E is duplicate '..' @e.\n"),
9128 PROMPT_FIX, 0 },
9129
9130 /* Internal error: couldn't find dir_info */
9131 { PR_2_NO_DIRINFO,
9132 N_("Internal error: cannot find dir_info for %i.\n"),
9133 PROMPT_NONE, PR_FATAL },
9134
9135 /* Final rec_len is wrong */
9136 { PR_2_FINAL_RECLEN,
9137 N_("@E has rec_len of %Dr, @s %N.\n"),
9138 PROMPT_FIX, 0 },
9139
9140 /* Error allocating icount structure */
9141 { PR_2_ALLOCATE_ICOUNT,
9142 N_("@A icount structure: %m\n"),
9143 PROMPT_NONE, PR_FATAL },
9144
9145 /* Error iterating over directory blocks */
9146 { PR_2_DBLIST_ITERATE,
9147 N_("Error iterating over @d @bs: %m\n"),
9148 PROMPT_NONE, PR_FATAL },
9149
9150 /* Error reading directory block */
9151 { PR_2_READ_DIRBLOCK,
9152 N_("Error reading @d @b %b (@i %i): %m\n"),
9153 PROMPT_CONTINUE, 0 },
9154
9155 /* Error writing directory block */
9156 { PR_2_WRITE_DIRBLOCK,
9157 N_("Error writing @d @b %b (@i %i): %m\n"),
9158 PROMPT_CONTINUE, 0 },
9159
9160 /* Error allocating new directory block */
9161 { PR_2_ALLOC_DIRBOCK,
9162 N_("@A new @d @b for @i %i (%s): %m\n"),
9163 PROMPT_NONE, 0 },
9164
9165 /* Error deallocating inode */
9166 { PR_2_DEALLOC_INODE,
9167 N_("Error deallocating @i %i: %m\n"),
9168 PROMPT_NONE, PR_FATAL },
9169
9170 /* Directory entry for '.' is big. Split? */
9171 { PR_2_SPLIT_DOT,
9172 N_("@d @e for '.' is big. "),
9173 PROMPT_SPLIT, PR_NO_OK },
9174
9175 /* Illegal FIFO inode */
9176 { PR_2_BAD_FIFO,
9177 N_("@i %i (%Q) is an @I FIFO.\n"),
9178 PROMPT_CLEAR, 0 },
9179
9180 /* Illegal socket inode */
9181 { PR_2_BAD_SOCKET,
9182 N_("@i %i (%Q) is an @I socket.\n"),
9183 PROMPT_CLEAR, 0 },
9184
9185 /* Directory filetype not set */
9186 { PR_2_SET_FILETYPE,
9187 N_("Setting filetype for @E to %N.\n"),
9188 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9189
9190 /* Directory filetype incorrect */
9191 { PR_2_BAD_FILETYPE,
9192 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193 PROMPT_FIX, 0 },
9194
9195 /* Directory filetype set on filesystem */
9196 { PR_2_CLEAR_FILETYPE,
9197 N_("@E has filetype set.\n"),
9198 PROMPT_CLEAR, PR_PREEN_OK },
9199
9200 /* Directory filename is null */
9201 { PR_2_NULL_NAME,
9202 N_("@E has a @z name.\n"),
9203 PROMPT_CLEAR, 0 },
9204
9205 /* Invalid symlink */
9206 { PR_2_INVALID_SYMLINK,
9207 N_("Symlink %Q (@i #%i) is @n.\n"),
9208 PROMPT_CLEAR, 0 },
9209
9210 /* i_file_acl (extended attribute block) is bad */
9211 { PR_2_FILE_ACL_BAD,
9212 N_("@a @b @F @n (%If).\n"),
9213 PROMPT_CLEAR, 0 },
9214
9215 /* Filesystem contains large files, but has no such flag in sb */
9216 { PR_2_FEATURE_LARGE_FILES,
9217 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218 PROMPT_FIX, 0 },
9219
9220 /* Node in HTREE directory not referenced */
9221 { PR_2_HTREE_NOTREF,
9222 N_("@p @h %d: node (%B) not referenced\n"),
9223 PROMPT_NONE, 0 },
9224
9225 /* Node in HTREE directory referenced twice */
9226 { PR_2_HTREE_DUPREF,
9227 N_("@p @h %d: node (%B) referenced twice\n"),
9228 PROMPT_NONE, 0 },
9229
9230 /* Node in HTREE directory has bad min hash */
9231 { PR_2_HTREE_MIN_HASH,
9232 N_("@p @h %d: node (%B) has bad min hash\n"),
9233 PROMPT_NONE, 0 },
9234
9235 /* Node in HTREE directory has bad max hash */
9236 { PR_2_HTREE_MAX_HASH,
9237 N_("@p @h %d: node (%B) has bad max hash\n"),
9238 PROMPT_NONE, 0 },
9239
9240 /* Clear invalid HTREE directory */
9241 { PR_2_HTREE_CLEAR,
9242 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9243
9244 /* Bad block in htree interior node */
9245 { PR_2_HTREE_BADBLK,
9246 N_("@p @h %d (%q): bad @b number %b.\n"),
9247 PROMPT_CLEAR_HTREE, 0 },
9248
9249 /* Error adjusting EA refcount */
9250 { PR_2_ADJ_EA_REFCOUNT,
9251 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252 PROMPT_NONE, PR_FATAL },
9253
9254 /* Invalid HTREE root node */
9255 { PR_2_HTREE_BAD_ROOT,
9256 N_("@p @h %d: root node is @n\n"),
9257 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9258
9259 /* Invalid HTREE limit */
9260 { PR_2_HTREE_BAD_LIMIT,
9261 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9263
9264 /* Invalid HTREE count */
9265 { PR_2_HTREE_BAD_COUNT,
9266 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9268
9269 /* HTREE interior node has out-of-order hashes in table */
9270 { PR_2_HTREE_HASH_ORDER,
9271 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9273
9274 /* Node in HTREE directory has invalid depth */
9275 { PR_2_HTREE_BAD_DEPTH,
9276 N_("@p @h %d: node (%B) has @n depth\n"),
9277 PROMPT_NONE, 0 },
9278
9279 /* Duplicate directory entry found */
9280 { PR_2_DUPLICATE_DIRENT,
9281 N_("Duplicate @E found. "),
9282 PROMPT_CLEAR, 0 },
9283
9284 /* Non-unique filename found */
9285 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286 N_("@E has a non-unique filename.\nRename to %s"),
9287 PROMPT_NULL, 0 },
9288
9289 /* Duplicate directory entry found */
9290 { PR_2_REPORT_DUP_DIRENT,
9291 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292 PROMPT_NONE, 0 },
9293
9294 /* Pass 3 errors */
9295
9296 /* Pass 3: Checking directory connectivity */
9297 { PR_3_PASS_HEADER,
9298 N_("Pass 3: Checking @d connectivity\n"),
9299 PROMPT_NONE, 0 },
9300
9301 /* Root inode not allocated */
9302 { PR_3_NO_ROOT_INODE,
9303 N_("@r not allocated. "),
9304 PROMPT_ALLOCATE, 0 },
9305
9306 /* No room in lost+found */
9307 { PR_3_EXPAND_LF_DIR,
9308 N_("No room in @l @d. "),
9309 PROMPT_EXPAND, 0 },
9310
9311 /* Unconnected directory inode */
9312 { PR_3_UNCONNECTED_DIR,
9313 N_("Unconnected @d @i %i (%p)\n"),
9314 PROMPT_CONNECT, 0 },
9315
9316 /* /lost+found not found */
9317 { PR_3_NO_LF_DIR,
9318 N_("/@l not found. "),
9319 PROMPT_CREATE, PR_PREEN_OK },
9320
9321 /* .. entry is incorrect */
9322 { PR_3_BAD_DOT_DOT,
9323 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324 PROMPT_FIX, 0 },
9325
9326 /* Bad or non-existent /lost+found. Cannot reconnect */
9327 { PR_3_NO_LPF,
9328 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9329 PROMPT_NONE, 0 },
9330
9331 /* Could not expand /lost+found */
9332 { PR_3_CANT_EXPAND_LPF,
9333 N_("Could not expand /@l: %m\n"),
9334 PROMPT_NONE, 0 },
9335
9336 /* Could not reconnect inode */
9337 { PR_3_CANT_RECONNECT,
9338 N_("Could not reconnect %i: %m\n"),
9339 PROMPT_NONE, 0 },
9340
9341 /* Error while trying to find /lost+found */
9342 { PR_3_ERR_FIND_LPF,
9343 N_("Error while trying to find /@l: %m\n"),
9344 PROMPT_NONE, 0 },
9345
9346 /* Error in ext2fs_new_block while creating /lost+found */
9347 { PR_3_ERR_LPF_NEW_BLOCK,
9348 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349 PROMPT_NONE, 0 },
9350
9351 /* Error in ext2fs_new_inode while creating /lost+found */
9352 { PR_3_ERR_LPF_NEW_INODE,
9353 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354 PROMPT_NONE, 0 },
9355
9356 /* Error in ext2fs_new_dir_block while creating /lost+found */
9357 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359 PROMPT_NONE, 0 },
9360
9361 /* Error while writing directory block for /lost+found */
9362 { PR_3_ERR_LPF_WRITE_BLOCK,
9363 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364 PROMPT_NONE, 0 },
9365
9366 /* Error while adjusting inode count */
9367 { PR_3_ADJUST_INODE,
9368 N_("Error while adjusting @i count on @i %i\n"),
9369 PROMPT_NONE, 0 },
9370
9371 /* Couldn't fix parent directory -- error */
9372 { PR_3_FIX_PARENT_ERR,
9373 N_("Couldn't fix parent of @i %i: %m\n\n"),
9374 PROMPT_NONE, 0 },
9375
9376 /* Couldn't fix parent directory -- couldn't find it */
9377 { PR_3_FIX_PARENT_NOFIND,
9378 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379 PROMPT_NONE, 0 },
9380
9381 /* Error allocating inode bitmap */
9382 { PR_3_ALLOCATE_IBITMAP_ERROR,
9383 N_("@A @i @B (%N): %m\n"),
9384 PROMPT_NONE, PR_FATAL },
9385
9386 /* Error creating root directory */
9387 { PR_3_CREATE_ROOT_ERROR,
9388 N_("Error creating root @d (%s): %m\n"),
9389 PROMPT_NONE, PR_FATAL },
9390
9391 /* Error creating lost and found directory */
9392 { PR_3_CREATE_LPF_ERROR,
9393 N_("Error creating /@l @d (%s): %m\n"),
9394 PROMPT_NONE, PR_FATAL },
9395
9396 /* Root inode is not directory; aborting */
9397 { PR_3_ROOT_NOT_DIR_ABORT,
9398 N_("@r is not a @d; aborting.\n"),
9399 PROMPT_NONE, PR_FATAL },
9400
9401 /* Cannot proceed without a root inode. */
9402 { PR_3_NO_ROOT_INODE_ABORT,
9403 N_("Cannot proceed without a @r.\n"),
9404 PROMPT_NONE, PR_FATAL },
9405
9406 /* Internal error: couldn't find dir_info */
9407 { PR_3_NO_DIRINFO,
9408 N_("Internal error: cannot find dir_info for %i.\n"),
9409 PROMPT_NONE, PR_FATAL },
9410
9411 /* Lost+found not a directory */
9412 { PR_3_LPF_NOTDIR,
9413 N_("/@l is not a @d (ino=%i)\n"),
9414 PROMPT_UNLINK, 0 },
9415
9416 /* Pass 3A Directory Optimization */
9417
9418 /* Pass 3A: Optimizing directories */
9419 { PR_3A_PASS_HEADER,
9420 N_("Pass 3A: Optimizing directories\n"),
9421 PROMPT_NONE, PR_PREEN_NOMSG },
9422
9423 /* Error iterating over directories */
9424 { PR_3A_OPTIMIZE_ITER,
9425 N_("Failed to create dirs_to_hash iterator: %m"),
9426 PROMPT_NONE, 0 },
9427
9428 /* Error rehash directory */
9429 { PR_3A_OPTIMIZE_DIR_ERR,
9430 N_("Failed to optimize directory %q (%d): %m"),
9431 PROMPT_NONE, 0 },
9432
9433 /* Rehashing dir header */
9434 { PR_3A_OPTIMIZE_DIR_HEADER,
9435 N_("Optimizing directories: "),
9436 PROMPT_NONE, PR_MSG_ONLY },
9437
9438 /* Rehashing directory %d */
9439 { PR_3A_OPTIMIZE_DIR,
9440 " %d",
9441 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9442
9443 /* Rehashing dir end */
9444 { PR_3A_OPTIMIZE_DIR_END,
9445 "\n",
9446 PROMPT_NONE, PR_PREEN_NOHDR },
9447
9448 /* Pass 4 errors */
9449
9450 /* Pass 4: Checking reference counts */
9451 { PR_4_PASS_HEADER,
9452 N_("Pass 4: Checking reference counts\n"),
9453 PROMPT_NONE, 0 },
9454
9455 /* Unattached zero-length inode */
9456 { PR_4_ZERO_LEN_INODE,
9457 N_("@u @z @i %i. "),
9458 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9459
9460 /* Unattached inode */
9461 { PR_4_UNATTACHED_INODE,
9462 N_("@u @i %i\n"),
9463 PROMPT_CONNECT, 0 },
9464
9465 /* Inode ref count wrong */
9466 { PR_4_BAD_REF_COUNT,
9467 N_("@i %i ref count is %Il, @s %N. "),
9468 PROMPT_FIX, PR_PREEN_OK },
9469
9470 { PR_4_INCONSISTENT_COUNT,
9471 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9474 "They @s the same!\n"),
9475 PROMPT_NONE, 0 },
9476
9477 /* Pass 5 errors */
9478
9479 /* Pass 5: Checking group summary information */
9480 { PR_5_PASS_HEADER,
9481 N_("Pass 5: Checking @g summary information\n"),
9482 PROMPT_NONE, 0 },
9483
9484 /* Padding at end of inode bitmap is not set. */
9485 { PR_5_INODE_BMAP_PADDING,
9486 N_("Padding at end of @i @B is not set. "),
9487 PROMPT_FIX, PR_PREEN_OK },
9488
9489 /* Padding at end of block bitmap is not set. */
9490 { PR_5_BLOCK_BMAP_PADDING,
9491 N_("Padding at end of @b @B is not set. "),
9492 PROMPT_FIX, PR_PREEN_OK },
9493
9494 /* Block bitmap differences header */
9495 { PR_5_BLOCK_BITMAP_HEADER,
9496 N_("@b @B differences: "),
9497 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9498
9499 /* Block not used, but marked in bitmap */
9500 { PR_5_BLOCK_UNUSED,
9501 " -%b",
9502 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9503
9504 /* Block used, but not marked used in bitmap */
9505 { PR_5_BLOCK_USED,
9506 " +%b",
9507 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9508
9509 /* Block bitmap differences end */
9510 { PR_5_BLOCK_BITMAP_END,
9511 "\n",
9512 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9513
9514 /* Inode bitmap differences header */
9515 { PR_5_INODE_BITMAP_HEADER,
9516 N_("@i @B differences: "),
9517 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9518
9519 /* Inode not used, but marked in bitmap */
9520 { PR_5_INODE_UNUSED,
9521 " -%i",
9522 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9523
9524 /* Inode used, but not marked used in bitmap */
9525 { PR_5_INODE_USED,
9526 " +%i",
9527 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528
9529 /* Inode bitmap differences end */
9530 { PR_5_INODE_BITMAP_END,
9531 "\n",
9532 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9533
9534 /* Free inodes count for group wrong */
9535 { PR_5_FREE_INODE_COUNT_GROUP,
9536 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538
9539 /* Directories count for group wrong */
9540 { PR_5_FREE_DIR_COUNT_GROUP,
9541 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9543
9544 /* Free inodes count wrong */
9545 { PR_5_FREE_INODE_COUNT,
9546 N_("Free @is count wrong (%i, counted=%j).\n"),
9547 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9548
9549 /* Free blocks count for group wrong */
9550 { PR_5_FREE_BLOCK_COUNT_GROUP,
9551 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9553
9554 /* Free blocks count wrong */
9555 { PR_5_FREE_BLOCK_COUNT,
9556 N_("Free @bs count wrong (%b, counted=%c).\n"),
9557 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558
9559 /* Programming error: bitmap endpoints don't match */
9560 { PR_5_BMAP_ENDPOINTS,
9561 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562 "match calculated @B endpoints (%i, %j)\n"),
9563 PROMPT_NONE, PR_FATAL },
9564
9565 /* Internal error: fudging end of bitmap */
9566 { PR_5_FUDGE_BITMAP_ERROR,
9567 N_("Internal error: fudging end of bitmap (%N)\n"),
9568 PROMPT_NONE, PR_FATAL },
9569
9570 /* Error copying in replacement inode bitmap */
9571 { PR_5_COPY_IBITMAP_ERROR,
9572 N_("Error copying in replacement @i @B: %m\n"),
9573 PROMPT_NONE, PR_FATAL },
9574
9575 /* Error copying in replacement block bitmap */
9576 { PR_5_COPY_BBITMAP_ERROR,
9577 N_("Error copying in replacement @b @B: %m\n"),
9578 PROMPT_NONE, PR_FATAL },
9579
9580 /* Block range not used, but marked in bitmap */
9581 { PR_5_BLOCK_RANGE_UNUSED,
9582 " -(%b--%c)",
9583 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9584
9585 /* Block range used, but not marked used in bitmap */
9586 { PR_5_BLOCK_RANGE_USED,
9587 " +(%b--%c)",
9588 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9589
9590 /* Inode range not used, but marked in bitmap */
9591 { PR_5_INODE_RANGE_UNUSED,
9592 " -(%i--%j)",
9593 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9594
9595 /* Inode range used, but not marked used in bitmap */
9596 { PR_5_INODE_RANGE_USED,
9597 " +(%i--%j)",
9598 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9599
9600 { 0 }
9601};
9602
9603/*
9604 * This is the latch flags register. It allows several problems to be
9605 * "latched" together. This means that the user has to answer but one
9606 * question for the set of problems, and all of the associated
9607 * problems will be either fixed or not fixed.
9608 */
9609static struct latch_descr pr_latch_info[] = {
9610 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619 { -1, 0, 0 },
9620};
9621
9622static const struct e2fsck_problem *find_problem(problem_t code)
9623{
9624 int i;
9625
9626 for (i=0; problem_table[i].e2p_code; i++) {
9627 if (problem_table[i].e2p_code == code)
9628 return &problem_table[i];
9629 }
9630 return 0;
9631}
9632
9633static struct latch_descr *find_latch(int code)
9634{
9635 int i;
9636
9637 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638 if (pr_latch_info[i].latch_code == code)
9639 return &pr_latch_info[i];
9640 }
9641 return 0;
9642}
9643
9644int end_problem_latch(e2fsck_t ctx, int mask)
9645{
9646 struct latch_descr *ldesc;
9647 struct problem_context pctx;
9648 int answer = -1;
9649
9650 ldesc = find_latch(mask);
9651 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652 clear_problem_context(&pctx);
9653 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9654 }
9655 ldesc->flags &= ~(PRL_VARIABLE);
9656 return answer;
9657}
9658
9659int set_latch_flags(int mask, int setflags, int clearflags)
9660{
9661 struct latch_descr *ldesc;
9662
9663 ldesc = find_latch(mask);
9664 if (!ldesc)
9665 return -1;
9666 ldesc->flags |= setflags;
9667 ldesc->flags &= ~clearflags;
9668 return 0;
9669}
9670
9671void clear_problem_context(struct problem_context *ctx)
9672{
9673 memset(ctx, 0, sizeof(struct problem_context));
9674 ctx->blkcount = -1;
9675 ctx->group = -1;
9676}
9677
9678int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9679{
9680 ext2_filsys fs = ctx->fs;
9681 const struct e2fsck_problem *ptr;
9682 struct latch_descr *ldesc = 0;
9683 const char *message;
9684 int def_yn, answer, ans;
9685 int print_answer = 0;
9686 int suppress = 0;
9687
9688 ptr = find_problem(code);
9689 if (!ptr) {
9690 printf(_("Unhandled error code (0x%x)!\n"), code);
9691 return 0;
9692 }
9693 def_yn = 1;
9694 if ((ptr->flags & PR_NO_DEFAULT) ||
9695 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696 (ctx->options & E2F_OPT_NO))
9697 def_yn= 0;
9698
9699 /*
9700 * Do special latch processing. This is where we ask the
9701 * latch question, if it exists
9702 */
9703 if (ptr->flags & PR_LATCH_MASK) {
9704 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706 ans = fix_problem(ctx, ldesc->question, pctx);
9707 if (ans == 1)
9708 ldesc->flags |= PRL_YES;
9709 if (ans == 0)
9710 ldesc->flags |= PRL_NO;
9711 ldesc->flags |= PRL_LATCHED;
9712 }
9713 if (ldesc->flags & PRL_SUPPRESS)
9714 suppress++;
9715 }
9716 if ((ptr->flags & PR_PREEN_NOMSG) &&
9717 (ctx->options & E2F_OPT_PREEN))
9718 suppress++;
9719 if ((ptr->flags & PR_NO_NOMSG) &&
9720 (ctx->options & E2F_OPT_NO))
9721 suppress++;
9722 if (!suppress) {
9723 message = ptr->e2p_description;
9724 if ((ctx->options & E2F_OPT_PREEN) &&
9725 !(ptr->flags & PR_PREEN_NOHDR)) {
9726 printf("%s: ", ctx->device_name ?
9727 ctx->device_name : ctx->filesystem_name);
9728 }
9729 if (*message)
9730 print_e2fsck_message(ctx, _(message), pctx, 1);
9731 }
9732 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733 preenhalt(ctx);
9734
9735 if (ptr->flags & PR_FATAL)
9736 bb_error_msg_and_die(0);
9737
9738 if (ptr->prompt == PROMPT_NONE) {
9739 if (ptr->flags & PR_NOCOLLATE)
9740 answer = -1;
9741 else
9742 answer = def_yn;
9743 } else {
9744 if (ctx->options & E2F_OPT_PREEN) {
9745 answer = def_yn;
9746 if (!(ptr->flags & PR_PREEN_NOMSG))
9747 print_answer = 1;
9748 } else if ((ptr->flags & PR_LATCH_MASK) &&
9749 (ldesc->flags & (PRL_YES | PRL_NO))) {
9750 if (!suppress)
9751 print_answer = 1;
9752 if (ldesc->flags & PRL_YES)
9753 answer = 1;
9754 else
9755 answer = 0;
9756 } else
9757 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758 if (!answer && !(ptr->flags & PR_NO_OK))
9759 ext2fs_unmark_valid(fs);
9760
9761 if (print_answer)
9762 printf("%s.\n", answer ?
9763 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9764
9765 }
9766
9767 if ((ptr->prompt == PROMPT_ABORT) && answer)
9768 bb_error_msg_and_die(0);
9769
9770 if (ptr->flags & PR_AFTER_CODE)
9771 answer = fix_problem(ctx, ptr->second_code, pctx);
9772
9773 return answer;
9774}
9775
9776/*
9777 * linux/fs/recovery.c
9778 *
9779 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9780 */
9781
9782/*
9783 * Maintain information about the progress of the recovery job, so that
9784 * the different passes can carry information between them.
9785 */
9786struct recovery_info
9787{
9788 tid_t start_transaction;
9789 tid_t end_transaction;
9790
9791 int nr_replays;
9792 int nr_revokes;
9793 int nr_revoke_hits;
9794};
9795
9796enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9797static int do_one_pass(journal_t *journal,
9798 struct recovery_info *info, enum passtype pass);
9799static int scan_revoke_records(journal_t *, struct buffer_head *,
9800 tid_t, struct recovery_info *);
9801
9802/*
9803 * Read a block from the journal
9804 */
9805
9806static int jread(struct buffer_head **bhp, journal_t *journal,
9807 unsigned int offset)
9808{
9809 int err;
9810 unsigned long blocknr;
9811 struct buffer_head *bh;
9812
9813 *bhp = NULL;
9814
9815 err = journal_bmap(journal, offset, &blocknr);
9816
9817 if (err) {
9818 printf("JBD: bad block at offset %u\n", offset);
9819 return err;
9820 }
9821
9822 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9823 if (!bh)
9824 return -ENOMEM;
9825
9826 if (!buffer_uptodate(bh)) {
9827 /* If this is a brand new buffer, start readahead.
9828 Otherwise, we assume we are already reading it. */
9829 if (!buffer_req(bh))
9830 do_readahead(journal, offset);
9831 wait_on_buffer(bh);
9832 }
9833
9834 if (!buffer_uptodate(bh)) {
9835 printf("JBD: Failed to read block at offset %u\n", offset);
9836 brelse(bh);
9837 return -EIO;
9838 }
9839
9840 *bhp = bh;
9841 return 0;
9842}
9843
9844
9845/*
9846 * Count the number of in-use tags in a journal descriptor block.
9847 */
9848
9849static int count_tags(struct buffer_head *bh, int size)
9850{
9851 char * tagp;
9852 journal_block_tag_t * tag;
9853 int nr = 0;
9854
9855 tagp = &bh->b_data[sizeof(journal_header_t)];
9856
9857 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9858 tag = (journal_block_tag_t *) tagp;
9859
9860 nr++;
9861 tagp += sizeof(journal_block_tag_t);
9862 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9863 tagp += 16;
9864
9865 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9866 break;
9867 }
9868
9869 return nr;
9870}
9871
9872
9873/* Make sure we wrap around the log correctly! */
9874#define wrap(journal, var) \
9875do { \
9876 if (var >= (journal)->j_last) \
9877 var -= ((journal)->j_last - (journal)->j_first); \
9878} while (0)
9879
9880/**
9881 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9882 * @journal: the journal to recover
9883 *
9884 * The primary function for recovering the log contents when mounting a
9885 * journaled device.
9886 *
9887 * Recovery is done in three passes. In the first pass, we look for the
9888 * end of the log. In the second, we assemble the list of revoke
9889 * blocks. In the third and final pass, we replay any un-revoked blocks
9890 * in the log.
9891 */
9892int journal_recover(journal_t *journal)
9893{
9894 int err;
9895 journal_superblock_t * sb;
9896
9897 struct recovery_info info;
9898
9899 memset(&info, 0, sizeof(info));
9900 sb = journal->j_superblock;
9901
9902 /*
9903 * The journal superblock's s_start field (the current log head)
9904 * is always zero if, and only if, the journal was cleanly
9905 * unmounted.
9906 */
9907
9908 if (!sb->s_start) {
9909 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9910 return 0;
9911 }
9912
9913 err = do_one_pass(journal, &info, PASS_SCAN);
9914 if (!err)
9915 err = do_one_pass(journal, &info, PASS_REVOKE);
9916 if (!err)
9917 err = do_one_pass(journal, &info, PASS_REPLAY);
9918
9919 /* Restart the log at the next transaction ID, thus invalidating
9920 * any existing commit records in the log. */
9921 journal->j_transaction_sequence = ++info.end_transaction;
9922
9923 journal_clear_revoke(journal);
9924 sync_blockdev(journal->j_fs_dev);
9925 return err;
9926}
9927
9928static int do_one_pass(journal_t *journal,
9929 struct recovery_info *info, enum passtype pass)
9930{
9931 unsigned int first_commit_ID, next_commit_ID;
9932 unsigned long next_log_block;
9933 int err, success = 0;
9934 journal_superblock_t * sb;
9935 journal_header_t * tmp;
9936 struct buffer_head * bh;
9937 unsigned int sequence;
9938 int blocktype;
9939
9940 /* Precompute the maximum metadata descriptors in a descriptor block */
9941 int MAX_BLOCKS_PER_DESC;
9942 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9943 / sizeof(journal_block_tag_t));
9944
9945 /*
9946 * First thing is to establish what we expect to find in the log
9947 * (in terms of transaction IDs), and where (in terms of log
9948 * block offsets): query the superblock.
9949 */
9950
9951 sb = journal->j_superblock;
9952 next_commit_ID = ntohl(sb->s_sequence);
9953 next_log_block = ntohl(sb->s_start);
9954
9955 first_commit_ID = next_commit_ID;
9956 if (pass == PASS_SCAN)
9957 info->start_transaction = first_commit_ID;
9958
9959 /*
9960 * Now we walk through the log, transaction by transaction,
9961 * making sure that each transaction has a commit block in the
9962 * expected place. Each complete transaction gets replayed back
9963 * into the main filesystem.
9964 */
9965
9966 while (1) {
9967 int flags;
9968 char * tagp;
9969 journal_block_tag_t * tag;
9970 struct buffer_head * obh;
9971 struct buffer_head * nbh;
9972
9973 /* If we already know where to stop the log traversal,
9974 * check right now that we haven't gone past the end of
9975 * the log. */
9976
9977 if (pass != PASS_SCAN)
9978 if (tid_geq(next_commit_ID, info->end_transaction))
9979 break;
9980
9981 /* Skip over each chunk of the transaction looking
9982 * either the next descriptor block or the final commit
9983 * record. */
9984
9985 err = jread(&bh, journal, next_log_block);
9986 if (err)
9987 goto failed;
9988
9989 next_log_block++;
9990 wrap(journal, next_log_block);
9991
9992 /* What kind of buffer is it?
9993 *
9994 * If it is a descriptor block, check that it has the
9995 * expected sequence number. Otherwise, we're all done
9996 * here. */
9997
9998 tmp = (journal_header_t *)bh->b_data;
9999
10000 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10001 brelse(bh);
10002 break;
10003 }
10004
10005 blocktype = ntohl(tmp->h_blocktype);
10006 sequence = ntohl(tmp->h_sequence);
10007
10008 if (sequence != next_commit_ID) {
10009 brelse(bh);
10010 break;
10011 }
10012
10013 /* OK, we have a valid descriptor block which matches
10014 * all of the sequence number checks. What are we going
10015 * to do with it? That depends on the pass... */
10016
Denis Vlasenkobb045062008-09-27 14:06:06 +000010017 switch (blocktype) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010018 case JFS_DESCRIPTOR_BLOCK:
10019 /* If it is a valid descriptor block, replay it
10020 * in pass REPLAY; otherwise, just skip over the
10021 * blocks it describes. */
10022 if (pass != PASS_REPLAY) {
10023 next_log_block +=
10024 count_tags(bh, journal->j_blocksize);
10025 wrap(journal, next_log_block);
10026 brelse(bh);
10027 continue;
10028 }
10029
10030 /* A descriptor block: we can now write all of
10031 * the data blocks. Yay, useful work is finally
10032 * getting done here! */
10033
10034 tagp = &bh->b_data[sizeof(journal_header_t)];
10035 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10036 <= journal->j_blocksize) {
10037 unsigned long io_block;
10038
10039 tag = (journal_block_tag_t *) tagp;
10040 flags = ntohl(tag->t_flags);
10041
10042 io_block = next_log_block++;
10043 wrap(journal, next_log_block);
10044 err = jread(&obh, journal, io_block);
10045 if (err) {
10046 /* Recover what we can, but
10047 * report failure at the end. */
10048 success = err;
10049 printf("JBD: IO error %d recovering "
10050 "block %ld in log\n",
10051 err, io_block);
10052 } else {
10053 unsigned long blocknr;
10054
10055 blocknr = ntohl(tag->t_blocknr);
10056
10057 /* If the block has been
10058 * revoked, then we're all done
10059 * here. */
10060 if (journal_test_revoke
10061 (journal, blocknr,
10062 next_commit_ID)) {
10063 brelse(obh);
10064 ++info->nr_revoke_hits;
10065 goto skip_write;
10066 }
10067
10068 /* Find a buffer for the new
10069 * data being restored */
10070 nbh = getblk(journal->j_fs_dev,
10071 blocknr,
10072 journal->j_blocksize);
10073 if (nbh == NULL) {
10074 printf("JBD: Out of memory "
10075 "during recovery.\n");
10076 err = -ENOMEM;
10077 brelse(bh);
10078 brelse(obh);
10079 goto failed;
10080 }
10081
10082 lock_buffer(nbh);
10083 memcpy(nbh->b_data, obh->b_data,
10084 journal->j_blocksize);
10085 if (flags & JFS_FLAG_ESCAPE) {
10086 *((unsigned int *)bh->b_data) =
10087 htonl(JFS_MAGIC_NUMBER);
10088 }
10089
10090 mark_buffer_uptodate(nbh, 1);
10091 mark_buffer_dirty(nbh);
10092 ++info->nr_replays;
10093 /* ll_rw_block(WRITE, 1, &nbh); */
10094 unlock_buffer(nbh);
10095 brelse(obh);
10096 brelse(nbh);
10097 }
10098
10099 skip_write:
10100 tagp += sizeof(journal_block_tag_t);
10101 if (!(flags & JFS_FLAG_SAME_UUID))
10102 tagp += 16;
10103
10104 if (flags & JFS_FLAG_LAST_TAG)
10105 break;
10106 }
10107
10108 brelse(bh);
10109 continue;
10110
10111 case JFS_COMMIT_BLOCK:
10112 /* Found an expected commit block: not much to
10113 * do other than move on to the next sequence
10114 * number. */
10115 brelse(bh);
10116 next_commit_ID++;
10117 continue;
10118
10119 case JFS_REVOKE_BLOCK:
10120 /* If we aren't in the REVOKE pass, then we can
10121 * just skip over this block. */
10122 if (pass != PASS_REVOKE) {
10123 brelse(bh);
10124 continue;
10125 }
10126
10127 err = scan_revoke_records(journal, bh,
10128 next_commit_ID, info);
10129 brelse(bh);
10130 if (err)
10131 goto failed;
10132 continue;
10133
10134 default:
10135 goto done;
10136 }
10137 }
10138
10139 done:
10140 /*
10141 * We broke out of the log scan loop: either we came to the
10142 * known end of the log or we found an unexpected block in the
10143 * log. If the latter happened, then we know that the "current"
10144 * transaction marks the end of the valid log.
10145 */
10146
10147 if (pass == PASS_SCAN)
10148 info->end_transaction = next_commit_ID;
10149 else {
10150 /* It's really bad news if different passes end up at
10151 * different places (but possible due to IO errors). */
10152 if (info->end_transaction != next_commit_ID) {
10153 printf("JBD: recovery pass %d ended at "
10154 "transaction %u, expected %u\n",
10155 pass, next_commit_ID, info->end_transaction);
10156 if (!success)
10157 success = -EIO;
10158 }
10159 }
10160
10161 return success;
10162
10163 failed:
10164 return err;
10165}
10166
10167
10168/* Scan a revoke record, marking all blocks mentioned as revoked. */
10169
10170static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10171 tid_t sequence, struct recovery_info *info)
10172{
10173 journal_revoke_header_t *header;
10174 int offset, max;
10175
10176 header = (journal_revoke_header_t *) bh->b_data;
10177 offset = sizeof(journal_revoke_header_t);
10178 max = ntohl(header->r_count);
10179
10180 while (offset < max) {
10181 unsigned long blocknr;
10182 int err;
10183
10184 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10185 offset += 4;
10186 err = journal_set_revoke(journal, blocknr, sequence);
10187 if (err)
10188 return err;
10189 ++info->nr_revokes;
10190 }
10191 return 0;
10192}
10193
10194
10195/*
10196 * rehash.c --- rebuild hash tree directories
10197 *
10198 * This algorithm is designed for simplicity of implementation and to
10199 * pack the directory as much as possible. It however requires twice
10200 * as much memory as the size of the directory. The maximum size
10201 * directory supported using a 4k blocksize is roughly a gigabyte, and
10202 * so there may very well be problems with machines that don't have
10203 * virtual memory, and obscenely large directories.
10204 *
10205 * An alternate algorithm which is much more disk intensive could be
10206 * written, and probably will need to be written in the future. The
10207 * design goals of such an algorithm are: (a) use (roughly) constant
10208 * amounts of memory, no matter how large the directory, (b) the
10209 * directory must be safe at all times, even if e2fsck is interrupted
10210 * in the middle, (c) we must use minimal amounts of extra disk
10211 * blocks. This pretty much requires an incremental approach, where
10212 * we are reading from one part of the directory, and inserting into
10213 * the front half. So the algorithm will have to keep track of a
10214 * moving block boundary between the new tree and the old tree, and
10215 * files will need to be moved from the old directory and inserted
10216 * into the new tree. If the new directory requires space which isn't
10217 * yet available, blocks from the beginning part of the old directory
10218 * may need to be moved to the end of the directory to make room for
10219 * the new tree:
10220 *
10221 * --------------------------------------------------------
10222 * | new tree | | old tree |
10223 * --------------------------------------------------------
10224 * ^ ptr ^ptr
10225 * tail new head old
10226 *
10227 * This is going to be a pain in the tuckus to implement, and will
10228 * require a lot more disk accesses. So I'm going to skip it for now;
10229 * it's only really going to be an issue for really, really big
10230 * filesystems (when we reach the level of tens of millions of files
10231 * in a single directory). It will probably be easier to simply
10232 * require that e2fsck use VM first.
10233 */
10234
10235struct fill_dir_struct {
10236 char *buf;
10237 struct ext2_inode *inode;
10238 int err;
10239 e2fsck_t ctx;
10240 struct hash_entry *harray;
10241 int max_array, num_array;
10242 int dir_size;
10243 int compress;
10244 ino_t parent;
10245};
10246
10247struct hash_entry {
10248 ext2_dirhash_t hash;
10249 ext2_dirhash_t minor_hash;
10250 struct ext2_dir_entry *dir;
10251};
10252
10253struct out_dir {
10254 int num;
10255 int max;
10256 char *buf;
10257 ext2_dirhash_t *hashes;
10258};
10259
10260static int fill_dir_block(ext2_filsys fs,
10261 blk_t *block_nr,
10262 e2_blkcnt_t blockcnt,
10263 blk_t ref_block FSCK_ATTR((unused)),
10264 int ref_offset FSCK_ATTR((unused)),
10265 void *priv_data)
10266{
10267 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10268 struct hash_entry *new_array, *ent;
10269 struct ext2_dir_entry *dirent;
10270 char *dir;
10271 unsigned int offset, dir_offset;
10272
10273 if (blockcnt < 0)
10274 return 0;
10275
10276 offset = blockcnt * fs->blocksize;
10277 if (offset + fs->blocksize > fd->inode->i_size) {
10278 fd->err = EXT2_ET_DIR_CORRUPTED;
10279 return BLOCK_ABORT;
10280 }
10281 dir = (fd->buf+offset);
10282 if (HOLE_BLKADDR(*block_nr)) {
10283 memset(dir, 0, fs->blocksize);
10284 dirent = (struct ext2_dir_entry *) dir;
10285 dirent->rec_len = fs->blocksize;
10286 } else {
10287 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10288 if (fd->err)
10289 return BLOCK_ABORT;
10290 }
10291 /* While the directory block is "hot", index it. */
10292 dir_offset = 0;
10293 while (dir_offset < fs->blocksize) {
10294 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10295 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10296 (dirent->rec_len < 8) ||
10297 ((dirent->rec_len % 4) != 0) ||
10298 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10299 fd->err = EXT2_ET_DIR_CORRUPTED;
10300 return BLOCK_ABORT;
10301 }
10302 dir_offset += dirent->rec_len;
10303 if (dirent->inode == 0)
10304 continue;
10305 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10306 (dirent->name[0] == '.'))
10307 continue;
10308 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10309 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10310 fd->parent = dirent->inode;
10311 continue;
10312 }
10313 if (fd->num_array >= fd->max_array) {
10314 new_array = realloc(fd->harray,
10315 sizeof(struct hash_entry) * (fd->max_array+500));
10316 if (!new_array) {
10317 fd->err = ENOMEM;
10318 return BLOCK_ABORT;
10319 }
10320 fd->harray = new_array;
10321 fd->max_array += 500;
10322 }
10323 ent = fd->harray + fd->num_array++;
10324 ent->dir = dirent;
10325 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10326 if (fd->compress)
10327 ent->hash = ent->minor_hash = 0;
10328 else {
10329 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10330 dirent->name,
10331 dirent->name_len & 0xFF,
10332 fs->super->s_hash_seed,
10333 &ent->hash, &ent->minor_hash);
10334 if (fd->err)
10335 return BLOCK_ABORT;
10336 }
10337 }
10338
10339 return 0;
10340}
10341
10342/* Used for sorting the hash entry */
10343static int name_cmp(const void *a, const void *b)
10344{
10345 const struct hash_entry *he_a = (const struct hash_entry *) a;
10346 const struct hash_entry *he_b = (const struct hash_entry *) b;
10347 int ret;
10348 int min_len;
10349
10350 min_len = he_a->dir->name_len;
10351 if (min_len > he_b->dir->name_len)
10352 min_len = he_b->dir->name_len;
10353
10354 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10355 if (ret == 0) {
10356 if (he_a->dir->name_len > he_b->dir->name_len)
10357 ret = 1;
10358 else if (he_a->dir->name_len < he_b->dir->name_len)
10359 ret = -1;
10360 else
10361 ret = he_b->dir->inode - he_a->dir->inode;
10362 }
10363 return ret;
10364}
10365
10366/* Used for sorting the hash entry */
10367static int hash_cmp(const void *a, const void *b)
10368{
10369 const struct hash_entry *he_a = (const struct hash_entry *) a;
10370 const struct hash_entry *he_b = (const struct hash_entry *) b;
10371 int ret;
10372
10373 if (he_a->hash > he_b->hash)
10374 ret = 1;
10375 else if (he_a->hash < he_b->hash)
10376 ret = -1;
10377 else {
10378 if (he_a->minor_hash > he_b->minor_hash)
10379 ret = 1;
10380 else if (he_a->minor_hash < he_b->minor_hash)
10381 ret = -1;
10382 else
10383 ret = name_cmp(a, b);
10384 }
10385 return ret;
10386}
10387
10388static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10389 int blocks)
10390{
10391 void *new_mem;
10392
10393 if (outdir->max) {
10394 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
10395 if (!new_mem)
10396 return ENOMEM;
10397 outdir->buf = new_mem;
10398 new_mem = realloc(outdir->hashes,
10399 blocks * sizeof(ext2_dirhash_t));
10400 if (!new_mem)
10401 return ENOMEM;
10402 outdir->hashes = new_mem;
10403 } else {
10404 outdir->buf = malloc(blocks * fs->blocksize);
10405 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
10406 outdir->num = 0;
10407 }
10408 outdir->max = blocks;
10409 return 0;
10410}
10411
10412static void free_out_dir(struct out_dir *outdir)
10413{
10414 free(outdir->buf);
10415 free(outdir->hashes);
10416 outdir->max = 0;
10417 outdir->num =0;
10418}
10419
10420static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10421 char ** ret)
10422{
10423 errcode_t retval;
10424
10425 if (outdir->num >= outdir->max) {
10426 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10427 if (retval)
10428 return retval;
10429 }
10430 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10431 memset(*ret, 0, fs->blocksize);
10432 return 0;
10433}
10434
10435/*
10436 * This function is used to make a unique filename. We do this by
10437 * appending ~0, and then incrementing the number. However, we cannot
10438 * expand the length of the filename beyond the padding available in
10439 * the directory entry.
10440 */
10441static void mutate_name(char *str, __u16 *len)
10442{
10443 int i;
10444 __u16 l = *len & 0xFF, h = *len & 0xff00;
10445
10446 /*
10447 * First check to see if it looks the name has been mutated
10448 * already
10449 */
10450 for (i = l-1; i > 0; i--) {
10451 if (!isdigit(str[i]))
10452 break;
10453 }
10454 if ((i == l-1) || (str[i] != '~')) {
10455 if (((l-1) & 3) < 2)
10456 l += 2;
10457 else
10458 l = (l+3) & ~3;
10459 str[l-2] = '~';
10460 str[l-1] = '0';
10461 *len = l | h;
10462 return;
10463 }
10464 for (i = l-1; i >= 0; i--) {
10465 if (isdigit(str[i])) {
10466 if (str[i] == '9')
10467 str[i] = '0';
10468 else {
10469 str[i]++;
10470 return;
10471 }
10472 continue;
10473 }
10474 if (i == 1) {
10475 if (str[0] == 'z')
10476 str[0] = 'A';
10477 else if (str[0] == 'Z') {
10478 str[0] = '~';
10479 str[1] = '0';
10480 } else
10481 str[0]++;
10482 } else if (i > 0) {
10483 str[i] = '1';
10484 str[i-1] = '~';
10485 } else {
10486 if (str[0] == '~')
10487 str[0] = 'a';
10488 else
10489 str[0]++;
10490 }
10491 break;
10492 }
10493}
10494
10495static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10496 ext2_ino_t ino,
10497 struct fill_dir_struct *fd)
10498{
10499 struct problem_context pctx;
10500 struct hash_entry *ent, *prev;
10501 int i, j;
10502 int fixed = 0;
10503 char new_name[256];
10504 __u16 new_len;
10505
10506 clear_problem_context(&pctx);
10507 pctx.ino = ino;
10508
10509 for (i=1; i < fd->num_array; i++) {
10510 ent = fd->harray + i;
10511 prev = ent - 1;
10512 if (!ent->dir->inode ||
10513 ((ent->dir->name_len & 0xFF) !=
10514 (prev->dir->name_len & 0xFF)) ||
10515 (strncmp(ent->dir->name, prev->dir->name,
10516 ent->dir->name_len & 0xFF)))
10517 continue;
10518 pctx.dirent = ent->dir;
10519 if ((ent->dir->inode == prev->dir->inode) &&
10520 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10521 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10522 ent->dir->inode = 0;
10523 fixed++;
10524 continue;
10525 }
10526 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10527 new_len = ent->dir->name_len;
10528 mutate_name(new_name, &new_len);
10529 for (j=0; j < fd->num_array; j++) {
10530 if ((i==j) ||
10531 ((ent->dir->name_len & 0xFF) !=
10532 (fd->harray[j].dir->name_len & 0xFF)) ||
10533 (strncmp(new_name, fd->harray[j].dir->name,
10534 new_len & 0xFF)))
10535 continue;
10536 mutate_name(new_name, &new_len);
10537
10538 j = -1;
10539 }
10540 new_name[new_len & 0xFF] = 0;
10541 pctx.str = new_name;
10542 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10543 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10544 ent->dir->name_len = new_len;
10545 ext2fs_dirhash(fs->super->s_def_hash_version,
10546 ent->dir->name,
10547 ent->dir->name_len & 0xFF,
10548 fs->super->s_hash_seed,
10549 &ent->hash, &ent->minor_hash);
10550 fixed++;
10551 }
10552 }
10553 return fixed;
10554}
10555
10556
10557static errcode_t copy_dir_entries(ext2_filsys fs,
10558 struct fill_dir_struct *fd,
10559 struct out_dir *outdir)
10560{
10561 errcode_t retval;
10562 char *block_start;
10563 struct hash_entry *ent;
10564 struct ext2_dir_entry *dirent;
10565 int i, rec_len, left;
10566 ext2_dirhash_t prev_hash;
10567 int offset;
10568
10569 outdir->max = 0;
10570 retval = alloc_size_dir(fs, outdir,
10571 (fd->dir_size / fs->blocksize) + 2);
10572 if (retval)
10573 return retval;
10574 outdir->num = fd->compress ? 0 : 1;
10575 offset = 0;
10576 outdir->hashes[0] = 0;
10577 prev_hash = 1;
10578 if ((retval = get_next_block(fs, outdir, &block_start)))
10579 return retval;
10580 dirent = (struct ext2_dir_entry *) block_start;
10581 left = fs->blocksize;
10582 for (i=0; i < fd->num_array; i++) {
10583 ent = fd->harray + i;
10584 if (ent->dir->inode == 0)
10585 continue;
10586 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10587 if (rec_len > left) {
10588 if (left)
10589 dirent->rec_len += left;
10590 if ((retval = get_next_block(fs, outdir,
10591 &block_start)))
10592 return retval;
10593 offset = 0;
10594 }
10595 left = fs->blocksize - offset;
10596 dirent = (struct ext2_dir_entry *) (block_start + offset);
10597 if (offset == 0) {
10598 if (ent->hash == prev_hash)
10599 outdir->hashes[outdir->num-1] = ent->hash | 1;
10600 else
10601 outdir->hashes[outdir->num-1] = ent->hash;
10602 }
10603 dirent->inode = ent->dir->inode;
10604 dirent->name_len = ent->dir->name_len;
10605 dirent->rec_len = rec_len;
10606 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10607 offset += rec_len;
10608 left -= rec_len;
10609 if (left < 12) {
10610 dirent->rec_len += left;
10611 offset += left;
10612 left = 0;
10613 }
10614 prev_hash = ent->hash;
10615 }
10616 if (left)
10617 dirent->rec_len += left;
10618
10619 return 0;
10620}
10621
10622
10623static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10624 ext2_ino_t ino, ext2_ino_t parent)
10625{
10626 struct ext2_dir_entry *dir;
10627 struct ext2_dx_root_info *root;
10628 struct ext2_dx_countlimit *limits;
10629 int filetype = 0;
10630
10631 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10632 filetype = EXT2_FT_DIR << 8;
10633
10634 memset(buf, 0, fs->blocksize);
10635 dir = (struct ext2_dir_entry *) buf;
10636 dir->inode = ino;
10637 dir->name[0] = '.';
10638 dir->name_len = 1 | filetype;
10639 dir->rec_len = 12;
10640 dir = (struct ext2_dir_entry *) (buf + 12);
10641 dir->inode = parent;
10642 dir->name[0] = '.';
10643 dir->name[1] = '.';
10644 dir->name_len = 2 | filetype;
10645 dir->rec_len = fs->blocksize - 12;
10646
10647 root = (struct ext2_dx_root_info *) (buf+24);
10648 root->reserved_zero = 0;
10649 root->hash_version = fs->super->s_def_hash_version;
10650 root->info_length = 8;
10651 root->indirect_levels = 0;
10652 root->unused_flags = 0;
10653
10654 limits = (struct ext2_dx_countlimit *) (buf+32);
10655 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10656 limits->count = 0;
10657
10658 return root;
10659}
10660
10661
10662static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10663{
10664 struct ext2_dir_entry *dir;
10665 struct ext2_dx_countlimit *limits;
10666
10667 memset(buf, 0, fs->blocksize);
10668 dir = (struct ext2_dir_entry *) buf;
10669 dir->inode = 0;
10670 dir->rec_len = fs->blocksize;
10671
10672 limits = (struct ext2_dx_countlimit *) (buf+8);
10673 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10674 limits->count = 0;
10675
10676 return (struct ext2_dx_entry *) limits;
10677}
10678
10679/*
10680 * This function takes the leaf nodes which have been written in
10681 * outdir, and populates the root node and any necessary interior nodes.
10682 */
10683static errcode_t calculate_tree(ext2_filsys fs,
10684 struct out_dir *outdir,
10685 ext2_ino_t ino,
10686 ext2_ino_t parent)
10687{
10688 struct ext2_dx_root_info *root_info;
10689 struct ext2_dx_entry *root, *dx_ent = 0;
10690 struct ext2_dx_countlimit *root_limit, *limit;
10691 errcode_t retval;
10692 char * block_start;
10693 int i, c1, c2, nblks;
10694 int limit_offset, root_offset;
10695
10696 root_info = set_root_node(fs, outdir->buf, ino, parent);
10697 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10698 root_info->info_length;
10699 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10700 c1 = root_limit->limit;
10701 nblks = outdir->num;
10702
10703 /* Write out the pointer blocks */
10704 if (nblks-1 <= c1) {
10705 /* Just write out the root block, and we're done */
10706 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10707 for (i=1; i < nblks; i++) {
10708 root->block = ext2fs_cpu_to_le32(i);
10709 if (i != 1)
10710 root->hash =
10711 ext2fs_cpu_to_le32(outdir->hashes[i]);
10712 root++;
10713 c1--;
10714 }
10715 } else {
10716 c2 = 0;
10717 limit = 0;
10718 root_info->indirect_levels = 1;
10719 for (i=1; i < nblks; i++) {
10720 if (c1 == 0)
10721 return ENOSPC;
10722 if (c2 == 0) {
10723 if (limit)
10724 limit->limit = limit->count =
10725 ext2fs_cpu_to_le16(limit->limit);
10726 root = (struct ext2_dx_entry *)
10727 (outdir->buf + root_offset);
10728 root->block = ext2fs_cpu_to_le32(outdir->num);
10729 if (i != 1)
10730 root->hash =
10731 ext2fs_cpu_to_le32(outdir->hashes[i]);
10732 if ((retval = get_next_block(fs, outdir,
10733 &block_start)))
10734 return retval;
10735 dx_ent = set_int_node(fs, block_start);
10736 limit = (struct ext2_dx_countlimit *) dx_ent;
10737 c2 = limit->limit;
10738 root_offset += sizeof(struct ext2_dx_entry);
10739 c1--;
10740 }
10741 dx_ent->block = ext2fs_cpu_to_le32(i);
10742 if (c2 != limit->limit)
10743 dx_ent->hash =
10744 ext2fs_cpu_to_le32(outdir->hashes[i]);
10745 dx_ent++;
10746 c2--;
10747 }
10748 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10749 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10750 }
10751 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10752 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10753 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10754
10755 return 0;
10756}
10757
10758struct write_dir_struct {
10759 struct out_dir *outdir;
10760 errcode_t err;
10761 e2fsck_t ctx;
10762 int cleared;
10763};
10764
10765/*
10766 * Helper function which writes out a directory block.
10767 */
10768static int write_dir_block(ext2_filsys fs,
10769 blk_t *block_nr,
10770 e2_blkcnt_t blockcnt,
10771 blk_t ref_block FSCK_ATTR((unused)),
10772 int ref_offset FSCK_ATTR((unused)),
10773 void *priv_data)
10774{
10775 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10776 blk_t blk;
10777 char *dir;
10778
10779 if (*block_nr == 0)
10780 return 0;
10781 if (blockcnt >= wd->outdir->num) {
10782 e2fsck_read_bitmaps(wd->ctx);
10783 blk = *block_nr;
10784 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10785 ext2fs_block_alloc_stats(fs, blk, -1);
10786 *block_nr = 0;
10787 wd->cleared++;
10788 return BLOCK_CHANGED;
10789 }
10790 if (blockcnt < 0)
10791 return 0;
10792
10793 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10794 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10795 if (wd->err)
10796 return BLOCK_ABORT;
10797 return 0;
10798}
10799
10800static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10801 struct out_dir *outdir,
10802 ext2_ino_t ino, int compress)
10803{
10804 struct write_dir_struct wd;
10805 errcode_t retval;
10806 struct ext2_inode inode;
10807
10808 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10809 if (retval)
10810 return retval;
10811
10812 wd.outdir = outdir;
10813 wd.err = 0;
10814 wd.ctx = ctx;
10815 wd.cleared = 0;
10816
10817 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10818 write_dir_block, &wd);
10819 if (retval)
10820 return retval;
10821 if (wd.err)
10822 return wd.err;
10823
10824 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10825 if (compress)
10826 inode.i_flags &= ~EXT2_INDEX_FL;
10827 else
10828 inode.i_flags |= EXT2_INDEX_FL;
10829 inode.i_size = outdir->num * fs->blocksize;
10830 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10831 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10832
10833 return 0;
10834}
10835
10836static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10837{
10838 ext2_filsys fs = ctx->fs;
10839 errcode_t retval;
10840 struct ext2_inode inode;
10841 char *dir_buf = 0;
10842 struct fill_dir_struct fd;
10843 struct out_dir outdir;
10844
10845 outdir.max = outdir.num = 0;
10846 outdir.buf = 0;
10847 outdir.hashes = 0;
10848 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10849
10850 retval = ENOMEM;
10851 fd.harray = 0;
10852 dir_buf = malloc(inode.i_size);
10853 if (!dir_buf)
10854 goto errout;
10855
10856 fd.max_array = inode.i_size / 32;
10857 fd.num_array = 0;
10858 fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
10859 if (!fd.harray)
10860 goto errout;
10861
10862 fd.ctx = ctx;
10863 fd.buf = dir_buf;
10864 fd.inode = &inode;
10865 fd.err = 0;
10866 fd.dir_size = 0;
10867 fd.compress = 0;
10868 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10869 (inode.i_size / fs->blocksize) < 2)
10870 fd.compress = 1;
10871 fd.parent = 0;
10872
10873 /* Read in the entire directory into memory */
10874 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10875 fill_dir_block, &fd);
10876 if (fd.err) {
10877 retval = fd.err;
10878 goto errout;
10879 }
10880
10881 /* Sort the list */
10882resort:
10883 if (fd.compress)
10884 qsort(fd.harray+2, fd.num_array-2,
10885 sizeof(struct hash_entry), name_cmp);
10886 else
10887 qsort(fd.harray, fd.num_array,
10888 sizeof(struct hash_entry), hash_cmp);
10889
10890 /*
10891 * Look for duplicates
10892 */
10893 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10894 goto resort;
10895
10896 if (ctx->options & E2F_OPT_NO) {
10897 retval = 0;
10898 goto errout;
10899 }
10900
10901 /*
10902 * Copy the directory entries. In a htree directory these
10903 * will become the leaf nodes.
10904 */
10905 retval = copy_dir_entries(fs, &fd, &outdir);
10906 if (retval)
10907 goto errout;
10908
10909 free(dir_buf); dir_buf = 0;
10910
10911 if (!fd.compress) {
10912 /* Calculate the interior nodes */
10913 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10914 if (retval)
10915 goto errout;
10916 }
10917
10918 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10919
10920errout:
10921 free(dir_buf);
10922 free(fd.harray);
10923
10924 free_out_dir(&outdir);
10925 return retval;
10926}
10927
10928void e2fsck_rehash_directories(e2fsck_t ctx)
10929{
10930 struct problem_context pctx;
10931 struct dir_info *dir;
10932 ext2_u32_iterate iter;
10933 ext2_ino_t ino;
10934 errcode_t retval;
10935 int i, cur, max, all_dirs, dir_index, first = 1;
10936
10937 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10938
10939 if (!ctx->dirs_to_hash && !all_dirs)
10940 return;
10941
10942 e2fsck_get_lost_and_found(ctx, 0);
10943
10944 clear_problem_context(&pctx);
10945
10946 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10947 cur = 0;
10948 if (all_dirs) {
10949 i = 0;
10950 max = e2fsck_get_num_dirinfo(ctx);
10951 } else {
10952 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10953 &iter);
10954 if (retval) {
10955 pctx.errcode = retval;
10956 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10957 return;
10958 }
10959 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10960 }
10961 while (1) {
10962 if (all_dirs) {
10963 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10964 break;
10965 ino = dir->ino;
10966 } else {
10967 if (!ext2fs_u32_list_iterate(iter, &ino))
10968 break;
10969 }
10970 if (ino == ctx->lost_and_found)
10971 continue;
10972 pctx.dir = ino;
10973 if (first) {
10974 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10975 first = 0;
10976 }
10977 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10978 if (pctx.errcode) {
10979 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10980 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10981 }
10982 if (ctx->progress && !ctx->progress_fd)
10983 e2fsck_simple_progress(ctx, "Rebuilding directory",
10984 100.0 * (float) (++cur) / (float) max, ino);
10985 }
10986 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10987 if (!all_dirs)
10988 ext2fs_u32_list_iterate_end(iter);
10989
10990 ext2fs_u32_list_free(ctx->dirs_to_hash);
10991 ctx->dirs_to_hash = 0;
10992}
10993
10994/*
10995 * linux/fs/revoke.c
10996 *
10997 * Journal revoke routines for the generic filesystem journaling code;
10998 * part of the ext2fs journaling system.
10999 *
11000 * Revoke is the mechanism used to prevent old log records for deleted
11001 * metadata from being replayed on top of newer data using the same
11002 * blocks. The revoke mechanism is used in two separate places:
11003 *
11004 * + Commit: during commit we write the entire list of the current
11005 * transaction's revoked blocks to the journal
11006 *
11007 * + Recovery: during recovery we record the transaction ID of all
11008 * revoked blocks. If there are multiple revoke records in the log
11009 * for a single block, only the last one counts, and if there is a log
11010 * entry for a block beyond the last revoke, then that log entry still
11011 * gets replayed.
11012 *
11013 * We can get interactions between revokes and new log data within a
11014 * single transaction:
11015 *
11016 * Block is revoked and then journaled:
11017 * The desired end result is the journaling of the new block, so we
11018 * cancel the revoke before the transaction commits.
11019 *
11020 * Block is journaled and then revoked:
11021 * The revoke must take precedence over the write of the block, so we
11022 * need either to cancel the journal entry or to write the revoke
11023 * later in the log than the log block. In this case, we choose the
11024 * latter: journaling a block cancels any revoke record for that block
11025 * in the current transaction, so any revoke for that block in the
11026 * transaction must have happened after the block was journaled and so
11027 * the revoke must take precedence.
11028 *
11029 * Block is revoked and then written as data:
11030 * The data write is allowed to succeed, but the revoke is _not_
11031 * cancelled. We still need to prevent old log records from
11032 * overwriting the new data. We don't even need to clear the revoke
11033 * bit here.
11034 *
11035 * Revoke information on buffers is a tri-state value:
11036 *
11037 * RevokeValid clear: no cached revoke status, need to look it up
11038 * RevokeValid set, Revoked clear:
11039 * buffer has not been revoked, and cancel_revoke
11040 * need do nothing.
11041 * RevokeValid set, Revoked set:
11042 * buffer has been revoked.
11043 */
11044
11045static kmem_cache_t *revoke_record_cache;
11046static kmem_cache_t *revoke_table_cache;
11047
11048/* Each revoke record represents one single revoked block. During
11049 journal replay, this involves recording the transaction ID of the
11050 last transaction to revoke this block. */
11051
11052struct jbd_revoke_record_s
11053{
11054 struct list_head hash;
11055 tid_t sequence; /* Used for recovery only */
11056 unsigned long blocknr;
11057};
11058
11059
11060/* The revoke table is just a simple hash table of revoke records. */
11061struct jbd_revoke_table_s
11062{
11063 /* It is conceivable that we might want a larger hash table
11064 * for recovery. Must be a power of two. */
11065 int hash_size;
11066 int hash_shift;
11067 struct list_head *hash_table;
11068};
11069
11070
11071/* Utility functions to maintain the revoke table */
11072
11073/* Borrowed from buffer.c: this is a tried and tested block hash function */
11074static int hash(journal_t *journal, unsigned long block)
11075{
11076 struct jbd_revoke_table_s *table = journal->j_revoke;
11077 int hash_shift = table->hash_shift;
11078
11079 return ((block << (hash_shift - 6)) ^
11080 (block >> 13) ^
11081 (block << (hash_shift - 12))) & (table->hash_size - 1);
11082}
11083
11084static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11085 tid_t seq)
11086{
11087 struct list_head *hash_list;
11088 struct jbd_revoke_record_s *record;
11089
11090 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11091 if (!record)
11092 goto oom;
11093
11094 record->sequence = seq;
11095 record->blocknr = blocknr;
11096 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11097 list_add(&record->hash, hash_list);
11098 return 0;
11099
11100oom:
11101 return -ENOMEM;
11102}
11103
11104/* Find a revoke record in the journal's hash table. */
11105
11106static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11107 unsigned long blocknr)
11108{
11109 struct list_head *hash_list;
11110 struct jbd_revoke_record_s *record;
11111
11112 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11113
11114 record = (struct jbd_revoke_record_s *) hash_list->next;
11115 while (&(record->hash) != hash_list) {
11116 if (record->blocknr == blocknr)
11117 return record;
11118 record = (struct jbd_revoke_record_s *) record->hash.next;
11119 }
11120 return NULL;
11121}
11122
11123int journal_init_revoke_caches(void)
11124{
11125 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11126 if (revoke_record_cache == 0)
11127 return -ENOMEM;
11128
11129 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11130 if (revoke_table_cache == 0) {
11131 do_cache_destroy(revoke_record_cache);
11132 revoke_record_cache = NULL;
11133 return -ENOMEM;
11134 }
11135 return 0;
11136}
11137
11138void journal_destroy_revoke_caches(void)
11139{
11140 do_cache_destroy(revoke_record_cache);
11141 revoke_record_cache = 0;
11142 do_cache_destroy(revoke_table_cache);
11143 revoke_table_cache = 0;
11144}
11145
11146/* Initialise the revoke table for a given journal to a given size. */
11147
11148int journal_init_revoke(journal_t *journal, int hash_size)
11149{
11150 int shift, tmp;
11151
11152 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11153 if (!journal->j_revoke)
11154 return -ENOMEM;
11155
11156 /* Check that the hash_size is a power of two */
11157 journal->j_revoke->hash_size = hash_size;
11158
11159 shift = 0;
11160 tmp = hash_size;
Denis Vlasenkobb045062008-09-27 14:06:06 +000011161 while ((tmp >>= 1UL) != 0UL)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011162 shift++;
11163 journal->j_revoke->hash_shift = shift;
11164
11165 journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
11166 if (!journal->j_revoke->hash_table) {
11167 free(journal->j_revoke);
11168 journal->j_revoke = NULL;
11169 return -ENOMEM;
11170 }
11171
11172 for (tmp = 0; tmp < hash_size; tmp++)
11173 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11174
11175 return 0;
11176}
11177
11178/* Destoy a journal's revoke table. The table must already be empty! */
11179
11180void journal_destroy_revoke(journal_t *journal)
11181{
11182 struct jbd_revoke_table_s *table;
11183 struct list_head *hash_list;
11184 int i;
11185
11186 table = journal->j_revoke;
11187 if (!table)
11188 return;
11189
11190 for (i=0; i<table->hash_size; i++) {
11191 hash_list = &table->hash_table[i];
11192 }
11193
11194 free(table->hash_table);
11195 free(table);
11196 journal->j_revoke = NULL;
11197}
11198
11199/*
11200 * Revoke support for recovery.
11201 *
11202 * Recovery needs to be able to:
11203 *
11204 * record all revoke records, including the tid of the latest instance
11205 * of each revoke in the journal
11206 *
11207 * check whether a given block in a given transaction should be replayed
11208 * (ie. has not been revoked by a revoke record in that or a subsequent
11209 * transaction)
11210 *
11211 * empty the revoke table after recovery.
11212 */
11213
11214/*
11215 * First, setting revoke records. We create a new revoke record for
11216 * every block ever revoked in the log as we scan it for recovery, and
11217 * we update the existing records if we find multiple revokes for a
11218 * single block.
11219 */
11220
11221int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11222 tid_t sequence)
11223{
11224 struct jbd_revoke_record_s *record;
11225
11226 record = find_revoke_record(journal, blocknr);
11227 if (record) {
11228 /* If we have multiple occurences, only record the
11229 * latest sequence number in the hashed record */
11230 if (tid_gt(sequence, record->sequence))
11231 record->sequence = sequence;
11232 return 0;
11233 }
11234 return insert_revoke_hash(journal, blocknr, sequence);
11235}
11236
11237/*
11238 * Test revoke records. For a given block referenced in the log, has
11239 * that block been revoked? A revoke record with a given transaction
11240 * sequence number revokes all blocks in that transaction and earlier
11241 * ones, but later transactions still need replayed.
11242 */
11243
11244int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11245 tid_t sequence)
11246{
11247 struct jbd_revoke_record_s *record;
11248
11249 record = find_revoke_record(journal, blocknr);
11250 if (!record)
11251 return 0;
11252 if (tid_gt(sequence, record->sequence))
11253 return 0;
11254 return 1;
11255}
11256
11257/*
11258 * Finally, once recovery is over, we need to clear the revoke table so
11259 * that it can be reused by the running filesystem.
11260 */
11261
11262void journal_clear_revoke(journal_t *journal)
11263{
11264 int i;
11265 struct list_head *hash_list;
11266 struct jbd_revoke_record_s *record;
11267 struct jbd_revoke_table_s *revoke_var;
11268
11269 revoke_var = journal->j_revoke;
11270
11271 for (i = 0; i < revoke_var->hash_size; i++) {
11272 hash_list = &revoke_var->hash_table[i];
11273 while (!list_empty(hash_list)) {
11274 record = (struct jbd_revoke_record_s*) hash_list->next;
11275 list_del(&record->hash);
11276 free(record);
11277 }
11278 }
11279}
11280
11281/*
11282 * e2fsck.c - superblock checks
11283 */
11284
11285#define MIN_CHECK 1
11286#define MAX_CHECK 2
11287
11288static void check_super_value(e2fsck_t ctx, const char *descr,
11289 unsigned long value, int flags,
11290 unsigned long min_val, unsigned long max_val)
11291{
11292 struct problem_context pctx;
11293
11294 if (((flags & MIN_CHECK) && (value < min_val)) ||
11295 ((flags & MAX_CHECK) && (value > max_val))) {
11296 clear_problem_context(&pctx);
11297 pctx.num = value;
11298 pctx.str = descr;
11299 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11300 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11301 }
11302}
11303
11304/*
11305 * This routine may get stubbed out in special compilations of the
11306 * e2fsck code..
11307 */
11308#ifndef EXT2_SPECIAL_DEVICE_SIZE
11309static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11310{
11311 return (ext2fs_get_device_size(ctx->filesystem_name,
11312 EXT2_BLOCK_SIZE(ctx->fs->super),
11313 &ctx->num_blocks));
11314}
11315#endif
11316
11317/*
11318 * helper function to release an inode
11319 */
11320struct process_block_struct {
11321 e2fsck_t ctx;
11322 char *buf;
11323 struct problem_context *pctx;
11324 int truncating;
11325 int truncate_offset;
11326 e2_blkcnt_t truncate_block;
11327 int truncated_blocks;
11328 int abort;
11329 errcode_t errcode;
11330};
11331
11332static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11333 e2_blkcnt_t blockcnt,
11334 blk_t ref_blk FSCK_ATTR((unused)),
11335 int ref_offset FSCK_ATTR((unused)),
11336 void *priv_data)
11337{
11338 struct process_block_struct *pb;
11339 e2fsck_t ctx;
11340 struct problem_context *pctx;
11341 blk_t blk = *block_nr;
11342 int retval = 0;
11343
11344 pb = (struct process_block_struct *) priv_data;
11345 ctx = pb->ctx;
11346 pctx = pb->pctx;
11347
11348 pctx->blk = blk;
11349 pctx->blkcount = blockcnt;
11350
11351 if (HOLE_BLKADDR(blk))
11352 return 0;
11353
11354 if ((blk < fs->super->s_first_data_block) ||
11355 (blk >= fs->super->s_blocks_count)) {
11356 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11357 return_abort:
11358 pb->abort = 1;
11359 return BLOCK_ABORT;
11360 }
11361
11362 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11363 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11364 goto return_abort;
11365 }
11366
11367 /*
11368 * If we are deleting an orphan, then we leave the fields alone.
11369 * If we are truncating an orphan, then update the inode fields
11370 * and clean up any partial block data.
11371 */
11372 if (pb->truncating) {
11373 /*
11374 * We only remove indirect blocks if they are
11375 * completely empty.
11376 */
11377 if (blockcnt < 0) {
11378 int i, limit;
11379 blk_t *bp;
11380
11381 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11382 pb->buf);
11383 if (pb->errcode)
11384 goto return_abort;
11385
11386 limit = fs->blocksize >> 2;
11387 for (i = 0, bp = (blk_t *) pb->buf;
11388 i < limit; i++, bp++)
11389 if (*bp)
11390 return 0;
11391 }
11392 /*
11393 * We don't remove direct blocks until we've reached
11394 * the truncation block.
11395 */
11396 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11397 return 0;
11398 /*
11399 * If part of the last block needs truncating, we do
11400 * it here.
11401 */
11402 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11403 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11404 pb->buf);
11405 if (pb->errcode)
11406 goto return_abort;
11407 memset(pb->buf + pb->truncate_offset, 0,
11408 fs->blocksize - pb->truncate_offset);
11409 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11410 pb->buf);
11411 if (pb->errcode)
11412 goto return_abort;
11413 }
11414 pb->truncated_blocks++;
11415 *block_nr = 0;
11416 retval |= BLOCK_CHANGED;
11417 }
11418
11419 ext2fs_block_alloc_stats(fs, blk, -1);
11420 return retval;
11421}
11422
11423/*
11424 * This function releases an inode. Returns 1 if an inconsistency was
11425 * found. If the inode has a link count, then it is being truncated and
11426 * not deleted.
11427 */
11428static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11429 struct ext2_inode *inode, char *block_buf,
11430 struct problem_context *pctx)
11431{
11432 struct process_block_struct pb;
11433 ext2_filsys fs = ctx->fs;
11434 errcode_t retval;
11435 __u32 count;
11436
11437 if (!ext2fs_inode_has_valid_blocks(inode))
11438 return 0;
11439
11440 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11441 pb.ctx = ctx;
11442 pb.abort = 0;
11443 pb.errcode = 0;
11444 pb.pctx = pctx;
11445 if (inode->i_links_count) {
11446 pb.truncating = 1;
11447 pb.truncate_block = (e2_blkcnt_t)
11448 ((((long long)inode->i_size_high << 32) +
11449 inode->i_size + fs->blocksize - 1) /
11450 fs->blocksize);
11451 pb.truncate_offset = inode->i_size % fs->blocksize;
11452 } else {
11453 pb.truncating = 0;
11454 pb.truncate_block = 0;
11455 pb.truncate_offset = 0;
11456 }
11457 pb.truncated_blocks = 0;
11458 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11459 block_buf, release_inode_block, &pb);
11460 if (retval) {
11461 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11462 ino);
11463 return 1;
11464 }
11465 if (pb.abort)
11466 return 1;
11467
11468 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11469 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11470
11471 if (pb.truncated_blocks)
11472 inode->i_blocks -= pb.truncated_blocks *
11473 (fs->blocksize / 512);
11474
11475 if (inode->i_file_acl) {
11476 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11477 block_buf, -1, &count);
11478 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11479 retval = 0;
11480 count = 1;
11481 }
11482 if (retval) {
11483 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11484 ino);
11485 return 1;
11486 }
11487 if (count == 0)
11488 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11489 inode->i_file_acl = 0;
11490 }
11491 return 0;
11492}
11493
11494/*
11495 * This function releases all of the orphan inodes. It returns 1 if
11496 * it hit some error, and 0 on success.
11497 */
11498static int release_orphan_inodes(e2fsck_t ctx)
11499{
11500 ext2_filsys fs = ctx->fs;
11501 ext2_ino_t ino, next_ino;
11502 struct ext2_inode inode;
11503 struct problem_context pctx;
11504 char *block_buf;
11505
11506 if ((ino = fs->super->s_last_orphan) == 0)
11507 return 0;
11508
11509 /*
11510 * Win or lose, we won't be using the head of the orphan inode
11511 * list again.
11512 */
11513 fs->super->s_last_orphan = 0;
11514 ext2fs_mark_super_dirty(fs);
11515
11516 /*
11517 * If the filesystem contains errors, don't run the orphan
11518 * list, since the orphan list can't be trusted; and we're
11519 * going to be running a full e2fsck run anyway...
11520 */
11521 if (fs->super->s_state & EXT2_ERROR_FS)
11522 return 0;
11523
11524 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11525 (ino > fs->super->s_inodes_count)) {
11526 clear_problem_context(&pctx);
11527 pctx.ino = ino;
11528 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11529 return 1;
11530 }
11531
11532 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11533 "block iterate buffer");
11534 e2fsck_read_bitmaps(ctx);
11535
11536 while (ino) {
11537 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11538 clear_problem_context(&pctx);
11539 pctx.ino = ino;
11540 pctx.inode = &inode;
11541 pctx.str = inode.i_links_count ? _("Truncating") :
11542 _("Clearing");
11543
11544 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11545
11546 next_ino = inode.i_dtime;
11547 if (next_ino &&
11548 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11549 (next_ino > fs->super->s_inodes_count))) {
11550 pctx.ino = next_ino;
11551 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11552 goto return_abort;
11553 }
11554
11555 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11556 goto return_abort;
11557
11558 if (!inode.i_links_count) {
11559 ext2fs_inode_alloc_stats2(fs, ino, -1,
11560 LINUX_S_ISDIR(inode.i_mode));
11561 inode.i_dtime = time(0);
11562 } else {
11563 inode.i_dtime = 0;
11564 }
11565 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11566 ino = next_ino;
11567 }
11568 ext2fs_free_mem(&block_buf);
11569 return 0;
11570return_abort:
11571 ext2fs_free_mem(&block_buf);
11572 return 1;
11573}
11574
11575/*
11576 * Check the resize inode to make sure it is sane. We check both for
11577 * the case where on-line resizing is not enabled (in which case the
11578 * resize inode should be cleared) as well as the case where on-line
11579 * resizing is enabled.
11580 */
11581static void check_resize_inode(e2fsck_t ctx)
11582{
11583 ext2_filsys fs = ctx->fs;
11584 struct ext2_inode inode;
11585 struct problem_context pctx;
11586 int i, j, gdt_off, ind_off;
11587 blk_t blk, pblk, expect;
11588 __u32 *dind_buf = 0, *ind_buf;
11589 errcode_t retval;
11590
11591 clear_problem_context(&pctx);
11592
11593 /*
11594 * If the resize inode feature isn't set, then
11595 * s_reserved_gdt_blocks must be zero.
11596 */
11597 if (!(fs->super->s_feature_compat &
11598 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11599 if (fs->super->s_reserved_gdt_blocks) {
11600 pctx.num = fs->super->s_reserved_gdt_blocks;
11601 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11602 &pctx)) {
11603 fs->super->s_reserved_gdt_blocks = 0;
11604 ext2fs_mark_super_dirty(fs);
11605 }
11606 }
11607 }
11608
11609 /* Read the resize inode */
11610 pctx.ino = EXT2_RESIZE_INO;
11611 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11612 if (retval) {
11613 if (fs->super->s_feature_compat &
11614 EXT2_FEATURE_COMPAT_RESIZE_INODE)
11615 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11616 return;
11617 }
11618
11619 /*
11620 * If the resize inode feature isn't set, check to make sure
11621 * the resize inode is cleared; then we're done.
11622 */
11623 if (!(fs->super->s_feature_compat &
11624 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11625 for (i=0; i < EXT2_N_BLOCKS; i++) {
11626 if (inode.i_block[i])
11627 break;
11628 }
11629 if ((i < EXT2_N_BLOCKS) &&
11630 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11631 memset(&inode, 0, sizeof(inode));
11632 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11633 "clear_resize");
11634 }
11635 return;
11636 }
11637
11638 /*
11639 * The resize inode feature is enabled; check to make sure the
11640 * only block in use is the double indirect block
11641 */
11642 blk = inode.i_block[EXT2_DIND_BLOCK];
11643 for (i=0; i < EXT2_N_BLOCKS; i++) {
11644 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11645 break;
11646 }
11647 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11648 !(inode.i_mode & LINUX_S_IFREG) ||
11649 (blk < fs->super->s_first_data_block ||
11650 blk >= fs->super->s_blocks_count)) {
11651 resize_inode_invalid:
11652 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11653 memset(&inode, 0, sizeof(inode));
11654 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11655 "clear_resize");
11656 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11657 }
11658 if (!(ctx->options & E2F_OPT_READONLY)) {
11659 fs->super->s_state &= ~EXT2_VALID_FS;
11660 ext2fs_mark_super_dirty(fs);
11661 }
11662 goto cleanup;
11663 }
11664 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11665 "resize dind buffer");
11666 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11667
11668 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11669 if (retval)
11670 goto resize_inode_invalid;
11671
11672 gdt_off = fs->desc_blocks;
11673 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11674 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11675 i++, gdt_off++, pblk++) {
11676 gdt_off %= fs->blocksize/4;
11677 if (dind_buf[gdt_off] != pblk)
11678 goto resize_inode_invalid;
11679 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11680 if (retval)
11681 goto resize_inode_invalid;
11682 ind_off = 0;
11683 for (j = 1; j < fs->group_desc_count; j++) {
11684 if (!ext2fs_bg_has_super(fs, j))
11685 continue;
11686 expect = pblk + (j * fs->super->s_blocks_per_group);
11687 if (ind_buf[ind_off] != expect)
11688 goto resize_inode_invalid;
11689 ind_off++;
11690 }
11691 }
11692
11693cleanup:
11694 ext2fs_free_mem(&dind_buf);
11695
11696 }
11697
11698static void check_super_block(e2fsck_t ctx)
11699{
11700 ext2_filsys fs = ctx->fs;
11701 blk_t first_block, last_block;
11702 struct ext2_super_block *sb = fs->super;
11703 struct ext2_group_desc *gd;
11704 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11705 blk_t bpg_max;
11706 int inodes_per_block;
11707 int ipg_max;
11708 int inode_size;
11709 dgrp_t i;
11710 blk_t should_be;
11711 struct problem_context pctx;
11712 __u32 free_blocks = 0, free_inodes = 0;
11713
11714 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11715 ipg_max = inodes_per_block * (blocks_per_group - 4);
11716 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11717 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11718 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11719 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11720 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11721
11722 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11723 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11724 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11725 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11726 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11727 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11728
11729 clear_problem_context(&pctx);
11730
11731 /*
11732 * Verify the super block constants...
11733 */
11734 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11735 MIN_CHECK, 1, 0);
11736 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11737 MIN_CHECK, 1, 0);
11738 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11739 MAX_CHECK, 0, sb->s_blocks_count);
11740 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11741 MIN_CHECK | MAX_CHECK, 0,
11742 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11743 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11744 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11745 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11746 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11747 bpg_max);
11748 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11749 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11750 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11751 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11752 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11753 MAX_CHECK, 0, sb->s_blocks_count / 2);
11754 check_super_value(ctx, "reserved_gdt_blocks",
11755 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11756 fs->blocksize/4);
11757 inode_size = EXT2_INODE_SIZE(sb);
11758 check_super_value(ctx, "inode_size",
11759 inode_size, MIN_CHECK | MAX_CHECK,
11760 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11761 if (inode_size & (inode_size - 1)) {
11762 pctx.num = inode_size;
11763 pctx.str = "inode_size";
11764 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11765 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11766 return;
11767 }
11768
11769 if (!ctx->num_blocks) {
11770 pctx.errcode = e2fsck_get_device_size(ctx);
11771 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11772 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11773 ctx->flags |= E2F_FLAG_ABORT;
11774 return;
11775 }
11776 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11777 (ctx->num_blocks < sb->s_blocks_count)) {
11778 pctx.blk = sb->s_blocks_count;
11779 pctx.blk2 = ctx->num_blocks;
11780 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11781 ctx->flags |= E2F_FLAG_ABORT;
11782 return;
11783 }
11784 }
11785 }
11786
11787 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11788 pctx.blk = EXT2_BLOCK_SIZE(sb);
11789 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11790 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11791 ctx->flags |= E2F_FLAG_ABORT;
11792 return;
11793 }
11794
11795 should_be = sb->s_frags_per_group >>
11796 (sb->s_log_block_size - sb->s_log_frag_size);
11797 if (sb->s_blocks_per_group != should_be) {
11798 pctx.blk = sb->s_blocks_per_group;
11799 pctx.blk2 = should_be;
11800 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11801 ctx->flags |= E2F_FLAG_ABORT;
11802 return;
11803 }
11804
11805 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11806 if (sb->s_first_data_block != should_be) {
11807 pctx.blk = sb->s_first_data_block;
11808 pctx.blk2 = should_be;
11809 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11810 ctx->flags |= E2F_FLAG_ABORT;
11811 return;
11812 }
11813
11814 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11815 if (sb->s_inodes_count != should_be) {
11816 pctx.ino = sb->s_inodes_count;
11817 pctx.ino2 = should_be;
11818 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11819 sb->s_inodes_count = should_be;
11820 ext2fs_mark_super_dirty(fs);
11821 }
11822 }
11823
11824 /*
11825 * Verify the group descriptors....
11826 */
11827 first_block = sb->s_first_data_block;
11828 last_block = first_block + blocks_per_group;
11829
11830 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11831 pctx.group = i;
11832
11833 if (i == fs->group_desc_count - 1)
11834 last_block = sb->s_blocks_count;
11835 if ((gd->bg_block_bitmap < first_block) ||
11836 (gd->bg_block_bitmap >= last_block)) {
11837 pctx.blk = gd->bg_block_bitmap;
11838 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11839 gd->bg_block_bitmap = 0;
11840 }
11841 if (gd->bg_block_bitmap == 0) {
11842 ctx->invalid_block_bitmap_flag[i]++;
11843 ctx->invalid_bitmaps++;
11844 }
11845 if ((gd->bg_inode_bitmap < first_block) ||
11846 (gd->bg_inode_bitmap >= last_block)) {
11847 pctx.blk = gd->bg_inode_bitmap;
11848 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11849 gd->bg_inode_bitmap = 0;
11850 }
11851 if (gd->bg_inode_bitmap == 0) {
11852 ctx->invalid_inode_bitmap_flag[i]++;
11853 ctx->invalid_bitmaps++;
11854 }
11855 if ((gd->bg_inode_table < first_block) ||
11856 ((gd->bg_inode_table +
11857 fs->inode_blocks_per_group - 1) >= last_block)) {
11858 pctx.blk = gd->bg_inode_table;
11859 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11860 gd->bg_inode_table = 0;
11861 }
11862 if (gd->bg_inode_table == 0) {
11863 ctx->invalid_inode_table_flag[i]++;
11864 ctx->invalid_bitmaps++;
11865 }
11866 free_blocks += gd->bg_free_blocks_count;
11867 free_inodes += gd->bg_free_inodes_count;
11868 first_block += sb->s_blocks_per_group;
11869 last_block += sb->s_blocks_per_group;
11870
11871 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11872 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11873 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11874 ext2fs_unmark_valid(fs);
11875
11876 }
11877
11878 /*
11879 * Update the global counts from the block group counts. This
11880 * is needed for an experimental patch which eliminates
11881 * locking the entire filesystem when allocating blocks or
11882 * inodes; if the filesystem is not unmounted cleanly, the
11883 * global counts may not be accurate.
11884 */
11885 if ((free_blocks != sb->s_free_blocks_count) ||
11886 (free_inodes != sb->s_free_inodes_count)) {
11887 if (ctx->options & E2F_OPT_READONLY)
11888 ext2fs_unmark_valid(fs);
11889 else {
11890 sb->s_free_blocks_count = free_blocks;
11891 sb->s_free_inodes_count = free_inodes;
11892 ext2fs_mark_super_dirty(fs);
11893 }
11894 }
11895
11896 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11897 (sb->s_free_inodes_count > sb->s_inodes_count))
11898 ext2fs_unmark_valid(fs);
11899
11900
11901 /*
11902 * If we have invalid bitmaps, set the error state of the
11903 * filesystem.
11904 */
11905 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11906 sb->s_state &= ~EXT2_VALID_FS;
11907 ext2fs_mark_super_dirty(fs);
11908 }
11909
11910 clear_problem_context(&pctx);
11911
11912 /*
11913 * If the UUID field isn't assigned, assign it.
11914 */
11915 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11916 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11917 uuid_generate(sb->s_uuid);
11918 ext2fs_mark_super_dirty(fs);
11919 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11920 }
11921 }
11922
11923 /* FIXME - HURD support?
11924 * For the Hurd, check to see if the filetype option is set,
11925 * since it doesn't support it.
11926 */
11927 if (!(ctx->options & E2F_OPT_READONLY) &&
11928 fs->super->s_creator_os == EXT2_OS_HURD &&
11929 (fs->super->s_feature_incompat &
11930 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11931 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11932 fs->super->s_feature_incompat &=
11933 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11934 ext2fs_mark_super_dirty(fs);
11935
11936 }
11937 }
11938
11939 /*
11940 * If we have any of the compatibility flags set, we need to have a
11941 * revision 1 filesystem. Most kernels will not check the flags on
11942 * a rev 0 filesystem and we may have corruption issues because of
11943 * the incompatible changes to the filesystem.
11944 */
11945 if (!(ctx->options & E2F_OPT_READONLY) &&
11946 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11947 (fs->super->s_feature_compat ||
11948 fs->super->s_feature_ro_compat ||
11949 fs->super->s_feature_incompat) &&
11950 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11951 ext2fs_update_dynamic_rev(fs);
11952 ext2fs_mark_super_dirty(fs);
11953 }
11954
11955 check_resize_inode(ctx);
11956
11957 /*
11958 * Clean up any orphan inodes, if present.
11959 */
11960 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11961 fs->super->s_state &= ~EXT2_VALID_FS;
11962 ext2fs_mark_super_dirty(fs);
11963 }
11964
11965 /*
11966 * Move the ext3 journal file, if necessary.
11967 */
11968 e2fsck_move_ext3_journal(ctx);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011969}
11970
11971/*
11972 * swapfs.c --- byte-swap an ext2 filesystem
11973 */
11974
11975#ifdef ENABLE_SWAPFS
11976
11977struct swap_block_struct {
11978 ext2_ino_t ino;
11979 int isdir;
11980 errcode_t errcode;
11981 char *dir_buf;
11982 struct ext2_inode *inode;
11983};
11984
11985/*
11986 * This is a helper function for block_iterate. We mark all of the
11987 * indirect and direct blocks as changed, so that block_iterate will
11988 * write them out.
11989 */
11990static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11991 void *priv_data)
11992{
11993 errcode_t retval;
11994
11995 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11996
11997 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11998 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11999 if (retval) {
12000 sb->errcode = retval;
12001 return BLOCK_ABORT;
12002 }
12003 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
12004 if (retval) {
12005 sb->errcode = retval;
12006 return BLOCK_ABORT;
12007 }
12008 }
12009 if (blockcnt >= 0) {
12010 if (blockcnt < EXT2_NDIR_BLOCKS)
12011 return 0;
12012 return BLOCK_CHANGED;
12013 }
12014 if (blockcnt == BLOCK_COUNT_IND) {
12015 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
12016 return 0;
12017 return BLOCK_CHANGED;
12018 }
12019 if (blockcnt == BLOCK_COUNT_DIND) {
12020 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12021 return 0;
12022 return BLOCK_CHANGED;
12023 }
12024 if (blockcnt == BLOCK_COUNT_TIND) {
12025 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12026 return 0;
12027 return BLOCK_CHANGED;
12028 }
12029 return BLOCK_CHANGED;
12030}
12031
12032/*
12033 * This function is responsible for byte-swapping all of the indirect,
12034 * block pointers. It is also responsible for byte-swapping directories.
12035 */
12036static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12037 struct ext2_inode *inode)
12038{
12039 errcode_t retval;
12040 struct swap_block_struct sb;
12041
12042 sb.ino = ino;
12043 sb.inode = inode;
12044 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12045 sb.errcode = 0;
12046 sb.isdir = 0;
12047 if (LINUX_S_ISDIR(inode->i_mode))
12048 sb.isdir = 1;
12049
12050 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12051 swap_block, &sb);
12052 if (retval) {
12053 bb_error_msg(_("while calling ext2fs_block_iterate"));
12054 ctx->flags |= E2F_FLAG_ABORT;
12055 return;
12056 }
12057 if (sb.errcode) {
12058 bb_error_msg(_("while calling iterator function"));
12059 ctx->flags |= E2F_FLAG_ABORT;
12060 return;
12061 }
12062}
12063
12064static void swap_inodes(e2fsck_t ctx)
12065{
12066 ext2_filsys fs = ctx->fs;
12067 dgrp_t group;
12068 unsigned int i;
12069 ext2_ino_t ino = 1;
12070 char *buf, *block_buf;
12071 errcode_t retval;
12072 struct ext2_inode * inode;
12073
12074 e2fsck_use_inode_shortcuts(ctx, 1);
12075
12076 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12077 &buf);
12078 if (retval) {
12079 bb_error_msg(_("while allocating inode buffer"));
12080 ctx->flags |= E2F_FLAG_ABORT;
12081 return;
12082 }
12083 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12084 "block interate buffer");
12085 for (group = 0; group < fs->group_desc_count; group++) {
12086 retval = io_channel_read_blk(fs->io,
12087 fs->group_desc[group].bg_inode_table,
12088 fs->inode_blocks_per_group, buf);
12089 if (retval) {
12090 bb_error_msg(_("while reading inode table (group %d)"),
12091 group);
12092 ctx->flags |= E2F_FLAG_ABORT;
12093 return;
12094 }
12095 inode = (struct ext2_inode *) buf;
12096 for (i=0; i < fs->super->s_inodes_per_group;
12097 i++, ino++, inode++) {
12098 ctx->stashed_ino = ino;
12099 ctx->stashed_inode = inode;
12100
12101 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12102 ext2fs_swap_inode(fs, inode, inode, 0);
12103
12104 /*
12105 * Skip deleted files.
12106 */
12107 if (inode->i_links_count == 0)
12108 continue;
12109
12110 if (LINUX_S_ISDIR(inode->i_mode) ||
12111 ((inode->i_block[EXT2_IND_BLOCK] ||
12112 inode->i_block[EXT2_DIND_BLOCK] ||
12113 inode->i_block[EXT2_TIND_BLOCK]) &&
12114 ext2fs_inode_has_valid_blocks(inode)))
12115 swap_inode_blocks(ctx, ino, block_buf, inode);
12116
12117 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12118 return;
12119
12120 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12121 ext2fs_swap_inode(fs, inode, inode, 1);
12122 }
12123 retval = io_channel_write_blk(fs->io,
12124 fs->group_desc[group].bg_inode_table,
12125 fs->inode_blocks_per_group, buf);
12126 if (retval) {
12127 bb_error_msg(_("while writing inode table (group %d)"),
12128 group);
12129 ctx->flags |= E2F_FLAG_ABORT;
12130 return;
12131 }
12132 }
12133 ext2fs_free_mem(&buf);
12134 ext2fs_free_mem(&block_buf);
12135 e2fsck_use_inode_shortcuts(ctx, 0);
12136 ext2fs_flush_icache(fs);
12137}
12138
12139#if defined(__powerpc__) && BB_BIG_ENDIAN
12140/*
12141 * On the PowerPC, the big-endian variant of the ext2 filesystem
12142 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12143 * of each word. Thus a bitmap with only bit 0 set would be, as
12144 * a string of bytes, 00 00 00 01 00 ...
12145 * To cope with this, we byte-reverse each word of a bitmap if
12146 * we have a big-endian filesystem, that is, if we are *not*
12147 * byte-swapping other word-sized numbers.
12148 */
12149#define EXT2_BIG_ENDIAN_BITMAPS
12150#endif
12151
12152#ifdef EXT2_BIG_ENDIAN_BITMAPS
12153static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12154{
12155 __u32 *p = (__u32 *) bmap->bitmap;
12156 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12157
12158 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12159 *p = ext2fs_swab32(*p);
12160}
12161#endif
12162
12163
12164#ifdef ENABLE_SWAPFS
12165static void swap_filesys(e2fsck_t ctx)
12166{
12167 ext2_filsys fs = ctx->fs;
12168 if (!(ctx->options & E2F_OPT_PREEN))
12169 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12170
12171 /* Byte swap */
12172
12173 if (fs->super->s_mnt_count) {
12174 fprintf(stderr, _("%s: the filesystem must be freshly "
12175 "checked using fsck\n"
12176 "and not mounted before trying to "
12177 "byte-swap it.\n"), ctx->device_name);
12178 ctx->flags |= E2F_FLAG_ABORT;
12179 return;
12180 }
12181 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12182 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12183 EXT2_FLAG_SWAP_BYTES_WRITE);
12184 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12185 } else {
12186 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12187 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12188 }
12189 swap_inodes(ctx);
12190 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12191 return;
12192 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12193 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12194 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12195 EXT2_FLAG_SWAP_BYTES_WRITE);
12196
12197#ifdef EXT2_BIG_ENDIAN_BITMAPS
12198 e2fsck_read_bitmaps(ctx);
12199 ext2fs_swap_bitmap(fs->inode_map);
12200 ext2fs_swap_bitmap(fs->block_map);
12201 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12202#endif
12203 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12204 ext2fs_flush(fs);
12205 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12206}
12207#endif /* ENABLE_SWAPFS */
12208
12209#endif
12210
12211/*
12212 * util.c --- miscellaneous utilities
12213 */
12214
12215
12216void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12217 const char *description)
12218{
12219 void *ret;
12220 char buf[256];
12221
12222 ret = malloc(size);
12223 if (!ret) {
12224 sprintf(buf, "Can't allocate %s\n", description);
12225 bb_error_msg_and_die(buf);
12226 }
12227 memset(ret, 0, size);
12228 return ret;
12229}
12230
12231static char *string_copy(const char *str, int len)
12232{
12233 char *ret;
12234
12235 if (!str)
12236 return NULL;
12237 if (!len)
12238 len = strlen(str);
12239 ret = malloc(len+1);
12240 if (ret) {
12241 strncpy(ret, str, len);
12242 ret[len] = 0;
12243 }
12244 return ret;
12245}
12246
12247#ifndef HAVE_CONIO_H
12248static int read_a_char(void)
12249{
12250 char c;
12251 int r;
12252 int fail = 0;
12253
Denis Vlasenkobb045062008-09-27 14:06:06 +000012254 while (1) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012255 if (e2fsck_global_ctx &&
12256 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12257 return 3;
12258 }
12259 r = read(0, &c, 1);
12260 if (r == 1)
12261 return c;
12262 if (fail++ > 100)
12263 break;
12264 }
12265 return EOF;
12266}
12267#endif
12268
12269static int ask_yn(const char * string, int def)
12270{
12271 int c;
12272 const char *defstr;
12273 static const char short_yes[] = "yY";
12274 static const char short_no[] = "nN";
12275
12276#ifdef HAVE_TERMIOS_H
12277 struct termios termios, tmp;
12278
12279 tcgetattr (0, &termios);
12280 tmp = termios;
12281 tmp.c_lflag &= ~(ICANON | ECHO);
12282 tmp.c_cc[VMIN] = 1;
12283 tmp.c_cc[VTIME] = 0;
12284 tcsetattr (0, TCSANOW, &tmp);
12285#endif
12286
12287 if (def == 1)
12288 defstr = "<y>";
12289 else if (def == 0)
12290 defstr = "<n>";
12291 else
12292 defstr = " (y/n)";
12293 printf("%s%s? ", string, defstr);
12294 while (1) {
12295 fflush (stdout);
12296 if ((c = read_a_char()) == EOF)
12297 break;
12298 if (c == 3) {
12299#ifdef HAVE_TERMIOS_H
12300 tcsetattr (0, TCSANOW, &termios);
12301#endif
12302 if (e2fsck_global_ctx &&
12303 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12304 puts("\n");
12305 longjmp(e2fsck_global_ctx->abort_loc, 1);
12306 }
12307 puts(_("cancelled!\n"));
12308 return 0;
12309 }
12310 if (strchr(short_yes, (char) c)) {
12311 def = 1;
12312 break;
12313 }
12314 else if (strchr(short_no, (char) c)) {
12315 def = 0;
12316 break;
12317 }
12318 else if ((c == ' ' || c == '\n') && (def != -1))
12319 break;
12320 }
12321 if (def)
12322 puts("yes\n");
12323 else
12324 puts ("no\n");
12325#ifdef HAVE_TERMIOS_H
12326 tcsetattr (0, TCSANOW, &termios);
12327#endif
12328 return def;
12329}
12330
12331int ask (e2fsck_t ctx, const char * string, int def)
12332{
12333 if (ctx->options & E2F_OPT_NO) {
12334 printf(_("%s? no\n\n"), string);
12335 return 0;
12336 }
12337 if (ctx->options & E2F_OPT_YES) {
12338 printf(_("%s? yes\n\n"), string);
12339 return 1;
12340 }
12341 if (ctx->options & E2F_OPT_PREEN) {
12342 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12343 return def;
12344 }
12345 return ask_yn(string, def);
12346}
12347
12348void e2fsck_read_bitmaps(e2fsck_t ctx)
12349{
12350 ext2_filsys fs = ctx->fs;
12351 errcode_t retval;
12352
12353 if (ctx->invalid_bitmaps) {
12354 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12355 ctx->device_name);
12356 bb_error_msg_and_die(0);
12357 }
12358
12359 ehandler_operation(_("reading inode and block bitmaps"));
12360 retval = ext2fs_read_bitmaps(fs);
12361 ehandler_operation(0);
12362 if (retval) {
12363 bb_error_msg(_("while retrying to read bitmaps for %s"),
12364 ctx->device_name);
12365 bb_error_msg_and_die(0);
12366 }
12367}
12368
12369static void e2fsck_write_bitmaps(e2fsck_t ctx)
12370{
12371 ext2_filsys fs = ctx->fs;
12372 errcode_t retval;
12373
12374 if (ext2fs_test_bb_dirty(fs)) {
12375 ehandler_operation(_("writing block bitmaps"));
12376 retval = ext2fs_write_block_bitmap(fs);
12377 ehandler_operation(0);
12378 if (retval) {
12379 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12380 ctx->device_name);
12381 bb_error_msg_and_die(0);
12382 }
12383 }
12384
12385 if (ext2fs_test_ib_dirty(fs)) {
12386 ehandler_operation(_("writing inode bitmaps"));
12387 retval = ext2fs_write_inode_bitmap(fs);
12388 ehandler_operation(0);
12389 if (retval) {
12390 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12391 ctx->device_name);
12392 bb_error_msg_and_die(0);
12393 }
12394 }
12395}
12396
12397void preenhalt(e2fsck_t ctx)
12398{
12399 ext2_filsys fs = ctx->fs;
12400
12401 if (!(ctx->options & E2F_OPT_PREEN))
12402 return;
12403 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12404 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12405 ctx->device_name);
12406 if (fs != NULL) {
12407 fs->super->s_state |= EXT2_ERROR_FS;
12408 ext2fs_mark_super_dirty(fs);
12409 ext2fs_close(fs);
12410 }
12411 exit(EXIT_UNCORRECTED);
12412}
12413
12414void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12415 struct ext2_inode * inode, const char *proc)
12416{
12417 int retval;
12418
12419 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12420 if (retval) {
12421 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12422 bb_error_msg_and_die(0);
12423 }
12424}
12425
12426extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12427 struct ext2_inode * inode, int bufsize,
12428 const char *proc)
12429{
12430 int retval;
12431
12432 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12433 if (retval) {
12434 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12435 bb_error_msg_and_die(0);
12436 }
12437}
12438
12439extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12440 struct ext2_inode * inode, const char *proc)
12441{
12442 int retval;
12443
12444 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12445 if (retval) {
12446 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12447 bb_error_msg_and_die(0);
12448 }
12449}
12450
12451blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12452 io_manager manager)
12453{
12454 struct ext2_super_block *sb;
12455 io_channel io = NULL;
12456 void *buf = NULL;
12457 int blocksize;
12458 blk_t superblock, ret_sb = 8193;
12459
12460 if (fs && fs->super) {
12461 ret_sb = (fs->super->s_blocks_per_group +
12462 fs->super->s_first_data_block);
12463 if (ctx) {
12464 ctx->superblock = ret_sb;
12465 ctx->blocksize = fs->blocksize;
12466 }
12467 return ret_sb;
12468 }
12469
12470 if (ctx) {
12471 if (ctx->blocksize) {
12472 ret_sb = ctx->blocksize * 8;
12473 if (ctx->blocksize == 1024)
12474 ret_sb++;
12475 ctx->superblock = ret_sb;
12476 return ret_sb;
12477 }
12478 ctx->superblock = ret_sb;
12479 ctx->blocksize = 1024;
12480 }
12481
12482 if (!name || !manager)
12483 goto cleanup;
12484
12485 if (manager->open(name, 0, &io) != 0)
12486 goto cleanup;
12487
12488 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12489 goto cleanup;
12490 sb = (struct ext2_super_block *) buf;
12491
12492 for (blocksize = EXT2_MIN_BLOCK_SIZE;
Denis Vlasenkob71c6682007-07-21 15:08:09 +000012493 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012494 superblock = blocksize*8;
12495 if (blocksize == 1024)
12496 superblock++;
12497 io_channel_set_blksize(io, blocksize);
12498 if (io_channel_read_blk(io, superblock,
12499 -SUPERBLOCK_SIZE, buf))
12500 continue;
12501#if BB_BIG_ENDIAN
12502 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12503 ext2fs_swap_super(sb);
12504#endif
12505 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12506 ret_sb = superblock;
12507 if (ctx) {
12508 ctx->superblock = superblock;
12509 ctx->blocksize = blocksize;
12510 }
12511 break;
12512 }
12513 }
12514
12515cleanup:
12516 if (io)
12517 io_channel_close(io);
12518 ext2fs_free_mem(&buf);
12519 return ret_sb;
12520}
12521
12522
12523/*
12524 * This function runs through the e2fsck passes and calls them all,
12525 * returning restart, abort, or cancel as necessary...
12526 */
12527typedef void (*pass_t)(e2fsck_t ctx);
12528
12529static const pass_t e2fsck_passes[] = {
12530 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12531 e2fsck_pass5, 0 };
12532
12533#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12534
12535static int e2fsck_run(e2fsck_t ctx)
12536{
12537 int i;
12538 pass_t e2fsck_pass;
12539
12540 if (setjmp(ctx->abort_loc)) {
12541 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12542 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12543 }
12544 ctx->flags |= E2F_FLAG_SETJMP_OK;
12545
12546 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12547 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12548 break;
12549 e2fsck_pass(ctx);
12550 if (ctx->progress)
12551 (void) (ctx->progress)(ctx, 0, 0, 0);
12552 }
12553 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12554
12555 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12556 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12557 return 0;
12558}
12559
12560
12561/*
12562 * unix.c - The unix-specific code for e2fsck
12563 */
12564
12565
12566/* Command line options */
12567static int swapfs;
12568#ifdef ENABLE_SWAPFS
12569static int normalize_swapfs;
12570#endif
12571static int cflag; /* check disk */
12572static int show_version_only;
12573static int verbose;
12574
12575#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12576
12577static void show_stats(e2fsck_t ctx)
12578{
12579 ext2_filsys fs = ctx->fs;
12580 int inodes, inodes_used, blocks, blocks_used;
12581 int dir_links;
12582 int num_files, num_links;
12583 int frag_percent;
12584
12585 dir_links = 2 * ctx->fs_directory_count - 1;
12586 num_files = ctx->fs_total_count - dir_links;
12587 num_links = ctx->fs_links_count - dir_links;
12588 inodes = fs->super->s_inodes_count;
12589 inodes_used = (fs->super->s_inodes_count -
12590 fs->super->s_free_inodes_count);
12591 blocks = fs->super->s_blocks_count;
12592 blocks_used = (fs->super->s_blocks_count -
12593 fs->super->s_free_blocks_count);
12594
12595 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12596 frag_percent = (frag_percent + 5) / 10;
12597
12598 if (!verbose) {
12599 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12600 ctx->device_name, inodes_used, inodes,
12601 frag_percent / 10, frag_percent % 10,
12602 blocks_used, blocks);
12603 return;
12604 }
12605 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12606 100 * inodes_used / inodes);
12607 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12608 P_E2("", "s", ctx->fs_fragmented),
12609 frag_percent / 10, frag_percent % 10);
12610 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12611 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12612 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12613 (int) ((long long) 100 * blocks_used / blocks));
12614 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12615 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12616 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12617 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12618 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12619 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12620 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12621 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12622 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12623 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12624 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12625}
12626
12627static void check_mount(e2fsck_t ctx)
12628{
12629 errcode_t retval;
12630 int cont;
12631
12632 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12633 &ctx->mount_flags);
12634 if (retval) {
12635 bb_error_msg(_("while determining whether %s is mounted."),
12636 ctx->filesystem_name);
12637 return;
12638 }
12639
12640 /*
12641 * If the filesystem isn't mounted, or it's the root filesystem
12642 * and it's mounted read-only, then everything's fine.
12643 */
12644 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12645 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12646 (ctx->mount_flags & EXT2_MF_READONLY)))
12647 return;
12648
12649 if (ctx->options & E2F_OPT_READONLY) {
12650 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12651 return;
12652 }
12653
12654 printf(_("%s is mounted. "), ctx->filesystem_name);
12655 if (!ctx->interactive)
12656 bb_error_msg_and_die(_("Cannot continue, aborting."));
12657 printf(_("\n\n\007\007\007\007WARNING!!! "
12658 "Running e2fsck on a mounted filesystem may cause\n"
12659 "SEVERE filesystem damage.\007\007\007\n\n"));
12660 cont = ask_yn(_("Do you really want to continue"), -1);
12661 if (!cont) {
12662 printf(_("check aborted.\n"));
Denis Vlasenko6398cf42007-04-11 17:04:29 +000012663 exit(0);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012664 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012665}
12666
12667static int is_on_batt(void)
12668{
12669 FILE *f;
12670 DIR *d;
12671 char tmp[80], tmp2[80], fname[80];
12672 unsigned int acflag;
12673 struct dirent* de;
12674
Denis Vlasenko5415c852008-07-21 23:05:26 +000012675 f = fopen_for_read("/proc/apm");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012676 if (f) {
12677 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12678 acflag = 1;
12679 fclose(f);
12680 return (acflag != 1);
12681 }
12682 d = opendir("/proc/acpi/ac_adapter");
12683 if (d) {
12684 while ((de=readdir(d)) != NULL) {
12685 if (!strncmp(".", de->d_name, 1))
12686 continue;
12687 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12688 de->d_name);
Denis Vlasenko5415c852008-07-21 23:05:26 +000012689 f = fopen_for_read(fname);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012690 if (!f)
12691 continue;
12692 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12693 tmp[0] = 0;
12694 fclose(f);
12695 if (strncmp(tmp, "off-line", 8) == 0) {
12696 closedir(d);
12697 return 1;
12698 }
12699 }
12700 closedir(d);
12701 }
12702 return 0;
12703}
12704
12705/*
12706 * This routine checks to see if a filesystem can be skipped; if so,
12707 * it will exit with EXIT_OK. Under some conditions it will print a
12708 * message explaining why a check is being forced.
12709 */
12710static void check_if_skip(e2fsck_t ctx)
12711{
12712 ext2_filsys fs = ctx->fs;
12713 const char *reason = NULL;
12714 unsigned int reason_arg = 0;
12715 long next_check;
12716 int batt = is_on_batt();
12717 time_t now = time(0);
12718
12719 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12720 return;
12721
12722 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12723 !ext2fs_test_valid(fs))
12724 reason = _(" contains a file system with errors");
12725 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12726 reason = _(" was not cleanly unmounted");
12727 else if ((fs->super->s_max_mnt_count > 0) &&
12728 (fs->super->s_mnt_count >=
12729 (unsigned) fs->super->s_max_mnt_count)) {
12730 reason = _(" has been mounted %u times without being checked");
12731 reason_arg = fs->super->s_mnt_count;
12732 if (batt && (fs->super->s_mnt_count <
12733 (unsigned) fs->super->s_max_mnt_count*2))
12734 reason = 0;
12735 } else if (fs->super->s_checkinterval &&
12736 ((now - fs->super->s_lastcheck) >=
12737 fs->super->s_checkinterval)) {
12738 reason = _(" has gone %u days without being checked");
12739 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12740 if (batt && ((now - fs->super->s_lastcheck) <
12741 fs->super->s_checkinterval*2))
12742 reason = 0;
12743 }
12744 if (reason) {
12745 fputs(ctx->device_name, stdout);
12746 printf(reason, reason_arg);
12747 fputs(_(", check forced.\n"), stdout);
12748 return;
12749 }
12750 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12751 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12752 fs->super->s_inodes_count,
12753 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12754 fs->super->s_blocks_count);
12755 next_check = 100000;
12756 if (fs->super->s_max_mnt_count > 0) {
12757 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12758 if (next_check <= 0)
12759 next_check = 1;
12760 }
12761 if (fs->super->s_checkinterval &&
12762 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12763 next_check = 1;
12764 if (next_check <= 5) {
12765 if (next_check == 1)
12766 fputs(_(" (check after next mount)"), stdout);
12767 else
12768 printf(_(" (check in %ld mounts)"), next_check);
12769 }
Denis Vlasenko4daad902007-09-27 10:20:47 +000012770 bb_putchar('\n');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012771 ext2fs_close(fs);
12772 ctx->fs = NULL;
12773 e2fsck_free_context(ctx);
12774 exit(EXIT_OK);
12775}
12776
12777/*
12778 * For completion notice
12779 */
12780struct percent_tbl {
12781 int max_pass;
12782 int table[32];
12783};
12784static const struct percent_tbl e2fsck_tbl = {
12785 5, { 0, 70, 90, 92, 95, 100 }
12786};
12787
12788static char bar[128], spaces[128];
12789
12790static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12791 int max)
12792{
12793 float percent;
12794
12795 if (pass <= 0)
12796 return 0.0;
12797 if (pass > tbl->max_pass || max == 0)
12798 return 100.0;
12799 percent = ((float) curr) / ((float) max);
12800 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12801 + tbl->table[pass-1]);
12802}
12803
12804void e2fsck_clear_progbar(e2fsck_t ctx)
12805{
12806 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12807 return;
12808
12809 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12810 ctx->stop_meta);
12811 fflush(stdout);
12812 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12813}
12814
12815int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12816 unsigned int dpynum)
12817{
12818 static const char spinner[] = "\\|/-";
12819 int i;
12820 unsigned int tick;
12821 struct timeval tv;
12822 int dpywidth;
12823 int fixed_percent;
12824
12825 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12826 return 0;
12827
12828 /*
12829 * Calculate the new progress position. If the
12830 * percentage hasn't changed, then we skip out right
12831 * away.
12832 */
12833 fixed_percent = (int) ((10 * percent) + 0.5);
12834 if (ctx->progress_last_percent == fixed_percent)
12835 return 0;
12836 ctx->progress_last_percent = fixed_percent;
12837
12838 /*
12839 * If we've already updated the spinner once within
12840 * the last 1/8th of a second, no point doing it
12841 * again.
12842 */
12843 gettimeofday(&tv, NULL);
12844 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12845 if ((tick == ctx->progress_last_time) &&
12846 (fixed_percent != 0) && (fixed_percent != 1000))
12847 return 0;
12848 ctx->progress_last_time = tick;
12849
12850 /*
12851 * Advance the spinner, and note that the progress bar
12852 * will be on the screen
12853 */
12854 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12855 ctx->flags |= E2F_FLAG_PROG_BAR;
12856
12857 dpywidth = 66 - strlen(label);
12858 dpywidth = 8 * (dpywidth / 8);
12859 if (dpynum)
12860 dpywidth -= 8;
12861
12862 i = ((percent * dpywidth) + 50) / 100;
12863 printf("%s%s: |%s%s", ctx->start_meta, label,
12864 bar + (sizeof(bar) - (i+1)),
12865 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12866 if (fixed_percent == 1000)
Denis Vlasenko4daad902007-09-27 10:20:47 +000012867 bb_putchar('|');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012868 else
Denis Vlasenko4daad902007-09-27 10:20:47 +000012869 bb_putchar(spinner[ctx->progress_pos & 3]);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012870 printf(" %4.1f%% ", percent);
12871 if (dpynum)
12872 printf("%u\r", dpynum);
12873 else
12874 fputs(" \r", stdout);
12875 fputs(ctx->stop_meta, stdout);
12876
12877 if (fixed_percent == 1000)
12878 e2fsck_clear_progbar(ctx);
12879 fflush(stdout);
12880
12881 return 0;
12882}
12883
12884static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12885 unsigned long cur, unsigned long max)
12886{
12887 char buf[80];
12888 float percent;
12889
12890 if (pass == 0)
12891 return 0;
12892
12893 if (ctx->progress_fd) {
12894 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12895 write(ctx->progress_fd, buf, strlen(buf));
12896 } else {
12897 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12898 e2fsck_simple_progress(ctx, ctx->device_name,
12899 percent, 0);
12900 }
12901 return 0;
12902}
12903
12904static void reserve_stdio_fds(void)
12905{
12906 int fd;
12907
12908 while (1) {
12909 fd = open(bb_dev_null, O_RDWR);
12910 if (fd > 2)
12911 break;
12912 if (fd < 0) {
12913 fprintf(stderr, _("ERROR: Cannot open "
12914 "/dev/null (%s)\n"),
12915 strerror(errno));
12916 break;
12917 }
12918 }
12919 close(fd);
12920}
12921
12922static void signal_progress_on(int sig FSCK_ATTR((unused)))
12923{
12924 e2fsck_t ctx = e2fsck_global_ctx;
12925
12926 if (!ctx)
12927 return;
12928
12929 ctx->progress = e2fsck_update_progress;
12930 ctx->progress_fd = 0;
12931}
12932
12933static void signal_progress_off(int sig FSCK_ATTR((unused)))
12934{
12935 e2fsck_t ctx = e2fsck_global_ctx;
12936
12937 if (!ctx)
12938 return;
12939
12940 e2fsck_clear_progbar(ctx);
12941 ctx->progress = 0;
12942}
12943
12944static void signal_cancel(int sig FSCK_ATTR((unused)))
12945{
12946 e2fsck_t ctx = e2fsck_global_ctx;
12947
12948 if (!ctx)
12949 exit(FSCK_CANCELED);
12950
12951 ctx->flags |= E2F_FLAG_CANCEL;
12952}
12953
12954static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12955{
12956 char *buf, *token, *next, *p, *arg;
12957 int ea_ver;
12958 int extended_usage = 0;
12959
12960 buf = string_copy(opts, 0);
12961 for (token = buf; token && *token; token = next) {
12962 p = strchr(token, ',');
12963 next = 0;
12964 if (p) {
12965 *p = 0;
12966 next = p+1;
12967 }
12968 arg = strchr(token, '=');
12969 if (arg) {
12970 *arg = 0;
12971 arg++;
12972 }
12973 if (strcmp(token, "ea_ver") == 0) {
12974 if (!arg) {
12975 extended_usage++;
12976 continue;
12977 }
12978 ea_ver = strtoul(arg, &p, 0);
12979 if (*p ||
12980 ((ea_ver != 1) && (ea_ver != 2))) {
12981 fprintf(stderr,
12982 _("Invalid EA version.\n"));
12983 extended_usage++;
12984 continue;
12985 }
12986 ctx->ext_attr_ver = ea_ver;
12987 } else {
12988 fprintf(stderr, _("Unknown extended option: %s\n"),
12989 token);
12990 extended_usage++;
12991 }
12992 }
12993 if (extended_usage) {
12994 bb_error_msg_and_die(
12995 "Extended options are separated by commas, "
12996 "and may take an argument which\n"
12997 "is set off by an equals ('=') sign. "
12998 "Valid extended options are:\n"
12999 "\tea_ver=<ea_version (1 or 2)>\n\n");
13000 }
13001}
13002
13003
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013004static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013005{
13006 int flush = 0;
13007 int c, fd;
13008 e2fsck_t ctx;
13009 errcode_t retval;
13010 struct sigaction sa;
13011 char *extended_opts = 0;
13012
13013 retval = e2fsck_allocate_context(&ctx);
13014 if (retval)
13015 return retval;
13016
13017 *ret_ctx = ctx;
13018
13019 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
13020 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
13021 if (isatty(0) && isatty(1)) {
13022 ctx->interactive = 1;
13023 } else {
13024 ctx->start_meta[0] = '\001';
13025 ctx->stop_meta[0] = '\002';
13026 }
13027 memset(bar, '=', sizeof(bar)-1);
13028 memset(spaces, ' ', sizeof(spaces)-1);
13029 blkid_get_cache(&ctx->blkid, NULL);
13030
13031 if (argc && *argv)
13032 ctx->program_name = *argv;
13033 else
13034 ctx->program_name = "e2fsck";
13035 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13036 switch (c) {
13037 case 'C':
13038 ctx->progress = e2fsck_update_progress;
13039 ctx->progress_fd = atoi(optarg);
13040 if (!ctx->progress_fd)
13041 break;
13042 /* Validate the file descriptor to avoid disasters */
13043 fd = dup(ctx->progress_fd);
13044 if (fd < 0) {
13045 fprintf(stderr,
13046 _("Error validating file descriptor %d: %s\n"),
13047 ctx->progress_fd,
13048 error_message(errno));
13049 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13050 } else
13051 close(fd);
13052 break;
13053 case 'D':
13054 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13055 break;
13056 case 'E':
13057 extended_opts = optarg;
13058 break;
13059 case 'p':
13060 case 'a':
13061 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13062 conflict_opt:
13063 bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
13064 }
13065 ctx->options |= E2F_OPT_PREEN;
13066 break;
13067 case 'n':
13068 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13069 goto conflict_opt;
13070 ctx->options |= E2F_OPT_NO;
13071 break;
13072 case 'y':
13073 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13074 goto conflict_opt;
13075 ctx->options |= E2F_OPT_YES;
13076 break;
13077 case 't':
13078 /* FIXME - This needs to go away in a future path - will change binary */
13079 fprintf(stderr, _("The -t option is not "
13080 "supported on this version of e2fsck.\n"));
13081 break;
13082 case 'c':
13083 if (cflag++)
13084 ctx->options |= E2F_OPT_WRITECHECK;
13085 ctx->options |= E2F_OPT_CHECKBLOCKS;
13086 break;
13087 case 'r':
13088 /* What we do by default, anyway! */
13089 break;
13090 case 'b':
13091 ctx->use_superblock = atoi(optarg);
13092 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13093 break;
13094 case 'B':
13095 ctx->blocksize = atoi(optarg);
13096 break;
13097 case 'I':
13098 ctx->inode_buffer_blocks = atoi(optarg);
13099 break;
13100 case 'j':
13101 ctx->journal_name = string_copy(optarg, 0);
13102 break;
13103 case 'P':
13104 ctx->process_inode_size = atoi(optarg);
13105 break;
13106 case 'd':
13107 ctx->options |= E2F_OPT_DEBUG;
13108 break;
13109 case 'f':
13110 ctx->options |= E2F_OPT_FORCE;
13111 break;
13112 case 'F':
13113 flush = 1;
13114 break;
13115 case 'v':
13116 verbose = 1;
13117 break;
13118 case 'V':
13119 show_version_only = 1;
13120 break;
13121 case 'N':
13122 ctx->device_name = optarg;
13123 break;
13124#ifdef ENABLE_SWAPFS
13125 case 's':
13126 normalize_swapfs = 1;
13127 case 'S':
13128 swapfs = 1;
13129 break;
13130#else
13131 case 's':
13132 case 'S':
13133 fprintf(stderr, _("Byte-swapping filesystems "
13134 "not compiled in this version "
13135 "of e2fsck\n"));
13136 exit(1);
13137#endif
13138 default:
13139 bb_show_usage();
13140 }
13141 if (show_version_only)
13142 return 0;
13143 if (optind != argc - 1)
13144 bb_show_usage();
13145 if ((ctx->options & E2F_OPT_NO) &&
13146 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13147 ctx->options |= E2F_OPT_READONLY;
13148 ctx->io_options = strchr(argv[optind], '?');
13149 if (ctx->io_options)
13150 *ctx->io_options++ = 0;
13151 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13152 if (!ctx->filesystem_name) {
13153 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13154 bb_error_msg_and_die(0);
13155 }
13156 if (extended_opts)
13157 parse_extended_opts(ctx, extended_opts);
13158
13159 if (flush) {
13160 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13161 if (fd < 0) {
13162 bb_error_msg(_("while opening %s for flushing"),
13163 ctx->filesystem_name);
13164 bb_error_msg_and_die(0);
13165 }
13166 if ((retval = ext2fs_sync_device(fd, 1))) {
13167 bb_error_msg(_("while trying to flush %s"),
13168 ctx->filesystem_name);
13169 bb_error_msg_and_die(0);
13170 }
13171 close(fd);
13172 }
13173#ifdef ENABLE_SWAPFS
13174 if (swapfs && cflag) {
13175 fprintf(stderr, _("Incompatible options not "
13176 "allowed when byte-swapping.\n"));
13177 exit(EXIT_USAGE);
13178 }
13179#endif
13180 /*
13181 * Set up signal action
13182 */
13183 memset(&sa, 0, sizeof(struct sigaction));
13184 sa.sa_handler = signal_cancel;
13185 sigaction(SIGINT, &sa, 0);
13186 sigaction(SIGTERM, &sa, 0);
13187#ifdef SA_RESTART
13188 sa.sa_flags = SA_RESTART;
13189#endif
13190 e2fsck_global_ctx = ctx;
13191 sa.sa_handler = signal_progress_on;
13192 sigaction(SIGUSR1, &sa, 0);
13193 sa.sa_handler = signal_progress_off;
13194 sigaction(SIGUSR2, &sa, 0);
13195
13196 /* Update our PATH to include /sbin if we need to run badblocks */
13197 if (cflag)
13198 e2fs_set_sbin_path();
13199 return 0;
13200}
13201
13202static const char my_ver_string[] = E2FSPROGS_VERSION;
13203static const char my_ver_date[] = E2FSPROGS_DATE;
13204
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013205int e2fsck_main (int argc, char **argv);
13206int e2fsck_main (int argc, char **argv)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013207{
13208 errcode_t retval;
13209 int exit_value = EXIT_OK;
13210 ext2_filsys fs = 0;
13211 io_manager io_ptr;
13212 struct ext2_super_block *sb;
13213 const char *lib_ver_date;
13214 int my_ver, lib_ver;
13215 e2fsck_t ctx;
13216 struct problem_context pctx;
13217 int flags, run_result;
13218
13219 clear_problem_context(&pctx);
13220
13221 my_ver = ext2fs_parse_version_string(my_ver_string);
13222 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13223 if (my_ver > lib_ver) {
13224 fprintf( stderr, _("Error: ext2fs library version "
13225 "out of date!\n"));
13226 show_version_only++;
13227 }
13228
13229 retval = PRS(argc, argv, &ctx);
13230 if (retval) {
13231 bb_error_msg(_("while trying to initialize program"));
13232 exit(EXIT_ERROR);
13233 }
13234 reserve_stdio_fds();
13235
13236 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13237 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13238 my_ver_date);
13239
13240 if (show_version_only) {
13241 fprintf(stderr, _("\tUsing %s, %s\n"),
13242 error_message(EXT2_ET_BASE), lib_ver_date);
13243 exit(EXIT_OK);
13244 }
13245
13246 check_mount(ctx);
13247
13248 if (!(ctx->options & E2F_OPT_PREEN) &&
13249 !(ctx->options & E2F_OPT_NO) &&
13250 !(ctx->options & E2F_OPT_YES)) {
13251 if (!ctx->interactive)
13252 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13253 }
13254 ctx->superblock = ctx->use_superblock;
13255restart:
13256#ifdef CONFIG_TESTIO_DEBUG
13257 io_ptr = test_io_manager;
13258 test_io_backing_manager = unix_io_manager;
13259#else
13260 io_ptr = unix_io_manager;
13261#endif
13262 flags = 0;
13263 if ((ctx->options & E2F_OPT_READONLY) == 0)
13264 flags |= EXT2_FLAG_RW;
13265
13266 if (ctx->superblock && ctx->blocksize) {
13267 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13268 flags, ctx->superblock, ctx->blocksize,
13269 io_ptr, &fs);
13270 } else if (ctx->superblock) {
13271 int blocksize;
13272 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13273 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13274 retval = ext2fs_open2(ctx->filesystem_name,
13275 ctx->io_options, flags,
13276 ctx->superblock, blocksize,
13277 io_ptr, &fs);
13278 if (!retval)
13279 break;
13280 }
13281 } else
13282 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13283 flags, 0, 0, io_ptr, &fs);
13284 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13285 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13286 ((retval == EXT2_ET_BAD_MAGIC) ||
13287 ((retval == 0) && ext2fs_check_desc(fs)))) {
13288 if (!fs || (fs->group_desc_count > 1)) {
13289 printf(_("%s trying backup blocks...\n"),
13290 retval ? _("Couldn't find ext2 superblock,") :
13291 _("Group descriptors look bad..."));
13292 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13293 if (fs)
13294 ext2fs_close(fs);
13295 goto restart;
13296 }
13297 }
13298 if (retval) {
13299 bb_error_msg(_("while trying to open %s"),
13300 ctx->filesystem_name);
13301 if (retval == EXT2_ET_REV_TOO_HIGH) {
13302 printf(_("The filesystem revision is apparently "
13303 "too high for this version of e2fsck.\n"
13304 "(Or the filesystem superblock "
13305 "is corrupt)\n\n"));
13306 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13307 } else if (retval == EXT2_ET_SHORT_READ)
13308 printf(_("Could this be a zero-length partition?\n"));
13309 else if ((retval == EPERM) || (retval == EACCES))
13310 printf(_("You must have %s access to the "
13311 "filesystem or be root\n"),
13312 (ctx->options & E2F_OPT_READONLY) ?
13313 "r/o" : "r/w");
13314 else if (retval == ENXIO)
13315 printf(_("Possibly non-existent or swap device?\n"));
13316#ifdef EROFS
13317 else if (retval == EROFS)
13318 printf(_("Disk write-protected; use the -n option "
13319 "to do a read-only\n"
13320 "check of the device.\n"));
13321#endif
13322 else
13323 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13324 bb_error_msg_and_die(0);
13325 }
13326 ctx->fs = fs;
13327 fs->priv_data = ctx;
13328 sb = fs->super;
13329 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13330 bb_error_msg(_("while trying to open %s"),
13331 ctx->filesystem_name);
13332 get_newer:
13333 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13334 }
13335
13336 /*
13337 * Set the device name, which is used whenever we print error
13338 * or informational messages to the user.
13339 */
13340 if (ctx->device_name == 0 &&
13341 (sb->s_volume_name[0] != 0)) {
13342 ctx->device_name = string_copy(sb->s_volume_name,
13343 sizeof(sb->s_volume_name));
13344 }
13345 if (ctx->device_name == 0)
13346 ctx->device_name = ctx->filesystem_name;
13347
13348 /*
13349 * Make sure the ext3 superblock fields are consistent.
13350 */
13351 retval = e2fsck_check_ext3_journal(ctx);
13352 if (retval) {
13353 bb_error_msg(_("while checking ext3 journal for %s"),
13354 ctx->device_name);
13355 bb_error_msg_and_die(0);
13356 }
13357
13358 /*
13359 * Check to see if we need to do ext3-style recovery. If so,
13360 * do it, and then restart the fsck.
13361 */
13362 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13363 if (ctx->options & E2F_OPT_READONLY) {
13364 printf(_("Warning: skipping journal recovery "
13365 "because doing a read-only filesystem "
13366 "check.\n"));
13367 io_channel_flush(ctx->fs->io);
13368 } else {
13369 if (ctx->flags & E2F_FLAG_RESTARTED) {
13370 /*
13371 * Whoops, we attempted to run the
13372 * journal twice. This should never
13373 * happen, unless the hardware or
13374 * device driver is being bogus.
13375 */
13376 bb_error_msg(_("cannot set superblock flags on %s"), ctx->device_name);
13377 bb_error_msg_and_die(0);
13378 }
13379 retval = e2fsck_run_ext3_journal(ctx);
13380 if (retval) {
13381 bb_error_msg(_("while recovering ext3 journal of %s"),
13382 ctx->device_name);
13383 bb_error_msg_and_die(0);
13384 }
13385 ext2fs_close(ctx->fs);
13386 ctx->fs = 0;
13387 ctx->flags |= E2F_FLAG_RESTARTED;
13388 goto restart;
13389 }
13390 }
13391
13392 /*
13393 * Check for compatibility with the feature sets. We need to
13394 * be more stringent than ext2fs_open().
13395 */
13396 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13397 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13398 bb_error_msg("(%s)", ctx->device_name);
13399 goto get_newer;
13400 }
13401 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13402 bb_error_msg("(%s)", ctx->device_name);
13403 goto get_newer;
13404 }
13405#ifdef ENABLE_COMPRESSION
13406 /* FIXME - do we support this at all? */
13407 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13408 bb_error_msg(_("Warning: compression support is experimental."));
13409#endif
13410#ifndef ENABLE_HTREE
13411 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13412 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13413 "but filesystem %s has HTREE directories."),
13414 ctx->device_name);
13415 goto get_newer;
13416 }
13417#endif
13418
13419 /*
13420 * If the user specified a specific superblock, presumably the
13421 * master superblock has been trashed. So we mark the
13422 * superblock as dirty, so it can be written out.
13423 */
13424 if (ctx->superblock &&
13425 !(ctx->options & E2F_OPT_READONLY))
13426 ext2fs_mark_super_dirty(fs);
13427
13428 /*
13429 * We only update the master superblock because (a) paranoia;
13430 * we don't want to corrupt the backup superblocks, and (b) we
13431 * don't need to update the mount count and last checked
13432 * fields in the backup superblock (the kernel doesn't
13433 * update the backup superblocks anyway).
13434 */
13435 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13436
13437 ehandler_init(fs->io);
13438
13439 if (ctx->superblock)
13440 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13441 ext2fs_mark_valid(fs);
13442 check_super_block(ctx);
13443 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13444 bb_error_msg_and_die(0);
13445 check_if_skip(ctx);
13446 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13447 bb_error_msg_and_die(0);
13448#ifdef ENABLE_SWAPFS
13449
13450#ifdef WORDS_BIGENDIAN
13451#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13452#else
13453#define NATIVE_FLAG 0
13454#endif
13455
13456
13457 if (normalize_swapfs) {
13458 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13459 fprintf(stderr, _("%s: Filesystem byte order "
13460 "already normalized.\n"), ctx->device_name);
13461 bb_error_msg_and_die(0);
13462 }
13463 }
13464 if (swapfs) {
13465 swap_filesys(ctx);
13466 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13467 bb_error_msg_and_die(0);
13468 }
13469#endif
13470
13471 /*
13472 * Mark the system as valid, 'til proven otherwise
13473 */
13474 ext2fs_mark_valid(fs);
13475
13476 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13477 if (retval) {
13478 bb_error_msg(_("while reading bad blocks inode"));
13479 preenhalt(ctx);
13480 printf(_("This doesn't bode well,"
13481 " but we'll try to go on...\n"));
13482 }
13483
13484 run_result = e2fsck_run(ctx);
13485 e2fsck_clear_progbar(ctx);
13486 if (run_result == E2F_FLAG_RESTART) {
13487 printf(_("Restarting e2fsck from the beginning...\n"));
13488 retval = e2fsck_reset_context(ctx);
13489 if (retval) {
13490 bb_error_msg(_("while resetting context"));
13491 bb_error_msg_and_die(0);
13492 }
13493 ext2fs_close(fs);
13494 goto restart;
13495 }
13496 if (run_result & E2F_FLAG_CANCEL) {
13497 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13498 ctx->device_name : ctx->filesystem_name);
13499 exit_value |= FSCK_CANCELED;
13500 }
13501 if (run_result & E2F_FLAG_ABORT)
13502 bb_error_msg_and_die(_("aborted"));
13503
13504 /* Cleanup */
13505 if (ext2fs_test_changed(fs)) {
13506 exit_value |= EXIT_NONDESTRUCT;
13507 if (!(ctx->options & E2F_OPT_PREEN))
13508 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13509 ctx->device_name);
13510 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13511 printf(_("%s: ***** REBOOT LINUX *****\n"),
13512 ctx->device_name);
13513 exit_value |= EXIT_DESTRUCT;
13514 }
13515 }
13516 if (!ext2fs_test_valid(fs)) {
13517 printf(_("\n%s: ********** WARNING: Filesystem still has "
13518 "errors **********\n\n"), ctx->device_name);
13519 exit_value |= EXIT_UNCORRECTED;
13520 exit_value &= ~EXIT_NONDESTRUCT;
13521 }
13522 if (exit_value & FSCK_CANCELED)
13523 exit_value &= ~EXIT_NONDESTRUCT;
13524 else {
13525 show_stats(ctx);
13526 if (!(ctx->options & E2F_OPT_READONLY)) {
13527 if (ext2fs_test_valid(fs)) {
13528 if (!(sb->s_state & EXT2_VALID_FS))
13529 exit_value |= EXIT_NONDESTRUCT;
13530 sb->s_state = EXT2_VALID_FS;
13531 } else
13532 sb->s_state &= ~EXT2_VALID_FS;
13533 sb->s_mnt_count = 0;
13534 sb->s_lastcheck = time(NULL);
13535 ext2fs_mark_super_dirty(fs);
13536 }
13537 }
13538
13539 e2fsck_write_bitmaps(ctx);
13540
13541 ext2fs_close(fs);
13542 ctx->fs = NULL;
13543 free(ctx->filesystem_name);
13544 free(ctx->journal_name);
13545 e2fsck_free_context(ctx);
13546
13547 return exit_value;
13548}