*: mass cosmetic removal of extra empty lines. no code changes
[platform/upstream/busybox.git] / e2fsprogs / old_e2fsprogs / e2fsck.c
1 /* 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 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
33
34 #define _(x) x
35 #define N_(x) x
36
37 /*
38  * Procedure declarations
39  */
40
41 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
42
43 /* pass1.c */
44 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
45
46 /* pass2.c */
47 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
48                                     ext2_ino_t ino, char *buf);
49
50 /* pass3.c */
51 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
52 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
53                                          int num, int gauranteed_size);
54 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
55 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
56                                            int adj);
57
58 /* rehash.c */
59 static void e2fsck_rehash_directories(e2fsck_t ctx);
60
61 /* util.c */
62 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
63                                     const char *description);
64 static int ask(e2fsck_t ctx, const char * string, int def);
65 static void e2fsck_read_bitmaps(e2fsck_t ctx);
66 static void preenhalt(e2fsck_t ctx);
67 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
68                               struct ext2_inode * inode, const char * proc);
69 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
70                                struct ext2_inode * inode, const char * proc);
71 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
72                            const char *name, io_manager manager);
73
74 /* unix.c */
75 static void e2fsck_clear_progbar(e2fsck_t ctx);
76 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
77                                   float percent, unsigned int dpynum);
78
79
80 /*
81  * problem.h --- e2fsck problem error codes
82  */
83
84 typedef __u32 problem_t;
85
86 struct problem_context {
87         errcode_t       errcode;
88         ext2_ino_t      ino, ino2, dir;
89         struct ext2_inode *inode;
90         struct ext2_dir_entry *dirent;
91         blk_t           blk, blk2;
92         e2_blkcnt_t     blkcount;
93         int             group;
94         __u64           num;
95         const char      *str;
96 };
97
98
99 /*
100  * Function declarations
101  */
102 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
103 static int end_problem_latch(e2fsck_t ctx, int mask);
104 static int set_latch_flags(int mask, int setflags, int clearflags);
105 static void clear_problem_context(struct problem_context *ctx);
106
107 /*
108  * Dictionary Abstract Data Type
109  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
110  *
111  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
112  * kazlib_1_20
113  */
114
115 #ifndef DICT_H
116 #define DICT_H
117
118 /*
119  * Blurb for inclusion into C++ translation units
120  */
121
122 typedef unsigned long dictcount_t;
123 #define DICTCOUNT_T_MAX ULONG_MAX
124
125 /*
126  * The dictionary is implemented as a red-black tree
127  */
128
129 typedef enum { dnode_red, dnode_black } dnode_color_t;
130
131 typedef struct dnode_t {
132         struct dnode_t *dict_left;
133         struct dnode_t *dict_right;
134         struct dnode_t *dict_parent;
135         dnode_color_t dict_color;
136         const void *dict_key;
137         void *dict_data;
138 } dnode_t;
139
140 typedef int (*dict_comp_t)(const void *, const void *);
141 typedef void (*dnode_free_t)(dnode_t *);
142
143 typedef struct dict_t {
144         dnode_t dict_nilnode;
145         dictcount_t dict_nodecount;
146         dictcount_t dict_maxcount;
147         dict_comp_t dict_compare;
148         dnode_free_t dict_freenode;
149         int dict_dupes;
150 } dict_t;
151
152 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
153
154 typedef struct dict_load_t {
155         dict_t *dict_dictptr;
156         dnode_t dict_nilnode;
157 } dict_load_t;
158
159 #define dict_count(D) ((D)->dict_nodecount)
160 #define dnode_get(N) ((N)->dict_data)
161 #define dnode_getkey(N) ((N)->dict_key)
162
163 #endif
164
165 /*
166  * Compatibility header file for e2fsck which should be included
167  * instead of linux/jfs.h
168  *
169  * Copyright (C) 2000 Stephen C. Tweedie
170  */
171
172 /*
173  * Pull in the definition of the e2fsck context structure
174  */
175
176 struct buffer_head {
177         char            b_data[8192];
178         e2fsck_t        b_ctx;
179         io_channel      b_io;
180         int             b_size;
181         blk_t           b_blocknr;
182         int             b_dirty;
183         int             b_uptodate;
184         int             b_err;
185 };
186
187
188 #define K_DEV_FS        1
189 #define K_DEV_JOURNAL   2
190
191 #define lock_buffer(bh) do {} while (0)
192 #define unlock_buffer(bh) do {} while (0)
193 #define buffer_req(bh) 1
194 #define do_readahead(journal, start) do {} while (0)
195
196 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
197
198 typedef struct {
199         int     object_length;
200 } kmem_cache_t;
201
202 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
203
204 /*
205  * We use the standard libext2fs portability tricks for inline
206  * functions.
207  */
208
209 static kmem_cache_t * do_cache_create(int len)
210 {
211         kmem_cache_t *new_cache;
212
213         new_cache = xmalloc(sizeof(*new_cache));
214         new_cache->object_length = len;
215         return new_cache;
216 }
217
218 static void do_cache_destroy(kmem_cache_t *cache)
219 {
220         free(cache);
221 }
222
223
224 /*
225  * Dictionary Abstract Data Type
226  */
227
228
229 /*
230  * These macros provide short convenient names for structure members,
231  * which are embellished with dict_ prefixes so that they are
232  * properly confined to the documented namespace. It's legal for a
233  * program which uses dict to define, for instance, a macro called ``parent''.
234  * Such a macro would interfere with the dnode_t struct definition.
235  * In general, highly portable and reusable C modules which expose their
236  * structures need to confine structure member names to well-defined spaces.
237  * The resulting identifiers aren't necessarily convenient to use, nor
238  * readable, in the implementation, however!
239  */
240
241 #define left dict_left
242 #define right dict_right
243 #define parent dict_parent
244 #define color dict_color
245 #define key dict_key
246 #define data dict_data
247
248 #define nilnode dict_nilnode
249 #define maxcount dict_maxcount
250 #define compare dict_compare
251 #define dupes dict_dupes
252
253 #define dict_root(D) ((D)->nilnode.left)
254 #define dict_nil(D) (&(D)->nilnode)
255
256 static void dnode_free(dnode_t *node);
257
258 /*
259  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
260  * its right child C are rearranged so that the P instead becomes the left
261  * child of C.   The left subtree of C is inherited as the new right subtree
262  * for P.  The ordering of the keys within the tree is thus preserved.
263  */
264
265 static void rotate_left(dnode_t *upper)
266 {
267         dnode_t *lower, *lowleft, *upparent;
268
269         lower = upper->right;
270         upper->right = lowleft = lower->left;
271         lowleft->parent = upper;
272
273         lower->parent = upparent = upper->parent;
274
275         /* don't need to check for root node here because root->parent is
276            the sentinel nil node, and root->parent->left points back to root */
277
278         if (upper == upparent->left) {
279                 upparent->left = lower;
280         } else {
281                 assert (upper == upparent->right);
282                 upparent->right = lower;
283         }
284
285         lower->left = upper;
286         upper->parent = lower;
287 }
288
289 /*
290  * This operation is the ``mirror'' image of rotate_left. It is
291  * the same procedure, but with left and right interchanged.
292  */
293
294 static void rotate_right(dnode_t *upper)
295 {
296         dnode_t *lower, *lowright, *upparent;
297
298         lower = upper->left;
299         upper->left = lowright = lower->right;
300         lowright->parent = upper;
301
302         lower->parent = upparent = upper->parent;
303
304         if (upper == upparent->right) {
305                 upparent->right = lower;
306         } else {
307                 assert (upper == upparent->left);
308                 upparent->left = lower;
309         }
310
311         lower->right = upper;
312         upper->parent = lower;
313 }
314
315 /*
316  * Do a postorder traversal of the tree rooted at the specified
317  * node and free everything under it.  Used by dict_free().
318  */
319
320 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
321 {
322         if (node == nil)
323                 return;
324         free_nodes(dict, node->left, nil);
325         free_nodes(dict, node->right, nil);
326         dict->dict_freenode(node);
327 }
328
329 /*
330  * Verify that the tree contains the given node. This is done by
331  * traversing all of the nodes and comparing their pointers to the
332  * given pointer. Returns 1 if the node is found, otherwise
333  * returns zero. It is intended for debugging purposes.
334  */
335
336 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
337 {
338         if (root != nil) {
339                 return root == node
340                         || verify_dict_has_node(nil, root->left, node)
341                         || verify_dict_has_node(nil, root->right, node);
342         }
343         return 0;
344 }
345
346
347 /*
348  * Select a different set of node allocator routines.
349  */
350
351 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
352 {
353         assert(dict_count(dict) == 0);
354         dict->dict_freenode = fr;
355 }
356
357 /*
358  * Free all the nodes in the dictionary by using the dictionary's
359  * installed free routine. The dictionary is emptied.
360  */
361
362 static void dict_free_nodes(dict_t *dict)
363 {
364         dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
365         free_nodes(dict, root, nil);
366         dict->dict_nodecount = 0;
367         dict->nilnode.left = &dict->nilnode;
368         dict->nilnode.right = &dict->nilnode;
369 }
370
371 /*
372  * Initialize a user-supplied dictionary object.
373  */
374
375 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
376 {
377         dict->compare = comp;
378         dict->dict_freenode = dnode_free;
379         dict->dict_nodecount = 0;
380         dict->maxcount = maxcount;
381         dict->nilnode.left = &dict->nilnode;
382         dict->nilnode.right = &dict->nilnode;
383         dict->nilnode.parent = &dict->nilnode;
384         dict->nilnode.color = dnode_black;
385         dict->dupes = 0;
386         return dict;
387 }
388
389 /*
390  * Locate a node in the dictionary having the given key.
391  * If the node is not found, a null a pointer is returned (rather than
392  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
393  * located node is returned.
394  */
395
396 static dnode_t *dict_lookup(dict_t *dict, const void *key)
397 {
398         dnode_t *root = dict_root(dict);
399         dnode_t *nil = dict_nil(dict);
400         dnode_t *saved;
401         int result;
402
403         /* simple binary search adapted for trees that contain duplicate keys */
404
405         while (root != nil) {
406                 result = dict->compare(key, root->key);
407                 if (result < 0)
408                         root = root->left;
409                 else if (result > 0)
410                         root = root->right;
411                 else {
412                         if (!dict->dupes) { /* no duplicates, return match          */
413                                 return root;
414                         } else {            /* could be dupes, find leftmost one    */
415                                 do {
416                                         saved = root;
417                                         root = root->left;
418                                         while (root != nil && dict->compare(key, root->key))
419                                                 root = root->right;
420                                 } while (root != nil);
421                                 return saved;
422                         }
423                 }
424         }
425
426         return NULL;
427 }
428
429 /*
430  * Insert a node into the dictionary. The node should have been
431  * initialized with a data field. All other fields are ignored.
432  * The behavior is undefined if the user attempts to insert into
433  * a dictionary that is already full (for which the dict_isfull()
434  * function returns true).
435  */
436
437 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
438 {
439         dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
440         dnode_t *parent = nil, *uncle, *grandpa;
441         int result = -1;
442
443         node->key = key;
444
445         /* basic binary tree insert */
446
447         while (where != nil) {
448                 parent = where;
449                 result = dict->compare(key, where->key);
450                 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
451                 assert(dict->dupes || result != 0);
452                 if (result < 0)
453                         where = where->left;
454                 else
455                         where = where->right;
456         }
457
458         assert(where == nil);
459
460         if (result < 0)
461                 parent->left = node;
462         else
463                 parent->right = node;
464
465         node->parent = parent;
466         node->left = nil;
467         node->right = nil;
468
469         dict->dict_nodecount++;
470
471         /* red black adjustments */
472
473         node->color = dnode_red;
474
475         while (parent->color == dnode_red) {
476                 grandpa = parent->parent;
477                 if (parent == grandpa->left) {
478                         uncle = grandpa->right;
479                         if (uncle->color == dnode_red) {    /* red parent, red uncle */
480                                 parent->color = dnode_black;
481                                 uncle->color = dnode_black;
482                                 grandpa->color = dnode_red;
483                                 node = grandpa;
484                                 parent = grandpa->parent;
485                         } else {                            /* red parent, black uncle */
486                                 if (node == parent->right) {
487                                         rotate_left(parent);
488                                         parent = node;
489                                         assert (grandpa == parent->parent);
490                                         /* rotation between parent and child preserves grandpa */
491                                 }
492                                 parent->color = dnode_black;
493                                 grandpa->color = dnode_red;
494                                 rotate_right(grandpa);
495                                 break;
496                         }
497                 } else {        /* symmetric cases: parent == parent->parent->right */
498                         uncle = grandpa->left;
499                         if (uncle->color == dnode_red) {
500                                 parent->color = dnode_black;
501                                 uncle->color = dnode_black;
502                                 grandpa->color = dnode_red;
503                                 node = grandpa;
504                                 parent = grandpa->parent;
505                         } else {
506                                 if (node == parent->left) {
507                                         rotate_right(parent);
508                                         parent = node;
509                                         assert (grandpa == parent->parent);
510                                 }
511                                 parent->color = dnode_black;
512                                 grandpa->color = dnode_red;
513                                 rotate_left(grandpa);
514                                 break;
515                         }
516                 }
517         }
518
519         dict_root(dict)->color = dnode_black;
520 }
521
522 /*
523  * Allocate a node using the dictionary's allocator routine, give it
524  * the data item.
525  */
526
527 static dnode_t *dnode_init(dnode_t *dnode, void *data)
528 {
529         dnode->data = data;
530         dnode->parent = NULL;
531         dnode->left = NULL;
532         dnode->right = NULL;
533         return dnode;
534 }
535
536 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
537 {
538         dnode_t *node = xmalloc(sizeof(dnode_t));
539
540         dnode_init(node, data);
541         dict_insert(dict, node, key);
542         return 1;
543 }
544
545 /*
546  * Return the node with the lowest (leftmost) key. If the dictionary is empty
547  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
548  */
549
550 static dnode_t *dict_first(dict_t *dict)
551 {
552         dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
553
554         if (root != nil)
555                 while ((left = root->left) != nil)
556                         root = left;
557
558         return (root == nil) ? NULL : root;
559 }
560
561 /*
562  * Return the given node's successor node---the node which has the
563  * next key in the the left to right ordering. If the node has
564  * no successor, a null pointer is returned rather than a pointer to
565  * the nil node.
566  */
567
568 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
569 {
570         dnode_t *nil = dict_nil(dict), *parent, *left;
571
572         if (curr->right != nil) {
573                 curr = curr->right;
574                 while ((left = curr->left) != nil)
575                         curr = left;
576                 return curr;
577         }
578
579         parent = curr->parent;
580
581         while (parent != nil && curr == parent->right) {
582                 curr = parent;
583                 parent = curr->parent;
584         }
585
586         return (parent == nil) ? NULL : parent;
587 }
588
589
590 static void dnode_free(dnode_t *node)
591 {
592         free(node);
593 }
594
595
596 #undef left
597 #undef right
598 #undef parent
599 #undef color
600 #undef key
601 #undef data
602
603 #undef nilnode
604 #undef maxcount
605 #undef compare
606 #undef dupes
607
608
609 /*
610  * dirinfo.c --- maintains the directory information table for e2fsck.
611  */
612
613 /*
614  * This subroutine is called during pass1 to create a directory info
615  * entry.  During pass1, the passed-in parent is 0; it will get filled
616  * in during pass2.
617  */
618 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
619 {
620         struct dir_info *dir;
621         int             i, j;
622         ext2_ino_t      num_dirs;
623         errcode_t       retval;
624         unsigned long   old_size;
625
626         if (!ctx->dir_info) {
627                 ctx->dir_info_count = 0;
628                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
629                 if (retval)
630                         num_dirs = 1024;        /* Guess */
631                 ctx->dir_info_size = num_dirs + 10;
632                 ctx->dir_info  = (struct dir_info *)
633                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
634                                                * sizeof (struct dir_info),
635                                                "directory map");
636         }
637
638         if (ctx->dir_info_count >= ctx->dir_info_size) {
639                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
640                 ctx->dir_info_size += 10;
641                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
642                                            sizeof(struct dir_info),
643                                            &ctx->dir_info);
644                 if (retval) {
645                         ctx->dir_info_size -= 10;
646                         return;
647                 }
648         }
649
650         /*
651          * Normally, add_dir_info is called with each inode in
652          * sequential order; but once in a while (like when pass 3
653          * needs to recreate the root directory or lost+found
654          * directory) it is called out of order.  In those cases, we
655          * need to move the dir_info entries down to make room, since
656          * the dir_info array needs to be sorted by inode number for
657          * get_dir_info()'s sake.
658          */
659         if (ctx->dir_info_count &&
660             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
661                 for (i = ctx->dir_info_count-1; i > 0; i--)
662                         if (ctx->dir_info[i-1].ino < ino)
663                                 break;
664                 dir = &ctx->dir_info[i];
665                 if (dir->ino != ino)
666                         for (j = ctx->dir_info_count++; j > i; j--)
667                                 ctx->dir_info[j] = ctx->dir_info[j-1];
668         } else
669                 dir = &ctx->dir_info[ctx->dir_info_count++];
670
671         dir->ino = ino;
672         dir->dotdot = parent;
673         dir->parent = parent;
674 }
675
676 /*
677  * get_dir_info() --- given an inode number, try to find the directory
678  * information entry for it.
679  */
680 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
681 {
682         int     low, high, mid;
683
684         low = 0;
685         high = ctx->dir_info_count-1;
686         if (!ctx->dir_info)
687                 return 0;
688         if (ino == ctx->dir_info[low].ino)
689                 return &ctx->dir_info[low];
690         if  (ino == ctx->dir_info[high].ino)
691                 return &ctx->dir_info[high];
692
693         while (low < high) {
694                 mid = (low+high)/2;
695                 if (mid == low || mid == high)
696                         break;
697                 if (ino == ctx->dir_info[mid].ino)
698                         return &ctx->dir_info[mid];
699                 if (ino < ctx->dir_info[mid].ino)
700                         high = mid;
701                 else
702                         low = mid;
703         }
704         return 0;
705 }
706
707 /*
708  * Free the dir_info structure when it isn't needed any more.
709  */
710 static void e2fsck_free_dir_info(e2fsck_t ctx)
711 {
712         ext2fs_free_mem(&ctx->dir_info);
713         ctx->dir_info_size = 0;
714         ctx->dir_info_count = 0;
715 }
716
717 /*
718  * Return the count of number of directories in the dir_info structure
719  */
720 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
721 {
722         return ctx->dir_info_count;
723 }
724
725 /*
726  * A simple interator function
727  */
728 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
729 {
730         if (*control >= ctx->dir_info_count)
731                 return 0;
732
733         return ctx->dir_info + (*control)++;
734 }
735
736 /*
737  * dirinfo.c --- maintains the directory information table for e2fsck.
738  *
739  */
740
741 #ifdef ENABLE_HTREE
742
743 /*
744  * This subroutine is called during pass1 to create a directory info
745  * entry.  During pass1, the passed-in parent is 0; it will get filled
746  * in during pass2.
747  */
748 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
749 {
750         struct dx_dir_info *dir;
751         int             i, j;
752         errcode_t       retval;
753         unsigned long   old_size;
754
755         if (!ctx->dx_dir_info) {
756                 ctx->dx_dir_info_count = 0;
757                 ctx->dx_dir_info_size = 100; /* Guess */
758                 ctx->dx_dir_info  = (struct dx_dir_info *)
759                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
760                                                * sizeof (struct dx_dir_info),
761                                                "directory map");
762         }
763
764         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
765                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
766                 ctx->dx_dir_info_size += 10;
767                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
768                                            sizeof(struct dx_dir_info),
769                                            &ctx->dx_dir_info);
770                 if (retval) {
771                         ctx->dx_dir_info_size -= 10;
772                         return;
773                 }
774         }
775
776         /*
777          * Normally, add_dx_dir_info is called with each inode in
778          * sequential order; but once in a while (like when pass 3
779          * needs to recreate the root directory or lost+found
780          * directory) it is called out of order.  In those cases, we
781          * need to move the dx_dir_info entries down to make room, since
782          * the dx_dir_info array needs to be sorted by inode number for
783          * get_dx_dir_info()'s sake.
784          */
785         if (ctx->dx_dir_info_count &&
786             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
787                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
788                         if (ctx->dx_dir_info[i-1].ino < ino)
789                                 break;
790                 dir = &ctx->dx_dir_info[i];
791                 if (dir->ino != ino)
792                         for (j = ctx->dx_dir_info_count++; j > i; j--)
793                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
794         } else
795                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
796
797         dir->ino = ino;
798         dir->numblocks = num_blocks;
799         dir->hashversion = 0;
800         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
801                                        * sizeof (struct dx_dirblock_info),
802                                        "dx_block info array");
803 }
804
805 /*
806  * get_dx_dir_info() --- given an inode number, try to find the directory
807  * information entry for it.
808  */
809 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
810 {
811         int     low, high, mid;
812
813         low = 0;
814         high = ctx->dx_dir_info_count-1;
815         if (!ctx->dx_dir_info)
816                 return 0;
817         if (ino == ctx->dx_dir_info[low].ino)
818                 return &ctx->dx_dir_info[low];
819         if  (ino == ctx->dx_dir_info[high].ino)
820                 return &ctx->dx_dir_info[high];
821
822         while (low < high) {
823                 mid = (low+high)/2;
824                 if (mid == low || mid == high)
825                         break;
826                 if (ino == ctx->dx_dir_info[mid].ino)
827                         return &ctx->dx_dir_info[mid];
828                 if (ino < ctx->dx_dir_info[mid].ino)
829                         high = mid;
830                 else
831                         low = mid;
832         }
833         return 0;
834 }
835
836 /*
837  * Free the dx_dir_info structure when it isn't needed any more.
838  */
839 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
840 {
841         int     i;
842         struct dx_dir_info *dir;
843
844         if (ctx->dx_dir_info) {
845                 dir = ctx->dx_dir_info;
846                 for (i=0; i < ctx->dx_dir_info_count; i++) {
847                         ext2fs_free_mem(&dir->dx_block);
848                 }
849                 ext2fs_free_mem(&ctx->dx_dir_info);
850         }
851         ctx->dx_dir_info_size = 0;
852         ctx->dx_dir_info_count = 0;
853 }
854
855 /*
856  * A simple interator function
857  */
858 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
859 {
860         if (*control >= ctx->dx_dir_info_count)
861                 return 0;
862
863         return ctx->dx_dir_info + (*control)++;
864 }
865
866 #endif /* ENABLE_HTREE */
867 /*
868  * e2fsck.c - a consistency checker for the new extended file system.
869  *
870  */
871
872 /*
873  * This function allocates an e2fsck context
874  */
875 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
876 {
877         e2fsck_t        context;
878         errcode_t       retval;
879
880         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
881         if (retval)
882                 return retval;
883
884         memset(context, 0, sizeof(struct e2fsck_struct));
885
886         context->process_inode_size = 256;
887         context->ext_attr_ver = 2;
888
889         *ret = context;
890         return 0;
891 }
892
893 struct ea_refcount_el {
894         blk_t   ea_blk;
895         int     ea_count;
896 };
897
898 struct ea_refcount {
899         blk_t           count;
900         blk_t           size;
901         blk_t           cursor;
902         struct ea_refcount_el   *list;
903 };
904
905 static void ea_refcount_free(ext2_refcount_t refcount)
906 {
907         if (!refcount)
908                 return;
909
910         ext2fs_free_mem(&refcount->list);
911         ext2fs_free_mem(&refcount);
912 }
913
914 /*
915  * This function resets an e2fsck context; it is called when e2fsck
916  * needs to be restarted.
917  */
918 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
919 {
920         ctx->flags = 0;
921         ctx->lost_and_found = 0;
922         ctx->bad_lost_and_found = 0;
923         ext2fs_free_inode_bitmap(ctx->inode_used_map);
924         ctx->inode_used_map = 0;
925         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
926         ctx->inode_dir_map = 0;
927         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
928         ctx->inode_reg_map = 0;
929         ext2fs_free_block_bitmap(ctx->block_found_map);
930         ctx->block_found_map = 0;
931         ext2fs_free_icount(ctx->inode_link_info);
932         ctx->inode_link_info = 0;
933         if (ctx->journal_io) {
934                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
935                         io_channel_close(ctx->journal_io);
936                 ctx->journal_io = 0;
937         }
938         if (ctx->fs) {
939                 ext2fs_free_dblist(ctx->fs->dblist);
940                 ctx->fs->dblist = 0;
941         }
942         e2fsck_free_dir_info(ctx);
943 #ifdef ENABLE_HTREE
944         e2fsck_free_dx_dir_info(ctx);
945 #endif
946         ea_refcount_free(ctx->refcount);
947         ctx->refcount = 0;
948         ea_refcount_free(ctx->refcount_extra);
949         ctx->refcount_extra = 0;
950         ext2fs_free_block_bitmap(ctx->block_dup_map);
951         ctx->block_dup_map = 0;
952         ext2fs_free_block_bitmap(ctx->block_ea_map);
953         ctx->block_ea_map = 0;
954         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
955         ctx->inode_bad_map = 0;
956         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
957         ctx->inode_imagic_map = 0;
958         ext2fs_u32_list_free(ctx->dirs_to_hash);
959         ctx->dirs_to_hash = 0;
960
961         /*
962          * Clear the array of invalid meta-data flags
963          */
964         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
965         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
966         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
967
968         /* Clear statistic counters */
969         ctx->fs_directory_count = 0;
970         ctx->fs_regular_count = 0;
971         ctx->fs_blockdev_count = 0;
972         ctx->fs_chardev_count = 0;
973         ctx->fs_links_count = 0;
974         ctx->fs_symlinks_count = 0;
975         ctx->fs_fast_symlinks_count = 0;
976         ctx->fs_fifo_count = 0;
977         ctx->fs_total_count = 0;
978         ctx->fs_sockets_count = 0;
979         ctx->fs_ind_count = 0;
980         ctx->fs_dind_count = 0;
981         ctx->fs_tind_count = 0;
982         ctx->fs_fragmented = 0;
983         ctx->large_files = 0;
984
985         /* Reset the superblock to the user's requested value */
986         ctx->superblock = ctx->use_superblock;
987
988         return 0;
989 }
990
991 static void e2fsck_free_context(e2fsck_t ctx)
992 {
993         if (!ctx)
994                 return;
995
996         e2fsck_reset_context(ctx);
997         if (ctx->blkid)
998                 blkid_put_cache(ctx->blkid);
999
1000         ext2fs_free_mem(&ctx);
1001 }
1002
1003 /*
1004  * ea_refcount.c
1005  */
1006
1007 /*
1008  * The strategy we use for keeping track of EA refcounts is as
1009  * follows.  We keep a sorted array of first EA blocks and its
1010  * reference counts.  Once the refcount has dropped to zero, it is
1011  * removed from the array to save memory space.  Once the EA block is
1012  * checked, its bit is set in the block_ea_map bitmap.
1013  */
1014
1015
1016 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1017 {
1018         ext2_refcount_t refcount;
1019         errcode_t       retval;
1020         size_t          bytes;
1021
1022         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1023         if (retval)
1024                 return retval;
1025         memset(refcount, 0, sizeof(struct ea_refcount));
1026
1027         if (!size)
1028                 size = 500;
1029         refcount->size = size;
1030         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1031 #ifdef DEBUG
1032         printf("Refcount allocated %d entries, %d bytes.\n",
1033                refcount->size, bytes);
1034 #endif
1035         retval = ext2fs_get_mem(bytes, &refcount->list);
1036         if (retval)
1037                 goto errout;
1038         memset(refcount->list, 0, bytes);
1039
1040         refcount->count = 0;
1041         refcount->cursor = 0;
1042
1043         *ret = refcount;
1044         return 0;
1045
1046 errout:
1047         ea_refcount_free(refcount);
1048         return retval;
1049 }
1050
1051 /*
1052  * collapse_refcount() --- go through the refcount array, and get rid
1053  * of any count == zero entries
1054  */
1055 static void refcount_collapse(ext2_refcount_t refcount)
1056 {
1057         unsigned int    i, j;
1058         struct ea_refcount_el   *list;
1059
1060         list = refcount->list;
1061         for (i = 0, j = 0; i < refcount->count; i++) {
1062                 if (list[i].ea_count) {
1063                         if (i != j)
1064                                 list[j] = list[i];
1065                         j++;
1066                 }
1067         }
1068 #if defined(DEBUG) || defined(TEST_PROGRAM)
1069         printf("Refcount_collapse: size was %d, now %d\n",
1070                refcount->count, j);
1071 #endif
1072         refcount->count = j;
1073 }
1074
1075
1076 /*
1077  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1078  *      specified position.
1079  */
1080 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1081                                                  blk_t blk, int pos)
1082 {
1083         struct ea_refcount_el   *el;
1084         errcode_t               retval;
1085         blk_t                   new_size = 0;
1086         int                     num;
1087
1088         if (refcount->count >= refcount->size) {
1089                 new_size = refcount->size + 100;
1090 #ifdef DEBUG
1091                 printf("Reallocating refcount %d entries...\n", new_size);
1092 #endif
1093                 retval = ext2fs_resize_mem((size_t) refcount->size *
1094                                            sizeof(struct ea_refcount_el),
1095                                            (size_t) new_size *
1096                                            sizeof(struct ea_refcount_el),
1097                                            &refcount->list);
1098                 if (retval)
1099                         return 0;
1100                 refcount->size = new_size;
1101         }
1102         num = (int) refcount->count - pos;
1103         if (num < 0)
1104                 return 0;       /* should never happen */
1105         if (num) {
1106                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1107                         sizeof(struct ea_refcount_el) * num);
1108         }
1109         refcount->count++;
1110         el = &refcount->list[pos];
1111         el->ea_count = 0;
1112         el->ea_blk = blk;
1113         return el;
1114 }
1115
1116
1117 /*
1118  * get_refcount_el() --- given an block number, try to find refcount
1119  *      information in the sorted list.  If the create flag is set,
1120  *      and we can't find an entry, create one in the sorted list.
1121  */
1122 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1123                                               blk_t blk, int create)
1124 {
1125         float   range;
1126         int     low, high, mid;
1127         blk_t   lowval, highval;
1128
1129         if (!refcount || !refcount->list)
1130                 return 0;
1131 retry:
1132         low = 0;
1133         high = (int) refcount->count-1;
1134         if (create && ((refcount->count == 0) ||
1135                        (blk > refcount->list[high].ea_blk))) {
1136                 if (refcount->count >= refcount->size)
1137                         refcount_collapse(refcount);
1138
1139                 return insert_refcount_el(refcount, blk,
1140                                           (unsigned) refcount->count);
1141         }
1142         if (refcount->count == 0)
1143                 return 0;
1144
1145         if (refcount->cursor >= refcount->count)
1146                 refcount->cursor = 0;
1147         if (blk == refcount->list[refcount->cursor].ea_blk)
1148                 return &refcount->list[refcount->cursor++];
1149 #ifdef DEBUG
1150         printf("Non-cursor get_refcount_el: %u\n", blk);
1151 #endif
1152         while (low <= high) {
1153                 if (low == high)
1154                         mid = low;
1155                 else {
1156                         /* Interpolate for efficiency */
1157                         lowval = refcount->list[low].ea_blk;
1158                         highval = refcount->list[high].ea_blk;
1159
1160                         if (blk < lowval)
1161                                 range = 0;
1162                         else if (blk > highval)
1163                                 range = 1;
1164                         else
1165                                 range = ((float) (blk - lowval)) /
1166                                         (highval - lowval);
1167                         mid = low + ((int) (range * (high-low)));
1168                 }
1169
1170                 if (blk == refcount->list[mid].ea_blk) {
1171                         refcount->cursor = mid+1;
1172                         return &refcount->list[mid];
1173                 }
1174                 if (blk < refcount->list[mid].ea_blk)
1175                         high = mid-1;
1176                 else
1177                         low = mid+1;
1178         }
1179         /*
1180          * If we need to create a new entry, it should be right at
1181          * low (where high will be left at low-1).
1182          */
1183         if (create) {
1184                 if (refcount->count >= refcount->size) {
1185                         refcount_collapse(refcount);
1186                         if (refcount->count < refcount->size)
1187                                 goto retry;
1188                 }
1189                 return insert_refcount_el(refcount, blk, low);
1190         }
1191         return 0;
1192 }
1193
1194 static errcode_t
1195 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1196 {
1197         struct ea_refcount_el   *el;
1198
1199         el = get_refcount_el(refcount, blk, 1);
1200         if (!el)
1201                 return EXT2_ET_NO_MEMORY;
1202         el->ea_count++;
1203
1204         if (ret)
1205                 *ret = el->ea_count;
1206         return 0;
1207 }
1208
1209 static errcode_t
1210 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1211 {
1212         struct ea_refcount_el   *el;
1213
1214         el = get_refcount_el(refcount, blk, 0);
1215         if (!el || el->ea_count == 0)
1216                 return EXT2_ET_INVALID_ARGUMENT;
1217
1218         el->ea_count--;
1219
1220         if (ret)
1221                 *ret = el->ea_count;
1222         return 0;
1223 }
1224
1225 static errcode_t
1226 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1227 {
1228         struct ea_refcount_el   *el;
1229
1230         /*
1231          * Get the refcount element
1232          */
1233         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1234         if (!el)
1235                 return count ? EXT2_ET_NO_MEMORY : 0;
1236         el->ea_count = count;
1237         return 0;
1238 }
1239
1240 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1241 {
1242         refcount->cursor = 0;
1243 }
1244
1245
1246 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1247 {
1248         struct ea_refcount_el   *list;
1249
1250         while (1) {
1251                 if (refcount->cursor >= refcount->count)
1252                         return 0;
1253                 list = refcount->list;
1254                 if (list[refcount->cursor].ea_count) {
1255                         if (ret)
1256                                 *ret = list[refcount->cursor].ea_count;
1257                         return list[refcount->cursor++].ea_blk;
1258                 }
1259                 refcount->cursor++;
1260         }
1261 }
1262
1263
1264 /*
1265  * ehandler.c --- handle bad block errors which come up during the
1266  *      course of an e2fsck session.
1267  */
1268
1269
1270 static const char *operation;
1271
1272 static errcode_t
1273 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1274                          void *data, size_t size FSCK_ATTR((unused)),
1275                          int actual FSCK_ATTR((unused)), errcode_t error)
1276 {
1277         int     i;
1278         char    *p;
1279         ext2_filsys fs = (ext2_filsys) channel->app_data;
1280         e2fsck_t ctx;
1281
1282         ctx = (e2fsck_t) fs->priv_data;
1283
1284         /*
1285          * If more than one block was read, try reading each block
1286          * separately.  We could use the actual bytes read to figure
1287          * out where to start, but we don't bother.
1288          */
1289         if (count > 1) {
1290                 p = (char *) data;
1291                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1292                         error = io_channel_read_blk(channel, block,
1293                                                     1, p);
1294                         if (error)
1295                                 return error;
1296                 }
1297                 return 0;
1298         }
1299         if (operation)
1300                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1301                        error_message(error), operation);
1302         else
1303                 printf(_("Error reading block %lu (%s).  "), block,
1304                        error_message(error));
1305         preenhalt(ctx);
1306         if (ask(ctx, _("Ignore error"), 1)) {
1307                 if (ask(ctx, _("Force rewrite"), 1))
1308                         io_channel_write_blk(channel, block, 1, data);
1309                 return 0;
1310         }
1311
1312         return error;
1313 }
1314
1315 static errcode_t
1316 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1317                         const void *data, size_t size FSCK_ATTR((unused)),
1318                         int actual FSCK_ATTR((unused)), errcode_t error)
1319 {
1320         int             i;
1321         const char      *p;
1322         ext2_filsys fs = (ext2_filsys) channel->app_data;
1323         e2fsck_t ctx;
1324
1325         ctx = (e2fsck_t) fs->priv_data;
1326
1327         /*
1328          * If more than one block was written, try writing each block
1329          * separately.  We could use the actual bytes read to figure
1330          * out where to start, but we don't bother.
1331          */
1332         if (count > 1) {
1333                 p = (const char *) data;
1334                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1335                         error = io_channel_write_blk(channel, block,
1336                                                      1, p);
1337                         if (error)
1338                                 return error;
1339                 }
1340                 return 0;
1341         }
1342
1343         if (operation)
1344                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1345                        error_message(error), operation);
1346         else
1347                 printf(_("Error writing block %lu (%s).  "), block,
1348                        error_message(error));
1349         preenhalt(ctx);
1350         if (ask(ctx, _("Ignore error"), 1))
1351                 return 0;
1352
1353         return error;
1354 }
1355
1356 static const char *ehandler_operation(const char *op)
1357 {
1358         const char *ret = operation;
1359
1360         operation = op;
1361         return ret;
1362 }
1363
1364 static void ehandler_init(io_channel channel)
1365 {
1366         channel->read_error = e2fsck_handle_read_error;
1367         channel->write_error = e2fsck_handle_write_error;
1368 }
1369
1370 /*
1371  * journal.c --- code for handling the "ext3" journal
1372  *
1373  * Copyright (C) 2000 Andreas Dilger
1374  * Copyright (C) 2000 Theodore Ts'o
1375  *
1376  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1377  * Copyright (C) 1999 Red Hat Software
1378  *
1379  * This file may be redistributed under the terms of the
1380  * GNU General Public License version 2 or at your discretion
1381  * any later version.
1382  */
1383
1384 /*
1385  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1386  * This creates a larger static binary, and a smaller binary using
1387  * shared libraries.  It's also probably slightly less CPU-efficient,
1388  * which is why it's not on by default.  But, it's a good way of
1389  * testing the functions in inode_io.c and fileio.c.
1390  */
1391 #undef USE_INODE_IO
1392
1393 /* Kernel compatibility functions for handling the journal.  These allow us
1394  * to use the recovery.c file virtually unchanged from the kernel, so we
1395  * don't have to do much to keep kernel and user recovery in sync.
1396  */
1397 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1398 {
1399 #ifdef USE_INODE_IO
1400         *phys = block;
1401         return 0;
1402 #else
1403         struct inode    *inode = journal->j_inode;
1404         errcode_t       retval;
1405         blk_t           pblk;
1406
1407         if (!inode) {
1408                 *phys = block;
1409                 return 0;
1410         }
1411
1412         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1413                             &inode->i_ext2, NULL, 0, block, &pblk);
1414         *phys = pblk;
1415         return retval;
1416 #endif
1417 }
1418
1419 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1420 {
1421         struct buffer_head *bh;
1422
1423         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1424         if (!bh)
1425                 return NULL;
1426
1427         bh->b_ctx = kdev->k_ctx;
1428         if (kdev->k_dev == K_DEV_FS)
1429                 bh->b_io = kdev->k_ctx->fs->io;
1430         else
1431                 bh->b_io = kdev->k_ctx->journal_io;
1432         bh->b_size = blocksize;
1433         bh->b_blocknr = blocknr;
1434
1435         return bh;
1436 }
1437
1438 static void sync_blockdev(kdev_t kdev)
1439 {
1440         io_channel      io;
1441
1442         if (kdev->k_dev == K_DEV_FS)
1443                 io = kdev->k_ctx->fs->io;
1444         else
1445                 io = kdev->k_ctx->journal_io;
1446
1447         io_channel_flush(io);
1448 }
1449
1450 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1451 {
1452         int retval;
1453         struct buffer_head *bh;
1454
1455         for (; nr > 0; --nr) {
1456                 bh = *bhp++;
1457                 if (rw == READ && !bh->b_uptodate) {
1458                         retval = io_channel_read_blk(bh->b_io,
1459                                                      bh->b_blocknr,
1460                                                      1, bh->b_data);
1461                         if (retval) {
1462                                 bb_error_msg("while reading block %lu",
1463                                         (unsigned long) bh->b_blocknr);
1464                                 bh->b_err = retval;
1465                                 continue;
1466                         }
1467                         bh->b_uptodate = 1;
1468                 } else if (rw == WRITE && bh->b_dirty) {
1469                         retval = io_channel_write_blk(bh->b_io,
1470                                                       bh->b_blocknr,
1471                                                       1, bh->b_data);
1472                         if (retval) {
1473                                 bb_error_msg("while writing block %lu",
1474                                         (unsigned long) bh->b_blocknr);
1475                                 bh->b_err = retval;
1476                                 continue;
1477                         }
1478                         bh->b_dirty = 0;
1479                         bh->b_uptodate = 1;
1480                 }
1481         }
1482 }
1483
1484 static void mark_buffer_dirty(struct buffer_head *bh)
1485 {
1486         bh->b_dirty = 1;
1487 }
1488
1489 static inline void mark_buffer_clean(struct buffer_head * bh)
1490 {
1491         bh->b_dirty = 0;
1492 }
1493
1494 static void brelse(struct buffer_head *bh)
1495 {
1496         if (bh->b_dirty)
1497                 ll_rw_block(WRITE, 1, &bh);
1498         ext2fs_free_mem(&bh);
1499 }
1500
1501 static int buffer_uptodate(struct buffer_head *bh)
1502 {
1503         return bh->b_uptodate;
1504 }
1505
1506 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1507 {
1508         bh->b_uptodate = val;
1509 }
1510
1511 static void wait_on_buffer(struct buffer_head *bh)
1512 {
1513         if (!bh->b_uptodate)
1514                 ll_rw_block(READ, 1, &bh);
1515 }
1516
1517
1518 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1519 {
1520         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1521
1522         /* if we had an error doing journal recovery, we need a full fsck */
1523         if (error)
1524                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1525         ext2fs_mark_super_dirty(ctx->fs);
1526 }
1527
1528 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1529 {
1530         struct ext2_super_block *sb = ctx->fs->super;
1531         struct ext2_super_block jsuper;
1532         struct problem_context  pctx;
1533         struct buffer_head      *bh;
1534         struct inode            *j_inode = NULL;
1535         struct kdev_s           *dev_fs = NULL, *dev_journal;
1536         const char              *journal_name = NULL;
1537         journal_t               *journal = NULL;
1538         errcode_t               retval = 0;
1539         io_manager              io_ptr = 0;
1540         unsigned long           start = 0;
1541         blk_t                   blk;
1542         int                     ext_journal = 0;
1543         int                     tried_backup_jnl = 0;
1544         int                     i;
1545
1546         clear_problem_context(&pctx);
1547
1548         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1549         if (!journal) {
1550                 return EXT2_ET_NO_MEMORY;
1551         }
1552
1553         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1554         if (!dev_fs) {
1555                 retval = EXT2_ET_NO_MEMORY;
1556                 goto errout;
1557         }
1558         dev_journal = dev_fs+1;
1559
1560         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1561         dev_fs->k_dev = K_DEV_FS;
1562         dev_journal->k_dev = K_DEV_JOURNAL;
1563
1564         journal->j_dev = dev_journal;
1565         journal->j_fs_dev = dev_fs;
1566         journal->j_inode = NULL;
1567         journal->j_blocksize = ctx->fs->blocksize;
1568
1569         if (uuid_is_null(sb->s_journal_uuid)) {
1570                 if (!sb->s_journal_inum)
1571                         return EXT2_ET_BAD_INODE_NUM;
1572                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1573                                                  "journal inode");
1574                 if (!j_inode) {
1575                         retval = EXT2_ET_NO_MEMORY;
1576                         goto errout;
1577                 }
1578
1579                 j_inode->i_ctx = ctx;
1580                 j_inode->i_ino = sb->s_journal_inum;
1581
1582                 if ((retval = ext2fs_read_inode(ctx->fs,
1583                                                 sb->s_journal_inum,
1584                                                 &j_inode->i_ext2))) {
1585                 try_backup_journal:
1586                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1587                             tried_backup_jnl)
1588                                 goto errout;
1589                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1590                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1591                                EXT2_N_BLOCKS*4);
1592                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1593                         j_inode->i_ext2.i_links_count = 1;
1594                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1595                         tried_backup_jnl++;
1596                 }
1597                 if (!j_inode->i_ext2.i_links_count ||
1598                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1599                         retval = EXT2_ET_NO_JOURNAL;
1600                         goto try_backup_journal;
1601                 }
1602                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1603                     JFS_MIN_JOURNAL_BLOCKS) {
1604                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1605                         goto try_backup_journal;
1606                 }
1607                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1608                         blk = j_inode->i_ext2.i_block[i];
1609                         if (!blk) {
1610                                 if (i < EXT2_NDIR_BLOCKS) {
1611                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1612                                         goto try_backup_journal;
1613                                 }
1614                                 continue;
1615                         }
1616                         if (blk < sb->s_first_data_block ||
1617                             blk >= sb->s_blocks_count) {
1618                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1619                                 goto try_backup_journal;
1620                         }
1621                 }
1622                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1623
1624 #ifdef USE_INODE_IO
1625                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1626                                                  &j_inode->i_ext2,
1627                                                  &journal_name);
1628                 if (retval)
1629                         goto errout;
1630
1631                 io_ptr = inode_io_manager;
1632 #else
1633                 journal->j_inode = j_inode;
1634                 ctx->journal_io = ctx->fs->io;
1635                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1636                         goto errout;
1637 #endif
1638         } else {
1639                 ext_journal = 1;
1640                 if (!ctx->journal_name) {
1641                         char uuid[37];
1642
1643                         uuid_unparse(sb->s_journal_uuid, uuid);
1644                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1645                                                               "UUID", uuid);
1646                         if (!ctx->journal_name)
1647                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1648                 }
1649                 journal_name = ctx->journal_name;
1650
1651                 if (!journal_name) {
1652                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1653                         return EXT2_ET_LOAD_EXT_JOURNAL;
1654                 }
1655
1656                 io_ptr = unix_io_manager;
1657         }
1658
1659 #ifndef USE_INODE_IO
1660         if (ext_journal)
1661 #endif
1662                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1663                                       &ctx->journal_io);
1664         if (retval)
1665                 goto errout;
1666
1667         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1668
1669         if (ext_journal) {
1670                 if (ctx->fs->blocksize == 1024)
1671                         start = 1;
1672                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1673                 if (!bh) {
1674                         retval = EXT2_ET_NO_MEMORY;
1675                         goto errout;
1676                 }
1677                 ll_rw_block(READ, 1, &bh);
1678                 if ((retval = bh->b_err) != 0)
1679                         goto errout;
1680                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1681                        sizeof(jsuper));
1682                 brelse(bh);
1683 #if BB_BIG_ENDIAN
1684                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1685                         ext2fs_swap_super(&jsuper);
1686 #endif
1687                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1688                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1689                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1690                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1691                         goto errout;
1692                 }
1693                 /* Make sure the journal UUID is correct */
1694                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1695                            sizeof(jsuper.s_uuid))) {
1696                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1697                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1698                         goto errout;
1699                 }
1700
1701                 journal->j_maxlen = jsuper.s_blocks_count;
1702                 start++;
1703         }
1704
1705         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1706                 retval = EXT2_ET_NO_MEMORY;
1707                 goto errout;
1708         }
1709
1710         journal->j_sb_buffer = bh;
1711         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1712
1713 #ifdef USE_INODE_IO
1714         ext2fs_free_mem(&j_inode);
1715 #endif
1716
1717         *ret_journal = journal;
1718         return 0;
1719
1720 errout:
1721         ext2fs_free_mem(&dev_fs);
1722         ext2fs_free_mem(&j_inode);
1723         ext2fs_free_mem(&journal);
1724         return retval;
1725 }
1726
1727 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1728                                               struct problem_context *pctx)
1729 {
1730         struct ext2_super_block *sb = ctx->fs->super;
1731         int recover = ctx->fs->super->s_feature_incompat &
1732                 EXT3_FEATURE_INCOMPAT_RECOVER;
1733         int has_journal = ctx->fs->super->s_feature_compat &
1734                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1735
1736         if (has_journal || sb->s_journal_inum) {
1737                 /* The journal inode is bogus, remove and force full fsck */
1738                 pctx->ino = sb->s_journal_inum;
1739                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1740                         if (has_journal && sb->s_journal_inum)
1741                                 printf("*** ext3 journal has been deleted - "
1742                                        "filesystem is now ext2 only ***\n\n");
1743                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1744                         sb->s_journal_inum = 0;
1745                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1746                         e2fsck_clear_recover(ctx, 1);
1747                         return 0;
1748                 }
1749                 return EXT2_ET_BAD_INODE_NUM;
1750         } else if (recover) {
1751                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1752                         e2fsck_clear_recover(ctx, 1);
1753                         return 0;
1754                 }
1755                 return EXT2_ET_UNSUPP_FEATURE;
1756         }
1757         return 0;
1758 }
1759
1760 #define V1_SB_SIZE      0x0024
1761 static void clear_v2_journal_fields(journal_t *journal)
1762 {
1763         e2fsck_t ctx = journal->j_dev->k_ctx;
1764         struct problem_context pctx;
1765
1766         clear_problem_context(&pctx);
1767
1768         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1769                 return;
1770
1771         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1772                ctx->fs->blocksize-V1_SB_SIZE);
1773         mark_buffer_dirty(journal->j_sb_buffer);
1774 }
1775
1776
1777 static errcode_t e2fsck_journal_load(journal_t *journal)
1778 {
1779         e2fsck_t ctx = journal->j_dev->k_ctx;
1780         journal_superblock_t *jsb;
1781         struct buffer_head *jbh = journal->j_sb_buffer;
1782         struct problem_context pctx;
1783
1784         clear_problem_context(&pctx);
1785
1786         ll_rw_block(READ, 1, &jbh);
1787         if (jbh->b_err) {
1788                 bb_error_msg(_("reading journal superblock"));
1789                 return jbh->b_err;
1790         }
1791
1792         jsb = journal->j_superblock;
1793         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1794         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1795                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1796
1797         switch (ntohl(jsb->s_header.h_blocktype)) {
1798         case JFS_SUPERBLOCK_V1:
1799                 journal->j_format_version = 1;
1800                 if (jsb->s_feature_compat ||
1801                     jsb->s_feature_incompat ||
1802                     jsb->s_feature_ro_compat ||
1803                     jsb->s_nr_users)
1804                         clear_v2_journal_fields(journal);
1805                 break;
1806
1807         case JFS_SUPERBLOCK_V2:
1808                 journal->j_format_version = 2;
1809                 if (ntohl(jsb->s_nr_users) > 1 &&
1810                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1811                         clear_v2_journal_fields(journal);
1812                 if (ntohl(jsb->s_nr_users) > 1) {
1813                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1814                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1815                 }
1816                 break;
1817
1818         /*
1819          * These should never appear in a journal super block, so if
1820          * they do, the journal is badly corrupted.
1821          */
1822         case JFS_DESCRIPTOR_BLOCK:
1823         case JFS_COMMIT_BLOCK:
1824         case JFS_REVOKE_BLOCK:
1825                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1826
1827         /* If we don't understand the superblock major type, but there
1828          * is a magic number, then it is likely to be a new format we
1829          * just don't understand, so leave it alone. */
1830         default:
1831                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1832         }
1833
1834         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1835                 return EXT2_ET_UNSUPP_FEATURE;
1836
1837         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1838                 return EXT2_ET_RO_UNSUPP_FEATURE;
1839
1840         /* We have now checked whether we know enough about the journal
1841          * format to be able to proceed safely, so any other checks that
1842          * fail we should attempt to recover from. */
1843         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1844                 bb_error_msg(_("%s: no valid journal superblock found"),
1845                         ctx->device_name);
1846                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1847         }
1848
1849         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1850                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1851         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1852                 bb_error_msg(_("%s: journal too short"),
1853                         ctx->device_name);
1854                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1855         }
1856
1857         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1858         journal->j_transaction_sequence = journal->j_tail_sequence;
1859         journal->j_tail = ntohl(jsb->s_start);
1860         journal->j_first = ntohl(jsb->s_first);
1861         journal->j_last = ntohl(jsb->s_maxlen);
1862
1863         return 0;
1864 }
1865
1866 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1867                                        journal_t *journal)
1868 {
1869         char *p;
1870         union {
1871                 uuid_t uuid;
1872                 __u32 val[4];
1873         } u;
1874         __u32 new_seq = 0;
1875         int i;
1876
1877         /* Leave a valid existing V1 superblock signature alone.
1878          * Anything unrecognizable we overwrite with a new V2
1879          * signature. */
1880
1881         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1882             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1883                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1884                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1885         }
1886
1887         /* Zero out everything else beyond the superblock header */
1888
1889         p = ((char *) jsb) + sizeof(journal_header_t);
1890         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1891
1892         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1893         jsb->s_maxlen = htonl(journal->j_maxlen);
1894         jsb->s_first = htonl(1);
1895
1896         /* Initialize the journal sequence number so that there is "no"
1897          * chance we will find old "valid" transactions in the journal.
1898          * This avoids the need to zero the whole journal (slow to do,
1899          * and risky when we are just recovering the filesystem).
1900          */
1901         uuid_generate(u.uuid);
1902         for (i = 0; i < 4; i ++)
1903                 new_seq ^= u.val[i];
1904         jsb->s_sequence = htonl(new_seq);
1905
1906         mark_buffer_dirty(journal->j_sb_buffer);
1907         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1908 }
1909
1910 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1911                                                   journal_t *journal,
1912                                                   struct problem_context *pctx)
1913 {
1914         struct ext2_super_block *sb = ctx->fs->super;
1915         int recover = ctx->fs->super->s_feature_incompat &
1916                 EXT3_FEATURE_INCOMPAT_RECOVER;
1917
1918         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1919                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1920                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1921                                                    journal);
1922                         journal->j_transaction_sequence = 1;
1923                         e2fsck_clear_recover(ctx, recover);
1924                         return 0;
1925                 }
1926                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1927         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1928                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1929
1930         return 0;
1931 }
1932
1933 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1934                                    int reset, int drop)
1935 {
1936         journal_superblock_t *jsb;
1937
1938         if (drop)
1939                 mark_buffer_clean(journal->j_sb_buffer);
1940         else if (!(ctx->options & E2F_OPT_READONLY)) {
1941                 jsb = journal->j_superblock;
1942                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1943                 if (reset)
1944                         jsb->s_start = 0; /* this marks the journal as empty */
1945                 mark_buffer_dirty(journal->j_sb_buffer);
1946         }
1947         brelse(journal->j_sb_buffer);
1948
1949         if (ctx->journal_io) {
1950                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1951                         io_channel_close(ctx->journal_io);
1952                 ctx->journal_io = 0;
1953         }
1954
1955 #ifndef USE_INODE_IO
1956         ext2fs_free_mem(&journal->j_inode);
1957 #endif
1958         ext2fs_free_mem(&journal->j_fs_dev);
1959         ext2fs_free_mem(&journal);
1960 }
1961
1962 /*
1963  * This function makes sure that the superblock fields regarding the
1964  * journal are consistent.
1965  */
1966 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1967 {
1968         struct ext2_super_block *sb = ctx->fs->super;
1969         journal_t *journal;
1970         int recover = ctx->fs->super->s_feature_incompat &
1971                 EXT3_FEATURE_INCOMPAT_RECOVER;
1972         struct problem_context pctx;
1973         problem_t problem;
1974         int reset = 0, force_fsck = 0;
1975         int retval;
1976
1977         /* If we don't have any journal features, don't do anything more */
1978         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1979             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1980             uuid_is_null(sb->s_journal_uuid))
1981                 return 0;
1982
1983         clear_problem_context(&pctx);
1984         pctx.num = sb->s_journal_inum;
1985
1986         retval = e2fsck_get_journal(ctx, &journal);
1987         if (retval) {
1988                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1989                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1990                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1991                     (retval == EXT2_ET_NO_JOURNAL))
1992                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1993                 return retval;
1994         }
1995
1996         retval = e2fsck_journal_load(journal);
1997         if (retval) {
1998                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
1999                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2000                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2001                                   &pctx))) ||
2002                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2003                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2004                                   &pctx))) ||
2005                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2006                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2007                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2008                                                                   &pctx);
2009                 e2fsck_journal_release(ctx, journal, 0, 1);
2010                 return retval;
2011         }
2012
2013         /*
2014          * We want to make the flags consistent here.  We will not leave with
2015          * needs_recovery set but has_journal clear.  We can't get in a loop
2016          * with -y, -n, or -p, only if a user isn't making up their mind.
2017          */
2018 no_has_journal:
2019         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2020                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2021                 pctx.str = "inode";
2022                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2023                         if (recover &&
2024                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2025                                 goto no_has_journal;
2026                         /*
2027                          * Need a full fsck if we are releasing a
2028                          * journal stored on a reserved inode.
2029                          */
2030                         force_fsck = recover ||
2031                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2032                         /* Clear all of the journal fields */
2033                         sb->s_journal_inum = 0;
2034                         sb->s_journal_dev = 0;
2035                         memset(sb->s_journal_uuid, 0,
2036                                sizeof(sb->s_journal_uuid));
2037                         e2fsck_clear_recover(ctx, force_fsck);
2038                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2039                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2040                         ext2fs_mark_super_dirty(ctx->fs);
2041                 }
2042         }
2043
2044         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2045             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2046             journal->j_superblock->s_start != 0) {
2047                 /* Print status information */
2048                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2049                 if (ctx->superblock)
2050                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2051                 else
2052                         problem = PR_0_JOURNAL_RUN;
2053                 if (fix_problem(ctx, problem, &pctx)) {
2054                         ctx->options |= E2F_OPT_FORCE;
2055                         sb->s_feature_incompat |=
2056                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2057                         ext2fs_mark_super_dirty(ctx->fs);
2058                 } else if (fix_problem(ctx,
2059                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2060                         reset = 1;
2061                         sb->s_state &= ~EXT2_VALID_FS;
2062                         ext2fs_mark_super_dirty(ctx->fs);
2063                 }
2064                 /*
2065                  * If the user answers no to the above question, we
2066                  * ignore the fact that journal apparently has data;
2067                  * accidentally replaying over valid data would be far
2068                  * worse than skipping a questionable recovery.
2069                  *
2070                  * XXX should we abort with a fatal error here?  What
2071                  * will the ext3 kernel code do if a filesystem with
2072                  * !NEEDS_RECOVERY but with a non-zero
2073                  * journal->j_superblock->s_start is mounted?
2074                  */
2075         }
2076
2077         e2fsck_journal_release(ctx, journal, reset, 0);
2078         return retval;
2079 }
2080
2081 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2082 {
2083         journal_t *journal;
2084         int retval;
2085
2086         journal_init_revoke_caches();
2087         retval = e2fsck_get_journal(ctx, &journal);
2088         if (retval)
2089                 return retval;
2090
2091         retval = e2fsck_journal_load(journal);
2092         if (retval)
2093                 goto errout;
2094
2095         retval = journal_init_revoke(journal, 1024);
2096         if (retval)
2097                 goto errout;
2098
2099         retval = -journal_recover(journal);
2100         if (retval)
2101                 goto errout;
2102
2103         if (journal->j_superblock->s_errno) {
2104                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2105                 ext2fs_mark_super_dirty(ctx->fs);
2106                 journal->j_superblock->s_errno = 0;
2107                 mark_buffer_dirty(journal->j_sb_buffer);
2108         }
2109
2110 errout:
2111         journal_destroy_revoke(journal);
2112         journal_destroy_revoke_caches();
2113         e2fsck_journal_release(ctx, journal, 1, 0);
2114         return retval;
2115 }
2116
2117 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2118 {
2119         io_manager io_ptr = ctx->fs->io->manager;
2120         int blocksize = ctx->fs->blocksize;
2121         errcode_t       retval, recover_retval;
2122
2123         printf(_("%s: recovering journal\n"), ctx->device_name);
2124         if (ctx->options & E2F_OPT_READONLY) {
2125                 printf(_("%s: won't do journal recovery while read-only\n"),
2126                        ctx->device_name);
2127                 return EXT2_ET_FILE_RO;
2128         }
2129
2130         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2131                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2132
2133         recover_retval = recover_ext3_journal(ctx);
2134
2135         /*
2136          * Reload the filesystem context to get up-to-date data from disk
2137          * because journal recovery will change the filesystem under us.
2138          */
2139         ext2fs_close(ctx->fs);
2140         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2141                              ctx->superblock, blocksize, io_ptr,
2142                              &ctx->fs);
2143
2144         if (retval) {
2145                 bb_error_msg(_("while trying to re-open %s"),
2146                         ctx->device_name);
2147                 bb_error_msg_and_die(0);
2148         }
2149         ctx->fs->priv_data = ctx;
2150
2151         /* Set the superblock flags */
2152         e2fsck_clear_recover(ctx, recover_retval);
2153         return recover_retval;
2154 }
2155
2156 /*
2157  * This function will move the journal inode from a visible file in
2158  * the filesystem directory hierarchy to the reserved inode if necessary.
2159  */
2160 static const char *const journal_names[] = {
2161         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2162
2163 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2164 {
2165         struct ext2_super_block *sb = ctx->fs->super;
2166         struct problem_context  pctx;
2167         struct ext2_inode       inode;
2168         ext2_filsys             fs = ctx->fs;
2169         ext2_ino_t              ino;
2170         errcode_t               retval;
2171         const char *const *    cpp;
2172         int                     group, mount_flags;
2173
2174         clear_problem_context(&pctx);
2175
2176         /*
2177          * If the filesystem is opened read-only, or there is no
2178          * journal, then do nothing.
2179          */
2180         if ((ctx->options & E2F_OPT_READONLY) ||
2181             (sb->s_journal_inum == 0) ||
2182             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2183                 return;
2184
2185         /*
2186          * Read in the journal inode
2187          */
2188         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2189                 return;
2190
2191         /*
2192          * If it's necessary to backup the journal inode, do so.
2193          */
2194         if ((sb->s_jnl_backup_type == 0) ||
2195             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2196              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2197                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2198                         memcpy(sb->s_jnl_blocks, inode.i_block,
2199                                EXT2_N_BLOCKS*4);
2200                         sb->s_jnl_blocks[16] = inode.i_size;
2201                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2202                         ext2fs_mark_super_dirty(fs);
2203                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2204                 }
2205         }
2206
2207         /*
2208          * If the journal is already the hidden inode, then do nothing
2209          */
2210         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2211                 return;
2212
2213         /*
2214          * The journal inode had better have only one link and not be readable.
2215          */
2216         if (inode.i_links_count != 1)
2217                 return;
2218
2219         /*
2220          * If the filesystem is mounted, or we can't tell whether
2221          * or not it's mounted, do nothing.
2222          */
2223         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2224         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2225                 return;
2226
2227         /*
2228          * If we can't find the name of the journal inode, then do
2229          * nothing.
2230          */
2231         for (cpp = journal_names; *cpp; cpp++) {
2232                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2233                                        strlen(*cpp), 0, &ino);
2234                 if ((retval == 0) && (ino == sb->s_journal_inum))
2235                         break;
2236         }
2237         if (*cpp == 0)
2238                 return;
2239
2240         /* We need the inode bitmap to be loaded */
2241         retval = ext2fs_read_bitmaps(fs);
2242         if (retval)
2243                 return;
2244
2245         pctx.str = *cpp;
2246         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2247                 return;
2248
2249         /*
2250          * OK, we've done all the checks, let's actually move the
2251          * journal inode.  Errors at this point mean we need to force
2252          * an ext2 filesystem check.
2253          */
2254         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2255                 goto err_out;
2256         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2257                 goto err_out;
2258         sb->s_journal_inum = EXT2_JOURNAL_INO;
2259         ext2fs_mark_super_dirty(fs);
2260         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2261         inode.i_links_count = 0;
2262         inode.i_dtime = time(NULL);
2263         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2264                 goto err_out;
2265
2266         group = ext2fs_group_of_ino(fs, ino);
2267         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2268         ext2fs_mark_ib_dirty(fs);
2269         fs->group_desc[group].bg_free_inodes_count++;
2270         fs->super->s_free_inodes_count++;
2271         return;
2272
2273 err_out:
2274         pctx.errcode = retval;
2275         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2276         fs->super->s_state &= ~EXT2_VALID_FS;
2277         ext2fs_mark_super_dirty(fs);
2278 }
2279
2280 /*
2281  * message.c --- print e2fsck messages (with compression)
2282  *
2283  * print_e2fsck_message() prints a message to the user, using
2284  * compression techniques and expansions of abbreviations.
2285  *
2286  * The following % expansions are supported:
2287  *
2288  *      %b      <blk>                   block number
2289  *      %B      <blkcount>              integer
2290  *      %c      <blk2>                  block number
2291  *      %Di     <dirent>->ino           inode number
2292  *      %Dn     <dirent>->name          string
2293  *      %Dr     <dirent>->rec_len
2294  *      %Dl     <dirent>->name_len
2295  *      %Dt     <dirent>->filetype
2296  *      %d      <dir>                   inode number
2297  *      %g      <group>                 integer
2298  *      %i      <ino>                   inode number
2299  *      %Is     <inode> -> i_size
2300  *      %IS     <inode> -> i_extra_isize
2301  *      %Ib     <inode> -> i_blocks
2302  *      %Il     <inode> -> i_links_count
2303  *      %Im     <inode> -> i_mode
2304  *      %IM     <inode> -> i_mtime
2305  *      %IF     <inode> -> i_faddr
2306  *      %If     <inode> -> i_file_acl
2307  *      %Id     <inode> -> i_dir_acl
2308  *      %Iu     <inode> -> i_uid
2309  *      %Ig     <inode> -> i_gid
2310  *      %j      <ino2>                  inode number
2311  *      %m      <com_err error message>
2312  *      %N      <num>
2313  *      %p      ext2fs_get_pathname of directory <ino>
2314  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2315  *                      the containing directory.  (If dirent is NULL
2316  *                      then return the pathname of directory <ino2>)
2317  *      %q      ext2fs_get_pathname of directory <dir>
2318  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2319  *                      the containing directory.
2320  *      %s      <str>                   miscellaneous string
2321  *      %S      backup superblock
2322  *      %X      <num> hexadecimal format
2323  *
2324  * The following '@' expansions are supported:
2325  *
2326  *      @a      extended attribute
2327  *      @A      error allocating
2328  *      @b      block
2329  *      @B      bitmap
2330  *      @c      compress
2331  *      @C      conflicts with some other fs block
2332  *      @D      deleted
2333  *      @d      directory
2334  *      @e      entry
2335  *      @E      Entry '%Dn' in %p (%i)
2336  *      @f      filesystem
2337  *      @F      for @i %i (%Q) is
2338  *      @g      group
2339  *      @h      HTREE directory inode
2340  *      @i      inode
2341  *      @I      illegal
2342  *      @j      journal
2343  *      @l      lost+found
2344  *      @L      is a link
2345  *      @m      multiply-claimed
2346  *      @n      invalid
2347  *      @o      orphaned
2348  *      @p      problem in
2349  *      @r      root inode
2350  *      @s      should be
2351  *      @S      superblock
2352  *      @u      unattached
2353  *      @v      device
2354  *      @z      zero-length
2355  */
2356
2357
2358 /*
2359  * This structure defines the abbreviations used by the text strings
2360  * below.  The first character in the string is the index letter.  An
2361  * abbreviation of the form '@<i>' is expanded by looking up the index
2362  * letter <i> in the table below.
2363  */
2364 static const char *const abbrevs[] = {
2365         N_("aextended attribute"),
2366         N_("Aerror allocating"),
2367         N_("bblock"),
2368         N_("Bbitmap"),
2369         N_("ccompress"),
2370         N_("Cconflicts with some other fs @b"),
2371         N_("iinode"),
2372         N_("Iillegal"),
2373         N_("jjournal"),
2374         N_("Ddeleted"),
2375         N_("ddirectory"),
2376         N_("eentry"),
2377         N_("E@e '%Dn' in %p (%i)"),
2378         N_("ffilesystem"),
2379         N_("Ffor @i %i (%Q) is"),
2380         N_("ggroup"),
2381         N_("hHTREE @d @i"),
2382         N_("llost+found"),
2383         N_("Lis a link"),
2384         N_("mmultiply-claimed"),
2385         N_("ninvalid"),
2386         N_("oorphaned"),
2387         N_("pproblem in"),
2388         N_("rroot @i"),
2389         N_("sshould be"),
2390         N_("Ssuper@b"),
2391         N_("uunattached"),
2392         N_("vdevice"),
2393         N_("zzero-length"),
2394         "@@",
2395         0
2396         };
2397
2398 /*
2399  * Give more user friendly names to the "special" inodes.
2400  */
2401 #define num_special_inodes      11
2402 static const char *const special_inode_name[] =
2403 {
2404         N_("<The NULL inode>"),                 /* 0 */
2405         N_("<The bad blocks inode>"),           /* 1 */
2406         "/",                                    /* 2 */
2407         N_("<The ACL index inode>"),            /* 3 */
2408         N_("<The ACL data inode>"),             /* 4 */
2409         N_("<The boot loader inode>"),          /* 5 */
2410         N_("<The undelete directory inode>"),   /* 6 */
2411         N_("<The group descriptor inode>"),     /* 7 */
2412         N_("<The journal inode>"),              /* 8 */
2413         N_("<Reserved inode 9>"),               /* 9 */
2414         N_("<Reserved inode 10>"),              /* 10 */
2415 };
2416
2417 /*
2418  * This function does "safe" printing.  It will convert non-printable
2419  * ASCII characters using '^' and M- notation.
2420  */
2421 static void safe_print(const char *cp, int len)
2422 {
2423         unsigned char   ch;
2424
2425         if (len < 0)
2426                 len = strlen(cp);
2427
2428         while (len--) {
2429                 ch = *cp++;
2430                 if (ch > 128) {
2431                         fputs("M-", stdout);
2432                         ch -= 128;
2433                 }
2434                 if ((ch < 32) || (ch == 0x7f)) {
2435                         bb_putchar('^');
2436                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2437                 }
2438                 bb_putchar(ch);
2439         }
2440 }
2441
2442
2443 /*
2444  * This function prints a pathname, using the ext2fs_get_pathname
2445  * function
2446  */
2447 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2448 {
2449         errcode_t       retval;
2450         char            *path;
2451
2452         if (!dir && (ino < num_special_inodes)) {
2453                 fputs(_(special_inode_name[ino]), stdout);
2454                 return;
2455         }
2456
2457         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2458         if (retval)
2459                 fputs("???", stdout);
2460         else {
2461                 safe_print(path, -1);
2462                 ext2fs_free_mem(&path);
2463         }
2464 }
2465
2466 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2467                           struct problem_context *pctx, int first);
2468 /*
2469  * This function handles the '@' expansion.  We allow recursive
2470  * expansion; an @ expression can contain further '@' and '%'
2471  * expressions.
2472  */
2473 static void expand_at_expression(e2fsck_t ctx, char ch,
2474                                           struct problem_context *pctx,
2475                                           int *first)
2476 {
2477         const char *const *cpp;
2478         const char *str;
2479
2480         /* Search for the abbreviation */
2481         for (cpp = abbrevs; *cpp; cpp++) {
2482                 if (ch == *cpp[0])
2483                         break;
2484         }
2485         if (*cpp) {
2486                 str = _(*cpp) + 1;
2487                 if (*first && islower(*str)) {
2488                         *first = 0;
2489                         bb_putchar(toupper(*str++));
2490                 }
2491                 print_e2fsck_message(ctx, str, pctx, *first);
2492         } else
2493                 printf("@%c", ch);
2494 }
2495
2496 /*
2497  * This function expands '%IX' expressions
2498  */
2499 static void expand_inode_expression(char ch,
2500                                              struct problem_context *ctx)
2501 {
2502         struct ext2_inode       *inode;
2503         struct ext2_inode_large *large_inode;
2504         char *                  time_str;
2505         time_t                  t;
2506         int                     do_gmt = -1;
2507
2508         if (!ctx || !ctx->inode)
2509                 goto no_inode;
2510
2511         inode = ctx->inode;
2512         large_inode = (struct ext2_inode_large *) inode;
2513
2514         switch (ch) {
2515         case 's':
2516                 if (LINUX_S_ISDIR(inode->i_mode))
2517                         printf("%u", inode->i_size);
2518                 else {
2519                         printf("%"PRIu64, (inode->i_size |
2520                                         ((uint64_t) inode->i_size_high << 32)));
2521                 }
2522                 break;
2523         case 'S':
2524                 printf("%u", large_inode->i_extra_isize);
2525                 break;
2526         case 'b':
2527                 printf("%u", inode->i_blocks);
2528                 break;
2529         case 'l':
2530                 printf("%d", inode->i_links_count);
2531                 break;
2532         case 'm':
2533                 printf("0%o", inode->i_mode);
2534                 break;
2535         case 'M':
2536                 /* The diet libc doesn't respect the TZ environemnt variable */
2537                 if (do_gmt == -1) {
2538                         time_str = getenv("TZ");
2539                         if (!time_str)
2540                                 time_str = "";
2541                         do_gmt = !strcmp(time_str, "GMT");
2542                 }
2543                 t = inode->i_mtime;
2544                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2545                 printf("%.24s", time_str);
2546                 break;
2547         case 'F':
2548                 printf("%u", inode->i_faddr);
2549                 break;
2550         case 'f':
2551                 printf("%u", inode->i_file_acl);
2552                 break;
2553         case 'd':
2554                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2555                               inode->i_dir_acl : 0));
2556                 break;
2557         case 'u':
2558                 printf("%d", (inode->i_uid |
2559                               (inode->osd2.linux2.l_i_uid_high << 16)));
2560                 break;
2561         case 'g':
2562                 printf("%d", (inode->i_gid |
2563                               (inode->osd2.linux2.l_i_gid_high << 16)));
2564                 break;
2565         default:
2566         no_inode:
2567                 printf("%%I%c", ch);
2568                 break;
2569         }
2570 }
2571
2572 /*
2573  * This function expands '%dX' expressions
2574  */
2575 static void expand_dirent_expression(char ch,
2576                                               struct problem_context *ctx)
2577 {
2578         struct ext2_dir_entry   *dirent;
2579         int     len;
2580
2581         if (!ctx || !ctx->dirent)
2582                 goto no_dirent;
2583
2584         dirent = ctx->dirent;
2585
2586         switch (ch) {
2587         case 'i':
2588                 printf("%u", dirent->inode);
2589                 break;
2590         case 'n':
2591                 len = dirent->name_len & 0xFF;
2592                 if (len > EXT2_NAME_LEN)
2593                         len = EXT2_NAME_LEN;
2594                 if (len > dirent->rec_len)
2595                         len = dirent->rec_len;
2596                 safe_print(dirent->name, len);
2597                 break;
2598         case 'r':
2599                 printf("%u", dirent->rec_len);
2600                 break;
2601         case 'l':
2602                 printf("%u", dirent->name_len & 0xFF);
2603                 break;
2604         case 't':
2605                 printf("%u", dirent->name_len >> 8);
2606                 break;
2607         default:
2608         no_dirent:
2609                 printf("%%D%c", ch);
2610                 break;
2611         }
2612 }
2613
2614 static void expand_percent_expression(ext2_filsys fs, char ch,
2615                                                struct problem_context *ctx)
2616 {
2617         if (!ctx)
2618                 goto no_context;
2619
2620         switch (ch) {
2621         case '%':
2622                 bb_putchar('%');
2623                 break;
2624         case 'b':
2625                 printf("%u", ctx->blk);
2626                 break;
2627         case 'B':
2628                 printf("%"PRIi64, ctx->blkcount);
2629                 break;
2630         case 'c':
2631                 printf("%u", ctx->blk2);
2632                 break;
2633         case 'd':
2634                 printf("%u", ctx->dir);
2635                 break;
2636         case 'g':
2637                 printf("%d", ctx->group);
2638                 break;
2639         case 'i':
2640                 printf("%u", ctx->ino);
2641                 break;
2642         case 'j':
2643                 printf("%u", ctx->ino2);
2644                 break;
2645         case 'm':
2646                 fputs(error_message(ctx->errcode), stdout);
2647                 break;
2648         case 'N':
2649                 printf("%"PRIi64, ctx->num);
2650                 break;
2651         case 'p':
2652                 print_pathname(fs, ctx->ino, 0);
2653                 break;
2654         case 'P':
2655                 print_pathname(fs, ctx->ino2,
2656                                ctx->dirent ? ctx->dirent->inode : 0);
2657                 break;
2658         case 'q':
2659                 print_pathname(fs, ctx->dir, 0);
2660                 break;
2661         case 'Q':
2662                 print_pathname(fs, ctx->dir, ctx->ino);
2663                 break;
2664         case 'S':
2665                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2666                 break;
2667         case 's':
2668                 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2669                 break;
2670         case 'X':
2671                 printf("0x%"PRIi64, ctx->num);
2672                 break;
2673         default:
2674         no_context:
2675                 printf("%%%c", ch);
2676                 break;
2677         }
2678 }
2679
2680
2681 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2682                           struct problem_context *pctx, int first)
2683 {
2684         ext2_filsys fs = ctx->fs;
2685         const char *    cp;
2686         int             i;
2687
2688         e2fsck_clear_progbar(ctx);
2689         for (cp = msg; *cp; cp++) {
2690                 if (cp[0] == '@') {
2691                         cp++;
2692                         expand_at_expression(ctx, *cp, pctx, &first);
2693                 } else if (cp[0] == '%' && cp[1] == 'I') {
2694                         cp += 2;
2695                         expand_inode_expression(*cp, pctx);
2696                 } else if (cp[0] == '%' && cp[1] == 'D') {
2697                         cp += 2;
2698                         expand_dirent_expression(*cp, pctx);
2699                 } else if ((cp[0] == '%')) {
2700                         cp++;
2701                         expand_percent_expression(fs, *cp, pctx);
2702                 } else {
2703                         for (i=0; cp[i]; i++)
2704                                 if ((cp[i] == '@') || cp[i] == '%')
2705                                         break;
2706                         printf("%.*s", i, cp);
2707                         cp += i-1;
2708                 }
2709                 first = 0;
2710         }
2711 }
2712
2713
2714 /*
2715  * region.c --- code which manages allocations within a region.
2716  */
2717
2718 struct region_el {
2719         region_addr_t   start;
2720         region_addr_t   end;
2721         struct region_el *next;
2722 };
2723
2724 struct region_struct {
2725         region_addr_t   min;
2726         region_addr_t   max;
2727         struct region_el *allocated;
2728 };
2729
2730 static region_t region_create(region_addr_t min, region_addr_t max)
2731 {
2732         region_t        region;
2733
2734         region = xzalloc(sizeof(struct region_struct));
2735         region->min = min;
2736         region->max = max;
2737         return region;
2738 }
2739
2740 static void region_free(region_t region)
2741 {
2742         struct region_el        *r, *next;
2743
2744         for (r = region->allocated; r; r = next) {
2745                 next = r->next;
2746                 free(r);
2747         }
2748         memset(region, 0, sizeof(struct region_struct));
2749         free(region);
2750 }
2751
2752 static int region_allocate(region_t region, region_addr_t start, int n)
2753 {
2754         struct region_el        *r, *new_region, *prev, *next;
2755         region_addr_t end;
2756
2757         end = start+n;
2758         if ((start < region->min) || (end > region->max))
2759                 return -1;
2760         if (n == 0)
2761                 return 1;
2762
2763         /*
2764          * Search through the linked list.  If we find that it
2765          * conflicts witih something that's already allocated, return
2766          * 1; if we can find an existing region which we can grow, do
2767          * so.  Otherwise, stop when we find the appropriate place
2768          * insert a new region element into the linked list.
2769          */
2770         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2771                 if (((start >= r->start) && (start < r->end)) ||
2772                     ((end > r->start) && (end <= r->end)) ||
2773                     ((start <= r->start) && (end >= r->end)))
2774                         return 1;
2775                 if (end == r->start) {
2776                         r->start = start;
2777                         return 0;
2778                 }
2779                 if (start == r->end) {
2780                         if ((next = r->next)) {
2781                                 if (end > next->start)
2782                                         return 1;
2783                                 if (end == next->start) {
2784                                         r->end = next->end;
2785                                         r->next = next->next;
2786                                         free(next);
2787                                         return 0;
2788                                 }
2789                         }
2790                         r->end = end;
2791                         return 0;
2792                 }
2793                 if (start < r->start)
2794                         break;
2795         }
2796         /*
2797          * Insert a new region element structure into the linked list
2798          */
2799         new_region = xmalloc(sizeof(struct region_el));
2800         new_region->start = start;
2801         new_region->end = start + n;
2802         new_region->next = r;
2803         if (prev)
2804                 prev->next = new_region;
2805         else
2806                 region->allocated = new_region;
2807         return 0;
2808 }
2809
2810 /*
2811  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2812  *
2813  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2814  * and applies the following tests to each inode:
2815  *
2816  *      - The mode field of the inode must be legal.
2817  *      - The size and block count fields of the inode are correct.
2818  *      - A data block must not be used by another inode
2819  *
2820  * Pass 1 also gathers the collects the following information:
2821  *
2822  *      - A bitmap of which inodes are in use.          (inode_used_map)
2823  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2824  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2825  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2826  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2827  *      - A bitmap of which blocks are in use.          (block_found_map)
2828  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2829  *      - The data blocks of the directory inodes.      (dir_map)
2830  *
2831  * Pass 1 is designed to stash away enough information so that the
2832  * other passes should not need to read in the inode information
2833  * during the normal course of a filesystem check.  (Althogh if an
2834  * inconsistency is detected, other passes may need to read in an
2835  * inode to fix it.)
2836  *
2837  * Note that pass 1B will be invoked if there are any duplicate blocks
2838  * found.
2839  */
2840
2841
2842 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2843                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2844                          int ref_offset, void *priv_data);
2845 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2846                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2847                              int ref_offset, void *priv_data);
2848 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2849                          char *block_buf);
2850 static void mark_table_blocks(e2fsck_t ctx);
2851 static void alloc_imagic_map(e2fsck_t ctx);
2852 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2853 static void handle_fs_bad_blocks(e2fsck_t ctx);
2854 static void process_inodes(e2fsck_t ctx, char *block_buf);
2855 static int process_inode_cmp(const void *a, const void *b);
2856 static errcode_t scan_callback(ext2_filsys fs,
2857                                   dgrp_t group, void * priv_data);
2858 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2859                                     char *block_buf, int adjust_sign);
2860 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2861
2862 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2863                                struct ext2_inode * inode, int bufsize,
2864                                const char *proc);
2865
2866 struct process_block_struct_1 {
2867         ext2_ino_t      ino;
2868         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2869                                 fragmented:1, compressed:1, bbcheck:1;
2870         blk_t           num_blocks;
2871         blk_t           max_blocks;
2872         e2_blkcnt_t     last_block;
2873         int             num_illegal_blocks;
2874         blk_t           previous_block;
2875         struct ext2_inode *inode;
2876         struct problem_context *pctx;
2877         ext2fs_block_bitmap fs_meta_blocks;
2878         e2fsck_t        ctx;
2879 };
2880
2881 struct process_inode_block {
2882         ext2_ino_t ino;
2883         struct ext2_inode inode;
2884 };
2885
2886 struct scan_callback_struct {
2887         e2fsck_t        ctx;
2888         char            *block_buf;
2889 };
2890
2891 /*
2892  * For the inodes to process list.
2893  */
2894 static struct process_inode_block *inodes_to_process;
2895 static int process_inode_count;
2896
2897 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2898                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2899
2900 /*
2901  * Free all memory allocated by pass1 in preparation for restarting
2902  * things.
2903  */
2904 static void unwind_pass1(void)
2905 {
2906         ext2fs_free_mem(&inodes_to_process);
2907 }
2908
2909 /*
2910  * Check to make sure a device inode is real.  Returns 1 if the device
2911  * checks out, 0 if not.
2912  *
2913  * Note: this routine is now also used to check FIFO's and Sockets,
2914  * since they have the same requirement; the i_block fields should be
2915  * zero.
2916  */
2917 static int
2918 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2919 {
2920         int     i;
2921
2922         /*
2923          * If i_blocks is non-zero, or the index flag is set, then
2924          * this is a bogus device/fifo/socket
2925          */
2926         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2927             (inode->i_flags & EXT2_INDEX_FL))
2928                 return 0;
2929
2930         /*
2931          * We should be able to do the test below all the time, but
2932          * because the kernel doesn't forcibly clear the device
2933          * inode's additional i_block fields, there are some rare
2934          * occasions when a legitimate device inode will have non-zero
2935          * additional i_block fields.  So for now, we only complain
2936          * when the immutable flag is set, which should never happen
2937          * for devices.  (And that's when the problem is caused, since
2938          * you can't set or clear immutable flags for devices.)  Once
2939          * the kernel has been fixed we can change this...
2940          */
2941         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2942                 for (i=4; i < EXT2_N_BLOCKS; i++)
2943                         if (inode->i_block[i])
2944                                 return 0;
2945         }
2946         return 1;
2947 }
2948
2949 /*
2950  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2951  * checks out, 0 if not.
2952  */
2953 static int
2954 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2955 {
2956         unsigned int len;
2957         int i;
2958         blk_t   blocks;
2959
2960         if ((inode->i_size_high || inode->i_size == 0) ||
2961             (inode->i_flags & EXT2_INDEX_FL))
2962                 return 0;
2963
2964         blocks = ext2fs_inode_data_blocks(fs, inode);
2965         if (blocks) {
2966                 if ((inode->i_size >= fs->blocksize) ||
2967                     (blocks != fs->blocksize >> 9) ||
2968                     (inode->i_block[0] < fs->super->s_first_data_block) ||
2969                     (inode->i_block[0] >= fs->super->s_blocks_count))
2970                         return 0;
2971
2972                 for (i = 1; i < EXT2_N_BLOCKS; i++)
2973                         if (inode->i_block[i])
2974                                 return 0;
2975
2976                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2977                         return 0;
2978
2979                 len = strnlen(buf, fs->blocksize);
2980                 if (len == fs->blocksize)
2981                         return 0;
2982         } else {
2983                 if (inode->i_size >= sizeof(inode->i_block))
2984                         return 0;
2985
2986                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2987                 if (len == sizeof(inode->i_block))
2988                         return 0;
2989         }
2990         if (len != inode->i_size)
2991                 return 0;
2992         return 1;
2993 }
2994
2995 /*
2996  * If the immutable (or append-only) flag is set on the inode, offer
2997  * to clear it.
2998  */
2999 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3000 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3001 {
3002         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3003                 return;
3004
3005         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3006                 return;
3007
3008         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3009         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3010 }
3011
3012 /*
3013  * If device, fifo or socket, check size is zero -- if not offer to
3014  * clear it
3015  */
3016 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3017 {
3018         struct ext2_inode *inode = pctx->inode;
3019
3020         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3021                 return;
3022
3023         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3024                 return;
3025
3026         inode->i_size = 0;
3027         inode->i_size_high = 0;
3028         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3029 }
3030
3031 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3032 {
3033         struct ext2_super_block *sb = ctx->fs->super;
3034         struct ext2_inode_large *inode;
3035         struct ext2_ext_attr_entry *entry;
3036         char *start, *end;
3037         int storage_size, remain, offs;
3038         int problem = 0;
3039
3040         inode = (struct ext2_inode_large *) pctx->inode;
3041         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3042                 inode->i_extra_isize;
3043         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3044                 inode->i_extra_isize + sizeof(__u32);
3045         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3046         entry = (struct ext2_ext_attr_entry *) start;
3047
3048         /* scan all entry's headers first */
3049
3050         /* take finish entry 0UL into account */
3051         remain = storage_size - sizeof(__u32);
3052         offs = end - start;
3053
3054         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3055
3056                 /* header eats this space */
3057                 remain -= sizeof(struct ext2_ext_attr_entry);
3058
3059                 /* is attribute name valid? */
3060                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3061                         pctx->num = entry->e_name_len;
3062                         problem = PR_1_ATTR_NAME_LEN;
3063                         goto fix;
3064                 }
3065
3066                 /* attribute len eats this space */
3067                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3068
3069                 /* check value size */
3070                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3071                         pctx->num = entry->e_value_size;
3072                         problem = PR_1_ATTR_VALUE_SIZE;
3073                         goto fix;
3074                 }
3075
3076                 /* check value placement */
3077                 if (entry->e_value_offs +
3078                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3079                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3080                         pctx->num = entry->e_value_offs;
3081                         problem = PR_1_ATTR_VALUE_OFFSET;
3082                         goto fix;
3083                 }
3084
3085                 /* e_value_block must be 0 in inode's ea */
3086                 if (entry->e_value_block != 0) {
3087                         pctx->num = entry->e_value_block;
3088                         problem = PR_1_ATTR_VALUE_BLOCK;
3089                         goto fix;
3090                 }
3091
3092                 /* e_hash must be 0 in inode's ea */
3093                 if (entry->e_hash != 0) {
3094                         pctx->num = entry->e_hash;
3095                         problem = PR_1_ATTR_HASH;
3096                         goto fix;
3097                 }
3098
3099                 remain -= entry->e_value_size;
3100                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3101
3102                 entry = EXT2_EXT_ATTR_NEXT(entry);
3103         }
3104 fix:
3105         /*
3106          * it seems like a corruption. it's very unlikely we could repair
3107          * EA(s) in automatic fashion -bzzz
3108          */
3109         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3110                 return;
3111
3112         /* simple remove all possible EA(s) */
3113         *((__u32 *)start) = 0UL;
3114         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3115                                 EXT2_INODE_SIZE(sb), "pass1");
3116 }
3117
3118 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3119 {
3120         struct ext2_super_block *sb = ctx->fs->super;
3121         struct ext2_inode_large *inode;
3122         __u32 *eamagic;
3123         int min, max;
3124
3125         inode = (struct ext2_inode_large *) pctx->inode;
3126         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3127                 /* this isn't large inode. so, nothing to check */
3128                 return;
3129         }
3130
3131         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3132         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3133         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3134         /*
3135          * For now we will allow i_extra_isize to be 0, but really
3136          * implementations should never allow i_extra_isize to be 0
3137          */
3138         if (inode->i_extra_isize &&
3139             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3140                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3141                         return;
3142                 inode->i_extra_isize = min;
3143                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3144                                         EXT2_INODE_SIZE(sb), "pass1");
3145                 return;
3146         }
3147
3148         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3149                         inode->i_extra_isize);
3150         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3151                 /* it seems inode has an extended attribute(s) in body */
3152                 check_ea_in_inode(ctx, pctx);
3153         }
3154 }
3155
3156 static void e2fsck_pass1(e2fsck_t ctx)
3157 {
3158         int     i;
3159         __u64   max_sizes;
3160         ext2_filsys fs = ctx->fs;
3161         ext2_ino_t      ino;
3162         struct ext2_inode *inode;
3163         ext2_inode_scan scan;
3164         char            *block_buf;
3165         unsigned char   frag, fsize;
3166         struct          problem_context pctx;
3167         struct          scan_callback_struct scan_struct;
3168         struct ext2_super_block *sb = ctx->fs->super;
3169         int             imagic_fs;
3170         int             busted_fs_time = 0;
3171         int             inode_size;
3172
3173         clear_problem_context(&pctx);
3174
3175         if (!(ctx->options & E2F_OPT_PREEN))
3176                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3177
3178         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3179             !(ctx->options & E2F_OPT_NO)) {
3180                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3181                         ctx->dirs_to_hash = 0;
3182         }
3183
3184         /* Pass 1 */
3185
3186 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3187
3188         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3189                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3190                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3191                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3192                 max_sizes = (max_sizes * (1UL << i)) - 1;
3193                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3194         }
3195 #undef EXT2_BPP
3196
3197         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3198
3199         /*
3200          * Allocate bitmaps structures
3201          */
3202         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3203                                               &ctx->inode_used_map);
3204         if (pctx.errcode) {
3205                 pctx.num = 1;
3206                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3207                 ctx->flags |= E2F_FLAG_ABORT;
3208                 return;
3209         }
3210         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3211                                 _("directory inode map"), &ctx->inode_dir_map);
3212         if (pctx.errcode) {
3213                 pctx.num = 2;
3214                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3215                 ctx->flags |= E2F_FLAG_ABORT;
3216                 return;
3217         }
3218         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3219                         _("regular file inode map"), &ctx->inode_reg_map);
3220         if (pctx.errcode) {
3221                 pctx.num = 6;
3222                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3223                 ctx->flags |= E2F_FLAG_ABORT;
3224                 return;
3225         }
3226         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3227                                               &ctx->block_found_map);
3228         if (pctx.errcode) {
3229                 pctx.num = 1;
3230                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3231                 ctx->flags |= E2F_FLAG_ABORT;
3232                 return;
3233         }
3234         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3235                                              &ctx->inode_link_info);
3236         if (pctx.errcode) {
3237                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3238                 ctx->flags |= E2F_FLAG_ABORT;
3239                 return;
3240         }
3241         inode_size = EXT2_INODE_SIZE(fs->super);
3242         inode = (struct ext2_inode *)
3243                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3244
3245         inodes_to_process = (struct process_inode_block *)
3246                 e2fsck_allocate_memory(ctx,
3247                                        (ctx->process_inode_size *
3248                                         sizeof(struct process_inode_block)),
3249                                        "array of inodes to process");
3250         process_inode_count = 0;
3251
3252         pctx.errcode = ext2fs_init_dblist(fs, 0);
3253         if (pctx.errcode) {
3254                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3255                 ctx->flags |= E2F_FLAG_ABORT;
3256                 return;
3257         }
3258
3259         /*
3260          * If the last orphan field is set, clear it, since the pass1
3261          * processing will automatically find and clear the orphans.
3262          * In the future, we may want to try using the last_orphan
3263          * linked list ourselves, but for now, we clear it so that the
3264          * ext3 mount code won't get confused.
3265          */
3266         if (!(ctx->options & E2F_OPT_READONLY)) {
3267                 if (fs->super->s_last_orphan) {
3268                         fs->super->s_last_orphan = 0;
3269                         ext2fs_mark_super_dirty(fs);
3270                 }
3271         }
3272
3273         mark_table_blocks(ctx);
3274         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3275                                                     "block interate buffer");
3276         e2fsck_use_inode_shortcuts(ctx, 1);
3277         ehandler_operation(_("doing inode scan"));
3278         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3279                                               &scan);
3280         if (pctx.errcode) {
3281                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3282                 ctx->flags |= E2F_FLAG_ABORT;
3283                 return;
3284         }
3285         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3286         ctx->stashed_inode = inode;
3287         scan_struct.ctx = ctx;
3288         scan_struct.block_buf = block_buf;
3289         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3290         if (ctx->progress)
3291                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3292                         return;
3293         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3294             (fs->super->s_mtime < fs->super->s_inodes_count))
3295                 busted_fs_time = 1;
3296
3297         while (1) {
3298                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3299                                                           inode, inode_size);
3300                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3301                         return;
3302                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3303                         continue;
3304                 }
3305                 if (pctx.errcode) {
3306                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3307                         ctx->flags |= E2F_FLAG_ABORT;
3308                         return;
3309                 }
3310                 if (!ino)
3311                         break;
3312                 pctx.ino = ino;
3313                 pctx.inode = inode;
3314                 ctx->stashed_ino = ino;
3315                 if (inode->i_links_count) {
3316                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3317                                            ino, inode->i_links_count);
3318                         if (pctx.errcode) {
3319                                 pctx.num = inode->i_links_count;
3320                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3321                                 ctx->flags |= E2F_FLAG_ABORT;
3322                                 return;
3323                         }
3324                 }
3325                 if (ino == EXT2_BAD_INO) {
3326                         struct process_block_struct_1 pb;
3327
3328                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3329                                                           &pb.fs_meta_blocks);
3330                         if (pctx.errcode) {
3331                                 pctx.num = 4;
3332                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3333                                 ctx->flags |= E2F_FLAG_ABORT;
3334                                 return;
3335                         }
3336                         pb.ino = EXT2_BAD_INO;
3337                         pb.num_blocks = pb.last_block = 0;
3338                         pb.num_illegal_blocks = 0;
3339                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3340                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3341                         pb.inode = inode;
3342                         pb.pctx = &pctx;
3343                         pb.ctx = ctx;
3344                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3345                                      block_buf, process_bad_block, &pb);
3346                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3347                         if (pctx.errcode) {
3348                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3349                                 ctx->flags |= E2F_FLAG_ABORT;
3350                                 return;
3351                         }
3352                         if (pb.bbcheck)
3353                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3354                                 ctx->flags |= E2F_FLAG_ABORT;
3355                                 return;
3356                         }
3357                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3358                         clear_problem_context(&pctx);
3359                         continue;
3360                 } else if (ino == EXT2_ROOT_INO) {
3361                         /*
3362                          * Make sure the root inode is a directory; if
3363                          * not, offer to clear it.  It will be
3364                          * regnerated in pass #3.
3365                          */
3366                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3367                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3368                                         inode->i_dtime = time(NULL);
3369                                         inode->i_links_count = 0;
3370                                         ext2fs_icount_store(ctx->inode_link_info,
3371                                                             ino, 0);
3372                                         e2fsck_write_inode(ctx, ino, inode,
3373                                                            "pass1");
3374                                 }
3375                         }
3376                         /*
3377                          * If dtime is set, offer to clear it.  mke2fs
3378                          * version 0.2b created filesystems with the
3379                          * dtime field set for the root and lost+found
3380                          * directories.  We won't worry about
3381                          * /lost+found, since that can be regenerated
3382                          * easily.  But we will fix the root directory
3383                          * as a special case.
3384                          */
3385                         if (inode->i_dtime && inode->i_links_count) {
3386                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3387                                         inode->i_dtime = 0;
3388                                         e2fsck_write_inode(ctx, ino, inode,
3389                                                            "pass1");
3390                                 }
3391                         }
3392                 } else if (ino == EXT2_JOURNAL_INO) {
3393                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3394                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3395                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3396                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3397                                                 &pctx)) {
3398                                         inode->i_mode = LINUX_S_IFREG;
3399                                         e2fsck_write_inode(ctx, ino, inode,
3400                                                            "pass1");
3401                                 }
3402                                 check_blocks(ctx, &pctx, block_buf);
3403                                 continue;
3404                         }
3405                         if ((inode->i_links_count || inode->i_blocks ||
3406                              inode->i_blocks || inode->i_block[0]) &&
3407                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3408                                         &pctx)) {
3409                                 memset(inode, 0, inode_size);
3410                                 ext2fs_icount_store(ctx->inode_link_info,
3411                                                     ino, 0);
3412                                 e2fsck_write_inode_full(ctx, ino, inode,
3413                                                         inode_size, "pass1");
3414                         }
3415                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3416                         int     problem = 0;
3417
3418                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3419                         if (ino == EXT2_BOOT_LOADER_INO) {
3420                                 if (LINUX_S_ISDIR(inode->i_mode))
3421                                         problem = PR_1_RESERVED_BAD_MODE;
3422                         } else if (ino == EXT2_RESIZE_INO) {
3423                                 if (inode->i_mode &&
3424                                     !LINUX_S_ISREG(inode->i_mode))
3425                                         problem = PR_1_RESERVED_BAD_MODE;
3426                         } else {
3427                                 if (inode->i_mode != 0)
3428                                         problem = PR_1_RESERVED_BAD_MODE;
3429                         }
3430                         if (problem) {
3431                                 if (fix_problem(ctx, problem, &pctx)) {
3432                                         inode->i_mode = 0;
3433                                         e2fsck_write_inode(ctx, ino, inode,
3434                                                            "pass1");
3435                                 }
3436                         }
3437                         check_blocks(ctx, &pctx, block_buf);
3438                         continue;
3439                 }
3440                 /*
3441                  * Check for inodes who might have been part of the
3442                  * orphaned list linked list.  They should have gotten
3443                  * dealt with by now, unless the list had somehow been
3444                  * corrupted.
3445                  *
3446                  * FIXME: In the future, inodes which are still in use
3447                  * (and which are therefore) pending truncation should
3448                  * be handled specially.  Right now we just clear the
3449                  * dtime field, and the normal e2fsck handling of
3450                  * inodes where i_size and the inode blocks are
3451                  * inconsistent is to fix i_size, instead of releasing
3452                  * the extra blocks.  This won't catch the inodes that
3453                  * was at the end of the orphan list, but it's better
3454                  * than nothing.  The right answer is that there
3455                  * shouldn't be any bugs in the orphan list handling.  :-)
3456                  */
3457                 if (inode->i_dtime && !busted_fs_time &&
3458                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3459                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3460                                 inode->i_dtime = inode->i_links_count ?
3461                                         0 : time(NULL);
3462                                 e2fsck_write_inode(ctx, ino, inode,
3463                                                    "pass1");
3464                         }
3465                 }
3466
3467                 /*
3468                  * This code assumes that deleted inodes have
3469                  * i_links_count set to 0.
3470                  */
3471                 if (!inode->i_links_count) {
3472                         if (!inode->i_dtime && inode->i_mode) {
3473                                 if (fix_problem(ctx,
3474                                             PR_1_ZERO_DTIME, &pctx)) {
3475                                         inode->i_dtime = time(NULL);
3476                                         e2fsck_write_inode(ctx, ino, inode,
3477                                                            "pass1");
3478                                 }
3479                         }
3480                         continue;
3481                 }
3482                 /*
3483                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3484                  * deleted files.  Oops.
3485                  *
3486                  * Since all new ext2 implementations get this right,
3487                  * we now assume that the case of non-zero
3488                  * i_links_count and non-zero dtime means that we
3489                  * should keep the file, not delete it.
3490                  *
3491                  */
3492                 if (inode->i_dtime) {
3493                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3494                                 inode->i_dtime = 0;
3495                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3496                         }
3497                 }
3498
3499                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3500                 switch (fs->super->s_creator_os) {
3501                     case EXT2_OS_LINUX:
3502                         frag = inode->osd2.linux2.l_i_frag;
3503                         fsize = inode->osd2.linux2.l_i_fsize;
3504                         break;
3505                     case EXT2_OS_HURD:
3506                         frag = inode->osd2.hurd2.h_i_frag;
3507                         fsize = inode->osd2.hurd2.h_i_fsize;
3508                         break;
3509                     case EXT2_OS_MASIX:
3510                         frag = inode->osd2.masix2.m_i_frag;
3511                         fsize = inode->osd2.masix2.m_i_fsize;
3512                         break;
3513                     default:
3514                         frag = fsize = 0;
3515                 }
3516
3517                 if (inode->i_faddr || frag || fsize ||
3518                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3519                         mark_inode_bad(ctx, ino);
3520                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3521                         if (imagic_fs) {
3522                                 if (!ctx->inode_imagic_map)
3523                                         alloc_imagic_map(ctx);
3524                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3525                                                          ino);
3526                         } else {
3527                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3528                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3529                                         e2fsck_write_inode(ctx, ino,
3530                                                            inode, "pass1");
3531                                 }
3532                         }
3533                 }
3534
3535                 check_inode_extra_space(ctx, &pctx);
3536
3537                 if (LINUX_S_ISDIR(inode->i_mode)) {
3538                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3539                         e2fsck_add_dir_info(ctx, ino, 0);
3540                         ctx->fs_directory_count++;
3541                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3542                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3543                         ctx->fs_regular_count++;
3544                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3545                            e2fsck_pass1_check_device_inode(fs, inode)) {
3546                         check_immutable(ctx, &pctx);
3547                         check_size(ctx, &pctx);
3548                         ctx->fs_chardev_count++;
3549                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3550                            e2fsck_pass1_check_device_inode(fs, inode)) {
3551                         check_immutable(ctx, &pctx);
3552                         check_size(ctx, &pctx);
3553                         ctx->fs_blockdev_count++;
3554                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3555                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3556                         check_immutable(ctx, &pctx);
3557                         ctx->fs_symlinks_count++;
3558                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3559                                 ctx->fs_fast_symlinks_count++;
3560                                 check_blocks(ctx, &pctx, block_buf);
3561                                 continue;
3562                         }
3563                 }
3564                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3565                          e2fsck_pass1_check_device_inode(fs, inode)) {
3566                         check_immutable(ctx, &pctx);
3567                         check_size(ctx, &pctx);
3568                         ctx->fs_fifo_count++;
3569                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3570                            e2fsck_pass1_check_device_inode(fs, inode)) {
3571                         check_immutable(ctx, &pctx);
3572                         check_size(ctx, &pctx);
3573                         ctx->fs_sockets_count++;
3574                 } else
3575                         mark_inode_bad(ctx, ino);
3576                 if (inode->i_block[EXT2_IND_BLOCK])
3577                         ctx->fs_ind_count++;
3578                 if (inode->i_block[EXT2_DIND_BLOCK])
3579                         ctx->fs_dind_count++;
3580                 if (inode->i_block[EXT2_TIND_BLOCK])
3581                         ctx->fs_tind_count++;
3582                 if (inode->i_block[EXT2_IND_BLOCK] ||
3583                     inode->i_block[EXT2_DIND_BLOCK] ||
3584                     inode->i_block[EXT2_TIND_BLOCK] ||
3585                     inode->i_file_acl) {
3586                         inodes_to_process[process_inode_count].ino = ino;
3587                         inodes_to_process[process_inode_count].inode = *inode;
3588                         process_inode_count++;
3589                 } else
3590                         check_blocks(ctx, &pctx, block_buf);
3591
3592                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3593                         return;
3594
3595                 if (process_inode_count >= ctx->process_inode_size) {
3596                         process_inodes(ctx, block_buf);
3597
3598                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3599                                 return;
3600                 }
3601         }
3602         process_inodes(ctx, block_buf);
3603         ext2fs_close_inode_scan(scan);
3604         ehandler_operation(0);
3605
3606         /*
3607          * If any extended attribute blocks' reference counts need to
3608          * be adjusted, either up (ctx->refcount_extra), or down
3609          * (ctx->refcount), then fix them.
3610          */
3611         if (ctx->refcount) {
3612                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3613                 ea_refcount_free(ctx->refcount);
3614                 ctx->refcount = 0;
3615         }
3616         if (ctx->refcount_extra) {
3617                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3618                                         block_buf, +1);
3619                 ea_refcount_free(ctx->refcount_extra);
3620                 ctx->refcount_extra = 0;
3621         }
3622
3623         if (ctx->invalid_bitmaps)
3624                 handle_fs_bad_blocks(ctx);
3625
3626         /* We don't need the block_ea_map any more */
3627         ext2fs_free_block_bitmap(ctx->block_ea_map);
3628         ctx->block_ea_map = 0;
3629
3630         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3631                 ext2fs_block_bitmap save_bmap;
3632
3633                 save_bmap = fs->block_map;
3634                 fs->block_map = ctx->block_found_map;
3635                 clear_problem_context(&pctx);
3636                 pctx.errcode = ext2fs_create_resize_inode(fs);
3637                 if (pctx.errcode) {
3638                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3639                         /* Should never get here */
3640                         ctx->flags |= E2F_FLAG_ABORT;
3641                         return;
3642                 }
3643                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3644                                   "recreate inode");
3645                 inode->i_mtime = time(NULL);
3646                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3647                                   "recreate inode");
3648                 fs->block_map = save_bmap;
3649                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3650         }
3651
3652         if (ctx->flags & E2F_FLAG_RESTART) {
3653                 /*
3654                  * Only the master copy of the superblock and block
3655                  * group descriptors are going to be written during a
3656                  * restart, so set the superblock to be used to be the
3657                  * master superblock.
3658                  */
3659                 ctx->use_superblock = 0;
3660                 unwind_pass1();
3661                 goto endit;
3662         }
3663
3664         if (ctx->block_dup_map) {
3665                 if (ctx->options & E2F_OPT_PREEN) {
3666                         clear_problem_context(&pctx);
3667                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3668                 }
3669                 e2fsck_pass1_dupblocks(ctx, block_buf);
3670         }
3671         ext2fs_free_mem(&inodes_to_process);
3672 endit:
3673         e2fsck_use_inode_shortcuts(ctx, 0);
3674
3675         ext2fs_free_mem(&block_buf);
3676         ext2fs_free_mem(&inode);
3677 }
3678
3679 /*
3680  * When the inode_scan routines call this callback at the end of the
3681  * glock group, call process_inodes.
3682  */
3683 static errcode_t scan_callback(ext2_filsys fs,
3684                                dgrp_t group, void * priv_data)
3685 {
3686         struct scan_callback_struct *scan_struct;
3687         e2fsck_t ctx;
3688
3689         scan_struct = (struct scan_callback_struct *) priv_data;
3690         ctx = scan_struct->ctx;
3691
3692         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3693
3694         if (ctx->progress)
3695                 if ((ctx->progress)(ctx, 1, group+1,
3696                                     ctx->fs->group_desc_count))
3697                         return EXT2_ET_CANCEL_REQUESTED;
3698
3699         return 0;
3700 }
3701
3702 /*
3703  * Process the inodes in the "inodes to process" list.
3704  */
3705 static void process_inodes(e2fsck_t ctx, char *block_buf)
3706 {
3707         int                     i;
3708         struct ext2_inode       *old_stashed_inode;
3709         ext2_ino_t              old_stashed_ino;
3710         const char              *old_operation;
3711         char                    buf[80];
3712         struct problem_context  pctx;
3713
3714         /* begin process_inodes */
3715         if (process_inode_count == 0)
3716                 return;
3717         old_operation = ehandler_operation(0);
3718         old_stashed_inode = ctx->stashed_inode;
3719         old_stashed_ino = ctx->stashed_ino;
3720         qsort(inodes_to_process, process_inode_count,
3721                       sizeof(struct process_inode_block), process_inode_cmp);
3722         clear_problem_context(&pctx);
3723         for (i=0; i < process_inode_count; i++) {
3724                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3725                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3726                 sprintf(buf, _("reading indirect blocks of inode %u"),
3727                         pctx.ino);
3728                 ehandler_operation(buf);
3729                 check_blocks(ctx, &pctx, block_buf);
3730                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3731                         break;
3732         }
3733         ctx->stashed_inode = old_stashed_inode;
3734         ctx->stashed_ino = old_stashed_ino;
3735         process_inode_count = 0;
3736         /* end process inodes */
3737
3738         ehandler_operation(old_operation);
3739 }
3740
3741 static int process_inode_cmp(const void *a, const void *b)
3742 {
3743         const struct process_inode_block *ib_a =
3744                 (const struct process_inode_block *) a;
3745         const struct process_inode_block *ib_b =
3746                 (const struct process_inode_block *) b;
3747         int     ret;
3748
3749         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3750                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3751         if (ret == 0)
3752                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3753         return ret;
3754 }
3755
3756 /*
3757  * Mark an inode as being bad in some what
3758  */
3759 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3760 {
3761         struct          problem_context pctx;
3762
3763         if (!ctx->inode_bad_map) {
3764                 clear_problem_context(&pctx);
3765
3766                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3767                             _("bad inode map"), &ctx->inode_bad_map);
3768                 if (pctx.errcode) {
3769                         pctx.num = 3;
3770                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3771                         /* Should never get here */
3772                         ctx->flags |= E2F_FLAG_ABORT;
3773                         return;
3774                 }
3775         }
3776         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3777 }
3778
3779
3780 /*
3781  * This procedure will allocate the inode imagic table
3782  */
3783 static void alloc_imagic_map(e2fsck_t ctx)
3784 {
3785         struct          problem_context pctx;
3786
3787         clear_problem_context(&pctx);
3788         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3789                                               _("imagic inode map"),
3790                                               &ctx->inode_imagic_map);
3791         if (pctx.errcode) {
3792                 pctx.num = 5;
3793                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3794                 /* Should never get here */
3795                 ctx->flags |= E2F_FLAG_ABORT;
3796                 return;
3797         }
3798 }
3799
3800 /*
3801  * Marks a block as in use, setting the dup_map if it's been set
3802  * already.  Called by process_block and process_bad_block.
3803  *
3804  * WARNING: Assumes checks have already been done to make sure block
3805  * is valid.  This is true in both process_block and process_bad_block.
3806  */
3807 static void mark_block_used(e2fsck_t ctx, blk_t block)
3808 {
3809         struct          problem_context pctx;
3810
3811         clear_problem_context(&pctx);
3812
3813         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3814                 if (!ctx->block_dup_map) {
3815                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3816                               _("multiply claimed block map"),
3817                               &ctx->block_dup_map);
3818                         if (pctx.errcode) {
3819                                 pctx.num = 3;
3820                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3821                                             &pctx);
3822                                 /* Should never get here */
3823                                 ctx->flags |= E2F_FLAG_ABORT;
3824                                 return;
3825                         }
3826                 }
3827                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3828         } else {
3829                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3830         }
3831 }
3832
3833 /*
3834  * Adjust the extended attribute block's reference counts at the end
3835  * of pass 1, either by subtracting out references for EA blocks that
3836  * are still referenced in ctx->refcount, or by adding references for
3837  * EA blocks that had extra references as accounted for in
3838  * ctx->refcount_extra.
3839  */
3840 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3841                                     char *block_buf, int adjust_sign)
3842 {
3843         struct ext2_ext_attr_header     *header;
3844         struct problem_context          pctx;
3845         ext2_filsys                     fs = ctx->fs;
3846         blk_t                           blk;
3847         __u32                           should_be;
3848         int                             count;
3849
3850         clear_problem_context(&pctx);
3851
3852         ea_refcount_intr_begin(refcount);
3853         while (1) {
3854                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3855                         break;
3856                 pctx.blk = blk;
3857                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3858                 if (pctx.errcode) {
3859                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3860                         return;
3861                 }
3862                 header = (struct ext2_ext_attr_header *) block_buf;
3863                 pctx.blkcount = header->h_refcount;
3864                 should_be = header->h_refcount + adjust_sign * count;
3865                 pctx.num = should_be;
3866                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3867                         header->h_refcount = should_be;
3868                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3869                                                              block_buf);
3870                         if (pctx.errcode) {
3871                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3872                                 continue;
3873                         }
3874                 }
3875         }
3876 }
3877
3878 /*
3879  * Handle processing the extended attribute blocks
3880  */
3881 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3882                            char *block_buf)
3883 {
3884         ext2_filsys fs = ctx->fs;
3885         ext2_ino_t      ino = pctx->ino;
3886         struct ext2_inode *inode = pctx->inode;
3887         blk_t           blk;
3888         char *          end;
3889         struct ext2_ext_attr_header *header;
3890         struct ext2_ext_attr_entry *entry;
3891         int             count;
3892         region_t        region;
3893
3894         blk = inode->i_file_acl;
3895         if (blk == 0)
3896                 return 0;
3897
3898         /*
3899          * If the Extended attribute flag isn't set, then a non-zero
3900          * file acl means that the inode is corrupted.
3901          *
3902          * Or if the extended attribute block is an invalid block,
3903          * then the inode is also corrupted.
3904          */
3905         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3906             (blk < fs->super->s_first_data_block) ||
3907             (blk >= fs->super->s_blocks_count)) {
3908                 mark_inode_bad(ctx, ino);
3909                 return 0;
3910         }
3911
3912         /* If ea bitmap hasn't been allocated, create it */
3913         if (!ctx->block_ea_map) {
3914                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3915                                                       _("ext attr block map"),
3916                                                       &ctx->block_ea_map);
3917                 if (pctx->errcode) {
3918                         pctx->num = 2;
3919                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3920                         ctx->flags |= E2F_FLAG_ABORT;
3921                         return 0;
3922                 }
3923         }
3924
3925         /* Create the EA refcount structure if necessary */
3926         if (!ctx->refcount) {
3927                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3928                 if (pctx->errcode) {
3929                         pctx->num = 1;
3930                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3931                         ctx->flags |= E2F_FLAG_ABORT;
3932                         return 0;
3933                 }
3934         }
3935
3936         /* Have we seen this EA block before? */
3937         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3938                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3939                         return 1;
3940                 /* Ooops, this EA was referenced more than it stated */
3941                 if (!ctx->refcount_extra) {
3942                         pctx->errcode = ea_refcount_create(0,
3943                                            &ctx->refcount_extra);
3944                         if (pctx->errcode) {
3945                                 pctx->num = 2;
3946                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3947                                 ctx->flags |= E2F_FLAG_ABORT;
3948                                 return 0;
3949                         }
3950                 }
3951                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3952                 return 1;
3953         }
3954
3955         /*
3956          * OK, we haven't seen this EA block yet.  So we need to
3957          * validate it
3958          */
3959         pctx->blk = blk;
3960         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3961         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3962                 goto clear_extattr;
3963         header = (struct ext2_ext_attr_header *) block_buf;
3964         pctx->blk = inode->i_file_acl;
3965         if (((ctx->ext_attr_ver == 1) &&
3966              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3967             ((ctx->ext_attr_ver == 2) &&
3968              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3969                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3970                         goto clear_extattr;
3971         }
3972
3973         if (header->h_blocks != 1) {
3974                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3975                         goto clear_extattr;
3976         }
3977
3978         region = region_create(0, fs->blocksize);
3979         if (!region) {
3980                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3981                 ctx->flags |= E2F_FLAG_ABORT;
3982                 return 0;
3983         }
3984         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3985                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3986                         goto clear_extattr;
3987         }
3988
3989         entry = (struct ext2_ext_attr_entry *)(header+1);
3990         end = block_buf + fs->blocksize;
3991         while ((char *)entry < end && *(__u32 *)entry) {
3992                 if (region_allocate(region, (char *)entry - (char *)header,
3993                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
3994                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3995                                 goto clear_extattr;
3996                 }
3997                 if ((ctx->ext_attr_ver == 1 &&
3998                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
3999                     (ctx->ext_attr_ver == 2 &&
4000                      entry->e_name_index == 0)) {
4001                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4002                                 goto clear_extattr;
4003                 }
4004                 if (entry->e_value_block != 0) {
4005                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4006                                 goto clear_extattr;
4007                 }
4008                 if (entry->e_value_size &&
4009                     region_allocate(region, entry->e_value_offs,
4010                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4011                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4012                                 goto clear_extattr;
4013                 }
4014                 entry = EXT2_EXT_ATTR_NEXT(entry);
4015         }
4016         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4017                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4018                         goto clear_extattr;
4019         }
4020         region_free(region);
4021
4022         count = header->h_refcount - 1;
4023         if (count)
4024                 ea_refcount_store(ctx->refcount, blk, count);
4025         mark_block_used(ctx, blk);
4026         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4027
4028         return 1;
4029
4030 clear_extattr:
4031         inode->i_file_acl = 0;
4032         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4033         return 0;
4034 }
4035
4036 /* Returns 1 if bad htree, 0 if OK */
4037 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4038                         ext2_ino_t ino FSCK_ATTR((unused)),
4039                         struct ext2_inode *inode,
4040                         char *block_buf)
4041 {
4042         struct ext2_dx_root_info        *root;
4043         ext2_filsys                     fs = ctx->fs;
4044         errcode_t                       retval;
4045         blk_t                           blk;
4046
4047         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4048              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4049             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4050              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4051                 return 1;
4052
4053         blk = inode->i_block[0];
4054         if (((blk == 0) ||
4055              (blk < fs->super->s_first_data_block) ||
4056              (blk >= fs->super->s_blocks_count)) &&
4057             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4058                 return 1;
4059
4060         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4061         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4062                 return 1;
4063
4064         /* XXX should check that beginning matches a directory */
4065         root = (struct ext2_dx_root_info *) (block_buf + 24);
4066
4067         if ((root->reserved_zero || root->info_length < 8) &&
4068             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4069                 return 1;
4070
4071         pctx->num = root->hash_version;
4072         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4073             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4074             (root->hash_version != EXT2_HASH_TEA) &&
4075             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4076                 return 1;
4077
4078         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4079             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4080                 return 1;
4081
4082         pctx->num = root->indirect_levels;
4083         if ((root->indirect_levels > 1) &&
4084             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4085                 return 1;
4086
4087         return 0;
4088 }
4089
4090 /*
4091  * This subroutine is called on each inode to account for all of the
4092  * blocks used by that inode.
4093  */
4094 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4095                          char *block_buf)
4096 {
4097         ext2_filsys fs = ctx->fs;
4098         struct process_block_struct_1 pb;
4099         ext2_ino_t      ino = pctx->ino;
4100         struct ext2_inode *inode = pctx->inode;
4101         int             bad_size = 0;
4102         int             dirty_inode = 0;
4103         __u64           size;
4104
4105         pb.ino = ino;
4106         pb.num_blocks = 0;
4107         pb.last_block = -1;
4108         pb.num_illegal_blocks = 0;
4109         pb.suppress = 0; pb.clear = 0;
4110         pb.fragmented = 0;
4111         pb.compressed = 0;
4112         pb.previous_block = 0;
4113         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4114         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4115         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4116         pb.inode = inode;
4117         pb.pctx = pctx;
4118         pb.ctx = ctx;
4119         pctx->ino = ino;
4120         pctx->errcode = 0;
4121
4122         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4123                 if (fs->super->s_feature_incompat &
4124                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4125                         pb.compressed = 1;
4126                 else {
4127                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4128                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4129                                 dirty_inode++;
4130                         }
4131                 }
4132         }
4133
4134         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4135                 pb.num_blocks++;
4136
4137         if (ext2fs_inode_has_valid_blocks(inode))
4138                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4139                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4140                                        block_buf, process_block, &pb);
4141         end_problem_latch(ctx, PR_LATCH_BLOCK);
4142         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4143         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4144                 goto out;
4145         if (pctx->errcode)
4146                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4147
4148         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4149                 ctx->fs_fragmented++;
4150
4151         if (pb.clear) {
4152                 inode->i_links_count = 0;
4153                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4154                 inode->i_dtime = time(NULL);
4155                 dirty_inode++;
4156                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4157                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4158                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4159                 /*
4160                  * The inode was probably partially accounted for
4161                  * before processing was aborted, so we need to
4162                  * restart the pass 1 scan.
4163                  */
4164                 ctx->flags |= E2F_FLAG_RESTART;
4165                 goto out;
4166         }
4167
4168         if (inode->i_flags & EXT2_INDEX_FL) {
4169                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4170                         inode->i_flags &= ~EXT2_INDEX_FL;
4171                         dirty_inode++;
4172                 } else {
4173 #ifdef ENABLE_HTREE
4174                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4175 #endif
4176                 }
4177         }
4178         if (ctx->dirs_to_hash && pb.is_dir &&
4179             !(inode->i_flags & EXT2_INDEX_FL) &&
4180             ((inode->i_size / fs->blocksize) >= 3))
4181                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4182
4183         if (!pb.num_blocks && pb.is_dir) {
4184                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4185                         inode->i_links_count = 0;
4186                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4187                         inode->i_dtime = time(NULL);
4188                         dirty_inode++;
4189                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4190                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4191                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4192                         ctx->fs_directory_count--;
4193                         goto out;
4194                 }
4195         }
4196
4197         pb.num_blocks *= (fs->blocksize / 512);
4198
4199         if (pb.is_dir) {
4200                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4201                 if (nblock > (pb.last_block + 1))
4202                         bad_size = 1;
4203                 else if (nblock < (pb.last_block + 1)) {
4204                         if (((pb.last_block + 1) - nblock) >
4205                             fs->super->s_prealloc_dir_blocks)
4206                                 bad_size = 2;
4207                 }
4208         } else {
4209                 size = EXT2_I_SIZE(inode);
4210                 if ((pb.last_block >= 0) &&
4211                     (size < (__u64) pb.last_block * fs->blocksize))
4212                         bad_size = 3;
4213                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4214                         bad_size = 4;
4215         }
4216         /* i_size for symlinks is checked elsewhere */
4217         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4218                 pctx->num = (pb.last_block+1) * fs->blocksize;
4219                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4220                         inode->i_size = pctx->num;
4221                         if (!LINUX_S_ISDIR(inode->i_mode))
4222                                 inode->i_size_high = pctx->num >> 32;
4223                         dirty_inode++;
4224                 }
4225                 pctx->num = 0;
4226         }
4227         if (LINUX_S_ISREG(inode->i_mode) &&
4228             (inode->i_size_high || inode->i_size & 0x80000000UL))
4229                 ctx->large_files++;
4230         if (pb.num_blocks != inode->i_blocks) {
4231                 pctx->num = pb.num_blocks;
4232                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4233                         inode->i_blocks = pb.num_blocks;
4234                         dirty_inode++;
4235                 }
4236                 pctx->num = 0;
4237         }
4238 out:
4239         if (dirty_inode)
4240                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4241 }
4242
4243
4244 /*
4245  * This is a helper function for check_blocks().
4246  */
4247 static int process_block(ext2_filsys fs,
4248                   blk_t *block_nr,
4249                   e2_blkcnt_t blockcnt,
4250                   blk_t ref_block FSCK_ATTR((unused)),
4251                   int ref_offset FSCK_ATTR((unused)),
4252                   void *priv_data)
4253 {
4254         struct process_block_struct_1 *p;
4255         struct problem_context *pctx;
4256         blk_t   blk = *block_nr;
4257         int     ret_code = 0;
4258         int     problem = 0;
4259         e2fsck_t        ctx;
4260
4261         p = (struct process_block_struct_1 *) priv_data;
4262         pctx = p->pctx;
4263         ctx = p->ctx;
4264
4265         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4266                 /* todo: Check that the comprblk_fl is high, that the
4267                    blkaddr pattern looks right (all non-holes up to
4268                    first EXT2FS_COMPRESSED_BLKADDR, then all
4269                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4270                    that the feature_incompat bit is high, and that the
4271                    inode is a regular file.  If we're doing a "full
4272                    check" (a concept introduced to e2fsck by e2compr,
4273                    meaning that we look at data blocks as well as
4274                    metadata) then call some library routine that
4275                    checks the compressed data.  I'll have to think
4276                    about this, because one particularly important
4277                    problem to be able to fix is to recalculate the
4278                    cluster size if necessary.  I think that perhaps
4279                    we'd better do most/all e2compr-specific checks
4280                    separately, after the non-e2compr checks.  If not
4281                    doing a full check, it may be useful to test that
4282                    the personality is linux; e.g. if it isn't then
4283                    perhaps this really is just an illegal block. */
4284                 return 0;
4285         }
4286
4287         if (blk == 0) {
4288                 if (p->is_dir == 0) {
4289                         /*
4290                          * Should never happen, since only directories
4291                          * get called with BLOCK_FLAG_HOLE
4292                          */
4293 #ifdef DEBUG_E2FSCK
4294                         printf("process_block() called with blk == 0, "
4295                                "blockcnt=%d, inode %lu???\n",
4296                                blockcnt, p->ino);
4297 #endif
4298                         return 0;
4299                 }
4300                 if (blockcnt < 0)
4301                         return 0;
4302                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4303                         goto mark_dir;
4304                 }
4305                 return 0;
4306         }
4307
4308         /*
4309          * Simplistic fragmentation check.  We merely require that the
4310          * file be contiguous.  (Which can never be true for really
4311          * big files that are greater than a block group.)
4312          */
4313         if (!HOLE_BLKADDR(p->previous_block)) {
4314                 if (p->previous_block+1 != blk)
4315                         p->fragmented = 1;
4316         }
4317         p->previous_block = blk;
4318
4319         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4320                 problem = PR_1_TOOBIG_DIR;
4321         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4322                 problem = PR_1_TOOBIG_REG;
4323         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4324                 problem = PR_1_TOOBIG_SYMLINK;
4325
4326         if (blk < fs->super->s_first_data_block ||
4327             blk >= fs->super->s_blocks_count)
4328                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4329
4330         if (problem) {
4331                 p->num_illegal_blocks++;
4332                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4333                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4334                                 p->clear = 1;
4335                                 return BLOCK_ABORT;
4336                         }
4337                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4338                                 p->suppress = 1;
4339                                 set_latch_flags(PR_LATCH_BLOCK,
4340                                                 PRL_SUPPRESS, 0);
4341                         }
4342                 }
4343                 pctx->blk = blk;
4344                 pctx->blkcount = blockcnt;
4345                 if (fix_problem(ctx, problem, pctx)) {
4346                         blk = *block_nr = 0;
4347                         ret_code = BLOCK_CHANGED;
4348                         goto mark_dir;
4349                 } else
4350                         return 0;
4351         }
4352
4353         if (p->ino == EXT2_RESIZE_INO) {
4354                 /*
4355                  * The resize inode has already be sanity checked
4356                  * during pass #0 (the superblock checks).  All we
4357                  * have to do is mark the double indirect block as
4358                  * being in use; all of the other blocks are handled
4359                  * by mark_table_blocks()).
4360                  */
4361                 if (blockcnt == BLOCK_COUNT_DIND)
4362                         mark_block_used(ctx, blk);
4363         } else
4364                 mark_block_used(ctx, blk);
4365         p->num_blocks++;
4366         if (blockcnt >= 0)
4367                 p->last_block = blockcnt;
4368 mark_dir:
4369         if (p->is_dir && (blockcnt >= 0)) {
4370                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4371                                                     blk, blockcnt);
4372                 if (pctx->errcode) {
4373                         pctx->blk = blk;
4374                         pctx->num = blockcnt;
4375                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4376                         /* Should never get here */
4377                         ctx->flags |= E2F_FLAG_ABORT;
4378                         return BLOCK_ABORT;
4379                 }
4380         }
4381         return ret_code;
4382 }
4383
4384 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4385                       blk_t *block_nr,
4386                       e2_blkcnt_t blockcnt,
4387                       blk_t ref_block FSCK_ATTR((unused)),
4388                       int ref_offset FSCK_ATTR((unused)),
4389                       void *priv_data EXT2FS_ATTR((unused)))
4390 {
4391         /*
4392          * Note: This function processes blocks for the bad blocks
4393          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4394          */
4395
4396         printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4397         return BLOCK_ERROR;
4398 }
4399
4400 /*
4401  * This routine gets called at the end of pass 1 if bad blocks are
4402  * detected in the superblock, group descriptors, inode_bitmaps, or
4403  * block bitmaps.  At this point, all of the blocks have been mapped
4404  * out, so we can try to allocate new block(s) to replace the bad
4405  * blocks.
4406  */
4407 static void handle_fs_bad_blocks(e2fsck_t ctx)
4408 {
4409         printf("Bad blocks detected on your filesystem\n"
4410                 "You should get your data off as the device will soon die\n");
4411 }
4412
4413 /*
4414  * This routine marks all blocks which are used by the superblock,
4415  * group descriptors, inode bitmaps, and block bitmaps.
4416  */
4417 static void mark_table_blocks(e2fsck_t ctx)
4418 {
4419         ext2_filsys fs = ctx->fs;
4420         blk_t   block, b;
4421         dgrp_t  i;
4422         int     j;
4423         struct problem_context pctx;
4424
4425         clear_problem_context(&pctx);
4426
4427         block = fs->super->s_first_data_block;
4428         for (i = 0; i < fs->group_desc_count; i++) {
4429                 pctx.group = i;
4430
4431                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4432
4433                 /*
4434                  * Mark the blocks used for the inode table
4435                  */
4436                 if (fs->group_desc[i].bg_inode_table) {
4437                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4438                              j < fs->inode_blocks_per_group;
4439                              j++, b++) {
4440                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4441                                                              b)) {
4442                                         pctx.blk = b;
4443                                         if (fix_problem(ctx,
4444                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4445                                                 ctx->invalid_inode_table_flag[i]++;
4446                                                 ctx->invalid_bitmaps++;
4447                                         }
4448                                 } else {
4449                                         ext2fs_mark_block_bitmap(ctx->block_found_map, b);
4450                                 }
4451                         }
4452                 }
4453
4454                 /*
4455                  * Mark block used for the block bitmap
4456                  */
4457                 if (fs->group_desc[i].bg_block_bitmap) {
4458                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4459                                      fs->group_desc[i].bg_block_bitmap)) {
4460                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4461                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4462                                         ctx->invalid_block_bitmap_flag[i]++;
4463                                         ctx->invalid_bitmaps++;
4464                                 }
4465                         } else {
4466                                 ext2fs_mark_block_bitmap(ctx->block_found_map,
4467                                         fs->group_desc[i].bg_block_bitmap);
4468                         }
4469                 }
4470                 /*
4471                  * Mark block used for the inode bitmap
4472                  */
4473                 if (fs->group_desc[i].bg_inode_bitmap) {
4474                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4475                                      fs->group_desc[i].bg_inode_bitmap)) {
4476                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4477                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4478                                         ctx->invalid_inode_bitmap_flag[i]++;
4479                                         ctx->invalid_bitmaps++;
4480                                 }
4481                         } else {
4482                                 ext2fs_mark_block_bitmap(ctx->block_found_map,
4483                                         fs->group_desc[i].bg_inode_bitmap);
4484                         }
4485                 }
4486                 block += fs->super->s_blocks_per_group;
4487         }
4488 }
4489
4490 /*
4491  * Thes subroutines short circuits ext2fs_get_blocks and
4492  * ext2fs_check_directory; we use them since we already have the inode
4493  * structure, so there's no point in letting the ext2fs library read
4494  * the inode again.
4495  */
4496 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4497                                   blk_t *blocks)
4498 {
4499         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4500         int     i;
4501
4502         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4503                 return EXT2_ET_CALLBACK_NOTHANDLED;
4504
4505         for (i=0; i < EXT2_N_BLOCKS; i++)
4506                 blocks[i] = ctx->stashed_inode->i_block[i];
4507         return 0;
4508 }
4509
4510 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4511                                   struct ext2_inode *inode)
4512 {
4513         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4514
4515         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4516                 return EXT2_ET_CALLBACK_NOTHANDLED;
4517         *inode = *ctx->stashed_inode;
4518         return 0;
4519 }
4520
4521 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4522                             struct ext2_inode *inode)
4523 {
4524         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4525
4526         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4527                 *ctx->stashed_inode = *inode;
4528         return EXT2_ET_CALLBACK_NOTHANDLED;
4529 }
4530
4531 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
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
4538         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4539                 return EXT2_ET_NO_DIRECTORY;
4540         return 0;
4541 }
4542
4543 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4544 {
4545         ext2_filsys fs = ctx->fs;
4546
4547         if (bool) {
4548                 fs->get_blocks = pass1_get_blocks;
4549                 fs->check_directory = pass1_check_directory;
4550                 fs->read_inode = pass1_read_inode;
4551                 fs->write_inode = pass1_write_inode;
4552                 ctx->stashed_ino = 0;
4553         } else {
4554                 fs->get_blocks = 0;
4555                 fs->check_directory = 0;
4556                 fs->read_inode = 0;
4557                 fs->write_inode = 0;
4558         }
4559 }
4560
4561 /*
4562  * pass1b.c --- Pass #1b of e2fsck
4563  *
4564  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4565  * only invoked if pass 1 discovered blocks which are in use by more
4566  * than one inode.
4567  *
4568  * Pass1B scans the data blocks of all the inodes again, generating a
4569  * complete list of duplicate blocks and which inodes have claimed
4570  * them.
4571  *
4572  * Pass1C does a tree-traversal of the filesystem, to determine the
4573  * parent directories of these inodes.  This step is necessary so that
4574  * e2fsck can print out the pathnames of affected inodes.
4575  *
4576  * Pass1D is a reconciliation pass.  For each inode with duplicate
4577  * blocks, the user is prompted if s/he would like to clone the file
4578  * (so that the file gets a fresh copy of the duplicated blocks) or
4579  * simply to delete the file.
4580  *
4581  */
4582
4583
4584 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4585 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4586 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4587
4588 /* Define an extension to the ext2 library's block count information */
4589 #define BLOCK_COUNT_EXTATTR     (-5)
4590
4591 struct block_el {
4592         blk_t   block;
4593         struct block_el *next;
4594 };
4595
4596 struct inode_el {
4597         ext2_ino_t      inode;
4598         struct inode_el *next;
4599 };
4600
4601 struct dup_block {
4602         int             num_bad;
4603         struct inode_el *inode_list;
4604 };
4605
4606 /*
4607  * This structure stores information about a particular inode which
4608  * is sharing blocks with other inodes.  This information is collected
4609  * to display to the user, so that the user knows what files he or she
4610  * is dealing with, when trying to decide how to resolve the conflict
4611  * of multiply-claimed blocks.
4612  */
4613 struct dup_inode {
4614         ext2_ino_t              dir;
4615         int                     num_dupblocks;
4616         struct ext2_inode       inode;
4617         struct block_el         *block_list;
4618 };
4619
4620 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4621                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4622                                 int ref_offset, void *priv_data);
4623 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4624                         struct dup_inode *dp, char *block_buf);
4625 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4626                       struct dup_inode *dp, char* block_buf);
4627 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4628
4629 static void pass1b(e2fsck_t ctx, char *block_buf);
4630 static void pass1c(e2fsck_t ctx, char *block_buf);
4631 static void pass1d(e2fsck_t ctx, char *block_buf);
4632
4633 static int dup_inode_count = 0;
4634
4635 static dict_t blk_dict, ino_dict;
4636
4637 static ext2fs_inode_bitmap inode_dup_map;
4638
4639 static int dict_int_cmp(const void *a, const void *b)
4640 {
4641         intptr_t        ia, ib;
4642
4643         ia = (intptr_t)a;
4644         ib = (intptr_t)b;
4645
4646         return (ia-ib);
4647 }
4648
4649 /*
4650  * Add a duplicate block record
4651  */
4652 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4653                      struct ext2_inode *inode)
4654 {
4655         dnode_t *n;
4656         struct dup_block        *db;
4657         struct dup_inode        *di;
4658         struct block_el         *blk_el;
4659         struct inode_el         *ino_el;
4660
4661         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4662         if (n)
4663                 db = (struct dup_block *) dnode_get(n);
4664         else {
4665                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4666                          sizeof(struct dup_block), "duplicate block header");
4667                 db->num_bad = 0;
4668                 db->inode_list = 0;
4669                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4670         }
4671         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4672                          sizeof(struct inode_el), "inode element");
4673         ino_el->inode = ino;
4674         ino_el->next = db->inode_list;
4675         db->inode_list = ino_el;
4676         db->num_bad++;
4677
4678         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4679         if (n)
4680                 di = (struct dup_inode *) dnode_get(n);
4681         else {
4682                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4683                          sizeof(struct dup_inode), "duplicate inode header");
4684                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4685                 di->num_dupblocks = 0;
4686                 di->block_list = 0;
4687                 di->inode = *inode;
4688                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4689         }
4690         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4691                          sizeof(struct block_el), "block element");
4692         blk_el->block = blk;
4693         blk_el->next = di->block_list;
4694         di->block_list = blk_el;
4695         di->num_dupblocks++;
4696 }
4697
4698 /*
4699  * Free a duplicate inode record
4700  */
4701 static void inode_dnode_free(dnode_t *node)
4702 {
4703         struct dup_inode        *di;
4704         struct block_el         *p, *next;
4705
4706         di = (struct dup_inode *) dnode_get(node);
4707         for (p = di->block_list; p; p = next) {
4708                 next = p->next;
4709                 free(p);
4710         }
4711         free(node);
4712 }
4713
4714 /*
4715  * Free a duplicate block record
4716  */
4717 static void block_dnode_free(dnode_t *node)
4718 {
4719         struct dup_block        *db;
4720         struct inode_el         *p, *next;
4721
4722         db = (struct dup_block *) dnode_get(node);
4723         for (p = db->inode_list; p; p = next) {
4724                 next = p->next;
4725                 free(p);
4726         }
4727         free(node);
4728 }
4729
4730
4731 /*
4732  * Main procedure for handling duplicate blocks
4733  */
4734 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4735 {
4736         ext2_filsys             fs = ctx->fs;
4737         struct problem_context  pctx;
4738
4739         clear_problem_context(&pctx);
4740
4741         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4742                       _("multiply claimed inode map"), &inode_dup_map);
4743         if (pctx.errcode) {
4744                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4745                 ctx->flags |= E2F_FLAG_ABORT;
4746                 return;
4747         }
4748
4749         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4750         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4751         dict_set_allocator(&ino_dict, inode_dnode_free);
4752         dict_set_allocator(&blk_dict, block_dnode_free);
4753
4754         pass1b(ctx, block_buf);
4755         pass1c(ctx, block_buf);
4756         pass1d(ctx, block_buf);
4757
4758         /*
4759          * Time to free all of the accumulated data structures that we
4760          * don't need anymore.
4761          */
4762         dict_free_nodes(&ino_dict);
4763         dict_free_nodes(&blk_dict);
4764 }
4765
4766 /*
4767  * Scan the inodes looking for inodes that contain duplicate blocks.
4768  */
4769 struct process_block_struct_1b {
4770         e2fsck_t        ctx;
4771         ext2_ino_t      ino;
4772         int             dup_blocks;
4773         struct ext2_inode *inode;
4774         struct problem_context *pctx;
4775 };
4776
4777 static void pass1b(e2fsck_t ctx, char *block_buf)
4778 {
4779         ext2_filsys fs = ctx->fs;
4780         ext2_ino_t ino;
4781         struct ext2_inode inode;
4782         ext2_inode_scan scan;
4783         struct process_block_struct_1b pb;
4784         struct problem_context pctx;
4785
4786         clear_problem_context(&pctx);
4787
4788         if (!(ctx->options & E2F_OPT_PREEN))
4789                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4790         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4791                                               &scan);
4792         if (pctx.errcode) {
4793                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4794                 ctx->flags |= E2F_FLAG_ABORT;
4795                 return;
4796         }
4797         ctx->stashed_inode = &inode;
4798         pb.ctx = ctx;
4799         pb.pctx = &pctx;
4800         pctx.str = "pass1b";
4801         while (1) {
4802                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4803                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4804                         continue;
4805                 if (pctx.errcode) {
4806                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4807                         ctx->flags |= E2F_FLAG_ABORT;
4808                         return;
4809                 }
4810                 if (!ino)
4811                         break;
4812                 pctx.ino = ctx->stashed_ino = ino;
4813                 if ((ino != EXT2_BAD_INO) &&
4814                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4815                         continue;
4816
4817                 pb.ino = ino;
4818                 pb.dup_blocks = 0;
4819                 pb.inode = &inode;
4820
4821                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4822                     (ino == EXT2_BAD_INO))
4823                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4824                                      0, block_buf, process_pass1b_block, &pb);
4825                 if (inode.i_file_acl)
4826                         process_pass1b_block(fs, &inode.i_file_acl,
4827                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4828                 if (pb.dup_blocks) {
4829                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4830                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4831                             ino == EXT2_ROOT_INO)
4832                                 dup_inode_count++;
4833                 }
4834                 if (pctx.errcode)
4835                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4836         }
4837         ext2fs_close_inode_scan(scan);
4838         e2fsck_use_inode_shortcuts(ctx, 0);
4839 }
4840
4841 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4842                                 blk_t   *block_nr,
4843                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4844                                 blk_t ref_blk FSCK_ATTR((unused)),
4845                                 int ref_offset FSCK_ATTR((unused)),
4846                                 void *priv_data)
4847 {
4848         struct process_block_struct_1b *p;
4849         e2fsck_t ctx;
4850
4851         if (HOLE_BLKADDR(*block_nr))
4852                 return 0;
4853         p = (struct process_block_struct_1b *) priv_data;
4854         ctx = p->ctx;
4855
4856         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4857                 return 0;
4858
4859         /* OK, this is a duplicate block */
4860         if (p->ino != EXT2_BAD_INO) {
4861                 p->pctx->blk = *block_nr;
4862                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4863         }
4864         p->dup_blocks++;
4865         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4866
4867         add_dupe(ctx, p->ino, *block_nr, p->inode);
4868
4869         return 0;
4870 }
4871
4872 /*
4873  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4874  * is used so that we can print pathnames when prompting the user for
4875  * what to do.
4876  */
4877 struct search_dir_struct {
4878         int             count;
4879         ext2_ino_t      first_inode;
4880         ext2_ino_t      max_inode;
4881 };
4882
4883 static int search_dirent_proc(ext2_ino_t dir, int entry,
4884                               struct ext2_dir_entry *dirent,
4885                               int offset FSCK_ATTR((unused)),
4886                               int blocksize FSCK_ATTR((unused)),
4887                               char *buf FSCK_ATTR((unused)),
4888                               void *priv_data)
4889 {
4890         struct search_dir_struct *sd;
4891         struct dup_inode        *p;
4892         dnode_t                 *n;
4893
4894         sd = (struct search_dir_struct *) priv_data;
4895
4896         if (dirent->inode > sd->max_inode)
4897                 /* Should abort this inode, but not everything */
4898                 return 0;
4899
4900         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4901             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4902                 return 0;
4903
4904         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4905         if (!n)
4906                 return 0;
4907         p = (struct dup_inode *) dnode_get(n);
4908         p->dir = dir;
4909         sd->count--;
4910
4911         return sd->count ? 0 : DIRENT_ABORT;
4912 }
4913
4914
4915 static void pass1c(e2fsck_t ctx, char *block_buf)
4916 {
4917         ext2_filsys fs = ctx->fs;
4918         struct search_dir_struct sd;
4919         struct problem_context pctx;
4920
4921         clear_problem_context(&pctx);
4922
4923         if (!(ctx->options & E2F_OPT_PREEN))
4924                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4925
4926         /*
4927          * Search through all directories to translate inodes to names
4928          * (by searching for the containing directory for that inode.)
4929          */
4930         sd.count = dup_inode_count;
4931         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4932         sd.max_inode = fs->super->s_inodes_count;
4933         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4934                                   search_dirent_proc, &sd);
4935 }
4936
4937 static void pass1d(e2fsck_t ctx, char *block_buf)
4938 {
4939         ext2_filsys fs = ctx->fs;
4940         struct dup_inode        *p, *t;
4941         struct dup_block        *q;
4942         ext2_ino_t              *shared, ino;
4943         int     shared_len;
4944         int     i;
4945         int     file_ok;
4946         int     meta_data = 0;
4947         struct problem_context pctx;
4948         dnode_t *n, *m;
4949         struct block_el *s;
4950         struct inode_el *r;
4951
4952         clear_problem_context(&pctx);
4953
4954         if (!(ctx->options & E2F_OPT_PREEN))
4955                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4956         e2fsck_read_bitmaps(ctx);
4957
4958         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4959         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4960         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4961                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4962                                 "Shared inode list");
4963         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4964                 p = (struct dup_inode *) dnode_get(n);
4965                 shared_len = 0;
4966                 file_ok = 1;
4967                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4968                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4969                         continue;
4970
4971                 /*
4972                  * Find all of the inodes which share blocks with this
4973                  * one.  First we find all of the duplicate blocks
4974                  * belonging to this inode, and then search each block
4975                  * get the list of inodes, and merge them together.
4976                  */
4977                 for (s = p->block_list; s; s = s->next) {
4978                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4979                         if (!m)
4980                                 continue; /* Should never happen... */
4981                         q = (struct dup_block *) dnode_get(m);
4982                         if (q->num_bad > 1)
4983                                 file_ok = 0;
4984                         if (check_if_fs_block(ctx, s->block)) {
4985                                 file_ok = 0;
4986                                 meta_data = 1;
4987                         }
4988
4989                         /*
4990                          * Add all inodes used by this block to the
4991                          * shared[] --- which is a unique list, so
4992                          * if an inode is already in shared[], don't
4993                          * add it again.
4994                          */
4995                         for (r = q->inode_list; r; r = r->next) {
4996                                 if (r->inode == ino)
4997                                         continue;
4998                                 for (i = 0; i < shared_len; i++)
4999                                         if (shared[i] == r->inode)
5000                                                 break;
5001                                 if (i == shared_len) {
5002                                         shared[shared_len++] = r->inode;
5003                                 }
5004                         }
5005                 }
5006
5007                 /*
5008                  * Report the inode that we are working on
5009                  */
5010                 pctx.inode = &p->inode;
5011                 pctx.ino = ino;
5012                 pctx.dir = p->dir;
5013                 pctx.blkcount = p->num_dupblocks;
5014                 pctx.num = meta_data ? shared_len+1 : shared_len;
5015                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5016                 pctx.blkcount = 0;
5017                 pctx.num = 0;
5018
5019                 if (meta_data)
5020                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5021
5022                 for (i = 0; i < shared_len; i++) {
5023                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5024                         if (!m)
5025                                 continue; /* should never happen */
5026                         t = (struct dup_inode *) dnode_get(m);
5027                         /*
5028                          * Report the inode that we are sharing with
5029                          */
5030                         pctx.inode = &t->inode;
5031                         pctx.ino = shared[i];
5032                         pctx.dir = t->dir;
5033                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5034                 }
5035                 if (file_ok) {
5036                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5037                         continue;
5038                 }
5039                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5040                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5041                         if (pctx.errcode)
5042                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5043                         else
5044                                 continue;
5045                 }
5046                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5047                         delete_file(ctx, ino, p, block_buf);
5048                 else
5049                         ext2fs_unmark_valid(fs);
5050         }
5051         ext2fs_free_mem(&shared);
5052 }
5053
5054 /*
5055  * Drop the refcount on the dup_block structure, and clear the entry
5056  * in the block_dup_map if appropriate.
5057  */
5058 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5059 {
5060         p->num_bad--;
5061         if (p->num_bad <= 0 ||
5062             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5063                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5064 }
5065
5066 static int delete_file_block(ext2_filsys fs,
5067                              blk_t      *block_nr,
5068                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5069                              blk_t ref_block FSCK_ATTR((unused)),
5070                              int ref_offset FSCK_ATTR((unused)),
5071                              void *priv_data)
5072 {
5073         struct process_block_struct_1b *pb;
5074         struct dup_block *p;
5075         dnode_t *n;
5076         e2fsck_t ctx;
5077
5078         pb = (struct process_block_struct_1b *) priv_data;
5079         ctx = pb->ctx;
5080
5081         if (HOLE_BLKADDR(*block_nr))
5082                 return 0;
5083
5084         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5085                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5086                 if (n) {
5087                         p = (struct dup_block *) dnode_get(n);
5088                         decrement_badcount(ctx, *block_nr, p);
5089                 } else
5090                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5091                                 *block_nr);
5092         } else {
5093                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5094                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5095         }
5096
5097         return 0;
5098 }
5099
5100 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5101                         struct dup_inode *dp, char* block_buf)
5102 {
5103         ext2_filsys fs = ctx->fs;
5104         struct process_block_struct_1b pb;
5105         struct ext2_inode       inode;
5106         struct problem_context  pctx;
5107         unsigned int            count;
5108
5109         clear_problem_context(&pctx);
5110         pctx.ino = pb.ino = ino;
5111         pb.dup_blocks = dp->num_dupblocks;
5112         pb.ctx = ctx;
5113         pctx.str = "delete_file";
5114
5115         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5116         if (ext2fs_inode_has_valid_blocks(&inode))
5117                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5118                                                      delete_file_block, &pb);
5119         if (pctx.errcode)
5120                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5121         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5122         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5123         if (ctx->inode_bad_map)
5124                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5125         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5126
5127         /* Inode may have changed by block_iterate, so reread it */
5128         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5129         inode.i_links_count = 0;
5130         inode.i_dtime = time(NULL);
5131         if (inode.i_file_acl &&
5132             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5133                 count = 1;
5134                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5135                                                    block_buf, -1, &count);
5136                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5137                         pctx.errcode = 0;
5138                         count = 1;
5139                 }
5140                 if (pctx.errcode) {
5141                         pctx.blk = inode.i_file_acl;
5142                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5143                 }
5144                 /*
5145                  * If the count is zero, then arrange to have the
5146                  * block deleted.  If the block is in the block_dup_map,
5147                  * also call delete_file_block since it will take care
5148                  * of keeping the accounting straight.
5149                  */
5150                 if ((count == 0) ||
5151                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5152                                              inode.i_file_acl))
5153                         delete_file_block(fs, &inode.i_file_acl,
5154                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5155         }
5156         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5157 }
5158
5159 struct clone_struct {
5160         errcode_t       errcode;
5161         ext2_ino_t      dir;
5162         char    *buf;
5163         e2fsck_t ctx;
5164 };
5165
5166 static int clone_file_block(ext2_filsys fs,
5167                             blk_t       *block_nr,
5168                             e2_blkcnt_t blockcnt,
5169                             blk_t ref_block FSCK_ATTR((unused)),
5170                             int ref_offset FSCK_ATTR((unused)),
5171                             void *priv_data)
5172 {
5173         struct dup_block *p;
5174         blk_t   new_block;
5175         errcode_t       retval;
5176         struct clone_struct *cs = (struct clone_struct *) priv_data;
5177         dnode_t *n;
5178         e2fsck_t ctx;
5179
5180         ctx = cs->ctx;
5181
5182         if (HOLE_BLKADDR(*block_nr))
5183                 return 0;
5184
5185         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5186                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5187                 if (n) {
5188                         p = (struct dup_block *) dnode_get(n);
5189                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5190                                                   &new_block);
5191                         if (retval) {
5192                                 cs->errcode = retval;
5193                                 return BLOCK_ABORT;
5194                         }
5195                         if (cs->dir && (blockcnt >= 0)) {
5196                                 retval = ext2fs_set_dir_block(fs->dblist,
5197                                       cs->dir, new_block, blockcnt);
5198                                 if (retval) {
5199                                         cs->errcode = retval;
5200                                         return BLOCK_ABORT;
5201                                 }
5202                         }
5203
5204                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5205                                                      cs->buf);
5206                         if (retval) {
5207                                 cs->errcode = retval;
5208                                 return BLOCK_ABORT;
5209                         }
5210                         retval = io_channel_write_blk(fs->io, new_block, 1,
5211                                                       cs->buf);
5212                         if (retval) {
5213                                 cs->errcode = retval;
5214                                 return BLOCK_ABORT;
5215                         }
5216                         decrement_badcount(ctx, *block_nr, p);
5217                         *block_nr = new_block;
5218                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5219                                                  new_block);
5220                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5221                         return BLOCK_CHANGED;
5222                 } else
5223                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5224                                 *block_nr);
5225         }
5226         return 0;
5227 }
5228
5229 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5230                       struct dup_inode *dp, char* block_buf)
5231 {
5232         ext2_filsys fs = ctx->fs;
5233         errcode_t       retval;
5234         struct clone_struct cs;
5235         struct problem_context  pctx;
5236         blk_t           blk;
5237         dnode_t         *n;
5238         struct inode_el *ino_el;
5239         struct dup_block        *db;
5240         struct dup_inode        *di;
5241
5242         clear_problem_context(&pctx);
5243         cs.errcode = 0;
5244         cs.dir = 0;
5245         cs.ctx = ctx;
5246         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5247         if (retval)
5248                 return retval;
5249
5250         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5251                 cs.dir = ino;
5252
5253         pctx.ino = ino;
5254         pctx.str = "clone_file";
5255         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5256                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5257                                                      clone_file_block, &cs);
5258         ext2fs_mark_bb_dirty(fs);
5259         if (pctx.errcode) {
5260                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5261                 retval = pctx.errcode;
5262                 goto errout;
5263         }
5264         if (cs.errcode) {
5265                 bb_error_msg(_("returned from clone_file_block"));
5266                 retval = cs.errcode;
5267                 goto errout;
5268         }
5269         /* The inode may have changed on disk, so we have to re-read it */
5270         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5271         blk = dp->inode.i_file_acl;
5272         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5273                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5274                     BLOCK_CHANGED)) {
5275                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5276                 /*
5277                  * If we cloned the EA block, find all other inodes
5278                  * which refered to that EA block, and modify
5279                  * them to point to the new EA block.
5280                  */
5281                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5282                 db = (struct dup_block *) dnode_get(n);
5283                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5284                         if (ino_el->inode == ino)
5285                                 continue;
5286                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5287                         di = (struct dup_inode *) dnode_get(n);
5288                         if (di->inode.i_file_acl == blk) {
5289                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5290                                 e2fsck_write_inode(ctx, ino_el->inode,
5291                                            &di->inode, "clone file EA");
5292                                 decrement_badcount(ctx, blk, db);
5293                         }
5294                 }
5295         }
5296         retval = 0;
5297 errout:
5298         ext2fs_free_mem(&cs.buf);
5299         return retval;
5300 }
5301
5302 /*
5303  * This routine returns 1 if a block overlaps with one of the superblocks,
5304  * group descriptors, inode bitmaps, or block bitmaps.
5305  */
5306 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5307 {
5308         ext2_filsys fs = ctx->fs;
5309         blk_t   block;
5310         dgrp_t  i;
5311
5312         block = fs->super->s_first_data_block;
5313         for (i = 0; i < fs->group_desc_count; i++) {
5314
5315                 /* Check superblocks/block group descriptros */
5316                 if (ext2fs_bg_has_super(fs, i)) {
5317                         if (test_block >= block &&
5318                             (test_block <= block + fs->desc_blocks))
5319                                 return 1;
5320                 }
5321
5322                 /* Check the inode table */
5323                 if ((fs->group_desc[i].bg_inode_table) &&
5324                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5325                     (test_block < (fs->group_desc[i].bg_inode_table +
5326                                    fs->inode_blocks_per_group)))
5327                         return 1;
5328
5329                 /* Check the bitmap blocks */
5330                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5331                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5332                         return 1;
5333
5334                 block += fs->super->s_blocks_per_group;
5335         }
5336         return 0;
5337 }
5338 /*
5339  * pass2.c --- check directory structure
5340  *
5341  * Pass 2 of e2fsck iterates through all active directory inodes, and
5342  * applies to following tests to each directory entry in the directory
5343  * blocks in the inodes:
5344  *
5345  *      - The length of the directory entry (rec_len) should be at
5346  *              least 8 bytes, and no more than the remaining space
5347  *              left in the directory block.
5348  *      - The length of the name in the directory entry (name_len)
5349  *              should be less than (rec_len - 8).
5350  *      - The inode number in the directory entry should be within
5351  *              legal bounds.
5352  *      - The inode number should refer to a in-use inode.
5353  *      - The first entry should be '.', and its inode should be
5354  *              the inode of the directory.
5355  *      - The second entry should be '..'.
5356  *
5357  * To minimize disk seek time, the directory blocks are processed in
5358  * sorted order of block numbers.
5359  *
5360  * Pass 2 also collects the following information:
5361  *      - The inode numbers of the subdirectories for each directory.
5362  *
5363  * Pass 2 relies on the following information from previous passes:
5364  *      - The directory information collected in pass 1.
5365  *      - The inode_used_map bitmap
5366  *      - The inode_bad_map bitmap
5367  *      - The inode_dir_map bitmap
5368  *
5369  * Pass 2 frees the following data structures
5370  *      - The inode_bad_map bitmap
5371  *      - The inode_reg_map bitmap
5372  */
5373
5374 /*
5375  * Keeps track of how many times an inode is referenced.
5376  */
5377 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5378 static int check_dir_block(ext2_filsys fs,
5379                            struct ext2_db_entry *dir_blocks_info,
5380                            void *priv_data);
5381 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5382                               struct problem_context *pctx);
5383 static int update_dir_block(ext2_filsys fs,
5384                             blk_t       *block_nr,
5385                             e2_blkcnt_t blockcnt,
5386                             blk_t       ref_block,
5387                             int         ref_offset,
5388                             void        *priv_data);
5389 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5390 static int htree_depth(struct dx_dir_info *dx_dir,
5391                        struct dx_dirblock_info *dx_db);
5392 static int special_dir_block_cmp(const void *a, const void *b);
5393
5394 struct check_dir_struct {
5395         char *buf;
5396         struct problem_context  pctx;
5397         int     count, max;
5398         e2fsck_t ctx;
5399 };
5400
5401 static void e2fsck_pass2(e2fsck_t ctx)
5402 {
5403         struct ext2_super_block *sb = ctx->fs->super;
5404         struct problem_context  pctx;
5405         ext2_filsys             fs = ctx->fs;
5406         char                    *buf;
5407         struct dir_info         *dir;
5408         struct check_dir_struct cd;
5409         struct dx_dir_info      *dx_dir;
5410         struct dx_dirblock_info *dx_db, *dx_parent;
5411         int                     b;
5412         int                     i, depth;
5413         problem_t               code;
5414         int                     bad_dir;
5415
5416         clear_problem_context(&cd.pctx);
5417
5418         /* Pass 2 */
5419
5420         if (!(ctx->options & E2F_OPT_PREEN))
5421                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5422
5423         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5424                                                 0, ctx->inode_link_info,
5425                                                 &ctx->inode_count);
5426         if (cd.pctx.errcode) {
5427                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5428                 ctx->flags |= E2F_FLAG_ABORT;
5429                 return;
5430         }
5431         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5432                                               "directory scan buffer");
5433
5434         /*
5435          * Set up the parent pointer for the root directory, if
5436          * present.  (If the root directory is not present, we will
5437          * create it in pass 3.)
5438          */
5439         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5440         if (dir)
5441                 dir->parent = EXT2_ROOT_INO;
5442
5443         cd.buf = buf;
5444         cd.ctx = ctx;
5445         cd.count = 1;
5446         cd.max = ext2fs_dblist_count(fs->dblist);
5447
5448         if (ctx->progress)
5449                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5450
5451         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5452                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5453
5454         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5455                                                 &cd);
5456         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5457                 return;
5458         if (cd.pctx.errcode) {
5459                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5460                 ctx->flags |= E2F_FLAG_ABORT;
5461                 return;
5462         }
5463
5464 #ifdef ENABLE_HTREE
5465         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5466                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5467                         return;
5468                 if (dx_dir->numblocks == 0)
5469                         continue;
5470                 clear_problem_context(&pctx);
5471                 bad_dir = 0;
5472                 pctx.dir = dx_dir->ino;
5473                 dx_db = dx_dir->dx_block;
5474                 if (dx_db->flags & DX_FLAG_REFERENCED)
5475                         dx_db->flags |= DX_FLAG_DUP_REF;
5476                 else
5477                         dx_db->flags |= DX_FLAG_REFERENCED;
5478                 /*
5479                  * Find all of the first and last leaf blocks, and
5480                  * update their parent's min and max hash values
5481                  */
5482                 for (b=0, dx_db = dx_dir->dx_block;
5483                      b < dx_dir->numblocks;
5484                      b++, dx_db++) {
5485                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5486                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5487                                 continue;
5488                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5489                         /*
5490                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5491                          */
5492                         if (dx_db->flags & DX_FLAG_FIRST)
5493                                 dx_parent->min_hash = dx_db->min_hash;
5494                         /*
5495                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5496                          */
5497                         if (dx_db->flags & DX_FLAG_LAST)
5498                                 dx_parent->max_hash = dx_db->max_hash;
5499                 }
5500
5501                 for (b=0, dx_db = dx_dir->dx_block;
5502                      b < dx_dir->numblocks;
5503                      b++, dx_db++) {
5504                         pctx.blkcount = b;
5505                         pctx.group = dx_db->parent;
5506                         code = 0;
5507                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5508                             (dx_db->min_hash < dx_db->node_min_hash)) {
5509                                 pctx.blk = dx_db->min_hash;
5510                                 pctx.blk2 = dx_db->node_min_hash;
5511                                 code = PR_2_HTREE_MIN_HASH;
5512                                 fix_problem(ctx, code, &pctx);
5513                                 bad_dir++;
5514                         }
5515                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5516                                 depth = htree_depth(dx_dir, dx_db);
5517                                 if (depth != dx_dir->depth) {
5518                                         code = PR_2_HTREE_BAD_DEPTH;
5519                                         fix_problem(ctx, code, &pctx);
5520                                         bad_dir++;
5521                                 }
5522                         }
5523                         /*
5524                          * This test doesn't apply for the root block
5525                          * at block #0
5526                          */
5527                         if (b &&
5528                             (dx_db->max_hash > dx_db->node_max_hash)) {
5529                                 pctx.blk = dx_db->max_hash;
5530                                 pctx.blk2 = dx_db->node_max_hash;
5531                                 code = PR_2_HTREE_MAX_HASH;
5532                                 fix_problem(ctx, code, &pctx);
5533                                 bad_dir++;
5534                         }
5535                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5536                                 code = PR_2_HTREE_NOTREF;
5537                                 fix_problem(ctx, code, &pctx);
5538                                 bad_dir++;
5539                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5540                                 code = PR_2_HTREE_DUPREF;
5541                                 fix_problem(ctx, code, &pctx);
5542                                 bad_dir++;
5543                         }
5544                         if (code == 0)
5545                                 continue;
5546                 }
5547                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5548                         clear_htree(ctx, dx_dir->ino);
5549                         dx_dir->numblocks = 0;
5550                 }
5551         }
5552 #endif
5553         ext2fs_free_mem(&buf);
5554         ext2fs_free_dblist(fs->dblist);
5555
5556         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5557         ctx->inode_bad_map = 0;
5558         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5559         ctx->inode_reg_map = 0;
5560
5561         clear_problem_context(&pctx);
5562         if (ctx->large_files) {
5563                 if (!(sb->s_feature_ro_compat &
5564                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5565                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5566                         sb->s_feature_ro_compat |=
5567                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5568                         ext2fs_mark_super_dirty(fs);
5569                 }
5570                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5571                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5572                         ext2fs_update_dynamic_rev(fs);
5573                         ext2fs_mark_super_dirty(fs);
5574                 }
5575         } else if (!ctx->large_files &&
5576             (sb->s_feature_ro_compat &
5577               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5578                 if (fs->flags & EXT2_FLAG_RW) {
5579                         sb->s_feature_ro_compat &=
5580                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5581                         ext2fs_mark_super_dirty(fs);
5582                 }
5583         }
5584 }
5585
5586 #define MAX_DEPTH 32000
5587 static int htree_depth(struct dx_dir_info *dx_dir,
5588                        struct dx_dirblock_info *dx_db)
5589 {
5590         int     depth = 0;
5591
5592         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5593                 dx_db = &dx_dir->dx_block[dx_db->parent];
5594                 depth++;
5595         }
5596         return depth;
5597 }
5598
5599 static int dict_de_cmp(const void *a, const void *b)
5600 {
5601         const struct ext2_dir_entry *de_a, *de_b;
5602         int     a_len, b_len;
5603
5604         de_a = (const struct ext2_dir_entry *) a;
5605         a_len = de_a->name_len & 0xFF;
5606         de_b = (const struct ext2_dir_entry *) b;
5607         b_len = de_b->name_len & 0xFF;
5608
5609         if (a_len != b_len)
5610                 return (a_len - b_len);
5611
5612         return strncmp(de_a->name, de_b->name, a_len);
5613 }
5614
5615 /*
5616  * This is special sort function that makes sure that directory blocks
5617  * with a dirblock of zero are sorted to the beginning of the list.
5618  * This guarantees that the root node of the htree directories are
5619  * processed first, so we know what hash version to use.
5620  */
5621 static int special_dir_block_cmp(const void *a, const void *b)
5622 {
5623         const struct ext2_db_entry *db_a =
5624                 (const struct ext2_db_entry *) a;
5625         const struct ext2_db_entry *db_b =
5626                 (const struct ext2_db_entry *) b;
5627
5628         if (db_a->blockcnt && !db_b->blockcnt)
5629                 return 1;
5630
5631         if (!db_a->blockcnt && db_b->blockcnt)
5632                 return -1;
5633
5634         if (db_a->blk != db_b->blk)
5635                 return (int) (db_a->blk - db_b->blk);
5636
5637         if (db_a->ino != db_b->ino)
5638                 return (int) (db_a->ino - db_b->ino);
5639
5640         return (int) (db_a->blockcnt - db_b->blockcnt);
5641 }
5642
5643
5644 /*
5645  * Make sure the first entry in the directory is '.', and that the
5646  * directory entry is sane.
5647  */
5648 static int check_dot(e2fsck_t ctx,
5649                      struct ext2_dir_entry *dirent,
5650                      ext2_ino_t ino, struct problem_context *pctx)
5651 {
5652         struct ext2_dir_entry *nextdir;
5653         int     status = 0;
5654         int     created = 0;
5655         int     new_len;
5656         int     problem = 0;
5657
5658         if (!dirent->inode)
5659                 problem = PR_2_MISSING_DOT;
5660         else if (((dirent->name_len & 0xFF) != 1) ||
5661                  (dirent->name[0] != '.'))
5662                 problem = PR_2_1ST_NOT_DOT;
5663         else if (dirent->name[1] != '\0')
5664                 problem = PR_2_DOT_NULL_TERM;
5665
5666         if (problem) {
5667                 if (fix_problem(ctx, problem, pctx)) {
5668                         if (dirent->rec_len < 12)
5669                                 dirent->rec_len = 12;
5670                         dirent->inode = ino;
5671                         dirent->name_len = 1;
5672                         dirent->name[0] = '.';
5673                         dirent->name[1] = '\0';
5674                         status = 1;
5675                         created = 1;
5676                 }
5677         }
5678         if (dirent->inode != ino) {
5679                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5680                         dirent->inode = ino;
5681                         status = 1;
5682                 }
5683         }
5684         if (dirent->rec_len > 12) {
5685                 new_len = dirent->rec_len - 12;
5686                 if (new_len > 12) {
5687                         if (created ||
5688                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5689                                 nextdir = (struct ext2_dir_entry *)
5690                                         ((char *) dirent + 12);
5691                                 dirent->rec_len = 12;
5692                                 nextdir->rec_len = new_len;
5693                                 nextdir->inode = 0;
5694                                 nextdir->name_len = 0;
5695                                 status = 1;
5696                         }
5697                 }
5698         }
5699         return status;
5700 }
5701
5702 /*
5703  * Make sure the second entry in the directory is '..', and that the
5704  * directory entry is sane.  We do not check the inode number of '..'
5705  * here; this gets done in pass 3.
5706  */
5707 static int check_dotdot(e2fsck_t ctx,
5708                         struct ext2_dir_entry *dirent,
5709                         struct dir_info *dir, struct problem_context *pctx)
5710 {
5711         int             problem = 0;
5712
5713         if (!dirent->inode)
5714                 problem = PR_2_MISSING_DOT_DOT;
5715         else if (((dirent->name_len & 0xFF) != 2) ||
5716                  (dirent->name[0] != '.') ||
5717                  (dirent->name[1] != '.'))
5718                 problem = PR_2_2ND_NOT_DOT_DOT;
5719         else if (dirent->name[2] != '\0')
5720                 problem = PR_2_DOT_DOT_NULL_TERM;
5721
5722         if (problem) {
5723                 if (fix_problem(ctx, problem, pctx)) {
5724                         if (dirent->rec_len < 12)
5725                                 dirent->rec_len = 12;
5726                         /*
5727                          * Note: we don't have the parent inode just
5728                          * yet, so we will fill it in with the root
5729                          * inode.  This will get fixed in pass 3.
5730                          */
5731                         dirent->inode = EXT2_ROOT_INO;
5732                         dirent->name_len = 2;
5733                         dirent->name[0] = '.';
5734                         dirent->name[1] = '.';
5735                         dirent->name[2] = '\0';
5736                         return 1;
5737                 }
5738                 return 0;
5739         }
5740         dir->dotdot = dirent->inode;
5741         return 0;
5742 }
5743
5744 /*
5745  * Check to make sure a directory entry doesn't contain any illegal
5746  * characters.
5747  */
5748 static int check_name(e2fsck_t ctx,
5749                       struct ext2_dir_entry *dirent,
5750                       struct problem_context *pctx)
5751 {
5752         int     i;
5753         int     fixup = -1;
5754         int     ret = 0;
5755
5756         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5757                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5758                         if (fixup < 0) {
5759                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5760                         }
5761                         if (fixup) {
5762                                 dirent->name[i] = '.';
5763                                 ret = 1;
5764                         }
5765                 }
5766         }
5767         return ret;
5768 }
5769
5770 /*
5771  * Check the directory filetype (if present)
5772  */
5773
5774 /*
5775  * Given a mode, return the ext2 file type
5776  */
5777 static int ext2_file_type(unsigned int mode)
5778 {
5779         if (LINUX_S_ISREG(mode))
5780                 return EXT2_FT_REG_FILE;
5781
5782         if (LINUX_S_ISDIR(mode))
5783                 return EXT2_FT_DIR;
5784
5785         if (LINUX_S_ISCHR(mode))
5786                 return EXT2_FT_CHRDEV;
5787
5788         if (LINUX_S_ISBLK(mode))
5789                 return EXT2_FT_BLKDEV;
5790
5791         if (LINUX_S_ISLNK(mode))
5792                 return EXT2_FT_SYMLINK;
5793
5794         if (LINUX_S_ISFIFO(mode))
5795                 return EXT2_FT_FIFO;
5796
5797         if (LINUX_S_ISSOCK(mode))
5798                 return EXT2_FT_SOCK;
5799
5800         return 0;
5801 }
5802
5803 static int check_filetype(e2fsck_t ctx,
5804                                    struct ext2_dir_entry *dirent,
5805                                    struct problem_context *pctx)
5806 {
5807         int     filetype = dirent->name_len >> 8;
5808         int     should_be = EXT2_FT_UNKNOWN;
5809         struct ext2_inode       inode;
5810
5811         if (!(ctx->fs->super->s_feature_incompat &
5812               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5813                 if (filetype == 0 ||
5814                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5815                         return 0;
5816                 dirent->name_len = dirent->name_len & 0xFF;
5817                 return 1;
5818         }
5819
5820         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5821                 should_be = EXT2_FT_DIR;
5822         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5823                                             dirent->inode)) {
5824                 should_be = EXT2_FT_REG_FILE;
5825         } else if (ctx->inode_bad_map &&
5826                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5827                                             dirent->inode))
5828                 should_be = 0;
5829         else {
5830                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5831                                   "check_filetype");
5832                 should_be = ext2_file_type(inode.i_mode);
5833         }
5834         if (filetype == should_be)
5835                 return 0;
5836         pctx->num = should_be;
5837
5838         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5839                         pctx) == 0)
5840                 return 0;
5841
5842         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5843         return 1;
5844 }
5845
5846 #ifdef ENABLE_HTREE
5847 static void parse_int_node(ext2_filsys fs,
5848                            struct ext2_db_entry *db,
5849                            struct check_dir_struct *cd,
5850                            struct dx_dir_info   *dx_dir,
5851                            char *block_buf)
5852 {
5853         struct          ext2_dx_root_info  *root;
5854         struct          ext2_dx_entry *ent;
5855         struct          ext2_dx_countlimit *limit;
5856         struct dx_dirblock_info *dx_db;
5857         int             i, expect_limit, count;
5858         blk_t           blk;
5859         ext2_dirhash_t  min_hash = 0xffffffff;
5860         ext2_dirhash_t  max_hash = 0;
5861         ext2_dirhash_t  hash = 0, prev_hash;
5862
5863         if (db->blockcnt == 0) {
5864                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5865                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5866         } else {
5867                 ent = (struct ext2_dx_entry *) (block_buf+8);
5868         }
5869         limit = (struct ext2_dx_countlimit *) ent;
5870
5871         count = ext2fs_le16_to_cpu(limit->count);
5872         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5873                 sizeof(struct ext2_dx_entry);
5874         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5875                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5876                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5877                         goto clear_and_exit;
5878         }
5879         if (count > expect_limit) {
5880                 cd->pctx.num = count;
5881                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5882                         goto clear_and_exit;
5883                 count = expect_limit;
5884         }
5885
5886         for (i=0; i < count; i++) {
5887                 prev_hash = hash;
5888                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5889                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5890                 /* Check to make sure the block is valid */
5891                 if (blk > (blk_t) dx_dir->numblocks) {
5892                         cd->pctx.blk = blk;
5893                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5894                                         &cd->pctx))
5895                                 goto clear_and_exit;
5896                 }
5897                 if (hash < prev_hash &&
5898                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5899                         goto clear_and_exit;
5900                 dx_db = &dx_dir->dx_block[blk];
5901                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5902                         dx_db->flags |= DX_FLAG_DUP_REF;
5903                 } else {
5904                         dx_db->flags |= DX_FLAG_REFERENCED;
5905                         dx_db->parent = db->blockcnt;
5906                 }
5907                 if (hash < min_hash)
5908                         min_hash = hash;
5909                 if (hash > max_hash)
5910                         max_hash = hash;
5911                 dx_db->node_min_hash = hash;
5912                 if ((i+1) < count)
5913                         dx_db->node_max_hash =
5914                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5915                 else {
5916                         dx_db->node_max_hash = 0xfffffffe;
5917                         dx_db->flags |= DX_FLAG_LAST;
5918                 }
5919                 if (i == 0)
5920                         dx_db->flags |= DX_FLAG_FIRST;
5921         }
5922         dx_db = &dx_dir->dx_block[db->blockcnt];
5923         dx_db->min_hash = min_hash;
5924         dx_db->max_hash = max_hash;
5925         return;
5926
5927 clear_and_exit:
5928         clear_htree(cd->ctx, cd->pctx.ino);
5929         dx_dir->numblocks = 0;
5930 }
5931 #endif /* ENABLE_HTREE */
5932
5933 /*
5934  * Given a busted directory, try to salvage it somehow.
5935  *
5936  */
5937 static void salvage_directory(ext2_filsys fs,
5938                               struct ext2_dir_entry *dirent,
5939                               struct ext2_dir_entry *prev,
5940                               unsigned int *offset)
5941 {
5942         char    *cp = (char *) dirent;
5943         int left = fs->blocksize - *offset - dirent->rec_len;
5944         int name_len = dirent->name_len & 0xFF;
5945
5946         /*
5947          * Special case of directory entry of size 8: copy what's left
5948          * of the directory block up to cover up the invalid hole.
5949          */
5950         if ((left >= 12) && (dirent->rec_len == 8)) {
5951                 memmove(cp, cp+8, left);
5952                 memset(cp + left, 0, 8);
5953                 return;
5954         }
5955         /*
5956          * If the directory entry overruns the end of the directory
5957          * block, and the name is small enough to fit, then adjust the
5958          * record length.
5959          */
5960         if ((left < 0) &&
5961             (name_len + 8 <= dirent->rec_len + left) &&
5962             dirent->inode <= fs->super->s_inodes_count &&
5963             strnlen(dirent->name, name_len) == name_len) {
5964                 dirent->rec_len += left;
5965                 return;
5966         }
5967         /*
5968          * If the directory entry is a multiple of four, so it is
5969          * valid, let the previous directory entry absorb the invalid
5970          * one.
5971          */
5972         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5973                 prev->rec_len += dirent->rec_len;
5974                 *offset += dirent->rec_len;
5975                 return;
5976         }
5977         /*
5978          * Default salvage method --- kill all of the directory
5979          * entries for the rest of the block.  We will either try to
5980          * absorb it into the previous directory entry, or create a
5981          * new empty directory entry the rest of the directory block.
5982          */
5983         if (prev) {
5984                 prev->rec_len += fs->blocksize - *offset;
5985                 *offset = fs->blocksize;
5986         } else {
5987                 dirent->rec_len = fs->blocksize - *offset;
5988                 dirent->name_len = 0;
5989                 dirent->inode = 0;
5990         }
5991 }
5992
5993 static int check_dir_block(ext2_filsys fs,
5994                            struct ext2_db_entry *db,
5995                            void *priv_data)
5996 {
5997         struct dir_info         *subdir, *dir;
5998         struct dx_dir_info      *dx_dir;
5999 #ifdef ENABLE_HTREE
6000         struct dx_dirblock_info *dx_db = NULL;
6001 #endif /* ENABLE_HTREE */
6002         struct ext2_dir_entry   *dirent, *prev;
6003         ext2_dirhash_t          hash;
6004         unsigned int            offset = 0;
6005         int                     dir_modified = 0;
6006         int                     dot_state;
6007         blk_t                   block_nr = db->blk;
6008         ext2_ino_t              ino = db->ino;
6009         __u16                   links;
6010         struct check_dir_struct *cd;
6011         char                    *buf;
6012         e2fsck_t                ctx;
6013         int                     problem;
6014         struct ext2_dx_root_info *root;
6015         struct ext2_dx_countlimit *limit;
6016         static dict_t de_dict;
6017         struct problem_context  pctx;
6018         int     dups_found = 0;
6019
6020         cd = (struct check_dir_struct *) priv_data;
6021         buf = cd->buf;
6022         ctx = cd->ctx;
6023
6024         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6025                 return DIRENT_ABORT;
6026
6027         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6028                 return DIRENT_ABORT;
6029
6030         /*
6031          * Make sure the inode is still in use (could have been
6032          * deleted in the duplicate/bad blocks pass.
6033          */
6034         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6035                 return 0;
6036
6037         cd->pctx.ino = ino;
6038         cd->pctx.blk = block_nr;
6039         cd->pctx.blkcount = db->blockcnt;
6040         cd->pctx.ino2 = 0;
6041         cd->pctx.dirent = 0;
6042         cd->pctx.num = 0;
6043
6044         if (db->blk == 0) {
6045                 if (allocate_dir_block(ctx, db, &cd->pctx))
6046                         return 0;
6047                 block_nr = db->blk;
6048         }
6049
6050         if (db->blockcnt)
6051                 dot_state = 2;
6052         else
6053                 dot_state = 0;
6054
6055         if (ctx->dirs_to_hash &&
6056             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6057                 dups_found++;
6058
6059         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6060         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6061                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6062         if (cd->pctx.errcode) {
6063                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6064                         ctx->flags |= E2F_FLAG_ABORT;
6065                         return DIRENT_ABORT;
6066                 }
6067                 memset(buf, 0, fs->blocksize);
6068         }
6069 #ifdef ENABLE_HTREE
6070         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6071         if (dx_dir && dx_dir->numblocks) {
6072                 if (db->blockcnt >= dx_dir->numblocks) {
6073                         printf("XXX should never happen!!!\n");
6074                         abort();
6075                 }
6076                 dx_db = &dx_dir->dx_block[db->blockcnt];
6077                 dx_db->type = DX_DIRBLOCK_LEAF;
6078                 dx_db->phys = block_nr;
6079                 dx_db->min_hash = ~0;
6080                 dx_db->max_hash = 0;
6081
6082                 dirent = (struct ext2_dir_entry *) buf;
6083                 limit = (struct ext2_dx_countlimit *) (buf+8);
6084                 if (db->blockcnt == 0) {
6085                         root = (struct ext2_dx_root_info *) (buf + 24);
6086                         dx_db->type = DX_DIRBLOCK_ROOT;
6087                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6088                         if ((root->reserved_zero ||
6089                              root->info_length < 8 ||
6090                              root->indirect_levels > 1) &&
6091                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6092                                 clear_htree(ctx, ino);
6093                                 dx_dir->numblocks = 0;
6094                                 dx_db = 0;
6095                         }
6096                         dx_dir->hashversion = root->hash_version;
6097                         dx_dir->depth = root->indirect_levels + 1;
6098                 } else if ((dirent->inode == 0) &&
6099                            (dirent->rec_len == fs->blocksize) &&
6100                            (dirent->name_len == 0) &&
6101                            (ext2fs_le16_to_cpu(limit->limit) ==
6102                             ((fs->blocksize-8) /
6103                              sizeof(struct ext2_dx_entry))))
6104                         dx_db->type = DX_DIRBLOCK_NODE;
6105         }
6106 #endif /* ENABLE_HTREE */
6107
6108         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6109         prev = 0;
6110         do {
6111                 problem = 0;
6112                 dirent = (struct ext2_dir_entry *) (buf + offset);
6113                 cd->pctx.dirent = dirent;
6114                 cd->pctx.num = offset;
6115                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6116                     (dirent->rec_len < 12) ||
6117                     ((dirent->rec_len % 4) != 0) ||
6118                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6119                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6120                                 salvage_directory(fs, dirent, prev, &offset);
6121                                 dir_modified++;
6122                                 continue;
6123                         } else
6124                                 goto abort_free_dict;
6125                 }
6126                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6127                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6128                                 dirent->name_len = EXT2_NAME_LEN;
6129                                 dir_modified++;
6130                         }
6131                 }
6132
6133                 if (dot_state == 0) {
6134                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6135                                 dir_modified++;
6136                 } else if (dot_state == 1) {
6137                         dir = e2fsck_get_dir_info(ctx, ino);
6138                         if (!dir) {
6139                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6140                                 goto abort_free_dict;
6141                         }
6142                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6143                                 dir_modified++;
6144                 } else if (dirent->inode == ino) {
6145                         problem = PR_2_LINK_DOT;
6146                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6147                                 dirent->inode = 0;
6148                                 dir_modified++;
6149                                 goto next;
6150                         }
6151                 }
6152                 if (!dirent->inode)
6153                         goto next;
6154
6155                 /*
6156                  * Make sure the inode listed is a legal one.
6157                  */
6158                 if (((dirent->inode != EXT2_ROOT_INO) &&
6159                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6160                     (dirent->inode > fs->super->s_inodes_count)) {
6161                         problem = PR_2_BAD_INO;
6162                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6163                                                dirent->inode))) {
6164                         /*
6165                          * If the inode is unused, offer to clear it.
6166                          */
6167                         problem = PR_2_UNUSED_INODE;
6168                 } else if ((dot_state > 1) &&
6169                            ((dirent->name_len & 0xFF) == 1) &&
6170                            (dirent->name[0] == '.')) {
6171                         /*
6172                          * If there's a '.' entry in anything other
6173                          * than the first directory entry, it's a
6174                          * duplicate entry that should be removed.
6175                          */
6176                         problem = PR_2_DUP_DOT;
6177                 } else if ((dot_state > 1) &&
6178                            ((dirent->name_len & 0xFF) == 2) &&
6179                            (dirent->name[0] == '.') &&
6180                            (dirent->name[1] == '.')) {
6181                         /*
6182                          * If there's a '..' entry in anything other
6183                          * than the second directory entry, it's a
6184                          * duplicate entry that should be removed.
6185                          */
6186                         problem = PR_2_DUP_DOT_DOT;
6187                 } else if ((dot_state > 1) &&
6188                            (dirent->inode == EXT2_ROOT_INO)) {
6189                         /*
6190                          * Don't allow links to the root directory.
6191                          * We check this specially to make sure we
6192                          * catch this error case even if the root
6193                          * directory hasn't been created yet.
6194                          */
6195                         problem = PR_2_LINK_ROOT;
6196                 } else if ((dot_state > 1) &&
6197                            (dirent->name_len & 0xFF) == 0) {
6198                         /*
6199                          * Don't allow zero-length directory names.
6200                          */
6201                         problem = PR_2_NULL_NAME;
6202                 }
6203
6204                 if (problem) {
6205                         if (fix_problem(ctx, problem, &cd->pctx)) {
6206                                 dirent->inode = 0;
6207                                 dir_modified++;
6208                                 goto next;
6209                         } else {
6210                                 ext2fs_unmark_valid(fs);
6211                                 if (problem == PR_2_BAD_INO)
6212                                         goto next;
6213                         }
6214                 }
6215
6216                 /*
6217                  * If the inode was marked as having bad fields in
6218                  * pass1, process it and offer to fix/clear it.
6219                  * (We wait until now so that we can display the
6220                  * pathname to the user.)
6221                  */
6222                 if (ctx->inode_bad_map &&
6223                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6224                                              dirent->inode)) {
6225                         if (e2fsck_process_bad_inode(ctx, ino,
6226                                                      dirent->inode,
6227                                                      buf + fs->blocksize)) {
6228                                 dirent->inode = 0;
6229                                 dir_modified++;
6230                                 goto next;
6231                         }
6232                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6233                                 return DIRENT_ABORT;
6234                 }
6235
6236                 if (check_name(ctx, dirent, &cd->pctx))
6237                         dir_modified++;
6238
6239                 if (check_filetype(ctx, dirent, &cd->pctx))
6240                         dir_modified++;
6241
6242 #ifdef ENABLE_HTREE
6243                 if (dx_db) {
6244                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6245                                        (dirent->name_len & 0xFF),
6246                                        fs->super->s_hash_seed, &hash, 0);
6247                         if (hash < dx_db->min_hash)
6248                                 dx_db->min_hash = hash;
6249                         if (hash > dx_db->max_hash)
6250                                 dx_db->max_hash = hash;
6251                 }
6252 #endif
6253
6254                 /*
6255                  * If this is a directory, then mark its parent in its
6256                  * dir_info structure.  If the parent field is already
6257                  * filled in, then this directory has more than one
6258                  * hard link.  We assume the first link is correct,
6259                  * and ask the user if he/she wants to clear this one.
6260                  */
6261                 if ((dot_state > 1) &&
6262                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6263                                               dirent->inode))) {
6264                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6265                         if (!subdir) {
6266                                 cd->pctx.ino = dirent->inode;
6267                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6268                                 goto abort_free_dict;
6269                         }
6270                         if (subdir->parent) {
6271                                 cd->pctx.ino2 = subdir->parent;
6272                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6273                                                 &cd->pctx)) {
6274                                         dirent->inode = 0;
6275                                         dir_modified++;
6276                                         goto next;
6277                                 }
6278                                 cd->pctx.ino2 = 0;
6279                         } else
6280                                 subdir->parent = ino;
6281                 }
6282
6283                 if (dups_found) {
6284                         ;
6285                 } else if (dict_lookup(&de_dict, dirent)) {
6286                         clear_problem_context(&pctx);
6287                         pctx.ino = ino;
6288                         pctx.dirent = dirent;
6289                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6290                         if (!ctx->dirs_to_hash)
6291                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6292                         if (ctx->dirs_to_hash)
6293                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6294                         dups_found++;
6295                 } else
6296                         dict_alloc_insert(&de_dict, dirent, dirent);
6297
6298                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6299                                         &links);
6300                 if (links > 1)
6301                         ctx->fs_links_count++;
6302                 ctx->fs_total_count++;
6303         next:
6304                 prev = dirent;
6305                 offset += dirent->rec_len;
6306                 dot_state++;
6307         } while (offset < fs->blocksize);
6308 #ifdef ENABLE_HTREE
6309         if (dx_db) {
6310                 cd->pctx.dir = cd->pctx.ino;
6311                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6312                     (dx_db->type == DX_DIRBLOCK_NODE))
6313                         parse_int_node(fs, db, cd, dx_dir, buf);
6314         }
6315 #endif /* ENABLE_HTREE */
6316         if (offset != fs->blocksize) {
6317                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6318                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6319                         dirent->rec_len = cd->pctx.num;
6320                         dir_modified++;
6321                 }
6322         }
6323         if (dir_modified) {
6324                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6325                 if (cd->pctx.errcode) {
6326                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6327                                          &cd->pctx))
6328                                 goto abort_free_dict;
6329                 }
6330                 ext2fs_mark_changed(fs);
6331         }
6332         dict_free_nodes(&de_dict);
6333         return 0;
6334 abort_free_dict:
6335         dict_free_nodes(&de_dict);
6336         ctx->flags |= E2F_FLAG_ABORT;
6337         return DIRENT_ABORT;
6338 }
6339
6340 /*
6341  * This function is called to deallocate a block, and is an interator
6342  * functioned called by deallocate inode via ext2fs_iterate_block().
6343  */
6344 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6345                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6346                                   blk_t ref_block FSCK_ATTR((unused)),
6347                                   int ref_offset FSCK_ATTR((unused)),
6348                                   void *priv_data)
6349 {
6350         e2fsck_t        ctx = (e2fsck_t) priv_data;
6351
6352         if (HOLE_BLKADDR(*block_nr))
6353                 return 0;
6354         if ((*block_nr < fs->super->s_first_data_block) ||
6355             (*block_nr >= fs->super->s_blocks_count))
6356                 return 0;
6357         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6358         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6359         return 0;
6360 }
6361
6362 /*
6363  * This fuction deallocates an inode
6364  */
6365 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6366 {
6367         ext2_filsys fs = ctx->fs;
6368         struct ext2_inode       inode;
6369         struct problem_context  pctx;
6370         __u32                   count;
6371
6372         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6373         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6374         inode.i_links_count = 0;
6375         inode.i_dtime = time(NULL);
6376         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6377         clear_problem_context(&pctx);
6378         pctx.ino = ino;
6379
6380         /*
6381          * Fix up the bitmaps...
6382          */
6383         e2fsck_read_bitmaps(ctx);
6384         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6385         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6386         if (ctx->inode_bad_map)
6387                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6388         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6389
6390         if (inode.i_file_acl &&
6391             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6392                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6393                                                    block_buf, -1, &count);
6394                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6395                         pctx.errcode = 0;
6396                         count = 1;
6397                 }
6398                 if (pctx.errcode) {
6399                         pctx.blk = inode.i_file_acl;
6400                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6401                         ctx->flags |= E2F_FLAG_ABORT;
6402                         return;
6403                 }
6404                 if (count == 0) {
6405                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6406                                                    inode.i_file_acl);
6407                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6408                 }
6409                 inode.i_file_acl = 0;
6410         }
6411
6412         if (!ext2fs_inode_has_valid_blocks(&inode))
6413                 return;
6414
6415         if (LINUX_S_ISREG(inode.i_mode) &&
6416             (inode.i_size_high || inode.i_size & 0x80000000UL))
6417                 ctx->large_files--;
6418
6419         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6420                                             deallocate_inode_block, ctx);
6421         if (pctx.errcode) {
6422                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6423                 ctx->flags |= E2F_FLAG_ABORT;
6424                 return;
6425         }
6426 }
6427
6428 /*
6429  * This fuction clears the htree flag on an inode
6430  */
6431 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6432 {
6433         struct ext2_inode       inode;
6434
6435         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6436         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6437         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6438         if (ctx->dirs_to_hash)
6439                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6440 }
6441
6442
6443 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6444                                     ext2_ino_t ino, char *buf)
6445 {
6446         ext2_filsys fs = ctx->fs;
6447         struct ext2_inode       inode;
6448         int                     inode_modified = 0;
6449         int                     not_fixed = 0;
6450         unsigned char           *frag, *fsize;
6451         struct problem_context  pctx;
6452         int     problem = 0;
6453
6454         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6455
6456         clear_problem_context(&pctx);
6457         pctx.ino = ino;
6458         pctx.dir = dir;
6459         pctx.inode = &inode;
6460
6461         if (inode.i_file_acl &&
6462             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6463             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6464                 inode.i_file_acl = 0;
6465 #if BB_BIG_ENDIAN
6466                 /*
6467                  * This is a special kludge to deal with long symlinks
6468                  * on big endian systems.  i_blocks had already been
6469                  * decremented earlier in pass 1, but since i_file_acl
6470                  * hadn't yet been cleared, ext2fs_read_inode()
6471                  * assumed that the file was short symlink and would
6472                  * not have byte swapped i_block[0].  Hence, we have
6473                  * to byte-swap it here.
6474                  */
6475                 if (LINUX_S_ISLNK(inode.i_mode) &&
6476                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6477                     (inode.i_blocks == fs->blocksize >> 9))
6478                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6479 #endif
6480                 inode_modified++;
6481         } else
6482                 not_fixed++;
6483
6484         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6485             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6486             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6487             !(LINUX_S_ISSOCK(inode.i_mode)))
6488                 problem = PR_2_BAD_MODE;
6489         else if (LINUX_S_ISCHR(inode.i_mode)
6490                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6491                 problem = PR_2_BAD_CHAR_DEV;
6492         else if (LINUX_S_ISBLK(inode.i_mode)
6493                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6494                 problem = PR_2_BAD_BLOCK_DEV;
6495         else if (LINUX_S_ISFIFO(inode.i_mode)
6496                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6497                 problem = PR_2_BAD_FIFO;
6498         else if (LINUX_S_ISSOCK(inode.i_mode)
6499                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6500                 problem = PR_2_BAD_SOCKET;
6501         else if (LINUX_S_ISLNK(inode.i_mode)
6502                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6503                 problem = PR_2_INVALID_SYMLINK;
6504         }
6505
6506         if (problem) {
6507                 if (fix_problem(ctx, problem, &pctx)) {
6508                         deallocate_inode(ctx, ino, 0);
6509                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6510                                 return 0;
6511                         return 1;
6512                 } else
6513                         not_fixed++;
6514                 problem = 0;
6515         }
6516
6517         if (inode.i_faddr) {
6518                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6519                         inode.i_faddr = 0;
6520                         inode_modified++;
6521                 } else
6522                         not_fixed++;
6523         }
6524
6525         switch (fs->super->s_creator_os) {
6526             case EXT2_OS_LINUX:
6527                 frag = &inode.osd2.linux2.l_i_frag;
6528                 fsize = &inode.osd2.linux2.l_i_fsize;
6529                 break;
6530             case EXT2_OS_HURD:
6531                 frag = &inode.osd2.hurd2.h_i_frag;
6532                 fsize = &inode.osd2.hurd2.h_i_fsize;
6533                 break;
6534             case EXT2_OS_MASIX:
6535                 frag = &inode.osd2.masix2.m_i_frag;
6536                 fsize = &inode.osd2.masix2.m_i_fsize;
6537                 break;
6538             default:
6539                 frag = fsize = 0;
6540         }
6541         if (frag && *frag) {
6542                 pctx.num = *frag;
6543                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6544                         *frag = 0;
6545                         inode_modified++;
6546                 } else
6547                         not_fixed++;
6548                 pctx.num = 0;
6549         }
6550         if (fsize && *fsize) {
6551                 pctx.num = *fsize;
6552                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6553                         *fsize = 0;
6554                         inode_modified++;
6555                 } else
6556                         not_fixed++;
6557                 pctx.num = 0;
6558         }
6559
6560         if (inode.i_file_acl &&
6561             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6562              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6563                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6564                         inode.i_file_acl = 0;
6565                         inode_modified++;
6566                 } else
6567                         not_fixed++;
6568         }
6569         if (inode.i_dir_acl &&
6570             LINUX_S_ISDIR(inode.i_mode)) {
6571                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6572                         inode.i_dir_acl = 0;
6573                         inode_modified++;
6574                 } else
6575                         not_fixed++;
6576         }
6577
6578         if (inode_modified)
6579                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6580         if (!not_fixed)
6581                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6582         return 0;
6583 }
6584
6585
6586 /*
6587  * allocate_dir_block --- this function allocates a new directory
6588  *      block for a particular inode; this is done if a directory has
6589  *      a "hole" in it, or if a directory has a illegal block number
6590  *      that was zeroed out and now needs to be replaced.
6591  */
6592 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6593                               struct problem_context *pctx)
6594 {
6595         ext2_filsys fs = ctx->fs;
6596         blk_t                   blk;
6597         char                    *block;
6598         struct ext2_inode       inode;
6599
6600         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6601                 return 1;
6602
6603         /*
6604          * Read the inode and block bitmaps in; we'll be messing with
6605          * them.
6606          */
6607         e2fsck_read_bitmaps(ctx);
6608
6609         /*
6610          * First, find a free block
6611          */
6612         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6613         if (pctx->errcode) {
6614                 pctx->str = "ext2fs_new_block";
6615                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6616                 return 1;
6617         }
6618         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6619         ext2fs_mark_block_bitmap(fs->block_map, blk);
6620         ext2fs_mark_bb_dirty(fs);
6621
6622         /*
6623          * Now let's create the actual data block for the inode
6624          */
6625         if (db->blockcnt)
6626                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6627         else
6628                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6629                                                      EXT2_ROOT_INO, &block);
6630
6631         if (pctx->errcode) {
6632                 pctx->str = "ext2fs_new_dir_block";
6633                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6634                 return 1;
6635         }
6636
6637         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6638         ext2fs_free_mem(&block);
6639         if (pctx->errcode) {
6640                 pctx->str = "ext2fs_write_dir_block";
6641                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6642                 return 1;
6643         }
6644
6645         /*
6646          * Update the inode block count
6647          */
6648         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6649         inode.i_blocks += fs->blocksize / 512;
6650         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6651                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6652         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6653
6654         /*
6655          * Finally, update the block pointers for the inode
6656          */
6657         db->blk = blk;
6658         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6659                                       0, update_dir_block, db);
6660         if (pctx->errcode) {
6661                 pctx->str = "ext2fs_block_iterate";
6662                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663                 return 1;
6664         }
6665
6666         return 0;
6667 }
6668
6669 /*
6670  * This is a helper function for allocate_dir_block().
6671  */
6672 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6673                             blk_t       *block_nr,
6674                             e2_blkcnt_t blockcnt,
6675                             blk_t ref_block FSCK_ATTR((unused)),
6676                             int ref_offset FSCK_ATTR((unused)),
6677                             void *priv_data)
6678 {
6679         struct ext2_db_entry *db;
6680
6681         db = (struct ext2_db_entry *) priv_data;
6682         if (db->blockcnt == (int) blockcnt) {
6683                 *block_nr = db->blk;
6684                 return BLOCK_CHANGED;
6685         }
6686         return 0;
6687 }
6688
6689 /*
6690  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6691  *
6692  * Pass #3 assures that all directories are connected to the
6693  * filesystem tree, using the following algorithm:
6694  *
6695  * First, the root directory is checked to make sure it exists; if
6696  * not, e2fsck will offer to create a new one.  It is then marked as
6697  * "done".
6698  *
6699  * Then, pass3 interates over all directory inodes; for each directory
6700  * it attempts to trace up the filesystem tree, using dirinfo.parent
6701  * until it reaches a directory which has been marked "done".  If it
6702  * cannot do so, then the directory must be disconnected, and e2fsck
6703  * will offer to reconnect it to /lost+found.  While it is chasing
6704  * parent pointers up the filesystem tree, if pass3 sees a directory
6705  * twice, then it has detected a filesystem loop, and it will again
6706  * offer to reconnect the directory to /lost+found in to break the
6707  * filesystem loop.
6708  *
6709  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6710  * reconnect inodes to /lost+found; this subroutine is also used by
6711  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6712  * is responsible for creating /lost+found if it does not exist.
6713  *
6714  * Pass 3 frees the following data structures:
6715  *      - The dirinfo directory information cache.
6716  */
6717
6718 static void check_root(e2fsck_t ctx);
6719 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6720                            struct problem_context *pctx);
6721 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6722
6723 static ext2fs_inode_bitmap inode_loop_detect;
6724 static ext2fs_inode_bitmap inode_done_map;
6725
6726 static void e2fsck_pass3(e2fsck_t ctx)
6727 {
6728         ext2_filsys fs = ctx->fs;
6729         int             i;
6730         struct problem_context  pctx;
6731         struct dir_info *dir;
6732         unsigned long maxdirs, count;
6733
6734         clear_problem_context(&pctx);
6735
6736         /* Pass 3 */
6737
6738         if (!(ctx->options & E2F_OPT_PREEN))
6739                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6740
6741         /*
6742          * Allocate some bitmaps to do loop detection.
6743          */
6744         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6745                                                     &inode_done_map);
6746         if (pctx.errcode) {
6747                 pctx.num = 2;
6748                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6749                 ctx->flags |= E2F_FLAG_ABORT;
6750                 goto abort_exit;
6751         }
6752         check_root(ctx);
6753         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6754                 goto abort_exit;
6755
6756         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6757
6758         maxdirs = e2fsck_get_num_dirinfo(ctx);
6759         count = 1;
6760
6761         if (ctx->progress)
6762                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6763                         goto abort_exit;
6764
6765         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6766                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6767                         goto abort_exit;
6768                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6769                         goto abort_exit;
6770                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6771                         if (check_directory(ctx, dir, &pctx))
6772                                 goto abort_exit;
6773         }
6774
6775         /*
6776          * Force the creation of /lost+found if not present
6777          */
6778         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6779                 e2fsck_get_lost_and_found(ctx, 1);
6780
6781         /*
6782          * If there are any directories that need to be indexed or
6783          * optimized, do it here.
6784          */
6785         e2fsck_rehash_directories(ctx);
6786
6787 abort_exit:
6788         e2fsck_free_dir_info(ctx);
6789         ext2fs_free_inode_bitmap(inode_loop_detect);
6790         inode_loop_detect = 0;
6791         ext2fs_free_inode_bitmap(inode_done_map);
6792         inode_done_map = 0;
6793 }
6794
6795 /*
6796  * This makes sure the root inode is present; if not, we ask if the
6797  * user wants us to create it.  Not creating it is a fatal error.
6798  */
6799 static void check_root(e2fsck_t ctx)
6800 {
6801         ext2_filsys fs = ctx->fs;
6802         blk_t                   blk;
6803         struct ext2_inode       inode;
6804         char *                  block;
6805         struct problem_context  pctx;
6806
6807         clear_problem_context(&pctx);
6808
6809         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6810                 /*
6811                  * If the root inode is not a directory, die here.  The
6812                  * user must have answered 'no' in pass1 when we
6813                  * offered to clear it.
6814                  */
6815                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6816                                                EXT2_ROOT_INO))) {
6817                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6818                         ctx->flags |= E2F_FLAG_ABORT;
6819                 }
6820                 return;
6821         }
6822
6823         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6824                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6825                 ctx->flags |= E2F_FLAG_ABORT;
6826                 return;
6827         }
6828
6829         e2fsck_read_bitmaps(ctx);
6830
6831         /*
6832          * First, find a free block
6833          */
6834         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6835         if (pctx.errcode) {
6836                 pctx.str = "ext2fs_new_block";
6837                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6838                 ctx->flags |= E2F_FLAG_ABORT;
6839                 return;
6840         }
6841         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6842         ext2fs_mark_block_bitmap(fs->block_map, blk);
6843         ext2fs_mark_bb_dirty(fs);
6844
6845         /*
6846          * Now let's create the actual data block for the inode
6847          */
6848         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6849                                             &block);
6850         if (pctx.errcode) {
6851                 pctx.str = "ext2fs_new_dir_block";
6852                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6853                 ctx->flags |= E2F_FLAG_ABORT;
6854                 return;
6855         }
6856
6857         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6858         if (pctx.errcode) {
6859                 pctx.str = "ext2fs_write_dir_block";
6860                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6861                 ctx->flags |= E2F_FLAG_ABORT;
6862                 return;
6863         }
6864         ext2fs_free_mem(&block);
6865
6866         /*
6867          * Set up the inode structure
6868          */
6869         memset(&inode, 0, sizeof(inode));
6870         inode.i_mode = 040755;
6871         inode.i_size = fs->blocksize;
6872         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6873         inode.i_links_count = 2;
6874         inode.i_blocks = fs->blocksize / 512;
6875         inode.i_block[0] = blk;
6876
6877         /*
6878          * Write out the inode.
6879          */
6880         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6881         if (pctx.errcode) {
6882                 pctx.str = "ext2fs_write_inode";
6883                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6884                 ctx->flags |= E2F_FLAG_ABORT;
6885                 return;
6886         }
6887
6888         /*
6889          * Miscellaneous bookkeeping...
6890          */
6891         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6892         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6893         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6894
6895         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6896         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6897         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6898         ext2fs_mark_ib_dirty(fs);
6899 }
6900
6901 /*
6902  * This subroutine is responsible for making sure that a particular
6903  * directory is connected to the root; if it isn't we trace it up as
6904  * far as we can go, and then offer to connect the resulting parent to
6905  * the lost+found.  We have to do loop detection; if we ever discover
6906  * a loop, we treat that as a disconnected directory and offer to
6907  * reparent it to lost+found.
6908  *
6909  * However, loop detection is expensive, because for very large
6910  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6911  * is non-trivial.  Loops in filesystems are also a rare error case,
6912  * and we shouldn't optimize for error cases.  So we try two passes of
6913  * the algorithm.  The first time, we ignore loop detection and merely
6914  * increment a counter; if the counter exceeds some extreme threshold,
6915  * then we try again with the loop detection bitmap enabled.
6916  */
6917 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6918                            struct problem_context *pctx)
6919 {
6920         ext2_filsys     fs = ctx->fs;
6921         struct dir_info *p = dir;
6922         int             loop_pass = 0, parent_count = 0;
6923
6924         if (!p)
6925                 return 0;
6926
6927         while (1) {
6928                 /*
6929                  * Mark this inode as being "done"; by the time we
6930                  * return from this function, the inode we either be
6931                  * verified as being connected to the directory tree,
6932                  * or we will have offered to reconnect this to
6933                  * lost+found.
6934                  *
6935                  * If it was marked done already, then we've reached a
6936                  * parent we've already checked.
6937                  */
6938                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6939                         break;
6940
6941                 /*
6942                  * If this directory doesn't have a parent, or we've
6943                  * seen the parent once already, then offer to
6944                  * reparent it to lost+found
6945                  */
6946                 if (!p->parent ||
6947                     (loop_pass &&
6948                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6949                                               p->parent)))) {
6950                         pctx->ino = p->ino;
6951                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6952                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6953                                         ext2fs_unmark_valid(fs);
6954                                 else {
6955                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
6956                                         p->parent = ctx->lost_and_found;
6957                                         fix_dotdot(ctx, p, ctx->lost_and_found);
6958                                 }
6959                         }
6960                         break;
6961                 }
6962                 p = e2fsck_get_dir_info(ctx, p->parent);
6963                 if (!p) {
6964                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6965                         return 0;
6966                 }
6967                 if (loop_pass) {
6968                         ext2fs_mark_inode_bitmap(inode_loop_detect,
6969                                                  p->ino);
6970                 } else if (parent_count++ > 2048) {
6971                         /*
6972                          * If we've run into a path depth that's
6973                          * greater than 2048, try again with the inode
6974                          * loop bitmap turned on and start from the
6975                          * top.
6976                          */
6977                         loop_pass = 1;
6978                         if (inode_loop_detect)
6979                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
6980                         else {
6981                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6982                                 if (pctx->errcode) {
6983                                         pctx->num = 1;
6984                                         fix_problem(ctx,
6985                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6986                                         ctx->flags |= E2F_FLAG_ABORT;
6987                                         return -1;
6988                                 }
6989                         }
6990                         p = dir;
6991                 }
6992         }
6993
6994         /*
6995          * Make sure that .. and the parent directory are the same;
6996          * offer to fix it if not.
6997          */
6998         if (dir->parent != dir->dotdot) {
6999                 pctx->ino = dir->ino;
7000                 pctx->ino2 = dir->dotdot;
7001                 pctx->dir = dir->parent;
7002                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7003                         fix_dotdot(ctx, dir, dir->parent);
7004         }
7005         return 0;
7006 }
7007
7008 /*
7009  * This routine gets the lost_and_found inode, making it a directory
7010  * if necessary
7011  */
7012 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7013 {
7014         ext2_filsys fs = ctx->fs;
7015         ext2_ino_t                      ino;
7016         blk_t                   blk;
7017         errcode_t               retval;
7018         struct ext2_inode       inode;
7019         char *                  block;
7020         static const char       name[] = "lost+found";
7021         struct  problem_context pctx;
7022         struct dir_info         *dirinfo;
7023
7024         if (ctx->lost_and_found)
7025                 return ctx->lost_and_found;
7026
7027         clear_problem_context(&pctx);
7028
7029         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7030                                sizeof(name)-1, 0, &ino);
7031         if (retval && !fix)
7032                 return 0;
7033         if (!retval) {
7034                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7035                         ctx->lost_and_found = ino;
7036                         return ino;
7037                 }
7038
7039                 /* Lost+found isn't a directory! */
7040                 if (!fix)
7041                         return 0;
7042                 pctx.ino = ino;
7043                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7044                         return 0;
7045
7046                 /* OK, unlink the old /lost+found file. */
7047                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7048                 if (pctx.errcode) {
7049                         pctx.str = "ext2fs_unlink";
7050                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7051                         return 0;
7052                 }
7053                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7054                 if (dirinfo)
7055                         dirinfo->parent = 0;
7056                 e2fsck_adjust_inode_count(ctx, ino, -1);
7057         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7058                 pctx.errcode = retval;
7059                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7060         }
7061         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7062                 return 0;
7063
7064         /*
7065          * Read the inode and block bitmaps in; we'll be messing with
7066          * them.
7067          */
7068         e2fsck_read_bitmaps(ctx);
7069
7070         /*
7071          * First, find a free block
7072          */
7073         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7074         if (retval) {
7075                 pctx.errcode = retval;
7076                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7077                 return 0;
7078         }
7079         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7080         ext2fs_block_alloc_stats(fs, blk, +1);
7081
7082         /*
7083          * Next find a free inode.
7084          */
7085         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7086                                   ctx->inode_used_map, &ino);
7087         if (retval) {
7088                 pctx.errcode = retval;
7089                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7090                 return 0;
7091         }
7092         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7093         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7094         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7095
7096         /*
7097          * Now let's create the actual data block for the inode
7098          */
7099         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7100         if (retval) {
7101                 pctx.errcode = retval;
7102                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7103                 return 0;
7104         }
7105
7106         retval = ext2fs_write_dir_block(fs, blk, block);
7107         ext2fs_free_mem(&block);
7108         if (retval) {
7109                 pctx.errcode = retval;
7110                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7111                 return 0;
7112         }
7113
7114         /*
7115          * Set up the inode structure
7116          */
7117         memset(&inode, 0, sizeof(inode));
7118         inode.i_mode = 040700;
7119         inode.i_size = fs->blocksize;
7120         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7121         inode.i_links_count = 2;
7122         inode.i_blocks = fs->blocksize / 512;
7123         inode.i_block[0] = blk;
7124
7125         /*
7126          * Next, write out the inode.
7127          */
7128         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7129         if (pctx.errcode) {
7130                 pctx.str = "ext2fs_write_inode";
7131                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7132                 return 0;
7133         }
7134         /*
7135          * Finally, create the directory link
7136          */
7137         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7138         if (pctx.errcode) {
7139                 pctx.str = "ext2fs_link";
7140                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7141                 return 0;
7142         }
7143
7144         /*
7145          * Miscellaneous bookkeeping that needs to be kept straight.
7146          */
7147         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7148         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7149         ext2fs_icount_store(ctx->inode_count, ino, 2);
7150         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7151         ctx->lost_and_found = ino;
7152         return ino;
7153 }
7154
7155 /*
7156  * This routine will connect a file to lost+found
7157  */
7158 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7159 {
7160         ext2_filsys fs = ctx->fs;
7161         errcode_t       retval;
7162         char            name[80];
7163         struct problem_context  pctx;
7164         struct ext2_inode       inode;
7165         int             file_type = 0;
7166
7167         clear_problem_context(&pctx);
7168         pctx.ino = ino;
7169
7170         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7171                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7172                         ctx->bad_lost_and_found++;
7173         }
7174         if (ctx->bad_lost_and_found) {
7175                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7176                 return 1;
7177         }
7178
7179         sprintf(name, "#%u", ino);
7180         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7181                 file_type = ext2_file_type(inode.i_mode);
7182         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7183         if (retval == EXT2_ET_DIR_NO_SPACE) {
7184                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7185                         return 1;
7186                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7187                                                  1, 0);
7188                 if (retval) {
7189                         pctx.errcode = retval;
7190                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7191                         return 1;
7192                 }
7193                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7194                                      ino, file_type);
7195         }
7196         if (retval) {
7197                 pctx.errcode = retval;
7198                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7199                 return 1;
7200         }
7201         e2fsck_adjust_inode_count(ctx, ino, 1);
7202
7203         return 0;
7204 }
7205
7206 /*
7207  * Utility routine to adjust the inode counts on an inode.
7208  */
7209 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7210 {
7211         ext2_filsys fs = ctx->fs;
7212         errcode_t               retval;
7213         struct ext2_inode       inode;
7214
7215         if (!ino)
7216                 return 0;
7217
7218         retval = ext2fs_read_inode(fs, ino, &inode);
7219         if (retval)
7220                 return retval;
7221
7222         if (adj == 1) {
7223                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7224                 if (inode.i_links_count == (__u16) ~0)
7225                         return 0;
7226                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7227                 inode.i_links_count++;
7228         } else if (adj == -1) {
7229                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7230                 if (inode.i_links_count == 0)
7231                         return 0;
7232                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7233                 inode.i_links_count--;
7234         }
7235
7236         retval = ext2fs_write_inode(fs, ino, &inode);
7237         if (retval)
7238                 return retval;
7239
7240         return 0;
7241 }
7242
7243 /*
7244  * Fix parent --- this routine fixes up the parent of a directory.
7245  */
7246 struct fix_dotdot_struct {
7247         ext2_filsys     fs;
7248         ext2_ino_t      parent;
7249         int             done;
7250         e2fsck_t        ctx;
7251 };
7252
7253 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7254                            int  offset FSCK_ATTR((unused)),
7255                            int  blocksize FSCK_ATTR((unused)),
7256                            char *buf FSCK_ATTR((unused)),
7257                            void *priv_data)
7258 {
7259         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7260         errcode_t       retval;
7261         struct problem_context pctx;
7262
7263         if ((dirent->name_len & 0xFF) != 2)
7264                 return 0;
7265         if (strncmp(dirent->name, "..", 2))
7266                 return 0;
7267
7268         clear_problem_context(&pctx);
7269
7270         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7271         if (retval) {
7272                 pctx.errcode = retval;
7273                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7274         }
7275         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7276         if (retval) {
7277                 pctx.errcode = retval;
7278                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7279         }
7280         dirent->inode = fp->parent;
7281
7282         fp->done++;
7283         return DIRENT_ABORT | DIRENT_CHANGED;
7284 }
7285
7286 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7287 {
7288         ext2_filsys fs = ctx->fs;
7289         errcode_t       retval;
7290         struct fix_dotdot_struct fp;
7291         struct problem_context pctx;
7292
7293         fp.fs = fs;
7294         fp.parent = parent;
7295         fp.done = 0;
7296         fp.ctx = ctx;
7297
7298         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7299                                     0, fix_dotdot_proc, &fp);
7300         if (retval || !fp.done) {
7301                 clear_problem_context(&pctx);
7302                 pctx.ino = dir->ino;
7303                 pctx.errcode = retval;
7304                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7305                             PR_3_FIX_PARENT_NOFIND, &pctx);
7306                 ext2fs_unmark_valid(fs);
7307         }
7308         dir->dotdot = parent;
7309 }
7310
7311 /*
7312  * These routines are responsible for expanding a /lost+found if it is
7313  * too small.
7314  */
7315
7316 struct expand_dir_struct {
7317         int                     num;
7318         int                     guaranteed_size;
7319         int                     newblocks;
7320         int                     last_block;
7321         errcode_t               err;
7322         e2fsck_t                ctx;
7323 };
7324
7325 static int expand_dir_proc(ext2_filsys fs,
7326                            blk_t        *blocknr,
7327                            e2_blkcnt_t  blockcnt,
7328                            blk_t ref_block FSCK_ATTR((unused)),
7329                            int ref_offset FSCK_ATTR((unused)),
7330                            void *priv_data)
7331 {
7332         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7333         blk_t   new_blk;
7334         static blk_t    last_blk = 0;
7335         char            *block;
7336         errcode_t       retval;
7337         e2fsck_t        ctx;
7338
7339         ctx = es->ctx;
7340
7341         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7342                 return BLOCK_ABORT;
7343
7344         if (blockcnt > 0)
7345                 es->last_block = blockcnt;
7346         if (*blocknr) {
7347                 last_blk = *blocknr;
7348                 return 0;
7349         }
7350         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7351                                   &new_blk);
7352         if (retval) {
7353                 es->err = retval;
7354                 return BLOCK_ABORT;
7355         }
7356         if (blockcnt > 0) {
7357                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7358                 if (retval) {
7359                         es->err = retval;
7360                         return BLOCK_ABORT;
7361                 }
7362                 es->num--;
7363                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7364         } else {
7365                 retval = ext2fs_get_mem(fs->blocksize, &block);
7366                 if (retval) {
7367                         es->err = retval;
7368                         return BLOCK_ABORT;
7369                 }
7370                 memset(block, 0, fs->blocksize);
7371                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7372         }
7373         if (retval) {
7374                 es->err = retval;
7375                 return BLOCK_ABORT;
7376         }
7377         ext2fs_free_mem(&block);
7378         *blocknr = new_blk;
7379         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7380         ext2fs_block_alloc_stats(fs, new_blk, +1);
7381         es->newblocks++;
7382
7383         if (es->num == 0)
7384                 return (BLOCK_CHANGED | BLOCK_ABORT);
7385         else
7386                 return BLOCK_CHANGED;
7387 }
7388
7389 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7390                                   int num, int guaranteed_size)
7391 {
7392         ext2_filsys fs = ctx->fs;
7393         errcode_t       retval;
7394         struct expand_dir_struct es;
7395         struct ext2_inode       inode;
7396
7397         if (!(fs->flags & EXT2_FLAG_RW))
7398                 return EXT2_ET_RO_FILSYS;
7399
7400         /*
7401          * Read the inode and block bitmaps in; we'll be messing with
7402          * them.
7403          */
7404         e2fsck_read_bitmaps(ctx);
7405
7406         retval = ext2fs_check_directory(fs, dir);
7407         if (retval)
7408                 return retval;
7409
7410         es.num = num;
7411         es.guaranteed_size = guaranteed_size;
7412         es.last_block = 0;
7413         es.err = 0;
7414         es.newblocks = 0;
7415         es.ctx = ctx;
7416
7417         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7418                                        0, expand_dir_proc, &es);
7419
7420         if (es.err)
7421                 return es.err;
7422
7423         /*
7424          * Update the size and block count fields in the inode.
7425          */
7426         retval = ext2fs_read_inode(fs, dir, &inode);
7427         if (retval)
7428                 return retval;
7429
7430         inode.i_size = (es.last_block + 1) * fs->blocksize;
7431         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7432
7433         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7434
7435         return 0;
7436 }
7437
7438 /*
7439  * pass4.c -- pass #4 of e2fsck: Check reference counts
7440  *
7441  * Pass 4 frees the following data structures:
7442  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7443  */
7444
7445 /*
7446  * This routine is called when an inode is not connected to the
7447  * directory tree.
7448  *
7449  * This subroutine returns 1 then the caller shouldn't bother with the
7450  * rest of the pass 4 tests.
7451  */
7452 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7453 {
7454         ext2_filsys fs = ctx->fs;
7455         struct ext2_inode       inode;
7456         struct problem_context  pctx;
7457
7458         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7459         clear_problem_context(&pctx);
7460         pctx.ino = i;
7461         pctx.inode = &inode;
7462
7463         /*
7464          * Offer to delete any zero-length files that does not have
7465          * blocks.  If there is an EA block, it might have useful
7466          * information, so we won't prompt to delete it, but let it be
7467          * reconnected to lost+found.
7468          */
7469         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7470                                 LINUX_S_ISDIR(inode.i_mode))) {
7471                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7472                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7473                         inode.i_links_count = 0;
7474                         inode.i_dtime = time(NULL);
7475                         e2fsck_write_inode(ctx, i, &inode,
7476                                            "disconnect_inode");
7477                         /*
7478                          * Fix up the bitmaps...
7479                          */
7480                         e2fsck_read_bitmaps(ctx);
7481                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7482                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7483                         ext2fs_inode_alloc_stats2(fs, i, -1,
7484                                                   LINUX_S_ISDIR(inode.i_mode));
7485                         return 0;
7486                 }
7487         }
7488
7489         /*
7490          * Prompt to reconnect.
7491          */
7492         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7493                 if (e2fsck_reconnect_file(ctx, i))
7494                         ext2fs_unmark_valid(fs);
7495         } else {
7496                 /*
7497                  * If we don't attach the inode, then skip the
7498                  * i_links_test since there's no point in trying to
7499                  * force i_links_count to zero.
7500                  */
7501                 ext2fs_unmark_valid(fs);
7502                 return 1;
7503         }
7504         return 0;
7505 }
7506
7507
7508 static void e2fsck_pass4(e2fsck_t ctx)
7509 {
7510         ext2_filsys fs = ctx->fs;
7511         ext2_ino_t      i;
7512         struct ext2_inode       inode;
7513         struct problem_context  pctx;
7514         __u16   link_count, link_counted;
7515         char    *buf = NULL;
7516         int     group, maxgroup;
7517
7518         /* Pass 4 */
7519
7520         clear_problem_context(&pctx);
7521
7522         if (!(ctx->options & E2F_OPT_PREEN))
7523                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7524
7525         group = 0;
7526         maxgroup = fs->group_desc_count;
7527         if (ctx->progress)
7528                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7529                         return;
7530
7531         for (i=1; i <= fs->super->s_inodes_count; i++) {
7532                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7533                         return;
7534                 if ((i % fs->super->s_inodes_per_group) == 0) {
7535                         group++;
7536                         if (ctx->progress)
7537                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7538                                         return;
7539                 }
7540                 if (i == EXT2_BAD_INO ||
7541                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7542                         continue;
7543                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7544                     (ctx->inode_imagic_map &&
7545                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7546                         continue;
7547                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7548                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7549                 if (link_counted == 0) {
7550                         if (!buf)
7551                                 buf = e2fsck_allocate_memory(ctx,
7552                                      fs->blocksize, "bad_inode buffer");
7553                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7554                                 continue;
7555                         if (disconnect_inode(ctx, i))
7556                                 continue;
7557                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7558                                             &link_count);
7559                         ext2fs_icount_fetch(ctx->inode_count, i,
7560                                             &link_counted);
7561                 }
7562                 if (link_counted != link_count) {
7563                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7564                         pctx.ino = i;
7565                         pctx.inode = &inode;
7566                         if (link_count != inode.i_links_count) {
7567                                 pctx.num = link_count;
7568                                 fix_problem(ctx,
7569                                             PR_4_INCONSISTENT_COUNT, &pctx);
7570                         }
7571                         pctx.num = link_counted;
7572                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7573                                 inode.i_links_count = link_counted;
7574                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7575                         }
7576                 }
7577         }
7578         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7579         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7580         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7581         ctx->inode_imagic_map = 0;
7582         ext2fs_free_mem(&buf);
7583 }
7584
7585 /*
7586  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7587  */
7588
7589 #define NO_BLK ((blk_t) -1)
7590
7591 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7592                             struct problem_context *pctx)
7593 {
7594         switch (problem) {
7595         case PR_5_BLOCK_UNUSED:
7596                 if (pctx->blk == pctx->blk2)
7597                         pctx->blk2 = 0;
7598                 else
7599                         problem = PR_5_BLOCK_RANGE_UNUSED;
7600                 break;
7601         case PR_5_BLOCK_USED:
7602                 if (pctx->blk == pctx->blk2)
7603                         pctx->blk2 = 0;
7604                 else
7605                         problem = PR_5_BLOCK_RANGE_USED;
7606                 break;
7607         case PR_5_INODE_UNUSED:
7608                 if (pctx->ino == pctx->ino2)
7609                         pctx->ino2 = 0;
7610                 else
7611                         problem = PR_5_INODE_RANGE_UNUSED;
7612                 break;
7613         case PR_5_INODE_USED:
7614                 if (pctx->ino == pctx->ino2)
7615                         pctx->ino2 = 0;
7616                 else
7617                         problem = PR_5_INODE_RANGE_USED;
7618                 break;
7619         }
7620         fix_problem(ctx, problem, pctx);
7621         pctx->blk = pctx->blk2 = NO_BLK;
7622         pctx->ino = pctx->ino2 = 0;
7623 }
7624
7625 static void check_block_bitmaps(e2fsck_t ctx)
7626 {
7627         ext2_filsys fs = ctx->fs;
7628         blk_t   i;
7629         int     *free_array;
7630         int     group = 0;
7631         unsigned int    blocks = 0;
7632         unsigned int    free_blocks = 0;
7633         int     group_free = 0;
7634         int     actual, bitmap;
7635         struct problem_context  pctx;
7636         int     problem, save_problem, fixit, had_problem;
7637         errcode_t       retval;
7638
7639         clear_problem_context(&pctx);
7640         free_array = (int *) e2fsck_allocate_memory(ctx,
7641             fs->group_desc_count * sizeof(int), "free block count array");
7642
7643         if ((fs->super->s_first_data_block <
7644              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7645             (fs->super->s_blocks_count-1 >
7646              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7647                 pctx.num = 1;
7648                 pctx.blk = fs->super->s_first_data_block;
7649                 pctx.blk2 = fs->super->s_blocks_count -1;
7650                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7651                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7652                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7653
7654                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7655                 return;
7656         }
7657
7658         if ((fs->super->s_first_data_block <
7659              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7660             (fs->super->s_blocks_count-1 >
7661              ext2fs_get_block_bitmap_end(fs->block_map))) {
7662                 pctx.num = 2;
7663                 pctx.blk = fs->super->s_first_data_block;
7664                 pctx.blk2 = fs->super->s_blocks_count -1;
7665                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7666                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7667                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7668
7669                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7670                 return;
7671         }
7672
7673 redo_counts:
7674         had_problem = 0;
7675         save_problem = 0;
7676         pctx.blk = pctx.blk2 = NO_BLK;
7677         for (i = fs->super->s_first_data_block;
7678              i < fs->super->s_blocks_count;
7679              i++) {
7680                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7681                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7682
7683                 if (actual == bitmap)
7684                         goto do_counts;
7685
7686                 if (!actual && bitmap) {
7687                         /*
7688                          * Block not used, but marked in use in the bitmap.
7689                          */
7690                         problem = PR_5_BLOCK_UNUSED;
7691                 } else {
7692                         /*
7693                          * Block used, but not marked in use in the bitmap.
7694                          */
7695                         problem = PR_5_BLOCK_USED;
7696                 }
7697                 if (pctx.blk == NO_BLK) {
7698                         pctx.blk = pctx.blk2 = i;
7699                         save_problem = problem;
7700                 } else {
7701                         if ((problem == save_problem) &&
7702                             (pctx.blk2 == i-1))
7703                                 pctx.blk2++;
7704                         else {
7705                                 print_bitmap_problem(ctx, save_problem, &pctx);
7706                                 pctx.blk = pctx.blk2 = i;
7707                                 save_problem = problem;
7708                         }
7709                 }
7710                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7711                 had_problem++;
7712
7713         do_counts:
7714                 if (!bitmap) {
7715                         group_free++;
7716                         free_blocks++;
7717                 }
7718                 blocks ++;
7719                 if ((blocks == fs->super->s_blocks_per_group) ||
7720                     (i == fs->super->s_blocks_count-1)) {
7721                         free_array[group] = group_free;
7722                         group ++;
7723                         blocks = 0;
7724                         group_free = 0;
7725                         if (ctx->progress)
7726                                 if ((ctx->progress)(ctx, 5, group,
7727                                                     fs->group_desc_count*2))
7728                                         return;
7729                 }
7730         }
7731         if (pctx.blk != NO_BLK)
7732                 print_bitmap_problem(ctx, save_problem, &pctx);
7733         if (had_problem)
7734                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7735         else
7736                 fixit = -1;
7737         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7738
7739         if (fixit == 1) {
7740                 ext2fs_free_block_bitmap(fs->block_map);
7741                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7742                                                   &fs->block_map);
7743                 if (retval) {
7744                         clear_problem_context(&pctx);
7745                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7746                         ctx->flags |= E2F_FLAG_ABORT;
7747                         return;
7748                 }
7749                 ext2fs_set_bitmap_padding(fs->block_map);
7750                 ext2fs_mark_bb_dirty(fs);
7751
7752                 /* Redo the counts */
7753                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7754                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7755                 goto redo_counts;
7756         } else if (fixit == 0)
7757                 ext2fs_unmark_valid(fs);
7758
7759         for (i = 0; i < fs->group_desc_count; i++) {
7760                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7761                         pctx.group = i;
7762                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7763                         pctx.blk2 = free_array[i];
7764
7765                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7766                                         &pctx)) {
7767                                 fs->group_desc[i].bg_free_blocks_count =
7768                                         free_array[i];
7769                                 ext2fs_mark_super_dirty(fs);
7770                         } else
7771                                 ext2fs_unmark_valid(fs);
7772                 }
7773         }
7774         if (free_blocks != fs->super->s_free_blocks_count) {
7775                 pctx.group = 0;
7776                 pctx.blk = fs->super->s_free_blocks_count;
7777                 pctx.blk2 = free_blocks;
7778
7779                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7780                         fs->super->s_free_blocks_count = free_blocks;
7781                         ext2fs_mark_super_dirty(fs);
7782                 } else
7783                         ext2fs_unmark_valid(fs);
7784         }
7785         ext2fs_free_mem(&free_array);
7786 }
7787
7788 static void check_inode_bitmaps(e2fsck_t ctx)
7789 {
7790         ext2_filsys fs = ctx->fs;
7791         ext2_ino_t      i;
7792         unsigned int    free_inodes = 0;
7793         int             group_free = 0;
7794         int             dirs_count = 0;
7795         int             group = 0;
7796         unsigned int    inodes = 0;
7797         int             *free_array;
7798         int             *dir_array;
7799         int             actual, bitmap;
7800         errcode_t       retval;
7801         struct problem_context  pctx;
7802         int             problem, save_problem, fixit, had_problem;
7803
7804         clear_problem_context(&pctx);
7805         free_array = (int *) e2fsck_allocate_memory(ctx,
7806             fs->group_desc_count * sizeof(int), "free inode count array");
7807
7808         dir_array = (int *) e2fsck_allocate_memory(ctx,
7809            fs->group_desc_count * sizeof(int), "directory count array");
7810
7811         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7812             (fs->super->s_inodes_count >
7813              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7814                 pctx.num = 3;
7815                 pctx.blk = 1;
7816                 pctx.blk2 = fs->super->s_inodes_count;
7817                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7818                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7819                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7820
7821                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7822                 return;
7823         }
7824         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7825             (fs->super->s_inodes_count >
7826              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7827                 pctx.num = 4;
7828                 pctx.blk = 1;
7829                 pctx.blk2 = fs->super->s_inodes_count;
7830                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7831                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7832                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7833
7834                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7835                 return;
7836         }
7837
7838 redo_counts:
7839         had_problem = 0;
7840         save_problem = 0;
7841         pctx.ino = pctx.ino2 = 0;
7842         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7843                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7844                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7845
7846                 if (actual == bitmap)
7847                         goto do_counts;
7848
7849                 if (!actual && bitmap) {
7850                         /*
7851                          * Inode wasn't used, but marked in bitmap
7852                          */
7853                         problem = PR_5_INODE_UNUSED;
7854                 } else /* if (actual && !bitmap) */ {
7855                         /*
7856                          * Inode used, but not in bitmap
7857                          */
7858                         problem = PR_5_INODE_USED;
7859                 }
7860                 if (pctx.ino == 0) {
7861                         pctx.ino = pctx.ino2 = i;
7862                         save_problem = problem;
7863                 } else {
7864                         if ((problem == save_problem) &&
7865                             (pctx.ino2 == i-1))
7866                                 pctx.ino2++;
7867                         else {
7868                                 print_bitmap_problem(ctx, save_problem, &pctx);
7869                                 pctx.ino = pctx.ino2 = i;
7870                                 save_problem = problem;
7871                         }
7872                 }
7873                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7874                 had_problem++;
7875
7876 do_counts:
7877                 if (!bitmap) {
7878                         group_free++;
7879                         free_inodes++;
7880                 } else {
7881                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7882                                 dirs_count++;
7883                 }
7884                 inodes++;
7885                 if ((inodes == fs->super->s_inodes_per_group) ||
7886                     (i == fs->super->s_inodes_count)) {
7887                         free_array[group] = group_free;
7888                         dir_array[group] = dirs_count;
7889                         group ++;
7890                         inodes = 0;
7891                         group_free = 0;
7892                         dirs_count = 0;
7893                         if (ctx->progress)
7894                                 if ((ctx->progress)(ctx, 5,
7895                                             group + fs->group_desc_count,
7896                                             fs->group_desc_count*2))
7897                                         return;
7898                 }
7899         }
7900         if (pctx.ino)
7901                 print_bitmap_problem(ctx, save_problem, &pctx);
7902
7903         if (had_problem)
7904                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7905         else
7906                 fixit = -1;
7907         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7908
7909         if (fixit == 1) {
7910                 ext2fs_free_inode_bitmap(fs->inode_map);
7911                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7912                                                   &fs->inode_map);
7913                 if (retval) {
7914                         clear_problem_context(&pctx);
7915                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7916                         ctx->flags |= E2F_FLAG_ABORT;
7917                         return;
7918                 }
7919                 ext2fs_set_bitmap_padding(fs->inode_map);
7920                 ext2fs_mark_ib_dirty(fs);
7921
7922                 /* redo counts */
7923                 inodes = 0; free_inodes = 0; group_free = 0;
7924                 dirs_count = 0; group = 0;
7925                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7926                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7927                 goto redo_counts;
7928         } else if (fixit == 0)
7929                 ext2fs_unmark_valid(fs);
7930
7931         for (i = 0; i < fs->group_desc_count; i++) {
7932                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7933                         pctx.group = i;
7934                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7935                         pctx.ino2 = free_array[i];
7936                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7937                                         &pctx)) {
7938                                 fs->group_desc[i].bg_free_inodes_count =
7939                                         free_array[i];
7940                                 ext2fs_mark_super_dirty(fs);
7941                         } else
7942                                 ext2fs_unmark_valid(fs);
7943                 }
7944                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7945                         pctx.group = i;
7946                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7947                         pctx.ino2 = dir_array[i];
7948
7949                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7950                                         &pctx)) {
7951                                 fs->group_desc[i].bg_used_dirs_count =
7952                                         dir_array[i];
7953                                 ext2fs_mark_super_dirty(fs);
7954                         } else
7955                                 ext2fs_unmark_valid(fs);
7956                 }
7957         }
7958         if (free_inodes != fs->super->s_free_inodes_count) {
7959                 pctx.group = -1;
7960                 pctx.ino = fs->super->s_free_inodes_count;
7961                 pctx.ino2 = free_inodes;
7962
7963                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7964                         fs->super->s_free_inodes_count = free_inodes;
7965                         ext2fs_mark_super_dirty(fs);
7966                 } else
7967                         ext2fs_unmark_valid(fs);
7968         }
7969         ext2fs_free_mem(&free_array);
7970         ext2fs_free_mem(&dir_array);
7971 }
7972
7973 static void check_inode_end(e2fsck_t ctx)
7974 {
7975         ext2_filsys fs = ctx->fs;
7976         ext2_ino_t      end, save_inodes_count, i;
7977         struct problem_context  pctx;
7978
7979         clear_problem_context(&pctx);
7980
7981         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7982         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7983                                                      &save_inodes_count);
7984         if (pctx.errcode) {
7985                 pctx.num = 1;
7986                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7987                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7988                 return;
7989         }
7990         if (save_inodes_count == end)
7991                 return;
7992
7993         for (i = save_inodes_count + 1; i <= end; i++) {
7994                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
7995                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
7996                                 for (i = save_inodes_count + 1; i <= end; i++)
7997                                         ext2fs_mark_inode_bitmap(fs->inode_map,
7998                                                                  i);
7999                                 ext2fs_mark_ib_dirty(fs);
8000                         } else
8001                                 ext2fs_unmark_valid(fs);
8002                         break;
8003                 }
8004         }
8005
8006         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8007                                                      save_inodes_count, 0);
8008         if (pctx.errcode) {
8009                 pctx.num = 2;
8010                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8011                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8012                 return;
8013         }
8014 }
8015
8016 static void check_block_end(e2fsck_t ctx)
8017 {
8018         ext2_filsys fs = ctx->fs;
8019         blk_t   end, save_blocks_count, i;
8020         struct problem_context  pctx;
8021
8022         clear_problem_context(&pctx);
8023
8024         end = fs->block_map->start +
8025                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8026         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8027                                                      &save_blocks_count);
8028         if (pctx.errcode) {
8029                 pctx.num = 3;
8030                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8031                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8032                 return;
8033         }
8034         if (save_blocks_count == end)
8035                 return;
8036
8037         for (i = save_blocks_count + 1; i <= end; i++) {
8038                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8039                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8040                                 for (i = save_blocks_count + 1; i <= end; i++)
8041                                         ext2fs_mark_block_bitmap(fs->block_map,
8042                                                                  i);
8043                                 ext2fs_mark_bb_dirty(fs);
8044                         } else
8045                                 ext2fs_unmark_valid(fs);
8046                         break;
8047                 }
8048         }
8049
8050         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8051                                                      save_blocks_count, 0);
8052         if (pctx.errcode) {
8053                 pctx.num = 4;
8054                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8055                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8056                 return;
8057         }
8058 }
8059
8060 static void e2fsck_pass5(e2fsck_t ctx)
8061 {
8062         struct problem_context  pctx;
8063
8064         /* Pass 5 */
8065
8066         clear_problem_context(&pctx);
8067
8068         if (!(ctx->options & E2F_OPT_PREEN))
8069                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8070
8071         if (ctx->progress)
8072                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8073                         return;
8074
8075         e2fsck_read_bitmaps(ctx);
8076
8077         check_block_bitmaps(ctx);
8078         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8079                 return;
8080         check_inode_bitmaps(ctx);
8081         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8082                 return;
8083         check_inode_end(ctx);
8084         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8085                 return;
8086         check_block_end(ctx);
8087         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8088                 return;
8089
8090         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8091         ctx->inode_used_map = 0;
8092         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8093         ctx->inode_dir_map = 0;
8094         ext2fs_free_block_bitmap(ctx->block_found_map);
8095         ctx->block_found_map = 0;
8096 }
8097
8098 /*
8099  * problem.c --- report filesystem problems to the user
8100  */
8101
8102 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8103 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8104 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8105 #define PR_MSG_ONLY     0x000008 /* Print message only */
8106
8107 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8108
8109 #define PR_FATAL        0x001000 /* Fatal error */
8110 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8111                                  /* ask another */
8112 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8113 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8114 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8115 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8116 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8117
8118
8119 #define PROMPT_NONE     0
8120 #define PROMPT_FIX      1
8121 #define PROMPT_CLEAR    2
8122 #define PROMPT_RELOCATE 3
8123 #define PROMPT_ALLOCATE 4
8124 #define PROMPT_EXPAND   5
8125 #define PROMPT_CONNECT  6
8126 #define PROMPT_CREATE   7
8127 #define PROMPT_SALVAGE  8
8128 #define PROMPT_TRUNCATE 9
8129 #define PROMPT_CLEAR_INODE 10
8130 #define PROMPT_ABORT    11
8131 #define PROMPT_SPLIT    12
8132 #define PROMPT_CONTINUE 13
8133 #define PROMPT_CLONE    14
8134 #define PROMPT_DELETE   15
8135 #define PROMPT_SUPPRESS 16
8136 #define PROMPT_UNLINK   17
8137 #define PROMPT_CLEAR_HTREE 18
8138 #define PROMPT_RECREATE 19
8139 #define PROMPT_NULL     20
8140
8141 struct e2fsck_problem {
8142         problem_t       e2p_code;
8143         const char *    e2p_description;
8144         char            prompt;
8145         int             flags;
8146         problem_t       second_code;
8147 };
8148
8149 struct latch_descr {
8150         int             latch_code;
8151         problem_t       question;
8152         problem_t       end_message;
8153         int             flags;
8154 };
8155
8156 /*
8157  * These are the prompts which are used to ask the user if they want
8158  * to fix a problem.
8159  */
8160 static const char *const prompt[] = {
8161         N_("(no prompt)"),      /* 0 */
8162         N_("Fix"),              /* 1 */
8163         N_("Clear"),            /* 2 */
8164         N_("Relocate"),         /* 3 */
8165         N_("Allocate"),         /* 4 */
8166         N_("Expand"),           /* 5 */
8167         N_("Connect to /lost+found"), /* 6 */
8168         N_("Create"),           /* 7 */
8169         N_("Salvage"),          /* 8 */
8170         N_("Truncate"),         /* 9 */
8171         N_("Clear inode"),      /* 10 */
8172         N_("Abort"),            /* 11 */
8173         N_("Split"),            /* 12 */
8174         N_("Continue"),         /* 13 */
8175         N_("Clone multiply-claimed blocks"), /* 14 */
8176         N_("Delete file"),      /* 15 */
8177         N_("Suppress messages"),/* 16 */
8178         N_("Unlink"),           /* 17 */
8179         N_("Clear HTree index"),/* 18 */
8180         N_("Recreate"),         /* 19 */
8181         "",                     /* 20 */
8182 };
8183
8184 /*
8185  * These messages are printed when we are preen mode and we will be
8186  * automatically fixing the problem.
8187  */
8188 static const char *const preen_msg[] = {
8189         N_("(NONE)"),           /* 0 */
8190         N_("FIXED"),            /* 1 */
8191         N_("CLEARED"),          /* 2 */
8192         N_("RELOCATED"),        /* 3 */
8193         N_("ALLOCATED"),        /* 4 */
8194         N_("EXPANDED"),         /* 5 */
8195         N_("RECONNECTED"),      /* 6 */
8196         N_("CREATED"),          /* 7 */
8197         N_("SALVAGED"),         /* 8 */
8198         N_("TRUNCATED"),        /* 9 */
8199         N_("INODE CLEARED"),    /* 10 */
8200         N_("ABORTED"),          /* 11 */
8201         N_("SPLIT"),            /* 12 */
8202         N_("CONTINUING"),       /* 13 */
8203         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8204         N_("FILE DELETED"),     /* 15 */
8205         N_("SUPPRESSED"),       /* 16 */
8206         N_("UNLINKED"),         /* 17 */
8207         N_("HTREE INDEX CLEARED"),/* 18 */
8208         N_("WILL RECREATE"),    /* 19 */
8209         "",                     /* 20 */
8210 };
8211
8212 static const struct e2fsck_problem problem_table[] = {
8213
8214         /* Pre-Pass 1 errors */
8215
8216         /* Block bitmap not in group */
8217         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8218           PROMPT_RELOCATE, PR_LATCH_RELOC },
8219
8220         /* Inode bitmap not in group */
8221         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8222           PROMPT_RELOCATE, PR_LATCH_RELOC },
8223
8224         /* Inode table not in group */
8225         { PR_0_ITABLE_NOT_GROUP,
8226           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8227           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8228           PROMPT_RELOCATE, PR_LATCH_RELOC },
8229
8230         /* Superblock corrupt */
8231         { PR_0_SB_CORRUPT,
8232           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8233           "@f.  If the @v is valid and it really contains an ext2\n"
8234           "@f (and not swap or ufs or something else), then the @S\n"
8235           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8236           "    e2fsck -b %S <@v>\n\n"),
8237           PROMPT_NONE, PR_FATAL },
8238
8239         /* Filesystem size is wrong */
8240         { PR_0_FS_SIZE_WRONG,
8241           N_("The @f size (according to the @S) is %b @bs\n"
8242           "The physical size of the @v is %c @bs\n"
8243           "Either the @S or the partition table is likely to be corrupt!\n"),
8244           PROMPT_ABORT, 0 },
8245
8246         /* Fragments not supported */
8247         { PR_0_NO_FRAGMENTS,
8248           N_("@S @b_size = %b, fragsize = %c.\n"
8249           "This version of e2fsck does not support fragment sizes different\n"
8250           "from the @b size.\n"),
8251           PROMPT_NONE, PR_FATAL },
8252
8253           /* Bad blocks_per_group */
8254         { PR_0_BLOCKS_PER_GROUP,
8255           N_("@S @bs_per_group = %b, should have been %c\n"),
8256           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8257
8258         /* Bad first_data_block */
8259         { PR_0_FIRST_DATA_BLOCK,
8260           N_("@S first_data_@b = %b, should have been %c\n"),
8261           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8262
8263         /* Adding UUID to filesystem */
8264         { PR_0_ADD_UUID,
8265           N_("@f did not have a UUID; generating one.\n\n"),
8266           PROMPT_NONE, 0 },
8267
8268         /* Relocate hint */
8269         { PR_0_RELOCATE_HINT,
8270           N_("Note: if several inode or block bitmap blocks or part\n"
8271           "of the inode table require relocation, you may wish to try\n"
8272           "running e2fsck with the '-b %S' option first.  The problem\n"
8273           "may lie only with the primary block group descriptors, and\n"
8274           "the backup block group descriptors may be OK.\n\n"),
8275           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8276
8277         /* Miscellaneous superblock corruption */
8278         { PR_0_MISC_CORRUPT_SUPER,
8279           N_("Corruption found in @S.  (%s = %N).\n"),
8280           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8281
8282         /* Error determing physical device size of filesystem */
8283         { PR_0_GETSIZE_ERROR,
8284           N_("Error determining size of the physical @v: %m\n"),
8285           PROMPT_NONE, PR_FATAL },
8286
8287         /* Inode count in superblock is incorrect */
8288         { PR_0_INODE_COUNT_WRONG,
8289           N_("@i count in @S is %i, @s %j.\n"),
8290           PROMPT_FIX, 0 },
8291
8292         { PR_0_HURD_CLEAR_FILETYPE,
8293           N_("The Hurd does not support the filetype feature.\n"),
8294           PROMPT_CLEAR, 0 },
8295
8296         /* Journal inode is invalid */
8297         { PR_0_JOURNAL_BAD_INODE,
8298           N_("@S has an @n ext3 @j (@i %i).\n"),
8299           PROMPT_CLEAR, PR_PREEN_OK },
8300
8301         /* The external journal has (unsupported) multiple filesystems */
8302         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8303           N_("External @j has multiple @f users (unsupported).\n"),
8304           PROMPT_NONE, PR_FATAL },
8305
8306         /* Can't find external journal */
8307         { PR_0_CANT_FIND_JOURNAL,
8308           N_("Can't find external @j\n"),
8309           PROMPT_NONE, PR_FATAL },
8310
8311         /* External journal has bad superblock */
8312         { PR_0_EXT_JOURNAL_BAD_SUPER,
8313           N_("External @j has bad @S\n"),
8314           PROMPT_NONE, PR_FATAL },
8315
8316         /* Superblock has a bad journal UUID */
8317         { PR_0_JOURNAL_BAD_UUID,
8318           N_("External @j does not support this @f\n"),
8319           PROMPT_NONE, PR_FATAL },
8320
8321         /* Journal has an unknown superblock type */
8322         { PR_0_JOURNAL_UNSUPP_SUPER,
8323           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8324              "It is likely that your copy of e2fsck is old and/or doesn't "
8325              "support this @j format.\n"
8326              "It is also possible the @j @S is corrupt.\n"),
8327           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8328
8329         /* Journal superblock is corrupt */
8330         { PR_0_JOURNAL_BAD_SUPER,
8331           N_("Ext3 @j @S is corrupt.\n"),
8332           PROMPT_FIX, PR_PREEN_OK },
8333
8334         /* Superblock flag should be cleared */
8335         { PR_0_JOURNAL_HAS_JOURNAL,
8336           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8337           PROMPT_CLEAR, PR_PREEN_OK },
8338
8339         /* Superblock flag is incorrect */
8340         { PR_0_JOURNAL_RECOVER_SET,
8341           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8342           PROMPT_CLEAR, PR_PREEN_OK },
8343
8344         /* Journal has data, but recovery flag is clear */
8345         { PR_0_JOURNAL_RECOVERY_CLEAR,
8346           N_("ext3 recovery flag is clear, but @j has data.\n"),
8347           PROMPT_NONE, 0 },
8348
8349         /* Ask if we should clear the journal */
8350         { PR_0_JOURNAL_RESET_JOURNAL,
8351           N_("Clear @j"),
8352           PROMPT_NULL, PR_PREEN_NOMSG },
8353
8354         /* Ask if we should run the journal anyway */
8355         { PR_0_JOURNAL_RUN,
8356           N_("Run @j anyway"),
8357           PROMPT_NULL, 0 },
8358
8359         /* Run the journal by default */
8360         { PR_0_JOURNAL_RUN_DEFAULT,
8361           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8362           PROMPT_NONE, 0 },
8363
8364         /* Clearing orphan inode */
8365         { PR_0_ORPHAN_CLEAR_INODE,
8366           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8367           PROMPT_NONE, 0 },
8368
8369         /* Illegal block found in orphaned inode */
8370         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8371            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8372           PROMPT_NONE, 0 },
8373
8374         /* Already cleared block found in orphaned inode */
8375         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8376            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8377           PROMPT_NONE, 0 },
8378
8379         /* Illegal orphan inode in superblock */
8380         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8381           N_("@I @o @i %i in @S.\n"),
8382           PROMPT_NONE, 0 },
8383
8384         /* Illegal inode in orphaned inode list */
8385         { PR_0_ORPHAN_ILLEGAL_INODE,
8386           N_("@I @i %i in @o @i list.\n"),
8387           PROMPT_NONE, 0 },
8388
8389         /* Filesystem revision is 0, but feature flags are set */
8390         { PR_0_FS_REV_LEVEL,
8391           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8392           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8393
8394         /* Journal superblock has an unknown read-only feature flag set */
8395         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8396           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8397           PROMPT_ABORT, 0 },
8398
8399         /* Journal superblock has an unknown incompatible feature flag set */
8400         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8401           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8402           PROMPT_ABORT, 0 },
8403
8404         /* Journal has unsupported version number */
8405         { PR_0_JOURNAL_UNSUPP_VERSION,
8406           N_("@j version not supported by this e2fsck.\n"),
8407           PROMPT_ABORT, 0 },
8408
8409         /* Moving journal to hidden file */
8410         { PR_0_MOVE_JOURNAL,
8411           N_("Moving @j from /%s to hidden @i.\n\n"),
8412           PROMPT_NONE, 0 },
8413
8414         /* Error moving journal to hidden file */
8415         { PR_0_ERR_MOVE_JOURNAL,
8416           N_("Error moving @j: %m\n\n"),
8417           PROMPT_NONE, 0 },
8418
8419         /* Clearing V2 journal superblock */
8420         { PR_0_CLEAR_V2_JOURNAL,
8421           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8422              "Clearing fields beyond the V1 @j @S...\n\n"),
8423           PROMPT_NONE, 0 },
8424
8425         /* Backup journal inode blocks */
8426         { PR_0_BACKUP_JNL,
8427           N_("Backing up @j @i @b information.\n\n"),
8428           PROMPT_NONE, 0 },
8429
8430         /* Reserved blocks w/o resize_inode */
8431         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8432           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8433              "is %N; @s zero.  "),
8434           PROMPT_FIX, 0 },
8435
8436         /* Resize_inode not enabled, but resize inode is non-zero */
8437         { PR_0_CLEAR_RESIZE_INODE,
8438           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8439           PROMPT_CLEAR, 0 },
8440
8441         /* Resize inode invalid */
8442         { PR_0_RESIZE_INODE_INVALID,
8443           N_("Resize @i not valid.  "),
8444           PROMPT_RECREATE, 0 },
8445
8446         /* Pass 1 errors */
8447
8448         /* Pass 1: Checking inodes, blocks, and sizes */
8449         { PR_1_PASS_HEADER,
8450           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8451           PROMPT_NONE, 0 },
8452
8453         /* Root directory is not an inode */
8454         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8455           PROMPT_CLEAR, 0 },
8456
8457         /* Root directory has dtime set */
8458         { PR_1_ROOT_DTIME,
8459           N_("@r has dtime set (probably due to old mke2fs).  "),
8460           PROMPT_FIX, PR_PREEN_OK },
8461
8462         /* Reserved inode has bad mode */
8463         { PR_1_RESERVED_BAD_MODE,
8464           N_("Reserved @i %i (%Q) has @n mode.  "),
8465           PROMPT_CLEAR, PR_PREEN_OK },
8466
8467         /* Deleted inode has zero dtime */
8468         { PR_1_ZERO_DTIME,
8469           N_("@D @i %i has zero dtime.  "),
8470           PROMPT_FIX, PR_PREEN_OK },
8471
8472         /* Inode in use, but dtime set */
8473         { PR_1_SET_DTIME,
8474           N_("@i %i is in use, but has dtime set.  "),
8475           PROMPT_FIX, PR_PREEN_OK },
8476
8477         /* Zero-length directory */
8478         { PR_1_ZERO_LENGTH_DIR,
8479           N_("@i %i is a @z @d.  "),
8480           PROMPT_CLEAR, PR_PREEN_OK },
8481
8482         /* Block bitmap conflicts with some other fs block */
8483         { PR_1_BB_CONFLICT,
8484           N_("@g %g's @b @B at %b @C.\n"),
8485           PROMPT_RELOCATE, 0 },
8486
8487         /* Inode bitmap conflicts with some other fs block */
8488         { PR_1_IB_CONFLICT,
8489           N_("@g %g's @i @B at %b @C.\n"),
8490           PROMPT_RELOCATE, 0 },
8491
8492         /* Inode table conflicts with some other fs block */
8493         { PR_1_ITABLE_CONFLICT,
8494           N_("@g %g's @i table at %b @C.\n"),
8495           PROMPT_RELOCATE, 0 },
8496
8497         /* Block bitmap is on a bad block */
8498         { PR_1_BB_BAD_BLOCK,
8499           N_("@g %g's @b @B (%b) is bad.  "),
8500           PROMPT_RELOCATE, 0 },
8501
8502         /* Inode bitmap is on a bad block */
8503         { PR_1_IB_BAD_BLOCK,
8504           N_("@g %g's @i @B (%b) is bad.  "),
8505           PROMPT_RELOCATE, 0 },
8506
8507         /* Inode has incorrect i_size */
8508         { PR_1_BAD_I_SIZE,
8509           N_("@i %i, i_size is %Is, @s %N.  "),
8510           PROMPT_FIX, PR_PREEN_OK },
8511
8512         /* Inode has incorrect i_blocks */
8513         { PR_1_BAD_I_BLOCKS,
8514           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8515           PROMPT_FIX, PR_PREEN_OK },
8516
8517         /* Illegal blocknumber in inode */
8518         { PR_1_ILLEGAL_BLOCK_NUM,
8519           N_("@I @b #%B (%b) in @i %i.  "),
8520           PROMPT_CLEAR, PR_LATCH_BLOCK },
8521
8522         /* Block number overlaps fs metadata */
8523         { PR_1_BLOCK_OVERLAPS_METADATA,
8524           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8525           PROMPT_CLEAR, PR_LATCH_BLOCK },
8526
8527         /* Inode has illegal blocks (latch question) */
8528         { PR_1_INODE_BLOCK_LATCH,
8529           N_("@i %i has illegal @b(s).  "),
8530           PROMPT_CLEAR, 0 },
8531
8532         /* Too many bad blocks in inode */
8533         { PR_1_TOO_MANY_BAD_BLOCKS,
8534           N_("Too many illegal @bs in @i %i.\n"),
8535           PROMPT_CLEAR_INODE, PR_NO_OK },
8536
8537         /* Illegal block number in bad block inode */
8538         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8539           N_("@I @b #%B (%b) in bad @b @i.  "),
8540           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8541
8542         /* Bad block inode has illegal blocks (latch question) */
8543         { PR_1_INODE_BBLOCK_LATCH,
8544           N_("Bad @b @i has illegal @b(s).  "),
8545           PROMPT_CLEAR, 0 },
8546
8547         /* Duplicate or bad blocks in use! */
8548         { PR_1_DUP_BLOCKS_PREENSTOP,
8549           N_("Duplicate or bad @b in use!\n"),
8550           PROMPT_NONE, 0 },
8551
8552         /* Bad block used as bad block indirect block */
8553         { PR_1_BBINODE_BAD_METABLOCK,
8554           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8555           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8556
8557         /* Inconsistency can't be fixed prompt */
8558         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8559           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8560              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8561              "in the @f.\n"),
8562           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8563
8564         /* Bad primary block */
8565         { PR_1_BAD_PRIMARY_BLOCK,
8566           N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8567           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8568
8569         /* Bad primary block prompt */
8570         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8571           N_("You can remove this @b from the bad @b list and hope\n"
8572              "that the @b is really OK.  But there are no guarantees.\n\n"),
8573           PROMPT_CLEAR, PR_PREEN_NOMSG },
8574
8575         /* Bad primary superblock */
8576         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8577           N_("The primary @S (%b) is on the bad @b list.\n"),
8578           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8579
8580         /* Bad primary block group descriptors */
8581         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8582           N_("Block %b in the primary @g descriptors "
8583           "is on the bad @b list\n"),
8584           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8585
8586         /* Bad superblock in group */
8587         { PR_1_BAD_SUPERBLOCK,
8588           N_("Warning: Group %g's @S (%b) is bad.\n"),
8589           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8590
8591         /* Bad block group descriptors in group */
8592         { PR_1_BAD_GROUP_DESCRIPTORS,
8593           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8594           "@b (%b).\n"),
8595           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8596
8597         /* Block claimed for no reason */
8598         { PR_1_PROGERR_CLAIMED_BLOCK,
8599           N_("Programming error?  @b #%b claimed for no reason in "
8600           "process_bad_@b.\n"),
8601           PROMPT_NONE, PR_PREEN_OK },
8602
8603         /* Error allocating blocks for relocating metadata */
8604         { PR_1_RELOC_BLOCK_ALLOCATE,
8605           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8606           PROMPT_NONE, PR_PREEN_OK },
8607
8608         /* Error allocating block buffer during relocation process */
8609         { PR_1_RELOC_MEMORY_ALLOCATE,
8610           N_("@A @b buffer for relocating %s\n"),
8611           PROMPT_NONE, PR_PREEN_OK },
8612
8613         /* Relocating metadata group information from X to Y */
8614         { PR_1_RELOC_FROM_TO,
8615           N_("Relocating @g %g's %s from %b to %c...\n"),
8616           PROMPT_NONE, PR_PREEN_OK },
8617
8618         /* Relocating metatdata group information to X */
8619         { PR_1_RELOC_TO,
8620           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8621           PROMPT_NONE, PR_PREEN_OK },
8622
8623         /* Block read error during relocation process */
8624         { PR_1_RELOC_READ_ERR,
8625           N_("Warning: could not read @b %b of %s: %m\n"),
8626           PROMPT_NONE, PR_PREEN_OK },
8627
8628         /* Block write error during relocation process */
8629         { PR_1_RELOC_WRITE_ERR,
8630           N_("Warning: could not write @b %b for %s: %m\n"),
8631           PROMPT_NONE, PR_PREEN_OK },
8632
8633         /* Error allocating inode bitmap */
8634         { PR_1_ALLOCATE_IBITMAP_ERROR,
8635           N_("@A @i @B (%N): %m\n"),
8636           PROMPT_NONE, PR_FATAL },
8637
8638         /* Error allocating block bitmap */
8639         { PR_1_ALLOCATE_BBITMAP_ERROR,
8640           N_("@A @b @B (%N): %m\n"),
8641           PROMPT_NONE, PR_FATAL },
8642
8643         /* Error allocating icount structure */
8644         { PR_1_ALLOCATE_ICOUNT,
8645           N_("@A icount link information: %m\n"),
8646           PROMPT_NONE, PR_FATAL },
8647
8648         /* Error allocating dbcount */
8649         { PR_1_ALLOCATE_DBCOUNT,
8650           N_("@A @d @b array: %m\n"),
8651           PROMPT_NONE, PR_FATAL },
8652
8653         /* Error while scanning inodes */
8654         { PR_1_ISCAN_ERROR,
8655           N_("Error while scanning @is (%i): %m\n"),
8656           PROMPT_NONE, PR_FATAL },
8657
8658         /* Error while iterating over blocks */
8659         { PR_1_BLOCK_ITERATE,
8660           N_("Error while iterating over @bs in @i %i: %m\n"),
8661           PROMPT_NONE, PR_FATAL },
8662
8663         /* Error while storing inode count information */
8664         { PR_1_ICOUNT_STORE,
8665           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8666           PROMPT_NONE, PR_FATAL },
8667
8668         /* Error while storing directory block information */
8669         { PR_1_ADD_DBLOCK,
8670           N_("Error storing @d @b information "
8671           "(@i=%i, @b=%b, num=%N): %m\n"),
8672           PROMPT_NONE, PR_FATAL },
8673
8674         /* Error while reading inode (for clearing) */
8675         { PR_1_READ_INODE,
8676           N_("Error reading @i %i: %m\n"),
8677           PROMPT_NONE, PR_FATAL },
8678
8679         /* Suppress messages prompt */
8680         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8681
8682         /* Imagic flag set on an inode when filesystem doesn't support it */
8683         { PR_1_SET_IMAGIC,
8684           N_("@i %i has imagic flag set.  "),
8685           PROMPT_CLEAR, 0 },
8686
8687         /* Immutable flag set on a device or socket inode */
8688         { PR_1_SET_IMMUTABLE,
8689           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8690              "or append-only flag set.  "),
8691           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8692
8693         /* Compression flag set on an inode when filesystem doesn't support it */
8694         { PR_1_COMPR_SET,
8695           N_("@i %i has @cion flag set on @f without @cion support.  "),
8696           PROMPT_CLEAR, 0 },
8697
8698         /* Non-zero size for device, fifo or socket inode */
8699         { PR_1_SET_NONZSIZE,
8700           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8701           PROMPT_FIX, PR_PREEN_OK },
8702
8703         /* Filesystem revision is 0, but feature flags are set */
8704         { PR_1_FS_REV_LEVEL,
8705           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8706           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8707
8708         /* Journal inode is not in use, but contains data */
8709         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8710           N_("@j @i is not in use, but contains data.  "),
8711           PROMPT_CLEAR, PR_PREEN_OK },
8712
8713         /* Journal has bad mode */
8714         { PR_1_JOURNAL_BAD_MODE,
8715           N_("@j is not regular file.  "),
8716           PROMPT_FIX, PR_PREEN_OK },
8717
8718         /* Deal with inodes that were part of orphan linked list */
8719         { PR_1_LOW_DTIME,
8720           N_("@i %i was part of the @o @i list.  "),
8721           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8722
8723         /* Deal with inodes that were part of corrupted orphan linked
8724            list (latch question) */
8725         { PR_1_ORPHAN_LIST_REFUGEES,
8726           N_("@is that were part of a corrupted orphan linked list found.  "),
8727           PROMPT_FIX, 0 },
8728
8729         /* Error allocating refcount structure */
8730         { PR_1_ALLOCATE_REFCOUNT,
8731           N_("@A refcount structure (%N): %m\n"),
8732           PROMPT_NONE, PR_FATAL },
8733
8734         /* Error reading extended attribute block */
8735         { PR_1_READ_EA_BLOCK,
8736           N_("Error reading @a @b %b for @i %i.  "),
8737           PROMPT_CLEAR, 0 },
8738
8739         /* Invalid extended attribute block */
8740         { PR_1_BAD_EA_BLOCK,
8741           N_("@i %i has a bad @a @b %b.  "),
8742           PROMPT_CLEAR, 0 },
8743
8744         /* Error reading Extended Attribute block while fixing refcount */
8745         { PR_1_EXTATTR_READ_ABORT,
8746           N_("Error reading @a @b %b (%m).  "),
8747           PROMPT_ABORT, 0 },
8748
8749         /* Extended attribute reference count incorrect */
8750         { PR_1_EXTATTR_REFCOUNT,
8751           N_("@a @b %b has reference count %B, @s %N.  "),
8752           PROMPT_FIX, 0 },
8753
8754         /* Error writing Extended Attribute block while fixing refcount */
8755         { PR_1_EXTATTR_WRITE,
8756           N_("Error writing @a @b %b (%m).  "),
8757           PROMPT_ABORT, 0 },
8758
8759         /* Multiple EA blocks not supported */
8760         { PR_1_EA_MULTI_BLOCK,
8761           N_("@a @b %b has h_@bs > 1.  "),
8762           PROMPT_CLEAR, 0},
8763
8764         /* Error allocating EA region allocation structure */
8765         { PR_1_EA_ALLOC_REGION,
8766           N_("@A @a @b %b.  "),
8767           PROMPT_ABORT, 0},
8768
8769         /* Error EA allocation collision */
8770         { PR_1_EA_ALLOC_COLLISION,
8771           N_("@a @b %b is corrupt (allocation collision).  "),
8772           PROMPT_CLEAR, 0},
8773
8774         /* Bad extended attribute name */
8775         { PR_1_EA_BAD_NAME,
8776           N_("@a @b %b is corrupt (@n name).  "),
8777           PROMPT_CLEAR, 0},
8778
8779         /* Bad extended attribute value */
8780         { PR_1_EA_BAD_VALUE,
8781           N_("@a @b %b is corrupt (@n value).  "),
8782           PROMPT_CLEAR, 0},
8783
8784         /* Inode too big (latch question) */
8785         { PR_1_INODE_TOOBIG,
8786           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8787
8788         /* Directory too big */
8789         { PR_1_TOOBIG_DIR,
8790           N_("@b #%B (%b) causes @d to be too big.  "),
8791           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8792
8793         /* Regular file too big */
8794         { PR_1_TOOBIG_REG,
8795           N_("@b #%B (%b) causes file to be too big.  "),
8796           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8797
8798         /* Symlink too big */
8799         { PR_1_TOOBIG_SYMLINK,
8800           N_("@b #%B (%b) causes symlink to be too big.  "),
8801           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8802
8803         /* INDEX_FL flag set on a non-HTREE filesystem */
8804         { PR_1_HTREE_SET,
8805           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8806           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8807
8808         /* INDEX_FL flag set on a non-directory */
8809         { PR_1_HTREE_NODIR,
8810           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8811           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8812
8813         /* Invalid root node in HTREE directory */
8814         { PR_1_HTREE_BADROOT,
8815           N_("@h %i has an @n root node.\n"),
8816           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8817
8818         /* Unsupported hash version in HTREE directory */
8819         { PR_1_HTREE_HASHV,
8820           N_("@h %i has an unsupported hash version (%N)\n"),
8821           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8822
8823         /* Incompatible flag in HTREE root node */
8824         { PR_1_HTREE_INCOMPAT,
8825           N_("@h %i uses an incompatible htree root node flag.\n"),
8826           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8827
8828         /* HTREE too deep */
8829         { PR_1_HTREE_DEPTH,
8830           N_("@h %i has a tree depth (%N) which is too big\n"),
8831           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8832
8833         /* Bad block has indirect block that conflicts with filesystem block */
8834         { PR_1_BB_FS_BLOCK,
8835           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8836              "@f metadata.  "),
8837           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8838
8839         /* Resize inode failed */
8840         { PR_1_RESIZE_INODE_CREATE,
8841           N_("Resize @i (re)creation failed: %m."),
8842           PROMPT_ABORT, 0 },
8843
8844         /* invalid inode->i_extra_isize */
8845         { PR_1_EXTRA_ISIZE,
8846           N_("@i %i has a extra size (%IS) which is @n\n"),
8847           PROMPT_FIX, PR_PREEN_OK },
8848
8849         /* invalid ea entry->e_name_len */
8850         { PR_1_ATTR_NAME_LEN,
8851           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8852           PROMPT_CLEAR, PR_PREEN_OK },
8853
8854         /* invalid ea entry->e_value_size */
8855         { PR_1_ATTR_VALUE_SIZE,
8856           N_("@a in @i %i has a value size (%N) which is @n\n"),
8857           PROMPT_CLEAR, PR_PREEN_OK },
8858
8859         /* invalid ea entry->e_value_offs */
8860         { PR_1_ATTR_VALUE_OFFSET,
8861           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8862           PROMPT_CLEAR, PR_PREEN_OK },
8863
8864         /* invalid ea entry->e_value_block */
8865         { PR_1_ATTR_VALUE_BLOCK,
8866           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8867           PROMPT_CLEAR, PR_PREEN_OK },
8868
8869         /* invalid ea entry->e_hash */
8870         { PR_1_ATTR_HASH,
8871           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8872           PROMPT_CLEAR, PR_PREEN_OK },
8873
8874         /* Pass 1b errors */
8875
8876         /* Pass 1B: Rescan for duplicate/bad blocks */
8877         { PR_1B_PASS_HEADER,
8878           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8879           "Pass 1B: Rescanning for @m @bs\n"),
8880           PROMPT_NONE, 0 },
8881
8882         /* Duplicate/bad block(s) header */
8883         { PR_1B_DUP_BLOCK_HEADER,
8884           N_("@m @b(s) in @i %i:"),
8885           PROMPT_NONE, 0 },
8886
8887         /* Duplicate/bad block(s) in inode */
8888         { PR_1B_DUP_BLOCK,
8889           " %b",
8890           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8891
8892         /* Duplicate/bad block(s) end */
8893         { PR_1B_DUP_BLOCK_END,
8894           "\n",
8895           PROMPT_NONE, PR_PREEN_NOHDR },
8896
8897         /* Error while scanning inodes */
8898         { PR_1B_ISCAN_ERROR,
8899           N_("Error while scanning inodes (%i): %m\n"),
8900           PROMPT_NONE, PR_FATAL },
8901
8902         /* Error allocating inode bitmap */
8903         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8904           N_("@A @i @B (@i_dup_map): %m\n"),
8905           PROMPT_NONE, PR_FATAL },
8906
8907         /* Error while iterating over blocks */
8908         { PR_1B_BLOCK_ITERATE,
8909           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8910           PROMPT_NONE, 0 },
8911
8912         /* Error adjusting EA refcount */
8913         { PR_1B_ADJ_EA_REFCOUNT,
8914           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8915           PROMPT_NONE, 0 },
8916
8917
8918         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8919         { PR_1C_PASS_HEADER,
8920           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8921           PROMPT_NONE, 0 },
8922
8923
8924         /* Pass 1D: Reconciling multiply-claimed blocks */
8925         { PR_1D_PASS_HEADER,
8926           N_("Pass 1D: Reconciling @m @bs\n"),
8927           PROMPT_NONE, 0 },
8928
8929         /* File has duplicate blocks */
8930         { PR_1D_DUP_FILE,
8931           N_("File %Q (@i #%i, mod time %IM)\n"
8932           "  has %B @m @b(s), shared with %N file(s):\n"),
8933           PROMPT_NONE, 0 },
8934
8935         /* List of files sharing duplicate blocks */
8936         { PR_1D_DUP_FILE_LIST,
8937           N_("\t%Q (@i #%i, mod time %IM)\n"),
8938           PROMPT_NONE, 0 },
8939
8940         /* File sharing blocks with filesystem metadata  */
8941         { PR_1D_SHARE_METADATA,
8942           N_("\t<@f metadata>\n"),
8943           PROMPT_NONE, 0 },
8944
8945         /* Report of how many duplicate/bad inodes */
8946         { PR_1D_NUM_DUP_INODES,
8947           N_("(There are %N @is containing @m @bs.)\n\n"),
8948           PROMPT_NONE, 0 },
8949
8950         /* Duplicated blocks already reassigned or cloned. */
8951         { PR_1D_DUP_BLOCKS_DEALT,
8952           N_("@m @bs already reassigned or cloned.\n\n"),
8953           PROMPT_NONE, 0 },
8954
8955         /* Clone duplicate/bad blocks? */
8956         { PR_1D_CLONE_QUESTION,
8957           "", PROMPT_CLONE, PR_NO_OK },
8958
8959         /* Delete file? */
8960         { PR_1D_DELETE_QUESTION,
8961           "", PROMPT_DELETE, 0 },
8962
8963         /* Couldn't clone file (error) */
8964         { PR_1D_CLONE_ERROR,
8965           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8966
8967         /* Pass 2 errors */
8968
8969         /* Pass 2: Checking directory structure */
8970         { PR_2_PASS_HEADER,
8971           N_("Pass 2: Checking @d structure\n"),
8972           PROMPT_NONE, 0 },
8973
8974         /* Bad inode number for '.' */
8975         { PR_2_BAD_INODE_DOT,
8976           N_("@n @i number for '.' in @d @i %i.\n"),
8977           PROMPT_FIX, 0 },
8978
8979         /* Directory entry has bad inode number */
8980         { PR_2_BAD_INO,
8981           N_("@E has @n @i #: %Di.\n"),
8982           PROMPT_CLEAR, 0 },
8983
8984         /* Directory entry has deleted or unused inode */
8985         { PR_2_UNUSED_INODE,
8986           N_("@E has @D/unused @i %Di.  "),
8987           PROMPT_CLEAR, PR_PREEN_OK },
8988
8989         /* Directry entry is link to '.' */
8990         { PR_2_LINK_DOT,
8991           N_("@E @L to '.'  "),
8992           PROMPT_CLEAR, 0 },
8993
8994         /* Directory entry points to inode now located in a bad block */
8995         { PR_2_BB_INODE,
8996           N_("@E points to @i (%Di) located in a bad @b.\n"),
8997           PROMPT_CLEAR, 0 },
8998
8999         /* Directory entry contains a link to a directory */
9000         { PR_2_LINK_DIR,
9001           N_("@E @L to @d %P (%Di).\n"),
9002           PROMPT_CLEAR, 0 },
9003
9004         /* Directory entry contains a link to the root directry */
9005         { PR_2_LINK_ROOT,
9006           N_("@E @L to the @r.\n"),
9007           PROMPT_CLEAR, 0 },
9008
9009         /* Directory entry has illegal characters in its name */
9010         { PR_2_BAD_NAME,
9011           N_("@E has illegal characters in its name.\n"),
9012           PROMPT_FIX, 0 },
9013
9014         /* Missing '.' in directory inode */
9015         { PR_2_MISSING_DOT,
9016           N_("Missing '.' in @d @i %i.\n"),
9017           PROMPT_FIX, 0 },
9018
9019         /* Missing '..' in directory inode */
9020         { PR_2_MISSING_DOT_DOT,
9021           N_("Missing '..' in @d @i %i.\n"),
9022           PROMPT_FIX, 0 },
9023
9024         /* First entry in directory inode doesn't contain '.' */
9025         { PR_2_1ST_NOT_DOT,
9026           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9027           PROMPT_FIX, 0 },
9028
9029         /* Second entry in directory inode doesn't contain '..' */
9030         { PR_2_2ND_NOT_DOT_DOT,
9031           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9032           PROMPT_FIX, 0 },
9033
9034         /* i_faddr should be zero */
9035         { PR_2_FADDR_ZERO,
9036           N_("i_faddr @F %IF, @s zero.\n"),
9037           PROMPT_CLEAR, 0 },
9038
9039         /* i_file_acl should be zero */
9040         { PR_2_FILE_ACL_ZERO,
9041           N_("i_file_acl @F %If, @s zero.\n"),
9042           PROMPT_CLEAR, 0 },
9043
9044         /* i_dir_acl should be zero */
9045         { PR_2_DIR_ACL_ZERO,
9046           N_("i_dir_acl @F %Id, @s zero.\n"),
9047           PROMPT_CLEAR, 0 },
9048
9049         /* i_frag should be zero */
9050         { PR_2_FRAG_ZERO,
9051           N_("i_frag @F %N, @s zero.\n"),
9052           PROMPT_CLEAR, 0 },
9053
9054         /* i_fsize should be zero */
9055         { PR_2_FSIZE_ZERO,
9056           N_("i_fsize @F %N, @s zero.\n"),
9057           PROMPT_CLEAR, 0 },
9058
9059         /* inode has bad mode */
9060         { PR_2_BAD_MODE,
9061           N_("@i %i (%Q) has @n mode (%Im).\n"),
9062           PROMPT_CLEAR, 0 },
9063
9064         /* directory corrupted */
9065         { PR_2_DIR_CORRUPTED,
9066           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9067           PROMPT_SALVAGE, 0 },
9068
9069         /* filename too long */
9070         { PR_2_FILENAME_LONG,
9071           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9072           PROMPT_TRUNCATE, 0 },
9073
9074         /* Directory inode has a missing block (hole) */
9075         { PR_2_DIRECTORY_HOLE,
9076           N_("@d @i %i has an unallocated @b #%B.  "),
9077           PROMPT_ALLOCATE, 0 },
9078
9079         /* '.' is not NULL terminated */
9080         { PR_2_DOT_NULL_TERM,
9081           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9082           PROMPT_FIX, 0 },
9083
9084         /* '..' is not NULL terminated */
9085         { PR_2_DOT_DOT_NULL_TERM,
9086           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9087           PROMPT_FIX, 0 },
9088
9089         /* Illegal character device inode */
9090         { PR_2_BAD_CHAR_DEV,
9091           N_("@i %i (%Q) is an @I character @v.\n"),
9092           PROMPT_CLEAR, 0 },
9093
9094         /* Illegal block device inode */
9095         { PR_2_BAD_BLOCK_DEV,
9096           N_("@i %i (%Q) is an @I @b @v.\n"),
9097           PROMPT_CLEAR, 0 },
9098
9099         /* Duplicate '.' entry */
9100         { PR_2_DUP_DOT,
9101           N_("@E is duplicate '.' @e.\n"),
9102           PROMPT_FIX, 0 },
9103
9104         /* Duplicate '..' entry */
9105         { PR_2_DUP_DOT_DOT,
9106           N_("@E is duplicate '..' @e.\n"),
9107           PROMPT_FIX, 0 },
9108
9109         /* Internal error: couldn't find dir_info */
9110         { PR_2_NO_DIRINFO,
9111           N_("Internal error: cannot find dir_info for %i.\n"),
9112           PROMPT_NONE, PR_FATAL },
9113
9114         /* Final rec_len is wrong */
9115         { PR_2_FINAL_RECLEN,
9116           N_("@E has rec_len of %Dr, @s %N.\n"),
9117           PROMPT_FIX, 0 },
9118
9119         /* Error allocating icount structure */
9120         { PR_2_ALLOCATE_ICOUNT,
9121           N_("@A icount structure: %m\n"),
9122           PROMPT_NONE, PR_FATAL },
9123
9124         /* Error iterating over directory blocks */
9125         { PR_2_DBLIST_ITERATE,
9126           N_("Error iterating over @d @bs: %m\n"),
9127           PROMPT_NONE, PR_FATAL },
9128
9129         /* Error reading directory block */
9130         { PR_2_READ_DIRBLOCK,
9131           N_("Error reading @d @b %b (@i %i): %m\n"),
9132           PROMPT_CONTINUE, 0 },
9133
9134         /* Error writing directory block */
9135         { PR_2_WRITE_DIRBLOCK,
9136           N_("Error writing @d @b %b (@i %i): %m\n"),
9137           PROMPT_CONTINUE, 0 },
9138
9139         /* Error allocating new directory block */
9140         { PR_2_ALLOC_DIRBOCK,
9141           N_("@A new @d @b for @i %i (%s): %m\n"),
9142           PROMPT_NONE, 0 },
9143
9144         /* Error deallocating inode */
9145         { PR_2_DEALLOC_INODE,
9146           N_("Error deallocating @i %i: %m\n"),
9147           PROMPT_NONE, PR_FATAL },
9148
9149         /* Directory entry for '.' is big.  Split? */
9150         { PR_2_SPLIT_DOT,
9151           N_("@d @e for '.' is big.  "),
9152           PROMPT_SPLIT, PR_NO_OK },
9153
9154         /* Illegal FIFO inode */
9155         { PR_2_BAD_FIFO,
9156           N_("@i %i (%Q) is an @I FIFO.\n"),
9157           PROMPT_CLEAR, 0 },
9158
9159         /* Illegal socket inode */
9160         { PR_2_BAD_SOCKET,
9161           N_("@i %i (%Q) is an @I socket.\n"),
9162           PROMPT_CLEAR, 0 },
9163
9164         /* Directory filetype not set */
9165         { PR_2_SET_FILETYPE,
9166           N_("Setting filetype for @E to %N.\n"),
9167           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9168
9169         /* Directory filetype incorrect */
9170         { PR_2_BAD_FILETYPE,
9171           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9172           PROMPT_FIX, 0 },
9173
9174         /* Directory filetype set on filesystem */
9175         { PR_2_CLEAR_FILETYPE,
9176           N_("@E has filetype set.\n"),
9177           PROMPT_CLEAR, PR_PREEN_OK },
9178
9179         /* Directory filename is null */
9180         { PR_2_NULL_NAME,
9181           N_("@E has a @z name.\n"),
9182           PROMPT_CLEAR, 0 },
9183
9184         /* Invalid symlink */
9185         { PR_2_INVALID_SYMLINK,
9186           N_("Symlink %Q (@i #%i) is @n.\n"),
9187           PROMPT_CLEAR, 0 },
9188
9189         /* i_file_acl (extended attribute block) is bad */
9190         { PR_2_FILE_ACL_BAD,
9191           N_("@a @b @F @n (%If).\n"),
9192           PROMPT_CLEAR, 0 },
9193
9194         /* Filesystem contains large files, but has no such flag in sb */
9195         { PR_2_FEATURE_LARGE_FILES,
9196           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9197           PROMPT_FIX, 0 },
9198
9199         /* Node in HTREE directory not referenced */
9200         { PR_2_HTREE_NOTREF,
9201           N_("@p @h %d: node (%B) not referenced\n"),
9202           PROMPT_NONE, 0 },
9203
9204         /* Node in HTREE directory referenced twice */
9205         { PR_2_HTREE_DUPREF,
9206           N_("@p @h %d: node (%B) referenced twice\n"),
9207           PROMPT_NONE, 0 },
9208
9209         /* Node in HTREE directory has bad min hash */
9210         { PR_2_HTREE_MIN_HASH,
9211           N_("@p @h %d: node (%B) has bad min hash\n"),
9212           PROMPT_NONE, 0 },
9213
9214         /* Node in HTREE directory has bad max hash */
9215         { PR_2_HTREE_MAX_HASH,
9216           N_("@p @h %d: node (%B) has bad max hash\n"),
9217           PROMPT_NONE, 0 },
9218
9219         /* Clear invalid HTREE directory */
9220         { PR_2_HTREE_CLEAR,
9221           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9222
9223         /* Bad block in htree interior node */
9224         { PR_2_HTREE_BADBLK,
9225           N_("@p @h %d (%q): bad @b number %b.\n"),
9226           PROMPT_CLEAR_HTREE, 0 },
9227
9228         /* Error adjusting EA refcount */
9229         { PR_2_ADJ_EA_REFCOUNT,
9230           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9231           PROMPT_NONE, PR_FATAL },
9232
9233         /* Invalid HTREE root node */
9234         { PR_2_HTREE_BAD_ROOT,
9235           N_("@p @h %d: root node is @n\n"),
9236           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9237
9238         /* Invalid HTREE limit */
9239         { PR_2_HTREE_BAD_LIMIT,
9240           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9241           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9242
9243         /* Invalid HTREE count */
9244         { PR_2_HTREE_BAD_COUNT,
9245           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9246           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9247
9248         /* HTREE interior node has out-of-order hashes in table */
9249         { PR_2_HTREE_HASH_ORDER,
9250           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9251           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9252
9253         /* Node in HTREE directory has invalid depth */
9254         { PR_2_HTREE_BAD_DEPTH,
9255           N_("@p @h %d: node (%B) has @n depth\n"),
9256           PROMPT_NONE, 0 },
9257
9258         /* Duplicate directory entry found */
9259         { PR_2_DUPLICATE_DIRENT,
9260           N_("Duplicate @E found.  "),
9261           PROMPT_CLEAR, 0 },
9262
9263         /* Non-unique filename found */
9264         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9265           N_("@E has a non-unique filename.\nRename to %s"),
9266           PROMPT_NULL, 0 },
9267
9268         /* Duplicate directory entry found */
9269         { PR_2_REPORT_DUP_DIRENT,
9270           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9271           PROMPT_NONE, 0 },
9272
9273         /* Pass 3 errors */
9274
9275         /* Pass 3: Checking directory connectivity */
9276         { PR_3_PASS_HEADER,
9277           N_("Pass 3: Checking @d connectivity\n"),
9278           PROMPT_NONE, 0 },
9279
9280         /* Root inode not allocated */
9281         { PR_3_NO_ROOT_INODE,
9282           N_("@r not allocated.  "),
9283           PROMPT_ALLOCATE, 0 },
9284
9285         /* No room in lost+found */
9286         { PR_3_EXPAND_LF_DIR,
9287           N_("No room in @l @d.  "),
9288           PROMPT_EXPAND, 0 },
9289
9290         /* Unconnected directory inode */
9291         { PR_3_UNCONNECTED_DIR,
9292           N_("Unconnected @d @i %i (%p)\n"),
9293           PROMPT_CONNECT, 0 },
9294
9295         /* /lost+found not found */
9296         { PR_3_NO_LF_DIR,
9297           N_("/@l not found.  "),
9298           PROMPT_CREATE, PR_PREEN_OK },
9299
9300         /* .. entry is incorrect */
9301         { PR_3_BAD_DOT_DOT,
9302           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9303           PROMPT_FIX, 0 },
9304
9305         /* Bad or non-existent /lost+found.  Cannot reconnect */
9306         { PR_3_NO_LPF,
9307           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9308           PROMPT_NONE, 0 },
9309
9310         /* Could not expand /lost+found */
9311         { PR_3_CANT_EXPAND_LPF,
9312           N_("Could not expand /@l: %m\n"),
9313           PROMPT_NONE, 0 },
9314
9315         /* Could not reconnect inode */
9316         { PR_3_CANT_RECONNECT,
9317           N_("Could not reconnect %i: %m\n"),
9318           PROMPT_NONE, 0 },
9319
9320         /* Error while trying to find /lost+found */
9321         { PR_3_ERR_FIND_LPF,
9322           N_("Error while trying to find /@l: %m\n"),
9323           PROMPT_NONE, 0 },
9324
9325         /* Error in ext2fs_new_block while creating /lost+found */
9326         { PR_3_ERR_LPF_NEW_BLOCK,
9327           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9328           PROMPT_NONE, 0 },
9329
9330         /* Error in ext2fs_new_inode while creating /lost+found */
9331         { PR_3_ERR_LPF_NEW_INODE,
9332           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9333           PROMPT_NONE, 0 },
9334
9335         /* Error in ext2fs_new_dir_block while creating /lost+found */
9336         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9337           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9338           PROMPT_NONE, 0 },
9339
9340         /* Error while writing directory block for /lost+found */
9341         { PR_3_ERR_LPF_WRITE_BLOCK,
9342           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9343           PROMPT_NONE, 0 },
9344
9345         /* Error while adjusting inode count */
9346         { PR_3_ADJUST_INODE,
9347           N_("Error while adjusting @i count on @i %i\n"),
9348           PROMPT_NONE, 0 },
9349
9350         /* Couldn't fix parent directory -- error */
9351         { PR_3_FIX_PARENT_ERR,
9352           N_("Couldn't fix parent of @i %i: %m\n\n"),
9353           PROMPT_NONE, 0 },
9354
9355         /* Couldn't fix parent directory -- couldn't find it */
9356         { PR_3_FIX_PARENT_NOFIND,
9357           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9358           PROMPT_NONE, 0 },
9359
9360         /* Error allocating inode bitmap */
9361         { PR_3_ALLOCATE_IBITMAP_ERROR,
9362           N_("@A @i @B (%N): %m\n"),
9363           PROMPT_NONE, PR_FATAL },
9364
9365         /* Error creating root directory */
9366         { PR_3_CREATE_ROOT_ERROR,
9367           N_("Error creating root @d (%s): %m\n"),
9368           PROMPT_NONE, PR_FATAL },
9369
9370         /* Error creating lost and found directory */
9371         { PR_3_CREATE_LPF_ERROR,
9372           N_("Error creating /@l @d (%s): %m\n"),
9373           PROMPT_NONE, PR_FATAL },
9374
9375         /* Root inode is not directory; aborting */
9376         { PR_3_ROOT_NOT_DIR_ABORT,
9377           N_("@r is not a @d; aborting.\n"),
9378           PROMPT_NONE, PR_FATAL },
9379
9380         /* Cannot proceed without a root inode. */
9381         { PR_3_NO_ROOT_INODE_ABORT,
9382           N_("can't proceed without a @r.\n"),
9383           PROMPT_NONE, PR_FATAL },
9384
9385         /* Internal error: couldn't find dir_info */
9386         { PR_3_NO_DIRINFO,
9387           N_("Internal error: cannot find dir_info for %i.\n"),
9388           PROMPT_NONE, PR_FATAL },
9389
9390         /* Lost+found not a directory */
9391         { PR_3_LPF_NOTDIR,
9392           N_("/@l is not a @d (ino=%i)\n"),
9393           PROMPT_UNLINK, 0 },
9394
9395         /* Pass 3A Directory Optimization       */
9396
9397         /* Pass 3A: Optimizing directories */
9398         { PR_3A_PASS_HEADER,
9399           N_("Pass 3A: Optimizing directories\n"),
9400           PROMPT_NONE, PR_PREEN_NOMSG },
9401
9402         /* Error iterating over directories */
9403         { PR_3A_OPTIMIZE_ITER,
9404           N_("Failed to create dirs_to_hash iterator: %m"),
9405           PROMPT_NONE, 0 },
9406
9407         /* Error rehash directory */
9408         { PR_3A_OPTIMIZE_DIR_ERR,
9409           N_("Failed to optimize directory %q (%d): %m"),
9410           PROMPT_NONE, 0 },
9411
9412         /* Rehashing dir header */
9413         { PR_3A_OPTIMIZE_DIR_HEADER,
9414           N_("Optimizing directories: "),
9415           PROMPT_NONE, PR_MSG_ONLY },
9416
9417         /* Rehashing directory %d */
9418         { PR_3A_OPTIMIZE_DIR,
9419           " %d",
9420           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9421
9422         /* Rehashing dir end */
9423         { PR_3A_OPTIMIZE_DIR_END,
9424           "\n",
9425           PROMPT_NONE, PR_PREEN_NOHDR },
9426
9427         /* Pass 4 errors */
9428
9429         /* Pass 4: Checking reference counts */
9430         { PR_4_PASS_HEADER,
9431           N_("Pass 4: Checking reference counts\n"),
9432           PROMPT_NONE, 0 },
9433
9434         /* Unattached zero-length inode */
9435         { PR_4_ZERO_LEN_INODE,
9436           N_("@u @z @i %i.  "),
9437           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9438
9439         /* Unattached inode */
9440         { PR_4_UNATTACHED_INODE,
9441           N_("@u @i %i\n"),
9442           PROMPT_CONNECT, 0 },
9443
9444         /* Inode ref count wrong */
9445         { PR_4_BAD_REF_COUNT,
9446           N_("@i %i ref count is %Il, @s %N.  "),
9447           PROMPT_FIX, PR_PREEN_OK },
9448
9449         { PR_4_INCONSISTENT_COUNT,
9450           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9451           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9452           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9453           "They @s the same!\n"),
9454           PROMPT_NONE, 0 },
9455
9456         /* Pass 5 errors */
9457
9458         /* Pass 5: Checking group summary information */
9459         { PR_5_PASS_HEADER,
9460           N_("Pass 5: Checking @g summary information\n"),
9461           PROMPT_NONE, 0 },
9462
9463         /* Padding at end of inode bitmap is not set. */
9464         { PR_5_INODE_BMAP_PADDING,
9465           N_("Padding at end of @i @B is not set. "),
9466           PROMPT_FIX, PR_PREEN_OK },
9467
9468         /* Padding at end of block bitmap is not set. */
9469         { PR_5_BLOCK_BMAP_PADDING,
9470           N_("Padding at end of @b @B is not set. "),
9471           PROMPT_FIX, PR_PREEN_OK },
9472
9473         /* Block bitmap differences header */
9474         { PR_5_BLOCK_BITMAP_HEADER,
9475           N_("@b @B differences: "),
9476           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9477
9478         /* Block not used, but marked in bitmap */
9479         { PR_5_BLOCK_UNUSED,
9480           " -%b",
9481           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9482
9483         /* Block used, but not marked used in bitmap */
9484         { PR_5_BLOCK_USED,
9485           " +%b",
9486           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9487
9488         /* Block bitmap differences end */
9489         { PR_5_BLOCK_BITMAP_END,
9490           "\n",
9491           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9492
9493         /* Inode bitmap differences header */
9494         { PR_5_INODE_BITMAP_HEADER,
9495           N_("@i @B differences: "),
9496           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9497
9498         /* Inode not used, but marked in bitmap */
9499         { PR_5_INODE_UNUSED,
9500           " -%i",
9501           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9502
9503         /* Inode used, but not marked used in bitmap */
9504         { PR_5_INODE_USED,
9505           " +%i",
9506           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9507
9508         /* Inode bitmap differences end */
9509         { PR_5_INODE_BITMAP_END,
9510           "\n",
9511           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9512
9513         /* Free inodes count for group wrong */
9514         { PR_5_FREE_INODE_COUNT_GROUP,
9515           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9516           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9517
9518         /* Directories count for group wrong */
9519         { PR_5_FREE_DIR_COUNT_GROUP,
9520           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9521           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9522
9523         /* Free inodes count wrong */
9524         { PR_5_FREE_INODE_COUNT,
9525           N_("Free @is count wrong (%i, counted=%j).\n"),
9526           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9527
9528         /* Free blocks count for group wrong */
9529         { PR_5_FREE_BLOCK_COUNT_GROUP,
9530           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9531           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9532
9533         /* Free blocks count wrong */
9534         { PR_5_FREE_BLOCK_COUNT,
9535           N_("Free @bs count wrong (%b, counted=%c).\n"),
9536           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9537
9538         /* Programming error: bitmap endpoints don't match */
9539         { PR_5_BMAP_ENDPOINTS,
9540           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9541           "match calculated @B endpoints (%i, %j)\n"),
9542           PROMPT_NONE, PR_FATAL },
9543
9544         /* Internal error: fudging end of bitmap */
9545         { PR_5_FUDGE_BITMAP_ERROR,
9546           N_("Internal error: fudging end of bitmap (%N)\n"),
9547           PROMPT_NONE, PR_FATAL },
9548
9549         /* Error copying in replacement inode bitmap */
9550         { PR_5_COPY_IBITMAP_ERROR,
9551           N_("Error copying in replacement @i @B: %m\n"),
9552           PROMPT_NONE, PR_FATAL },
9553
9554         /* Error copying in replacement block bitmap */
9555         { PR_5_COPY_BBITMAP_ERROR,
9556           N_("Error copying in replacement @b @B: %m\n"),
9557           PROMPT_NONE, PR_FATAL },
9558
9559         /* Block range not used, but marked in bitmap */
9560         { PR_5_BLOCK_RANGE_UNUSED,
9561           " -(%b--%c)",
9562           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9563
9564         /* Block range used, but not marked used in bitmap */
9565         { PR_5_BLOCK_RANGE_USED,
9566           " +(%b--%c)",
9567           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9568
9569         /* Inode range not used, but marked in bitmap */
9570         { PR_5_INODE_RANGE_UNUSED,
9571           " -(%i--%j)",
9572           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9573
9574         /* Inode range used, but not marked used in bitmap */
9575         { PR_5_INODE_RANGE_USED,
9576           " +(%i--%j)",
9577           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9578
9579         { 0 }
9580 };
9581
9582 /*
9583  * This is the latch flags register.  It allows several problems to be
9584  * "latched" together.  This means that the user has to answer but one
9585  * question for the set of problems, and all of the associated
9586  * problems will be either fixed or not fixed.
9587  */
9588 static struct latch_descr pr_latch_info[] = {
9589         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9590         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9591         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9592         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9593         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9594         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9595         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9596         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9597         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9598         { -1, 0, 0 },
9599 };
9600
9601 static const struct e2fsck_problem *find_problem(problem_t code)
9602 {
9603         int     i;
9604
9605         for (i=0; problem_table[i].e2p_code; i++) {
9606                 if (problem_table[i].e2p_code == code)
9607                         return &problem_table[i];
9608         }
9609         return 0;
9610 }
9611
9612 static struct latch_descr *find_latch(int code)
9613 {
9614         int     i;
9615
9616         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9617                 if (pr_latch_info[i].latch_code == code)
9618                         return &pr_latch_info[i];
9619         }
9620         return 0;
9621 }
9622
9623 int end_problem_latch(e2fsck_t ctx, int mask)
9624 {
9625         struct latch_descr *ldesc;
9626         struct problem_context pctx;
9627         int answer = -1;
9628
9629         ldesc = find_latch(mask);
9630         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9631                 clear_problem_context(&pctx);
9632                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9633         }
9634         ldesc->flags &= ~(PRL_VARIABLE);
9635         return answer;
9636 }
9637
9638 int set_latch_flags(int mask, int setflags, int clearflags)
9639 {
9640         struct latch_descr *ldesc;
9641
9642         ldesc = find_latch(mask);
9643         if (!ldesc)
9644                 return -1;
9645         ldesc->flags |= setflags;
9646         ldesc->flags &= ~clearflags;
9647         return 0;
9648 }
9649
9650 void clear_problem_context(struct problem_context *ctx)
9651 {
9652         memset(ctx, 0, sizeof(struct problem_context));
9653         ctx->blkcount = -1;
9654         ctx->group = -1;
9655 }
9656
9657 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9658 {
9659         ext2_filsys fs = ctx->fs;
9660         const struct e2fsck_problem *ptr;
9661         struct latch_descr *ldesc = NULL;
9662         const char *message;
9663         int             def_yn, answer, ans;
9664         int             print_answer = 0;
9665         int             suppress = 0;
9666
9667         ptr = find_problem(code);
9668         if (!ptr) {
9669                 printf(_("Unhandled error code (0x%x)!\n"), code);
9670                 return 0;
9671         }
9672         def_yn = 1;
9673         if ((ptr->flags & PR_NO_DEFAULT) ||
9674             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9675             (ctx->options & E2F_OPT_NO))
9676                 def_yn= 0;
9677
9678         /*
9679          * Do special latch processing.  This is where we ask the
9680          * latch question, if it exists
9681          */
9682         if (ptr->flags & PR_LATCH_MASK) {
9683                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9684                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9685                         ans = fix_problem(ctx, ldesc->question, pctx);
9686                         if (ans == 1)
9687                                 ldesc->flags |= PRL_YES;
9688                         if (ans == 0)
9689                                 ldesc->flags |= PRL_NO;
9690                         ldesc->flags |= PRL_LATCHED;
9691                 }
9692                 if (ldesc->flags & PRL_SUPPRESS)
9693                         suppress++;
9694         }
9695         if ((ptr->flags & PR_PREEN_NOMSG) &&
9696             (ctx->options & E2F_OPT_PREEN))
9697                 suppress++;
9698         if ((ptr->flags & PR_NO_NOMSG) &&
9699             (ctx->options & E2F_OPT_NO))
9700                 suppress++;
9701         if (!suppress) {
9702                 message = ptr->e2p_description;
9703                 if ((ctx->options & E2F_OPT_PREEN) &&
9704                     !(ptr->flags & PR_PREEN_NOHDR)) {
9705                         printf("%s: ", ctx->device_name ?
9706                                ctx->device_name : ctx->filesystem_name);
9707                 }
9708                 if (*message)
9709                         print_e2fsck_message(ctx, _(message), pctx, 1);
9710         }
9711         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9712                 preenhalt(ctx);
9713
9714         if (ptr->flags & PR_FATAL)
9715                 bb_error_msg_and_die(0);
9716
9717         if (ptr->prompt == PROMPT_NONE) {
9718                 if (ptr->flags & PR_NOCOLLATE)
9719                         answer = -1;
9720                 else
9721                         answer = def_yn;
9722         } else {
9723                 if (ctx->options & E2F_OPT_PREEN) {
9724                         answer = def_yn;
9725                         if (!(ptr->flags & PR_PREEN_NOMSG))
9726                                 print_answer = 1;
9727                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9728                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9729                         if (!suppress)
9730                                 print_answer = 1;
9731                         if (ldesc->flags & PRL_YES)
9732                                 answer = 1;
9733                         else
9734                                 answer = 0;
9735                 } else
9736                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9737                 if (!answer && !(ptr->flags & PR_NO_OK))
9738                         ext2fs_unmark_valid(fs);
9739
9740                 if (print_answer)
9741                         printf("%s.\n", answer ?
9742                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9743         }
9744
9745         if ((ptr->prompt == PROMPT_ABORT) && answer)
9746                 bb_error_msg_and_die(0);
9747
9748         if (ptr->flags & PR_AFTER_CODE)
9749                 answer = fix_problem(ctx, ptr->second_code, pctx);
9750
9751         return answer;
9752 }
9753
9754 /*
9755  * linux/fs/recovery.c
9756  *
9757  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9758  */
9759
9760 /*
9761  * Maintain information about the progress of the recovery job, so that
9762  * the different passes can carry information between them.
9763  */
9764 struct recovery_info
9765 {
9766         tid_t           start_transaction;
9767         tid_t           end_transaction;
9768
9769         int             nr_replays;
9770         int             nr_revokes;
9771         int             nr_revoke_hits;
9772 };
9773
9774 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9775 static int do_one_pass(journal_t *journal,
9776                                 struct recovery_info *info, enum passtype pass);
9777 static int scan_revoke_records(journal_t *, struct buffer_head *,
9778                                 tid_t, struct recovery_info *);
9779
9780 /*
9781  * Read a block from the journal
9782  */
9783
9784 static int jread(struct buffer_head **bhp, journal_t *journal,
9785                  unsigned int offset)
9786 {
9787         int err;
9788         unsigned long blocknr;
9789         struct buffer_head *bh;
9790
9791         *bhp = NULL;
9792
9793         err = journal_bmap(journal, offset, &blocknr);
9794
9795         if (err) {
9796                 printf("JBD: bad block at offset %u\n", offset);
9797                 return err;
9798         }
9799
9800         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9801         if (!bh)
9802                 return -ENOMEM;
9803
9804         if (!buffer_uptodate(bh)) {
9805                 /* If this is a brand new buffer, start readahead.
9806                    Otherwise, we assume we are already reading it.  */
9807                 if (!buffer_req(bh))
9808                         do_readahead(journal, offset);
9809                 wait_on_buffer(bh);
9810         }
9811
9812         if (!buffer_uptodate(bh)) {
9813                 printf("JBD: Failed to read block at offset %u\n", offset);
9814                 brelse(bh);
9815                 return -EIO;
9816         }
9817
9818         *bhp = bh;
9819         return 0;
9820 }
9821
9822
9823 /*
9824  * Count the number of in-use tags in a journal descriptor block.
9825  */
9826
9827 static int count_tags(struct buffer_head *bh, int size)
9828 {
9829         char *                  tagp;
9830         journal_block_tag_t *   tag;
9831         int                     nr = 0;
9832
9833         tagp = &bh->b_data[sizeof(journal_header_t)];
9834
9835         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9836                 tag = (journal_block_tag_t *) tagp;
9837
9838                 nr++;
9839                 tagp += sizeof(journal_block_tag_t);
9840                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9841                         tagp += 16;
9842
9843                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9844                         break;
9845         }
9846
9847         return nr;
9848 }
9849
9850
9851 /* Make sure we wrap around the log correctly! */
9852 #define wrap(journal, var)                                            \
9853 do {                                                                \
9854         if (var >= (journal)->j_last)                                   \
9855                 var -= ((journal)->j_last - (journal)->j_first);        \
9856 } while (0)
9857
9858 /**
9859  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9860  * @journal: the journal to recover
9861  *
9862  * The primary function for recovering the log contents when mounting a
9863  * journaled device.
9864  *
9865  * Recovery is done in three passes.  In the first pass, we look for the
9866  * end of the log.  In the second, we assemble the list of revoke
9867  * blocks.  In the third and final pass, we replay any un-revoked blocks
9868  * in the log.
9869  */
9870 int journal_recover(journal_t *journal)
9871 {
9872         int                     err;
9873         journal_superblock_t *  sb;
9874
9875         struct recovery_info    info;
9876
9877         memset(&info, 0, sizeof(info));
9878         sb = journal->j_superblock;
9879
9880         /*
9881          * The journal superblock's s_start field (the current log head)
9882          * is always zero if, and only if, the journal was cleanly
9883          * unmounted.
9884          */
9885
9886         if (!sb->s_start) {
9887                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9888                 return 0;
9889         }
9890
9891         err = do_one_pass(journal, &info, PASS_SCAN);
9892         if (!err)
9893                 err = do_one_pass(journal, &info, PASS_REVOKE);
9894         if (!err)
9895                 err = do_one_pass(journal, &info, PASS_REPLAY);
9896
9897         /* Restart the log at the next transaction ID, thus invalidating
9898          * any existing commit records in the log. */
9899         journal->j_transaction_sequence = ++info.end_transaction;
9900
9901         journal_clear_revoke(journal);
9902         sync_blockdev(journal->j_fs_dev);
9903         return err;
9904 }
9905
9906 static int do_one_pass(journal_t *journal,
9907                         struct recovery_info *info, enum passtype pass)
9908 {
9909         unsigned int            first_commit_ID, next_commit_ID;
9910         unsigned long           next_log_block;
9911         int                     err, success = 0;
9912         journal_superblock_t *  sb;
9913         journal_header_t *      tmp;
9914         struct buffer_head *    bh;
9915         unsigned int            sequence;
9916         int                     blocktype;
9917
9918         /* Precompute the maximum metadata descriptors in a descriptor block */
9919         int                     MAX_BLOCKS_PER_DESC;
9920         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9921                                / sizeof(journal_block_tag_t));
9922
9923         /*
9924          * First thing is to establish what we expect to find in the log
9925          * (in terms of transaction IDs), and where (in terms of log
9926          * block offsets): query the superblock.
9927          */
9928
9929         sb = journal->j_superblock;
9930         next_commit_ID = ntohl(sb->s_sequence);
9931         next_log_block = ntohl(sb->s_start);
9932
9933         first_commit_ID = next_commit_ID;
9934         if (pass == PASS_SCAN)
9935                 info->start_transaction = first_commit_ID;
9936
9937         /*
9938          * Now we walk through the log, transaction by transaction,
9939          * making sure that each transaction has a commit block in the
9940          * expected place.  Each complete transaction gets replayed back
9941          * into the main filesystem.
9942          */
9943
9944         while (1) {
9945                 int                     flags;
9946                 char *                  tagp;
9947                 journal_block_tag_t *   tag;
9948                 struct buffer_head *    obh;
9949                 struct buffer_head *    nbh;
9950
9951                 /* If we already know where to stop the log traversal,
9952                  * check right now that we haven't gone past the end of
9953                  * the log. */
9954
9955                 if (pass != PASS_SCAN)
9956                         if (tid_geq(next_commit_ID, info->end_transaction))
9957                                 break;
9958
9959                 /* Skip over each chunk of the transaction looking
9960                  * either the next descriptor block or the final commit
9961                  * record. */
9962
9963                 err = jread(&bh, journal, next_log_block);
9964                 if (err)
9965                         goto failed;
9966
9967                 next_log_block++;
9968                 wrap(journal, next_log_block);
9969
9970                 /* What kind of buffer is it?
9971                  *
9972                  * If it is a descriptor block, check that it has the
9973                  * expected sequence number.  Otherwise, we're all done
9974                  * here. */
9975
9976                 tmp = (journal_header_t *)bh->b_data;
9977
9978                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9979                         brelse(bh);
9980                         break;
9981                 }
9982
9983                 blocktype = ntohl(tmp->h_blocktype);
9984                 sequence = ntohl(tmp->h_sequence);
9985
9986                 if (sequence != next_commit_ID) {
9987                         brelse(bh);
9988                         break;
9989                 }
9990
9991                 /* OK, we have a valid descriptor block which matches
9992                  * all of the sequence number checks.  What are we going
9993                  * to do with it?  That depends on the pass... */
9994
9995                 switch (blocktype) {
9996                 case JFS_DESCRIPTOR_BLOCK:
9997                         /* If it is a valid descriptor block, replay it
9998                          * in pass REPLAY; otherwise, just skip over the
9999                          * blocks it describes. */
10000                         if (pass != PASS_REPLAY) {
10001                                 next_log_block +=
10002                                         count_tags(bh, journal->j_blocksize);
10003                                 wrap(journal, next_log_block);
10004                                 brelse(bh);
10005                                 continue;
10006                         }
10007
10008                         /* A descriptor block: we can now write all of
10009                          * the data blocks.  Yay, useful work is finally
10010                          * getting done here! */
10011
10012                         tagp = &bh->b_data[sizeof(journal_header_t)];
10013                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10014                                <= journal->j_blocksize) {
10015                                 unsigned long io_block;
10016
10017                                 tag = (journal_block_tag_t *) tagp;
10018                                 flags = ntohl(tag->t_flags);
10019
10020                                 io_block = next_log_block++;
10021                                 wrap(journal, next_log_block);
10022                                 err = jread(&obh, journal, io_block);
10023                                 if (err) {
10024                                         /* Recover what we can, but
10025                                          * report failure at the end. */
10026                                         success = err;
10027                                         printf("JBD: IO error %d recovering "
10028                                                 "block %ld in log\n",
10029                                                 err, io_block);
10030                                 } else {
10031                                         unsigned long blocknr;
10032
10033                                         blocknr = ntohl(tag->t_blocknr);
10034
10035                                         /* If the block has been
10036                                          * revoked, then we're all done
10037                                          * here. */
10038                                         if (journal_test_revoke
10039                                             (journal, blocknr,
10040                                              next_commit_ID)) {
10041                                                 brelse(obh);
10042                                                 ++info->nr_revoke_hits;
10043                                                 goto skip_write;
10044                                         }
10045
10046                                         /* Find a buffer for the new
10047                                          * data being restored */
10048                                         nbh = getblk(journal->j_fs_dev,
10049                                                        blocknr,
10050                                                      journal->j_blocksize);
10051                                         if (nbh == NULL) {
10052                                                 printf("JBD: Out of memory "
10053                                                        "during recovery.\n");
10054                                                 err = -ENOMEM;
10055                                                 brelse(bh);
10056                                                 brelse(obh);
10057                                                 goto failed;
10058                                         }
10059
10060                                         lock_buffer(nbh);
10061                                         memcpy(nbh->b_data, obh->b_data,
10062                                                         journal->j_blocksize);
10063                                         if (flags & JFS_FLAG_ESCAPE) {
10064                                                 *((unsigned int *)bh->b_data) =
10065                                                         htonl(JFS_MAGIC_NUMBER);
10066                                         }
10067
10068                                         mark_buffer_uptodate(nbh, 1);
10069                                         mark_buffer_dirty(nbh);
10070                                         ++info->nr_replays;
10071                                         /* ll_rw_block(WRITE, 1, &nbh); */
10072                                         unlock_buffer(nbh);
10073                                         brelse(obh);
10074                                         brelse(nbh);
10075                                 }
10076
10077                         skip_write:
10078                                 tagp += sizeof(journal_block_tag_t);
10079                                 if (!(flags & JFS_FLAG_SAME_UUID))
10080                                         tagp += 16;
10081
10082                                 if (flags & JFS_FLAG_LAST_TAG)
10083                                         break;
10084                         }
10085
10086                         brelse(bh);
10087                         continue;
10088
10089                 case JFS_COMMIT_BLOCK:
10090                         /* Found an expected commit block: not much to
10091                          * do other than move on to the next sequence
10092                          * number. */
10093                         brelse(bh);
10094                         next_commit_ID++;
10095                         continue;
10096
10097                 case JFS_REVOKE_BLOCK:
10098                         /* If we aren't in the REVOKE pass, then we can
10099                          * just skip over this block. */
10100                         if (pass != PASS_REVOKE) {
10101                                 brelse(bh);
10102                                 continue;
10103                         }
10104
10105                         err = scan_revoke_records(journal, bh,
10106                                                   next_commit_ID, info);
10107                         brelse(bh);
10108                         if (err)
10109                                 goto failed;
10110                         continue;
10111
10112                 default:
10113                         goto done;
10114                 }
10115         }
10116
10117  done:
10118         /*
10119          * We broke out of the log scan loop: either we came to the
10120          * known end of the log or we found an unexpected block in the
10121          * log.  If the latter happened, then we know that the "current"
10122          * transaction marks the end of the valid log.
10123          */
10124
10125         if (pass == PASS_SCAN)
10126                 info->end_transaction = next_commit_ID;
10127         else {
10128                 /* It's really bad news if different passes end up at
10129                  * different places (but possible due to IO errors). */
10130                 if (info->end_transaction != next_commit_ID) {
10131                         printf("JBD: recovery pass %d ended at "
10132                                 "transaction %u, expected %u\n",
10133                                 pass, next_commit_ID, info->end_transaction);
10134                         if (!success)
10135                                 success = -EIO;
10136                 }
10137         }
10138
10139         return success;
10140
10141  failed:
10142         return err;
10143 }
10144
10145
10146 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10147
10148 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10149                                tid_t sequence, struct recovery_info *info)
10150 {
10151         journal_revoke_header_t *header;
10152         int offset, max;
10153
10154         header = (journal_revoke_header_t *) bh->b_data;
10155         offset = sizeof(journal_revoke_header_t);
10156         max = ntohl(header->r_count);
10157
10158         while (offset < max) {
10159                 unsigned long blocknr;
10160                 int err;
10161
10162                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10163                 offset += 4;
10164                 err = journal_set_revoke(journal, blocknr, sequence);
10165                 if (err)
10166                         return err;
10167                 ++info->nr_revokes;
10168         }
10169         return 0;
10170 }
10171
10172
10173 /*
10174  * rehash.c --- rebuild hash tree directories
10175  *
10176  * This algorithm is designed for simplicity of implementation and to
10177  * pack the directory as much as possible.  It however requires twice
10178  * as much memory as the size of the directory.  The maximum size
10179  * directory supported using a 4k blocksize is roughly a gigabyte, and
10180  * so there may very well be problems with machines that don't have
10181  * virtual memory, and obscenely large directories.
10182  *
10183  * An alternate algorithm which is much more disk intensive could be
10184  * written, and probably will need to be written in the future.  The
10185  * design goals of such an algorithm are: (a) use (roughly) constant
10186  * amounts of memory, no matter how large the directory, (b) the
10187  * directory must be safe at all times, even if e2fsck is interrupted
10188  * in the middle, (c) we must use minimal amounts of extra disk
10189  * blocks.  This pretty much requires an incremental approach, where
10190  * we are reading from one part of the directory, and inserting into
10191  * the front half.  So the algorithm will have to keep track of a
10192  * moving block boundary between the new tree and the old tree, and
10193  * files will need to be moved from the old directory and inserted
10194  * into the new tree.  If the new directory requires space which isn't
10195  * yet available, blocks from the beginning part of the old directory
10196  * may need to be moved to the end of the directory to make room for
10197  * the new tree:
10198  *
10199  *    --------------------------------------------------------
10200  *    |  new tree   |        | old tree                      |
10201  *    --------------------------------------------------------
10202  *                  ^ ptr    ^ptr
10203  *                tail new   head old
10204  *
10205  * This is going to be a pain in the tuckus to implement, and will
10206  * require a lot more disk accesses.  So I'm going to skip it for now;
10207  * it's only really going to be an issue for really, really big
10208  * filesystems (when we reach the level of tens of millions of files
10209  * in a single directory).  It will probably be easier to simply
10210  * require that e2fsck use VM first.
10211  */
10212
10213 struct fill_dir_struct {
10214         char *buf;
10215         struct ext2_inode *inode;
10216         int err;
10217         e2fsck_t ctx;
10218         struct hash_entry *harray;
10219         int max_array, num_array;
10220         int dir_size;
10221         int compress;
10222         ino_t parent;
10223 };
10224
10225 struct hash_entry {
10226         ext2_dirhash_t  hash;
10227         ext2_dirhash_t  minor_hash;
10228         struct ext2_dir_entry   *dir;
10229 };
10230
10231 struct out_dir {
10232         int             num;
10233         int             max;
10234         char            *buf;
10235         ext2_dirhash_t  *hashes;
10236 };
10237
10238 static int fill_dir_block(ext2_filsys fs,
10239                           blk_t *block_nr,
10240                           e2_blkcnt_t blockcnt,
10241                           blk_t ref_block FSCK_ATTR((unused)),
10242                           int ref_offset FSCK_ATTR((unused)),
10243                           void *priv_data)
10244 {
10245         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10246         struct hash_entry       *new_array, *ent;
10247         struct ext2_dir_entry   *dirent;
10248         char                    *dir;
10249         unsigned int            offset, dir_offset;
10250
10251         if (blockcnt < 0)
10252                 return 0;
10253
10254         offset = blockcnt * fs->blocksize;
10255         if (offset + fs->blocksize > fd->inode->i_size) {
10256                 fd->err = EXT2_ET_DIR_CORRUPTED;
10257                 return BLOCK_ABORT;
10258         }
10259         dir = (fd->buf+offset);
10260         if (HOLE_BLKADDR(*block_nr)) {
10261                 memset(dir, 0, fs->blocksize);
10262                 dirent = (struct ext2_dir_entry *) dir;
10263                 dirent->rec_len = fs->blocksize;
10264         } else {
10265                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10266                 if (fd->err)
10267                         return BLOCK_ABORT;
10268         }
10269         /* While the directory block is "hot", index it. */
10270         dir_offset = 0;
10271         while (dir_offset < fs->blocksize) {
10272                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10273                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10274                     (dirent->rec_len < 8) ||
10275                     ((dirent->rec_len % 4) != 0) ||
10276                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10277                         fd->err = EXT2_ET_DIR_CORRUPTED;
10278                         return BLOCK_ABORT;
10279                 }
10280                 dir_offset += dirent->rec_len;
10281                 if (dirent->inode == 0)
10282                         continue;
10283                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10284                     (dirent->name[0] == '.'))
10285                         continue;
10286                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10287                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10288                         fd->parent = dirent->inode;
10289                         continue;
10290                 }
10291                 if (fd->num_array >= fd->max_array) {
10292                         new_array = xrealloc(fd->harray,
10293                             sizeof(struct hash_entry) * (fd->max_array+500));
10294                         fd->harray = new_array;
10295                         fd->max_array += 500;
10296                 }
10297                 ent = fd->harray + fd->num_array++;
10298                 ent->dir = dirent;
10299                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10300                 if (fd->compress)
10301                         ent->hash = ent->minor_hash = 0;
10302                 else {
10303                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10304                                                  dirent->name,
10305                                                  dirent->name_len & 0xFF,
10306                                                  fs->super->s_hash_seed,
10307                                                  &ent->hash, &ent->minor_hash);
10308                         if (fd->err)
10309                                 return BLOCK_ABORT;
10310                 }
10311         }
10312
10313         return 0;
10314 }
10315
10316 /* Used for sorting the hash entry */
10317 static int name_cmp(const void *a, const void *b)
10318 {
10319         const struct hash_entry *he_a = (const struct hash_entry *) a;
10320         const struct hash_entry *he_b = (const struct hash_entry *) b;
10321         int     ret;
10322         int     min_len;
10323
10324         min_len = he_a->dir->name_len;
10325         if (min_len > he_b->dir->name_len)
10326                 min_len = he_b->dir->name_len;
10327
10328         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10329         if (ret == 0) {
10330                 if (he_a->dir->name_len > he_b->dir->name_len)
10331                         ret = 1;
10332                 else if (he_a->dir->name_len < he_b->dir->name_len)
10333                         ret = -1;
10334                 else
10335                         ret = he_b->dir->inode - he_a->dir->inode;
10336         }
10337         return ret;
10338 }
10339
10340 /* Used for sorting the hash entry */
10341 static int hash_cmp(const void *a, const void *b)
10342 {
10343         const struct hash_entry *he_a = (const struct hash_entry *) a;
10344         const struct hash_entry *he_b = (const struct hash_entry *) b;
10345         int     ret;
10346
10347         if (he_a->hash > he_b->hash)
10348                 ret = 1;
10349         else if (he_a->hash < he_b->hash)
10350                 ret = -1;
10351         else {
10352                 if (he_a->minor_hash > he_b->minor_hash)
10353                         ret = 1;
10354                 else if (he_a->minor_hash < he_b->minor_hash)
10355                         ret = -1;
10356                 else
10357                         ret = name_cmp(a, b);
10358         }
10359         return ret;
10360 }
10361
10362 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10363                                 int blocks)
10364 {
10365         void                    *new_mem;
10366
10367         if (outdir->max) {
10368                 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10369                 outdir->buf = new_mem;
10370                 new_mem = xrealloc(outdir->hashes,
10371                                   blocks * sizeof(ext2_dirhash_t));
10372                 outdir->hashes = new_mem;
10373         } else {
10374                 outdir->buf = xmalloc(blocks * fs->blocksize);
10375                 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10376                 outdir->num = 0;
10377         }
10378         outdir->max = blocks;
10379         return 0;
10380 }
10381
10382 static void free_out_dir(struct out_dir *outdir)
10383 {
10384         free(outdir->buf);
10385         free(outdir->hashes);
10386         outdir->max = 0;
10387         outdir->num =0;
10388 }
10389
10390 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10391                          char ** ret)
10392 {
10393         errcode_t       retval;
10394
10395         if (outdir->num >= outdir->max) {
10396                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10397                 if (retval)
10398                         return retval;
10399         }
10400         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10401         memset(*ret, 0, fs->blocksize);
10402         return 0;
10403 }
10404
10405 /*
10406  * This function is used to make a unique filename.  We do this by
10407  * appending ~0, and then incrementing the number.  However, we cannot
10408  * expand the length of the filename beyond the padding available in
10409  * the directory entry.
10410  */
10411 static void mutate_name(char *str, __u16 *len)
10412 {
10413         int     i;
10414         __u16   l = *len & 0xFF, h = *len & 0xff00;
10415
10416         /*
10417          * First check to see if it looks the name has been mutated
10418          * already
10419          */
10420         for (i = l-1; i > 0; i--) {
10421                 if (!isdigit(str[i]))
10422                         break;
10423         }
10424         if ((i == l-1) || (str[i] != '~')) {
10425                 if (((l-1) & 3) < 2)
10426                         l += 2;
10427                 else
10428                         l = (l+3) & ~3;
10429                 str[l-2] = '~';
10430                 str[l-1] = '0';
10431                 *len = l | h;
10432                 return;
10433         }
10434         for (i = l-1; i >= 0; i--) {
10435                 if (isdigit(str[i])) {
10436                         if (str[i] == '9')
10437                                 str[i] = '0';
10438                         else {
10439                                 str[i]++;
10440                                 return;
10441                         }
10442                         continue;
10443                 }
10444                 if (i == 1) {
10445                         if (str[0] == 'z')
10446                                 str[0] = 'A';
10447                         else if (str[0] == 'Z') {
10448                                 str[0] = '~';
10449                                 str[1] = '0';
10450                         } else
10451                                 str[0]++;
10452                 } else if (i > 0) {
10453                         str[i] = '1';
10454                         str[i-1] = '~';
10455                 } else {
10456                         if (str[0] == '~')
10457                                 str[0] = 'a';
10458                         else
10459                                 str[0]++;
10460                 }
10461                 break;
10462         }
10463 }
10464
10465 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10466                                     ext2_ino_t ino,
10467                                     struct fill_dir_struct *fd)
10468 {
10469         struct problem_context  pctx;
10470         struct hash_entry       *ent, *prev;
10471         int                     i, j;
10472         int                     fixed = 0;
10473         char                    new_name[256];
10474         __u16                   new_len;
10475
10476         clear_problem_context(&pctx);
10477         pctx.ino = ino;
10478
10479         for (i=1; i < fd->num_array; i++) {
10480                 ent = fd->harray + i;
10481                 prev = ent - 1;
10482                 if (!ent->dir->inode ||
10483                     ((ent->dir->name_len & 0xFF) !=
10484                      (prev->dir->name_len & 0xFF)) ||
10485                     (strncmp(ent->dir->name, prev->dir->name,
10486                              ent->dir->name_len & 0xFF)))
10487                         continue;
10488                 pctx.dirent = ent->dir;
10489                 if ((ent->dir->inode == prev->dir->inode) &&
10490                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10491                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10492                         ent->dir->inode = 0;
10493                         fixed++;
10494                         continue;
10495                 }
10496                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10497                 new_len = ent->dir->name_len;
10498                 mutate_name(new_name, &new_len);
10499                 for (j=0; j < fd->num_array; j++) {
10500                         if ((i==j) ||
10501                             ((ent->dir->name_len & 0xFF) !=
10502                              (fd->harray[j].dir->name_len & 0xFF)) ||
10503                             (strncmp(new_name, fd->harray[j].dir->name,
10504                                      new_len & 0xFF)))
10505                                 continue;
10506                         mutate_name(new_name, &new_len);
10507
10508                         j = -1;
10509                 }
10510                 new_name[new_len & 0xFF] = 0;
10511                 pctx.str = new_name;
10512                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10513                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10514                         ent->dir->name_len = new_len;
10515                         ext2fs_dirhash(fs->super->s_def_hash_version,
10516                                        ent->dir->name,
10517                                        ent->dir->name_len & 0xFF,
10518                                        fs->super->s_hash_seed,
10519                                        &ent->hash, &ent->minor_hash);
10520                         fixed++;
10521                 }
10522         }
10523         return fixed;
10524 }
10525
10526
10527 static errcode_t copy_dir_entries(ext2_filsys fs,
10528                                   struct fill_dir_struct *fd,
10529                                   struct out_dir *outdir)
10530 {
10531         errcode_t               retval;
10532         char                    *block_start;
10533         struct hash_entry       *ent;
10534         struct ext2_dir_entry   *dirent;
10535         int                     i, rec_len, left;
10536         ext2_dirhash_t          prev_hash;
10537         int                     offset;
10538
10539         outdir->max = 0;
10540         retval = alloc_size_dir(fs, outdir,
10541                                 (fd->dir_size / fs->blocksize) + 2);
10542         if (retval)
10543                 return retval;
10544         outdir->num = fd->compress ? 0 : 1;
10545         offset = 0;
10546         outdir->hashes[0] = 0;
10547         prev_hash = 1;
10548         if ((retval = get_next_block(fs, outdir, &block_start)))
10549                 return retval;
10550         dirent = (struct ext2_dir_entry *) block_start;
10551         left = fs->blocksize;
10552         for (i=0; i < fd->num_array; i++) {
10553                 ent = fd->harray + i;
10554                 if (ent->dir->inode == 0)
10555                         continue;
10556                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10557                 if (rec_len > left) {
10558                         if (left)
10559                                 dirent->rec_len += left;
10560                         if ((retval = get_next_block(fs, outdir,
10561                                                       &block_start)))
10562                                 return retval;
10563                         offset = 0;
10564                 }
10565                 left = fs->blocksize - offset;
10566                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10567                 if (offset == 0) {
10568                         if (ent->hash == prev_hash)
10569                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10570                         else
10571                                 outdir->hashes[outdir->num-1] = ent->hash;
10572                 }
10573                 dirent->inode = ent->dir->inode;
10574                 dirent->name_len = ent->dir->name_len;
10575                 dirent->rec_len = rec_len;
10576                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10577                 offset += rec_len;
10578                 left -= rec_len;
10579                 if (left < 12) {
10580                         dirent->rec_len += left;
10581                         offset += left;
10582                         left = 0;
10583                 }
10584                 prev_hash = ent->hash;
10585         }
10586         if (left)
10587                 dirent->rec_len += left;
10588
10589         return 0;
10590 }
10591
10592
10593 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10594                                     ext2_ino_t ino, ext2_ino_t parent)
10595 {
10596         struct ext2_dir_entry           *dir;
10597         struct ext2_dx_root_info        *root;
10598         struct ext2_dx_countlimit       *limits;
10599         int                             filetype = 0;
10600
10601         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10602                 filetype = EXT2_FT_DIR << 8;
10603
10604         memset(buf, 0, fs->blocksize);
10605         dir = (struct ext2_dir_entry *) buf;
10606         dir->inode = ino;
10607         dir->name[0] = '.';
10608         dir->name_len = 1 | filetype;
10609         dir->rec_len = 12;
10610         dir = (struct ext2_dir_entry *) (buf + 12);
10611         dir->inode = parent;
10612         dir->name[0] = '.';
10613         dir->name[1] = '.';
10614         dir->name_len = 2 | filetype;
10615         dir->rec_len = fs->blocksize - 12;
10616
10617         root = (struct ext2_dx_root_info *) (buf+24);
10618         root->reserved_zero = 0;
10619         root->hash_version = fs->super->s_def_hash_version;
10620         root->info_length = 8;
10621         root->indirect_levels = 0;
10622         root->unused_flags = 0;
10623
10624         limits = (struct ext2_dx_countlimit *) (buf+32);
10625         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10626         limits->count = 0;
10627
10628         return root;
10629 }
10630
10631
10632 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10633 {
10634         struct ext2_dir_entry           *dir;
10635         struct ext2_dx_countlimit       *limits;
10636
10637         memset(buf, 0, fs->blocksize);
10638         dir = (struct ext2_dir_entry *) buf;
10639         dir->inode = 0;
10640         dir->rec_len = fs->blocksize;
10641
10642         limits = (struct ext2_dx_countlimit *) (buf+8);
10643         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10644         limits->count = 0;
10645
10646         return (struct ext2_dx_entry *) limits;
10647 }
10648
10649 /*
10650  * This function takes the leaf nodes which have been written in
10651  * outdir, and populates the root node and any necessary interior nodes.
10652  */
10653 static errcode_t calculate_tree(ext2_filsys fs,
10654                                 struct out_dir *outdir,
10655                                 ext2_ino_t ino,
10656                                 ext2_ino_t parent)
10657 {
10658         struct ext2_dx_root_info        *root_info;
10659         struct ext2_dx_entry            *root, *dx_ent = NULL;
10660         struct ext2_dx_countlimit       *root_limit, *limit;
10661         errcode_t                       retval;
10662         char                            * block_start;
10663         int                             i, c1, c2, nblks;
10664         int                             limit_offset, root_offset;
10665
10666         root_info = set_root_node(fs, outdir->buf, ino, parent);
10667         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10668                 root_info->info_length;
10669         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10670         c1 = root_limit->limit;
10671         nblks = outdir->num;
10672
10673         /* Write out the pointer blocks */
10674         if (nblks-1 <= c1) {
10675                 /* Just write out the root block, and we're done */
10676                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10677                 for (i=1; i < nblks; i++) {
10678                         root->block = ext2fs_cpu_to_le32(i);
10679                         if (i != 1)
10680                                 root->hash =
10681                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10682                         root++;
10683                         c1--;
10684                 }
10685         } else {
10686                 c2 = 0;
10687                 limit = 0;
10688                 root_info->indirect_levels = 1;
10689                 for (i=1; i < nblks; i++) {
10690                         if (c1 == 0)
10691                                 return ENOSPC;
10692                         if (c2 == 0) {
10693                                 if (limit)
10694                                         limit->limit = limit->count =
10695                 ext2fs_cpu_to_le16(limit->limit);
10696                                 root = (struct ext2_dx_entry *)
10697                                         (outdir->buf + root_offset);
10698                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10699                                 if (i != 1)
10700                                         root->hash =
10701                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10702                                 if ((retval =  get_next_block(fs, outdir,
10703                                                               &block_start)))
10704                                         return retval;
10705                                 dx_ent = set_int_node(fs, block_start);
10706                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10707                                 c2 = limit->limit;
10708                                 root_offset += sizeof(struct ext2_dx_entry);
10709                                 c1--;
10710                         }
10711                         dx_ent->block = ext2fs_cpu_to_le32(i);
10712                         if (c2 != limit->limit)
10713                                 dx_ent->hash =
10714                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10715                         dx_ent++;
10716                         c2--;
10717                 }
10718                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10719                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10720         }
10721         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10722         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10723         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10724
10725         return 0;
10726 }
10727
10728 struct write_dir_struct {
10729         struct out_dir *outdir;
10730         errcode_t       err;
10731         e2fsck_t        ctx;
10732         int             cleared;
10733 };
10734
10735 /*
10736  * Helper function which writes out a directory block.
10737  */
10738 static int write_dir_block(ext2_filsys fs,
10739                            blk_t        *block_nr,
10740                            e2_blkcnt_t blockcnt,
10741                            blk_t ref_block FSCK_ATTR((unused)),
10742                            int ref_offset FSCK_ATTR((unused)),
10743                            void *priv_data)
10744 {
10745         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10746         blk_t   blk;
10747         char    *dir;
10748
10749         if (*block_nr == 0)
10750                 return 0;
10751         if (blockcnt >= wd->outdir->num) {
10752                 e2fsck_read_bitmaps(wd->ctx);
10753                 blk = *block_nr;
10754                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10755                 ext2fs_block_alloc_stats(fs, blk, -1);
10756                 *block_nr = 0;
10757                 wd->cleared++;
10758                 return BLOCK_CHANGED;
10759         }
10760         if (blockcnt < 0)
10761                 return 0;
10762
10763         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10764         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10765         if (wd->err)
10766                 return BLOCK_ABORT;
10767         return 0;
10768 }
10769
10770 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10771                                  struct out_dir *outdir,
10772                                  ext2_ino_t ino, int compress)
10773 {
10774         struct write_dir_struct wd;
10775         errcode_t       retval;
10776         struct ext2_inode       inode;
10777
10778         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10779         if (retval)
10780                 return retval;
10781
10782         wd.outdir = outdir;
10783         wd.err = 0;
10784         wd.ctx = ctx;
10785         wd.cleared = 0;
10786
10787         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10788                                        write_dir_block, &wd);
10789         if (retval)
10790                 return retval;
10791         if (wd.err)
10792                 return wd.err;
10793
10794         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10795         if (compress)
10796                 inode.i_flags &= ~EXT2_INDEX_FL;
10797         else
10798                 inode.i_flags |= EXT2_INDEX_FL;
10799         inode.i_size = outdir->num * fs->blocksize;
10800         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10801         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10802
10803         return 0;
10804 }
10805
10806 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10807 {
10808         ext2_filsys             fs = ctx->fs;
10809         errcode_t               retval;
10810         struct ext2_inode       inode;
10811         char                    *dir_buf = NULL;
10812         struct fill_dir_struct  fd;
10813         struct out_dir          outdir;
10814
10815         outdir.max = outdir.num = 0;
10816         outdir.buf = 0;
10817         outdir.hashes = 0;
10818         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10819
10820         retval = ENOMEM;
10821         fd.harray = 0;
10822         dir_buf = xmalloc(inode.i_size);
10823
10824         fd.max_array = inode.i_size / 32;
10825         fd.num_array = 0;
10826         fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10827
10828         fd.ctx = ctx;
10829         fd.buf = dir_buf;
10830         fd.inode = &inode;
10831         fd.err = 0;
10832         fd.dir_size = 0;
10833         fd.compress = 0;
10834         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10835             (inode.i_size / fs->blocksize) < 2)
10836                 fd.compress = 1;
10837         fd.parent = 0;
10838
10839         /* Read in the entire directory into memory */
10840         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10841                                        fill_dir_block, &fd);
10842         if (fd.err) {
10843                 retval = fd.err;
10844                 goto errout;
10845         }
10846
10847         /* Sort the list */
10848 resort:
10849         if (fd.compress)
10850                 qsort(fd.harray+2, fd.num_array-2,
10851                       sizeof(struct hash_entry), name_cmp);
10852         else
10853                 qsort(fd.harray, fd.num_array,
10854                       sizeof(struct hash_entry), hash_cmp);
10855
10856         /*
10857          * Look for duplicates
10858          */
10859         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10860                 goto resort;
10861
10862         if (ctx->options & E2F_OPT_NO) {
10863                 retval = 0;
10864                 goto errout;
10865         }
10866
10867         /*
10868          * Copy the directory entries.  In a htree directory these
10869          * will become the leaf nodes.
10870          */
10871         retval = copy_dir_entries(fs, &fd, &outdir);
10872         if (retval)
10873                 goto errout;
10874
10875         free(dir_buf); dir_buf = 0;
10876
10877         if (!fd.compress) {
10878                 /* Calculate the interior nodes */
10879                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10880                 if (retval)
10881                         goto errout;
10882         }
10883
10884         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10885
10886 errout:
10887         free(dir_buf);
10888         free(fd.harray);
10889
10890         free_out_dir(&outdir);
10891         return retval;
10892 }
10893
10894 void e2fsck_rehash_directories(e2fsck_t ctx)
10895 {
10896         struct problem_context  pctx;
10897         struct dir_info         *dir;
10898         ext2_u32_iterate        iter;
10899         ext2_ino_t              ino;
10900         errcode_t               retval;
10901         int                     i, cur, max, all_dirs, dir_index, first = 1;
10902
10903         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10904
10905         if (!ctx->dirs_to_hash && !all_dirs)
10906                 return;
10907
10908         e2fsck_get_lost_and_found(ctx, 0);
10909
10910         clear_problem_context(&pctx);
10911
10912         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10913         cur = 0;
10914         if (all_dirs) {
10915                 i = 0;
10916                 max = e2fsck_get_num_dirinfo(ctx);
10917         } else {
10918                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10919                                                        &iter);
10920                 if (retval) {
10921                         pctx.errcode = retval;
10922                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10923                         return;
10924                 }
10925                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10926         }
10927         while (1) {
10928                 if (all_dirs) {
10929                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10930                                 break;
10931                         ino = dir->ino;
10932                 } else {
10933                         if (!ext2fs_u32_list_iterate(iter, &ino))
10934                                 break;
10935                 }
10936                 if (ino == ctx->lost_and_found)
10937                         continue;
10938                 pctx.dir = ino;
10939                 if (first) {
10940                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10941                         first = 0;
10942                 }
10943                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10944                 if (pctx.errcode) {
10945                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10946                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10947                 }
10948                 if (ctx->progress && !ctx->progress_fd)
10949                         e2fsck_simple_progress(ctx, "Rebuilding directory",
10950                                100.0 * (float) (++cur) / (float) max, ino);
10951         }
10952         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10953         if (!all_dirs)
10954                 ext2fs_u32_list_iterate_end(iter);
10955
10956         ext2fs_u32_list_free(ctx->dirs_to_hash);
10957         ctx->dirs_to_hash = 0;
10958 }
10959
10960 /*
10961  * linux/fs/revoke.c
10962  *
10963  * Journal revoke routines for the generic filesystem journaling code;
10964  * part of the ext2fs journaling system.
10965  *
10966  * Revoke is the mechanism used to prevent old log records for deleted
10967  * metadata from being replayed on top of newer data using the same
10968  * blocks.  The revoke mechanism is used in two separate places:
10969  *
10970  * + Commit: during commit we write the entire list of the current
10971  *   transaction's revoked blocks to the journal
10972  *
10973  * + Recovery: during recovery we record the transaction ID of all
10974  *   revoked blocks.  If there are multiple revoke records in the log
10975  *   for a single block, only the last one counts, and if there is a log
10976  *   entry for a block beyond the last revoke, then that log entry still
10977  *   gets replayed.
10978  *
10979  * We can get interactions between revokes and new log data within a
10980  * single transaction:
10981  *
10982  * Block is revoked and then journaled:
10983  *   The desired end result is the journaling of the new block, so we
10984  *   cancel the revoke before the transaction commits.
10985  *
10986  * Block is journaled and then revoked:
10987  *   The revoke must take precedence over the write of the block, so we
10988  *   need either to cancel the journal entry or to write the revoke
10989  *   later in the log than the log block.  In this case, we choose the
10990  *   latter: journaling a block cancels any revoke record for that block
10991  *   in the current transaction, so any revoke for that block in the
10992  *   transaction must have happened after the block was journaled and so
10993  *   the revoke must take precedence.
10994  *
10995  * Block is revoked and then written as data:
10996  *   The data write is allowed to succeed, but the revoke is _not_
10997  *   cancelled.  We still need to prevent old log records from
10998  *   overwriting the new data.  We don't even need to clear the revoke
10999  *   bit here.
11000  *
11001  * Revoke information on buffers is a tri-state value:
11002  *
11003  * RevokeValid clear:   no cached revoke status, need to look it up
11004  * RevokeValid set, Revoked clear:
11005  *                      buffer has not been revoked, and cancel_revoke
11006  *                      need do nothing.
11007  * RevokeValid set, Revoked set:
11008  *                      buffer has been revoked.
11009  */
11010
11011 static kmem_cache_t *revoke_record_cache;
11012 static kmem_cache_t *revoke_table_cache;
11013
11014 /* Each revoke record represents one single revoked block.  During
11015    journal replay, this involves recording the transaction ID of the
11016    last transaction to revoke this block. */
11017
11018 struct jbd_revoke_record_s
11019 {
11020         struct list_head  hash;
11021         tid_t             sequence;     /* Used for recovery only */
11022         unsigned long     blocknr;
11023 };
11024
11025
11026 /* The revoke table is just a simple hash table of revoke records. */
11027 struct jbd_revoke_table_s
11028 {
11029         /* It is conceivable that we might want a larger hash table
11030          * for recovery.  Must be a power of two. */
11031         int               hash_size;
11032         int               hash_shift;
11033         struct list_head *hash_table;
11034 };
11035
11036
11037 /* Utility functions to maintain the revoke table */
11038
11039 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11040 static int hash(journal_t *journal, unsigned long block)
11041 {
11042         struct jbd_revoke_table_s *table = journal->j_revoke;
11043         int hash_shift = table->hash_shift;
11044
11045         return ((block << (hash_shift - 6)) ^
11046                 (block >> 13) ^
11047                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11048 }
11049
11050 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11051                               tid_t seq)
11052 {
11053         struct list_head *hash_list;
11054         struct jbd_revoke_record_s *record;
11055
11056         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11057         if (!record)
11058                 goto oom;
11059
11060         record->sequence = seq;
11061         record->blocknr = blocknr;
11062         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11063         list_add(&record->hash, hash_list);
11064         return 0;
11065
11066 oom:
11067         return -ENOMEM;
11068 }
11069
11070 /* Find a revoke record in the journal's hash table. */
11071
11072 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11073                                                       unsigned long blocknr)
11074 {
11075         struct list_head *hash_list;
11076         struct jbd_revoke_record_s *record;
11077
11078         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11079
11080         record = (struct jbd_revoke_record_s *) hash_list->next;
11081         while (&(record->hash) != hash_list) {
11082                 if (record->blocknr == blocknr)
11083                         return record;
11084                 record = (struct jbd_revoke_record_s *) record->hash.next;
11085         }
11086         return NULL;
11087 }
11088
11089 int journal_init_revoke_caches(void)
11090 {
11091         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11092         if (revoke_record_cache == 0)
11093                 return -ENOMEM;
11094
11095         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11096         if (revoke_table_cache == 0) {
11097                 do_cache_destroy(revoke_record_cache);
11098                 revoke_record_cache = NULL;
11099                 return -ENOMEM;
11100         }
11101         return 0;
11102 }
11103
11104 void journal_destroy_revoke_caches(void)
11105 {
11106         do_cache_destroy(revoke_record_cache);
11107         revoke_record_cache = 0;
11108         do_cache_destroy(revoke_table_cache);
11109         revoke_table_cache = 0;
11110 }
11111
11112 /* Initialise the revoke table for a given journal to a given size. */
11113
11114 int journal_init_revoke(journal_t *journal, int hash_size)
11115 {
11116         int shift, tmp;
11117
11118         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11119         if (!journal->j_revoke)
11120                 return -ENOMEM;
11121
11122         /* Check that the hash_size is a power of two */
11123         journal->j_revoke->hash_size = hash_size;
11124
11125         shift = 0;
11126         tmp = hash_size;
11127         while ((tmp >>= 1UL) != 0UL)
11128                 shift++;
11129         journal->j_revoke->hash_shift = shift;
11130
11131         journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11132
11133         for (tmp = 0; tmp < hash_size; tmp++)
11134                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11135
11136         return 0;
11137 }
11138
11139 /* Destoy a journal's revoke table.  The table must already be empty! */
11140
11141 void journal_destroy_revoke(journal_t *journal)
11142 {
11143         struct jbd_revoke_table_s *table;
11144         struct list_head *hash_list;
11145         int i;
11146
11147         table = journal->j_revoke;
11148         if (!table)
11149                 return;
11150
11151         for (i=0; i<table->hash_size; i++) {
11152                 hash_list = &table->hash_table[i];
11153         }
11154
11155         free(table->hash_table);
11156         free(table);
11157         journal->j_revoke = NULL;
11158 }
11159
11160 /*
11161  * Revoke support for recovery.
11162  *
11163  * Recovery needs to be able to:
11164  *
11165  *  record all revoke records, including the tid of the latest instance
11166  *  of each revoke in the journal
11167  *
11168  *  check whether a given block in a given transaction should be replayed
11169  *  (ie. has not been revoked by a revoke record in that or a subsequent
11170  *  transaction)
11171  *
11172  *  empty the revoke table after recovery.
11173  */
11174
11175 /*
11176  * First, setting revoke records.  We create a new revoke record for
11177  * every block ever revoked in the log as we scan it for recovery, and
11178  * we update the existing records if we find multiple revokes for a
11179  * single block.
11180  */
11181
11182 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11183                        tid_t sequence)
11184 {
11185         struct jbd_revoke_record_s *record;
11186
11187         record = find_revoke_record(journal, blocknr);
11188         if (record) {
11189                 /* If we have multiple occurences, only record the
11190                  * latest sequence number in the hashed record */
11191                 if (tid_gt(sequence, record->sequence))
11192                         record->sequence = sequence;
11193                 return 0;
11194         }
11195         return insert_revoke_hash(journal, blocknr, sequence);
11196 }
11197
11198 /*
11199  * Test revoke records.  For a given block referenced in the log, has
11200  * that block been revoked?  A revoke record with a given transaction
11201  * sequence number revokes all blocks in that transaction and earlier
11202  * ones, but later transactions still need replayed.
11203  */
11204
11205 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11206                         tid_t sequence)
11207 {
11208         struct jbd_revoke_record_s *record;
11209
11210         record = find_revoke_record(journal, blocknr);
11211         if (!record)
11212                 return 0;
11213         if (tid_gt(sequence, record->sequence))
11214                 return 0;
11215         return 1;
11216 }
11217
11218 /*
11219  * Finally, once recovery is over, we need to clear the revoke table so
11220  * that it can be reused by the running filesystem.
11221  */
11222
11223 void journal_clear_revoke(journal_t *journal)
11224 {
11225         int i;
11226         struct list_head *hash_list;
11227         struct jbd_revoke_record_s *record;
11228         struct jbd_revoke_table_s *revoke_var;
11229
11230         revoke_var = journal->j_revoke;
11231
11232         for (i = 0; i < revoke_var->hash_size; i++) {
11233                 hash_list = &revoke_var->hash_table[i];
11234                 while (!list_empty(hash_list)) {
11235                         record = (struct jbd_revoke_record_s*) hash_list->next;
11236                         list_del(&record->hash);
11237                         free(record);
11238                 }
11239         }
11240 }
11241
11242 /*
11243  * e2fsck.c - superblock checks
11244  */
11245
11246 #define MIN_CHECK 1
11247 #define MAX_CHECK 2
11248
11249 static void check_super_value(e2fsck_t ctx, const char *descr,
11250                               unsigned long value, int flags,
11251                               unsigned long min_val, unsigned long max_val)
11252 {
11253         struct          problem_context pctx;
11254
11255         if (((flags & MIN_CHECK) && (value < min_val)) ||
11256             ((flags & MAX_CHECK) && (value > max_val))) {
11257                 clear_problem_context(&pctx);
11258                 pctx.num = value;
11259                 pctx.str = descr;
11260                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11261                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11262         }
11263 }
11264
11265 /*
11266  * This routine may get stubbed out in special compilations of the
11267  * e2fsck code..
11268  */
11269 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11270 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11271 {
11272         return (ext2fs_get_device_size(ctx->filesystem_name,
11273                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11274                                        &ctx->num_blocks));
11275 }
11276 #endif
11277
11278 /*
11279  * helper function to release an inode
11280  */
11281 struct process_block_struct {
11282         e2fsck_t        ctx;
11283         char            *buf;
11284         struct problem_context *pctx;
11285         int             truncating;
11286         int             truncate_offset;
11287         e2_blkcnt_t     truncate_block;
11288         int             truncated_blocks;
11289         int             abort;
11290         errcode_t       errcode;
11291 };
11292
11293 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11294                                e2_blkcnt_t blockcnt,
11295                                blk_t    ref_blk FSCK_ATTR((unused)),
11296                                int      ref_offset FSCK_ATTR((unused)),
11297                                void *priv_data)
11298 {
11299         struct process_block_struct *pb;
11300         e2fsck_t                ctx;
11301         struct problem_context  *pctx;
11302         blk_t                   blk = *block_nr;
11303         int                     retval = 0;
11304
11305         pb = (struct process_block_struct *) priv_data;
11306         ctx = pb->ctx;
11307         pctx = pb->pctx;
11308
11309         pctx->blk = blk;
11310         pctx->blkcount = blockcnt;
11311
11312         if (HOLE_BLKADDR(blk))
11313                 return 0;
11314
11315         if ((blk < fs->super->s_first_data_block) ||
11316             (blk >= fs->super->s_blocks_count)) {
11317                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11318  return_abort:
11319                 pb->abort = 1;
11320                 return BLOCK_ABORT;
11321         }
11322
11323         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11324                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11325                 goto return_abort;
11326         }
11327
11328         /*
11329          * If we are deleting an orphan, then we leave the fields alone.
11330          * If we are truncating an orphan, then update the inode fields
11331          * and clean up any partial block data.
11332          */
11333         if (pb->truncating) {
11334                 /*
11335                  * We only remove indirect blocks if they are
11336                  * completely empty.
11337                  */
11338                 if (blockcnt < 0) {
11339                         int     i, limit;
11340                         blk_t   *bp;
11341
11342                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11343                                                         pb->buf);
11344                         if (pb->errcode)
11345                                 goto return_abort;
11346
11347                         limit = fs->blocksize >> 2;
11348                         for (i = 0, bp = (blk_t *) pb->buf;
11349                              i < limit;  i++, bp++)
11350                                 if (*bp)
11351                                         return 0;
11352                 }
11353                 /*
11354                  * We don't remove direct blocks until we've reached
11355                  * the truncation block.
11356                  */
11357                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11358                         return 0;
11359                 /*
11360                  * If part of the last block needs truncating, we do
11361                  * it here.
11362                  */
11363                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11364                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11365                                                         pb->buf);
11366                         if (pb->errcode)
11367                                 goto return_abort;
11368                         memset(pb->buf + pb->truncate_offset, 0,
11369                                fs->blocksize - pb->truncate_offset);
11370                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11371                                                          pb->buf);
11372                         if (pb->errcode)
11373                                 goto return_abort;
11374                 }
11375                 pb->truncated_blocks++;
11376                 *block_nr = 0;
11377                 retval |= BLOCK_CHANGED;
11378         }
11379
11380         ext2fs_block_alloc_stats(fs, blk, -1);
11381         return retval;
11382 }
11383
11384 /*
11385  * This function releases an inode.  Returns 1 if an inconsistency was
11386  * found.  If the inode has a link count, then it is being truncated and
11387  * not deleted.
11388  */
11389 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11390                                 struct ext2_inode *inode, char *block_buf,
11391                                 struct problem_context *pctx)
11392 {
11393         struct process_block_struct     pb;
11394         ext2_filsys                     fs = ctx->fs;
11395         errcode_t                       retval;
11396         __u32                           count;
11397
11398         if (!ext2fs_inode_has_valid_blocks(inode))
11399                 return 0;
11400
11401         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11402         pb.ctx = ctx;
11403         pb.abort = 0;
11404         pb.errcode = 0;
11405         pb.pctx = pctx;
11406         if (inode->i_links_count) {
11407                 pb.truncating = 1;
11408                 pb.truncate_block = (e2_blkcnt_t)
11409                         ((((long long)inode->i_size_high << 32) +
11410                           inode->i_size + fs->blocksize - 1) /
11411                          fs->blocksize);
11412                 pb.truncate_offset = inode->i_size % fs->blocksize;
11413         } else {
11414                 pb.truncating = 0;
11415                 pb.truncate_block = 0;
11416                 pb.truncate_offset = 0;
11417         }
11418         pb.truncated_blocks = 0;
11419         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11420                                       block_buf, release_inode_block, &pb);
11421         if (retval) {
11422                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11423                         ino);
11424                 return 1;
11425         }
11426         if (pb.abort)
11427                 return 1;
11428
11429         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11430         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11431
11432         if (pb.truncated_blocks)
11433                 inode->i_blocks -= pb.truncated_blocks *
11434                         (fs->blocksize / 512);
11435
11436         if (inode->i_file_acl) {
11437                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11438                                                    block_buf, -1, &count);
11439                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11440                         retval = 0;
11441                         count = 1;
11442                 }
11443                 if (retval) {
11444                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11445                                 ino);
11446                         return 1;
11447                 }
11448                 if (count == 0)
11449                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11450                 inode->i_file_acl = 0;
11451         }
11452         return 0;
11453 }
11454
11455 /*
11456  * This function releases all of the orphan inodes.  It returns 1 if
11457  * it hit some error, and 0 on success.
11458  */
11459 static int release_orphan_inodes(e2fsck_t ctx)
11460 {
11461         ext2_filsys fs = ctx->fs;
11462         ext2_ino_t      ino, next_ino;
11463         struct ext2_inode inode;
11464         struct problem_context pctx;
11465         char *block_buf;
11466
11467         if ((ino = fs->super->s_last_orphan) == 0)
11468                 return 0;
11469
11470         /*
11471          * Win or lose, we won't be using the head of the orphan inode
11472          * list again.
11473          */
11474         fs->super->s_last_orphan = 0;
11475         ext2fs_mark_super_dirty(fs);
11476
11477         /*
11478          * If the filesystem contains errors, don't run the orphan
11479          * list, since the orphan list can't be trusted; and we're
11480          * going to be running a full e2fsck run anyway...
11481          */
11482         if (fs->super->s_state & EXT2_ERROR_FS)
11483                 return 0;
11484
11485         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11486             (ino > fs->super->s_inodes_count)) {
11487                 clear_problem_context(&pctx);
11488                 pctx.ino = ino;
11489                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11490                 return 1;
11491         }
11492
11493         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11494                                                     "block iterate buffer");
11495         e2fsck_read_bitmaps(ctx);
11496
11497         while (ino) {
11498                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11499                 clear_problem_context(&pctx);
11500                 pctx.ino = ino;
11501                 pctx.inode = &inode;
11502                 pctx.str = inode.i_links_count ? _("Truncating") :
11503                         _("Clearing");
11504
11505                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11506
11507                 next_ino = inode.i_dtime;
11508                 if (next_ino &&
11509                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11510                      (next_ino > fs->super->s_inodes_count))) {
11511                         pctx.ino = next_ino;
11512                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11513                         goto return_abort;
11514                 }
11515
11516                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11517                         goto return_abort;
11518
11519                 if (!inode.i_links_count) {
11520                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11521                                                   LINUX_S_ISDIR(inode.i_mode));
11522                         inode.i_dtime = time(NULL);
11523                 } else {
11524                         inode.i_dtime = 0;
11525                 }
11526                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11527                 ino = next_ino;
11528         }
11529         ext2fs_free_mem(&block_buf);
11530         return 0;
11531  return_abort:
11532         ext2fs_free_mem(&block_buf);
11533         return 1;
11534 }
11535
11536 /*
11537  * Check the resize inode to make sure it is sane.  We check both for
11538  * the case where on-line resizing is not enabled (in which case the
11539  * resize inode should be cleared) as well as the case where on-line
11540  * resizing is enabled.
11541  */
11542 static void check_resize_inode(e2fsck_t ctx)
11543 {
11544         ext2_filsys fs = ctx->fs;
11545         struct ext2_inode inode;
11546         struct problem_context  pctx;
11547         int             i, j, gdt_off, ind_off;
11548         blk_t           blk, pblk, expect;
11549         __u32           *dind_buf = NULL, *ind_buf;
11550         errcode_t       retval;
11551
11552         clear_problem_context(&pctx);
11553
11554         /*
11555          * If the resize inode feature isn't set, then
11556          * s_reserved_gdt_blocks must be zero.
11557          */
11558         if (!(fs->super->s_feature_compat &
11559               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11560                 if (fs->super->s_reserved_gdt_blocks) {
11561                         pctx.num = fs->super->s_reserved_gdt_blocks;
11562                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11563                                         &pctx)) {
11564                                 fs->super->s_reserved_gdt_blocks = 0;
11565                                 ext2fs_mark_super_dirty(fs);
11566                         }
11567                 }
11568         }
11569
11570         /* Read the resize inode */
11571         pctx.ino = EXT2_RESIZE_INO;
11572         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11573         if (retval) {
11574                 if (fs->super->s_feature_compat &
11575                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11576                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11577                 return;
11578         }
11579
11580         /*
11581          * If the resize inode feature isn't set, check to make sure
11582          * the resize inode is cleared; then we're done.
11583          */
11584         if (!(fs->super->s_feature_compat &
11585               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11586                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11587                         if (inode.i_block[i])
11588                                 break;
11589                 }
11590                 if ((i < EXT2_N_BLOCKS) &&
11591                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11592                         memset(&inode, 0, sizeof(inode));
11593                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11594                                            "clear_resize");
11595                 }
11596                 return;
11597         }
11598
11599         /*
11600          * The resize inode feature is enabled; check to make sure the
11601          * only block in use is the double indirect block
11602          */
11603         blk = inode.i_block[EXT2_DIND_BLOCK];
11604         for (i=0; i < EXT2_N_BLOCKS; i++) {
11605                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11606                         break;
11607         }
11608         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11609             !(inode.i_mode & LINUX_S_IFREG) ||
11610             (blk < fs->super->s_first_data_block ||
11611              blk >= fs->super->s_blocks_count)) {
11612  resize_inode_invalid:
11613                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11614                         memset(&inode, 0, sizeof(inode));
11615                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11616                                            "clear_resize");
11617                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11618                 }
11619                 if (!(ctx->options & E2F_OPT_READONLY)) {
11620                         fs->super->s_state &= ~EXT2_VALID_FS;
11621                         ext2fs_mark_super_dirty(fs);
11622                 }
11623                 goto cleanup;
11624         }
11625         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11626                                                     "resize dind buffer");
11627         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11628
11629         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11630         if (retval)
11631                 goto resize_inode_invalid;
11632
11633         gdt_off = fs->desc_blocks;
11634         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11635         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11636              i++, gdt_off++, pblk++) {
11637                 gdt_off %= fs->blocksize/4;
11638                 if (dind_buf[gdt_off] != pblk)
11639                         goto resize_inode_invalid;
11640                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11641                 if (retval)
11642                         goto resize_inode_invalid;
11643                 ind_off = 0;
11644                 for (j = 1; j < fs->group_desc_count; j++) {
11645                         if (!ext2fs_bg_has_super(fs, j))
11646                                 continue;
11647                         expect = pblk + (j * fs->super->s_blocks_per_group);
11648                         if (ind_buf[ind_off] != expect)
11649                                 goto resize_inode_invalid;
11650                         ind_off++;
11651                 }
11652         }
11653
11654  cleanup:
11655         ext2fs_free_mem(&dind_buf);
11656 }
11657
11658 static void check_super_block(e2fsck_t ctx)
11659 {
11660         ext2_filsys fs = ctx->fs;
11661         blk_t   first_block, last_block;
11662         struct ext2_super_block *sb = fs->super;
11663         struct ext2_group_desc *gd;
11664         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11665         blk_t   bpg_max;
11666         int     inodes_per_block;
11667         int     ipg_max;
11668         int     inode_size;
11669         dgrp_t  i;
11670         blk_t   should_be;
11671         struct problem_context  pctx;
11672         __u32   free_blocks = 0, free_inodes = 0;
11673
11674         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11675         ipg_max = inodes_per_block * (blocks_per_group - 4);
11676         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11677                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11678         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11679         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11680                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11681
11682         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11683                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11684         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11685                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11686         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11687                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11688
11689         clear_problem_context(&pctx);
11690
11691         /*
11692          * Verify the super block constants...
11693          */
11694         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11695                           MIN_CHECK, 1, 0);
11696         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11697                           MIN_CHECK, 1, 0);
11698         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11699                           MAX_CHECK, 0, sb->s_blocks_count);
11700         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11701                           MIN_CHECK | MAX_CHECK, 0,
11702                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11703         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11704                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11705         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11706                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11707                           bpg_max);
11708         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11709                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11710         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11711                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11712         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11713                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11714         check_super_value(ctx, "reserved_gdt_blocks",
11715                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11716                           fs->blocksize/4);
11717         inode_size = EXT2_INODE_SIZE(sb);
11718         check_super_value(ctx, "inode_size",
11719                           inode_size, MIN_CHECK | MAX_CHECK,
11720                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11721         if (inode_size & (inode_size - 1)) {
11722                 pctx.num = inode_size;
11723                 pctx.str = "inode_size";
11724                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11725                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11726                 return;
11727         }
11728
11729         if (!ctx->num_blocks) {
11730                 pctx.errcode = e2fsck_get_device_size(ctx);
11731                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11732                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11733                         ctx->flags |= E2F_FLAG_ABORT;
11734                         return;
11735                 }
11736                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11737                     (ctx->num_blocks < sb->s_blocks_count)) {
11738                         pctx.blk = sb->s_blocks_count;
11739                         pctx.blk2 = ctx->num_blocks;
11740                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11741                                 ctx->flags |= E2F_FLAG_ABORT;
11742                                 return;
11743                         }
11744                 }
11745         }
11746
11747         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11748                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11749                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11750                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11751                 ctx->flags |= E2F_FLAG_ABORT;
11752                 return;
11753         }
11754
11755         should_be = sb->s_frags_per_group >>
11756                 (sb->s_log_block_size - sb->s_log_frag_size);
11757         if (sb->s_blocks_per_group != should_be) {
11758                 pctx.blk = sb->s_blocks_per_group;
11759                 pctx.blk2 = should_be;
11760                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11761                 ctx->flags |= E2F_FLAG_ABORT;
11762                 return;
11763         }
11764
11765         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11766         if (sb->s_first_data_block != should_be) {
11767                 pctx.blk = sb->s_first_data_block;
11768                 pctx.blk2 = should_be;
11769                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11770                 ctx->flags |= E2F_FLAG_ABORT;
11771                 return;
11772         }
11773
11774         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11775         if (sb->s_inodes_count != should_be) {
11776                 pctx.ino = sb->s_inodes_count;
11777                 pctx.ino2 = should_be;
11778                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11779                         sb->s_inodes_count = should_be;
11780                         ext2fs_mark_super_dirty(fs);
11781                 }
11782         }
11783
11784         /*
11785          * Verify the group descriptors....
11786          */
11787         first_block =  sb->s_first_data_block;
11788         last_block = first_block + blocks_per_group;
11789
11790         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11791                 pctx.group = i;
11792
11793                 if (i == fs->group_desc_count - 1)
11794                         last_block = sb->s_blocks_count;
11795                 if ((gd->bg_block_bitmap < first_block) ||
11796                     (gd->bg_block_bitmap >= last_block)) {
11797                         pctx.blk = gd->bg_block_bitmap;
11798                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11799                                 gd->bg_block_bitmap = 0;
11800                 }
11801                 if (gd->bg_block_bitmap == 0) {
11802                         ctx->invalid_block_bitmap_flag[i]++;
11803                         ctx->invalid_bitmaps++;
11804                 }
11805                 if ((gd->bg_inode_bitmap < first_block) ||
11806                     (gd->bg_inode_bitmap >= last_block)) {
11807                         pctx.blk = gd->bg_inode_bitmap;
11808                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11809                                 gd->bg_inode_bitmap = 0;
11810                 }
11811                 if (gd->bg_inode_bitmap == 0) {
11812                         ctx->invalid_inode_bitmap_flag[i]++;
11813                         ctx->invalid_bitmaps++;
11814                 }
11815                 if ((gd->bg_inode_table < first_block) ||
11816                     ((gd->bg_inode_table +
11817                       fs->inode_blocks_per_group - 1) >= last_block)) {
11818                         pctx.blk = gd->bg_inode_table;
11819                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11820                                 gd->bg_inode_table = 0;
11821                 }
11822                 if (gd->bg_inode_table == 0) {
11823                         ctx->invalid_inode_table_flag[i]++;
11824                         ctx->invalid_bitmaps++;
11825                 }
11826                 free_blocks += gd->bg_free_blocks_count;
11827                 free_inodes += gd->bg_free_inodes_count;
11828                 first_block += sb->s_blocks_per_group;
11829                 last_block += sb->s_blocks_per_group;
11830
11831                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11832                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11833                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11834                         ext2fs_unmark_valid(fs);
11835         }
11836
11837         /*
11838          * Update the global counts from the block group counts.  This
11839          * is needed for an experimental patch which eliminates
11840          * locking the entire filesystem when allocating blocks or
11841          * inodes; if the filesystem is not unmounted cleanly, the
11842          * global counts may not be accurate.
11843          */
11844         if ((free_blocks != sb->s_free_blocks_count) ||
11845             (free_inodes != sb->s_free_inodes_count)) {
11846                 if (ctx->options & E2F_OPT_READONLY)
11847                         ext2fs_unmark_valid(fs);
11848                 else {
11849                         sb->s_free_blocks_count = free_blocks;
11850                         sb->s_free_inodes_count = free_inodes;
11851                         ext2fs_mark_super_dirty(fs);
11852                 }
11853         }
11854
11855         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11856             (sb->s_free_inodes_count > sb->s_inodes_count))
11857                 ext2fs_unmark_valid(fs);
11858
11859
11860         /*
11861          * If we have invalid bitmaps, set the error state of the
11862          * filesystem.
11863          */
11864         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11865                 sb->s_state &= ~EXT2_VALID_FS;
11866                 ext2fs_mark_super_dirty(fs);
11867         }
11868
11869         clear_problem_context(&pctx);
11870
11871         /*
11872          * If the UUID field isn't assigned, assign it.
11873          */
11874         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11875                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11876                         uuid_generate(sb->s_uuid);
11877                         ext2fs_mark_super_dirty(fs);
11878                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11879                 }
11880         }
11881
11882         /* FIXME - HURD support?
11883          * For the Hurd, check to see if the filetype option is set,
11884          * since it doesn't support it.
11885          */
11886         if (!(ctx->options & E2F_OPT_READONLY) &&
11887             fs->super->s_creator_os == EXT2_OS_HURD &&
11888             (fs->super->s_feature_incompat &
11889              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11890                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11891                         fs->super->s_feature_incompat &=
11892                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11893                         ext2fs_mark_super_dirty(fs);
11894                 }
11895         }
11896
11897         /*
11898          * If we have any of the compatibility flags set, we need to have a
11899          * revision 1 filesystem.  Most kernels will not check the flags on
11900          * a rev 0 filesystem and we may have corruption issues because of
11901          * the incompatible changes to the filesystem.
11902          */
11903         if (!(ctx->options & E2F_OPT_READONLY) &&
11904             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11905             (fs->super->s_feature_compat ||
11906              fs->super->s_feature_ro_compat ||
11907              fs->super->s_feature_incompat) &&
11908             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11909                 ext2fs_update_dynamic_rev(fs);
11910                 ext2fs_mark_super_dirty(fs);
11911         }
11912
11913         check_resize_inode(ctx);
11914
11915         /*
11916          * Clean up any orphan inodes, if present.
11917          */
11918         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11919                 fs->super->s_state &= ~EXT2_VALID_FS;
11920                 ext2fs_mark_super_dirty(fs);
11921         }
11922
11923         /*
11924          * Move the ext3 journal file, if necessary.
11925          */
11926         e2fsck_move_ext3_journal(ctx);
11927 }
11928
11929 /*
11930  * swapfs.c --- byte-swap an ext2 filesystem
11931  */
11932
11933 #ifdef ENABLE_SWAPFS
11934
11935 struct swap_block_struct {
11936         ext2_ino_t      ino;
11937         int             isdir;
11938         errcode_t       errcode;
11939         char            *dir_buf;
11940         struct ext2_inode *inode;
11941 };
11942
11943 /*
11944  * This is a helper function for block_iterate.  We mark all of the
11945  * indirect and direct blocks as changed, so that block_iterate will
11946  * write them out.
11947  */
11948 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11949                       void *priv_data)
11950 {
11951         errcode_t       retval;
11952
11953         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11954
11955         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11956                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11957                 if (retval) {
11958                         sb->errcode = retval;
11959                         return BLOCK_ABORT;
11960                 }
11961                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11962                 if (retval) {
11963                         sb->errcode = retval;
11964                         return BLOCK_ABORT;
11965                 }
11966         }
11967         if (blockcnt >= 0) {
11968                 if (blockcnt < EXT2_NDIR_BLOCKS)
11969                         return 0;
11970                 return BLOCK_CHANGED;
11971         }
11972         if (blockcnt == BLOCK_COUNT_IND) {
11973                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11974                         return 0;
11975                 return BLOCK_CHANGED;
11976         }
11977         if (blockcnt == BLOCK_COUNT_DIND) {
11978                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11979                         return 0;
11980                 return BLOCK_CHANGED;
11981         }
11982         if (blockcnt == BLOCK_COUNT_TIND) {
11983                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
11984                         return 0;
11985                 return BLOCK_CHANGED;
11986         }
11987         return BLOCK_CHANGED;
11988 }
11989
11990 /*
11991  * This function is responsible for byte-swapping all of the indirect,
11992  * block pointers.  It is also responsible for byte-swapping directories.
11993  */
11994 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
11995                               struct ext2_inode *inode)
11996 {
11997         errcode_t                       retval;
11998         struct swap_block_struct        sb;
11999
12000         sb.ino = ino;
12001         sb.inode = inode;
12002         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12003         sb.errcode = 0;
12004         sb.isdir = 0;
12005         if (LINUX_S_ISDIR(inode->i_mode))
12006                 sb.isdir = 1;
12007
12008         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12009                                       swap_block, &sb);
12010         if (retval) {
12011                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12012                 ctx->flags |= E2F_FLAG_ABORT;
12013                 return;
12014         }
12015         if (sb.errcode) {
12016                 bb_error_msg(_("while calling iterator function"));
12017                 ctx->flags |= E2F_FLAG_ABORT;
12018                 return;
12019         }
12020 }
12021
12022 static void swap_inodes(e2fsck_t ctx)
12023 {
12024         ext2_filsys fs = ctx->fs;
12025         dgrp_t                  group;
12026         unsigned int            i;
12027         ext2_ino_t              ino = 1;
12028         char                    *buf, *block_buf;
12029         errcode_t               retval;
12030         struct ext2_inode *     inode;
12031
12032         e2fsck_use_inode_shortcuts(ctx, 1);
12033
12034         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12035                                 &buf);
12036         if (retval) {
12037                 bb_error_msg(_("while allocating inode buffer"));
12038                 ctx->flags |= E2F_FLAG_ABORT;
12039                 return;
12040         }
12041         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12042                                                     "block interate buffer");
12043         for (group = 0; group < fs->group_desc_count; group++) {
12044                 retval = io_channel_read_blk(fs->io,
12045                       fs->group_desc[group].bg_inode_table,
12046                       fs->inode_blocks_per_group, buf);
12047                 if (retval) {
12048                         bb_error_msg(_("while reading inode table (group %d)"),
12049                                 group);
12050                         ctx->flags |= E2F_FLAG_ABORT;
12051                         return;
12052                 }
12053                 inode = (struct ext2_inode *) buf;
12054                 for (i=0; i < fs->super->s_inodes_per_group;
12055                      i++, ino++, inode++) {
12056                         ctx->stashed_ino = ino;
12057                         ctx->stashed_inode = inode;
12058
12059                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12060                                 ext2fs_swap_inode(fs, inode, inode, 0);
12061
12062                         /*
12063                          * Skip deleted files.
12064                          */
12065                         if (inode->i_links_count == 0)
12066                                 continue;
12067
12068                         if (LINUX_S_ISDIR(inode->i_mode) ||
12069                             ((inode->i_block[EXT2_IND_BLOCK] ||
12070                               inode->i_block[EXT2_DIND_BLOCK] ||
12071                               inode->i_block[EXT2_TIND_BLOCK]) &&
12072                              ext2fs_inode_has_valid_blocks(inode)))
12073                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12074
12075                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12076                                 return;
12077
12078                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12079                                 ext2fs_swap_inode(fs, inode, inode, 1);
12080                 }
12081                 retval = io_channel_write_blk(fs->io,
12082                       fs->group_desc[group].bg_inode_table,
12083                       fs->inode_blocks_per_group, buf);
12084                 if (retval) {
12085                         bb_error_msg(_("while writing inode table (group %d)"),
12086                                 group);
12087                         ctx->flags |= E2F_FLAG_ABORT;
12088                         return;
12089                 }
12090         }
12091         ext2fs_free_mem(&buf);
12092         ext2fs_free_mem(&block_buf);
12093         e2fsck_use_inode_shortcuts(ctx, 0);
12094         ext2fs_flush_icache(fs);
12095 }
12096
12097 #if defined(__powerpc__) && BB_BIG_ENDIAN
12098 /*
12099  * On the PowerPC, the big-endian variant of the ext2 filesystem
12100  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12101  * of each word.  Thus a bitmap with only bit 0 set would be, as
12102  * a string of bytes, 00 00 00 01 00 ...
12103  * To cope with this, we byte-reverse each word of a bitmap if
12104  * we have a big-endian filesystem, that is, if we are *not*
12105  * byte-swapping other word-sized numbers.
12106  */
12107 #define EXT2_BIG_ENDIAN_BITMAPS
12108 #endif
12109
12110 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12111 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12112 {
12113         __u32 *p = (__u32 *) bmap->bitmap;
12114         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12115
12116         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12117                 *p = ext2fs_swab32(*p);
12118 }
12119 #endif
12120
12121
12122 #ifdef ENABLE_SWAPFS
12123 static void swap_filesys(e2fsck_t ctx)
12124 {
12125         ext2_filsys fs = ctx->fs;
12126         if (!(ctx->options & E2F_OPT_PREEN))
12127                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12128
12129         /* Byte swap */
12130
12131         if (fs->super->s_mnt_count) {
12132                 fprintf(stderr, _("%s: the filesystem must be freshly "
12133                         "checked using fsck\n"
12134                         "and not mounted before trying to "
12135                         "byte-swap it.\n"), ctx->device_name);
12136                 ctx->flags |= E2F_FLAG_ABORT;
12137                 return;
12138         }
12139         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12140                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12141                                EXT2_FLAG_SWAP_BYTES_WRITE);
12142                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12143         } else {
12144                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12145                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12146         }
12147         swap_inodes(ctx);
12148         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12149                 return;
12150         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12151                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12152         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12153                        EXT2_FLAG_SWAP_BYTES_WRITE);
12154
12155 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12156         e2fsck_read_bitmaps(ctx);
12157         ext2fs_swap_bitmap(fs->inode_map);
12158         ext2fs_swap_bitmap(fs->block_map);
12159         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12160 #endif
12161         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12162         ext2fs_flush(fs);
12163         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12164 }
12165 #endif  /* ENABLE_SWAPFS */
12166
12167 #endif
12168
12169 /*
12170  * util.c --- miscellaneous utilities
12171  */
12172
12173
12174 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12175                              const char *description)
12176 {
12177         void *ret;
12178         char buf[256];
12179
12180         ret = xzalloc(size);
12181         return ret;
12182 }
12183
12184 static char *string_copy(const char *str, int len)
12185 {
12186         char    *ret;
12187
12188         if (!str)
12189                 return NULL;
12190         if (!len)
12191                 len = strlen(str);
12192         ret = xmalloc(len+1);
12193         strncpy(ret, str, len);
12194         ret[len] = 0;
12195         return ret;
12196 }
12197
12198 #ifndef HAVE_CONIO_H
12199 static int read_a_char(void)
12200 {
12201         char    c;
12202         int     r;
12203         int     fail = 0;
12204
12205         while (1) {
12206                 if (e2fsck_global_ctx &&
12207                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12208                         return 3;
12209                 }
12210                 r = read(0, &c, 1);
12211                 if (r == 1)
12212                         return c;
12213                 if (fail++ > 100)
12214                         break;
12215         }
12216         return EOF;
12217 }
12218 #endif
12219
12220 static int ask_yn(const char * string, int def)
12221 {
12222         int             c;
12223         const char      *defstr;
12224         static const char short_yes[] = "yY";
12225         static const char short_no[] = "nN";
12226
12227 #ifdef HAVE_TERMIOS_H
12228         struct termios  termios, tmp;
12229
12230         tcgetattr (0, &termios);
12231         tmp = termios;
12232         tmp.c_lflag &= ~(ICANON | ECHO);
12233         tmp.c_cc[VMIN] = 1;
12234         tmp.c_cc[VTIME] = 0;
12235         tcsetattr_stdin_TCSANOW(&tmp);
12236 #endif
12237
12238         if (def == 1)
12239                 defstr = "<y>";
12240         else if (def == 0)
12241                 defstr = "<n>";
12242         else
12243                 defstr = " (y/n)";
12244         printf("%s%s? ", string, defstr);
12245         while (1) {
12246                 fflush (stdout);
12247                 if ((c = read_a_char()) == EOF)
12248                         break;
12249                 if (c == 3) {
12250 #ifdef HAVE_TERMIOS_H
12251                         tcsetattr_stdin_TCSANOW(&termios);
12252 #endif
12253                         if (e2fsck_global_ctx &&
12254                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12255                                 puts("\n");
12256                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12257                         }
12258                         puts(_("cancelled!\n"));
12259                         return 0;
12260                 }
12261                 if (strchr(short_yes, (char) c)) {
12262                         def = 1;
12263                         break;
12264                 }
12265                 else if (strchr(short_no, (char) c)) {
12266                         def = 0;
12267                         break;
12268                 }
12269                 else if ((c == ' ' || c == '\n') && (def != -1))
12270                         break;
12271         }
12272         if (def)
12273                 puts("yes\n");
12274         else
12275                 puts ("no\n");
12276 #ifdef HAVE_TERMIOS_H
12277         tcsetattr_stdin_TCSANOW(&termios);
12278 #endif
12279         return def;
12280 }
12281
12282 int ask (e2fsck_t ctx, const char * string, int def)
12283 {
12284         if (ctx->options & E2F_OPT_NO) {
12285                 printf(_("%s? no\n\n"), string);
12286                 return 0;
12287         }
12288         if (ctx->options & E2F_OPT_YES) {
12289                 printf(_("%s? yes\n\n"), string);
12290                 return 1;
12291         }
12292         if (ctx->options & E2F_OPT_PREEN) {
12293                 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12294                 return def;
12295         }
12296         return ask_yn(string, def);
12297 }
12298
12299 void e2fsck_read_bitmaps(e2fsck_t ctx)
12300 {
12301         ext2_filsys fs = ctx->fs;
12302         errcode_t       retval;
12303
12304         if (ctx->invalid_bitmaps) {
12305                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12306                         ctx->device_name);
12307                 bb_error_msg_and_die(0);
12308         }
12309
12310         ehandler_operation(_("reading inode and block bitmaps"));
12311         retval = ext2fs_read_bitmaps(fs);
12312         ehandler_operation(0);
12313         if (retval) {
12314                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12315                         ctx->device_name);
12316                 bb_error_msg_and_die(0);
12317         }
12318 }
12319
12320 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12321 {
12322         ext2_filsys fs = ctx->fs;
12323         errcode_t       retval;
12324
12325         if (ext2fs_test_bb_dirty(fs)) {
12326                 ehandler_operation(_("writing block bitmaps"));
12327                 retval = ext2fs_write_block_bitmap(fs);
12328                 ehandler_operation(0);
12329                 if (retval) {
12330                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12331                                 ctx->device_name);
12332                         bb_error_msg_and_die(0);
12333                 }
12334         }
12335
12336         if (ext2fs_test_ib_dirty(fs)) {
12337                 ehandler_operation(_("writing inode bitmaps"));
12338                 retval = ext2fs_write_inode_bitmap(fs);
12339                 ehandler_operation(0);
12340                 if (retval) {
12341                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12342                                 ctx->device_name);
12343                         bb_error_msg_and_die(0);
12344                 }
12345         }
12346 }
12347
12348 void preenhalt(e2fsck_t ctx)
12349 {
12350         ext2_filsys fs = ctx->fs;
12351
12352         if (!(ctx->options & E2F_OPT_PREEN))
12353                 return;
12354         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12355                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12356                ctx->device_name);
12357         if (fs != NULL) {
12358                 fs->super->s_state |= EXT2_ERROR_FS;
12359                 ext2fs_mark_super_dirty(fs);
12360                 ext2fs_close(fs);
12361         }
12362         exit(EXIT_UNCORRECTED);
12363 }
12364
12365 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12366                               struct ext2_inode * inode, const char *proc)
12367 {
12368         int retval;
12369
12370         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12371         if (retval) {
12372                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12373                 bb_error_msg_and_die(0);
12374         }
12375 }
12376
12377 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12378                                struct ext2_inode * inode, int bufsize,
12379                                const char *proc)
12380 {
12381         int retval;
12382
12383         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12384         if (retval) {
12385                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12386                 bb_error_msg_and_die(0);
12387         }
12388 }
12389
12390 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12391                                struct ext2_inode * inode, const char *proc)
12392 {
12393         int retval;
12394
12395         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12396         if (retval) {
12397                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12398                 bb_error_msg_and_die(0);
12399         }
12400 }
12401
12402 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12403                    io_manager manager)
12404 {
12405         struct ext2_super_block *sb;
12406         io_channel              io = NULL;
12407         void                    *buf = NULL;
12408         int                     blocksize;
12409         blk_t                   superblock, ret_sb = 8193;
12410
12411         if (fs && fs->super) {
12412                 ret_sb = (fs->super->s_blocks_per_group +
12413                           fs->super->s_first_data_block);
12414                 if (ctx) {
12415                         ctx->superblock = ret_sb;
12416                         ctx->blocksize = fs->blocksize;
12417                 }
12418                 return ret_sb;
12419         }
12420
12421         if (ctx) {
12422                 if (ctx->blocksize) {
12423                         ret_sb = ctx->blocksize * 8;
12424                         if (ctx->blocksize == 1024)
12425                                 ret_sb++;
12426                         ctx->superblock = ret_sb;
12427                         return ret_sb;
12428                 }
12429                 ctx->superblock = ret_sb;
12430                 ctx->blocksize = 1024;
12431         }
12432
12433         if (!name || !manager)
12434                 goto cleanup;
12435
12436         if (manager->open(name, 0, &io) != 0)
12437                 goto cleanup;
12438
12439         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12440                 goto cleanup;
12441         sb = (struct ext2_super_block *) buf;
12442
12443         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12444              blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12445                 superblock = blocksize*8;
12446                 if (blocksize == 1024)
12447                         superblock++;
12448                 io_channel_set_blksize(io, blocksize);
12449                 if (io_channel_read_blk(io, superblock,
12450                                         -SUPERBLOCK_SIZE, buf))
12451                         continue;
12452 #if BB_BIG_ENDIAN
12453                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12454                         ext2fs_swap_super(sb);
12455 #endif
12456                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12457                         ret_sb = superblock;
12458                         if (ctx) {
12459                                 ctx->superblock = superblock;
12460                                 ctx->blocksize = blocksize;
12461                         }
12462                         break;
12463                 }
12464         }
12465
12466 cleanup:
12467         if (io)
12468                 io_channel_close(io);
12469         ext2fs_free_mem(&buf);
12470         return ret_sb;
12471 }
12472
12473
12474 /*
12475  * This function runs through the e2fsck passes and calls them all,
12476  * returning restart, abort, or cancel as necessary...
12477  */
12478 typedef void (*pass_t)(e2fsck_t ctx);
12479
12480 static const pass_t e2fsck_passes[] = {
12481         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12482         e2fsck_pass5, 0 };
12483
12484 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12485
12486 static int e2fsck_run(e2fsck_t ctx)
12487 {
12488         int     i;
12489         pass_t  e2fsck_pass;
12490
12491         if (setjmp(ctx->abort_loc)) {
12492                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12493                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12494         }
12495         ctx->flags |= E2F_FLAG_SETJMP_OK;
12496
12497         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12498                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12499                         break;
12500                 e2fsck_pass(ctx);
12501                 if (ctx->progress)
12502                         (void) (ctx->progress)(ctx, 0, 0, 0);
12503         }
12504         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12505
12506         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12507                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12508         return 0;
12509 }
12510
12511
12512 /*
12513  * unix.c - The unix-specific code for e2fsck
12514  */
12515
12516
12517 /* Command line options */
12518 static int swapfs;
12519 #ifdef ENABLE_SWAPFS
12520 static int normalize_swapfs;
12521 #endif
12522 static int cflag;               /* check disk */
12523 static int show_version_only;
12524 static int verbose;
12525
12526 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12527
12528 static void show_stats(e2fsck_t ctx)
12529 {
12530         ext2_filsys fs = ctx->fs;
12531         int inodes, inodes_used, blocks, blocks_used;
12532         int dir_links;
12533         int num_files, num_links;
12534         int frag_percent;
12535
12536         dir_links = 2 * ctx->fs_directory_count - 1;
12537         num_files = ctx->fs_total_count - dir_links;
12538         num_links = ctx->fs_links_count - dir_links;
12539         inodes = fs->super->s_inodes_count;
12540         inodes_used = (fs->super->s_inodes_count -
12541                        fs->super->s_free_inodes_count);
12542         blocks = fs->super->s_blocks_count;
12543         blocks_used = (fs->super->s_blocks_count -
12544                        fs->super->s_free_blocks_count);
12545
12546         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12547         frag_percent = (frag_percent + 5) / 10;
12548
12549         if (!verbose) {
12550                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12551                        ctx->device_name, inodes_used, inodes,
12552                        frag_percent / 10, frag_percent % 10,
12553                        blocks_used, blocks);
12554                 return;
12555         }
12556         printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12557                 100 * inodes_used / inodes);
12558         printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12559                 P_E2("", "s", ctx->fs_fragmented),
12560                 frag_percent / 10, frag_percent % 10);
12561         printf(_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12562                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12563         printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12564                 (int) ((long long) 100 * blocks_used / blocks));
12565         printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12566         printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12567         printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12568         printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12569         printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12570         printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12571         printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12572         printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12573         printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12574         printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12575         printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12576 }
12577
12578 static void check_mount(e2fsck_t ctx)
12579 {
12580         errcode_t       retval;
12581         int             cont;
12582
12583         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12584                                          &ctx->mount_flags);
12585         if (retval) {
12586                 bb_error_msg(_("while determining whether %s is mounted"),
12587                         ctx->filesystem_name);
12588                 return;
12589         }
12590
12591         /*
12592          * If the filesystem isn't mounted, or it's the root filesystem
12593          * and it's mounted read-only, then everything's fine.
12594          */
12595         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12596             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12597              (ctx->mount_flags & EXT2_MF_READONLY)))
12598                 return;
12599
12600         if (ctx->options & E2F_OPT_READONLY) {
12601                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12602                 return;
12603         }
12604
12605         printf(_("%s is mounted.  "), ctx->filesystem_name);
12606         if (!ctx->interactive)
12607                 bb_error_msg_and_die(_("can't continue, aborting"));
12608         printf(_("\n\n\007\007\007\007WARNING!!!  "
12609                "Running e2fsck on a mounted filesystem may cause\n"
12610                "SEVERE filesystem damage.\007\007\007\n\n"));
12611         cont = ask_yn(_("Do you really want to continue"), -1);
12612         if (!cont) {
12613                 printf(_("check aborted.\n"));
12614                 exit(0);
12615         }
12616 }
12617
12618 static int is_on_batt(void)
12619 {
12620         FILE    *f;
12621         DIR     *d;
12622         char    tmp[80], tmp2[80], fname[80];
12623         unsigned int    acflag;
12624         struct dirent*  de;
12625
12626         f = fopen_for_read("/proc/apm");
12627         if (f) {
12628                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12629                         acflag = 1;
12630                 fclose(f);
12631                 return (acflag != 1);
12632         }
12633         d = opendir("/proc/acpi/ac_adapter");
12634         if (d) {
12635                 while ((de=readdir(d)) != NULL) {
12636                         if (!strncmp(".", de->d_name, 1))
12637                                 continue;
12638                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12639                                  de->d_name);
12640                         f = fopen_for_read(fname);
12641                         if (!f)
12642                                 continue;
12643                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12644                                 tmp[0] = 0;
12645                         fclose(f);
12646                         if (strncmp(tmp, "off-line", 8) == 0) {
12647                                 closedir(d);
12648                                 return 1;
12649                         }
12650                 }
12651                 closedir(d);
12652         }
12653         return 0;
12654 }
12655
12656 /*
12657  * This routine checks to see if a filesystem can be skipped; if so,
12658  * it will exit with EXIT_OK.  Under some conditions it will print a
12659  * message explaining why a check is being forced.
12660  */
12661 static void check_if_skip(e2fsck_t ctx)
12662 {
12663         ext2_filsys fs = ctx->fs;
12664         const char *reason = NULL;
12665         unsigned int reason_arg = 0;
12666         long next_check;
12667         int batt = is_on_batt();
12668         time_t now = time(NULL);
12669
12670         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12671                 return;
12672
12673         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12674             !ext2fs_test_valid(fs))
12675                 reason = _(" contains a file system with errors");
12676         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12677                 reason = _(" was not cleanly unmounted");
12678         else if ((fs->super->s_max_mnt_count > 0) &&
12679                  (fs->super->s_mnt_count >=
12680                   (unsigned) fs->super->s_max_mnt_count)) {
12681                 reason = _(" has been mounted %u times without being checked");
12682                 reason_arg = fs->super->s_mnt_count;
12683                 if (batt && (fs->super->s_mnt_count <
12684                              (unsigned) fs->super->s_max_mnt_count*2))
12685                         reason = 0;
12686         } else if (fs->super->s_checkinterval &&
12687                    ((now - fs->super->s_lastcheck) >=
12688                     fs->super->s_checkinterval)) {
12689                 reason = _(" has gone %u days without being checked");
12690                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12691                 if (batt && ((now - fs->super->s_lastcheck) <
12692                              fs->super->s_checkinterval*2))
12693                         reason = 0;
12694         }
12695         if (reason) {
12696                 fputs(ctx->device_name, stdout);
12697                 printf(reason, reason_arg);
12698                 fputs(_(", check forced.\n"), stdout);
12699                 return;
12700         }
12701         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12702                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12703                fs->super->s_inodes_count,
12704                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12705                fs->super->s_blocks_count);
12706         next_check = 100000;
12707         if (fs->super->s_max_mnt_count > 0) {
12708                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12709                 if (next_check <= 0)
12710                         next_check = 1;
12711         }
12712         if (fs->super->s_checkinterval &&
12713             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12714                 next_check = 1;
12715         if (next_check <= 5) {
12716                 if (next_check == 1)
12717                         fputs(_(" (check after next mount)"), stdout);
12718                 else
12719                         printf(_(" (check in %ld mounts)"), next_check);
12720         }
12721         bb_putchar('\n');
12722         ext2fs_close(fs);
12723         ctx->fs = NULL;
12724         e2fsck_free_context(ctx);
12725         exit(EXIT_OK);
12726 }
12727
12728 /*
12729  * For completion notice
12730  */
12731 struct percent_tbl {
12732         int     max_pass;
12733         int     table[32];
12734 };
12735 static const struct percent_tbl e2fsck_tbl = {
12736         5, { 0, 70, 90, 92,  95, 100 }
12737 };
12738
12739 static char bar[128], spaces[128];
12740
12741 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12742                           int max)
12743 {
12744         float   percent;
12745
12746         if (pass <= 0)
12747                 return 0.0;
12748         if (pass > tbl->max_pass || max == 0)
12749                 return 100.0;
12750         percent = ((float) curr) / ((float) max);
12751         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12752                 + tbl->table[pass-1]);
12753 }
12754
12755 void e2fsck_clear_progbar(e2fsck_t ctx)
12756 {
12757         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12758                 return;
12759
12760         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12761                ctx->stop_meta);
12762         fflush(stdout);
12763         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12764 }
12765
12766 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12767                            unsigned int dpynum)
12768 {
12769         static const char spinner[] = "\\|/-";
12770         int     i;
12771         unsigned int    tick;
12772         struct timeval  tv;
12773         int dpywidth;
12774         int fixed_percent;
12775
12776         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12777                 return 0;
12778
12779         /*
12780          * Calculate the new progress position.  If the
12781          * percentage hasn't changed, then we skip out right
12782          * away.
12783          */
12784         fixed_percent = (int) ((10 * percent) + 0.5);
12785         if (ctx->progress_last_percent == fixed_percent)
12786                 return 0;
12787         ctx->progress_last_percent = fixed_percent;
12788
12789         /*
12790          * If we've already updated the spinner once within
12791          * the last 1/8th of a second, no point doing it
12792          * again.
12793          */
12794         gettimeofday(&tv, NULL);
12795         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12796         if ((tick == ctx->progress_last_time) &&
12797             (fixed_percent != 0) && (fixed_percent != 1000))
12798                 return 0;
12799         ctx->progress_last_time = tick;
12800
12801         /*
12802          * Advance the spinner, and note that the progress bar
12803          * will be on the screen
12804          */
12805         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12806         ctx->flags |= E2F_FLAG_PROG_BAR;
12807
12808         dpywidth = 66 - strlen(label);
12809         dpywidth = 8 * (dpywidth / 8);
12810         if (dpynum)
12811                 dpywidth -= 8;
12812
12813         i = ((percent * dpywidth) + 50) / 100;
12814         printf("%s%s: |%s%s", ctx->start_meta, label,
12815                bar + (sizeof(bar) - (i+1)),
12816                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12817         if (fixed_percent == 1000)
12818                 bb_putchar('|');
12819         else
12820                 bb_putchar(spinner[ctx->progress_pos & 3]);
12821         printf(" %4.1f%%  ", percent);
12822         if (dpynum)
12823                 printf("%u\r", dpynum);
12824         else
12825                 fputs(" \r", stdout);
12826         fputs(ctx->stop_meta, stdout);
12827
12828         if (fixed_percent == 1000)
12829                 e2fsck_clear_progbar(ctx);
12830         fflush(stdout);
12831
12832         return 0;
12833 }
12834
12835 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12836                                   unsigned long cur, unsigned long max)
12837 {
12838         char buf[80];
12839         float percent;
12840
12841         if (pass == 0)
12842                 return 0;
12843
12844         if (ctx->progress_fd) {
12845                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12846                 xwrite_str(ctx->progress_fd, buf);
12847         } else {
12848                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12849                 e2fsck_simple_progress(ctx, ctx->device_name,
12850                                        percent, 0);
12851         }
12852         return 0;
12853 }
12854
12855 static void reserve_stdio_fds(void)
12856 {
12857         int     fd;
12858
12859         while (1) {
12860                 fd = open(bb_dev_null, O_RDWR);
12861                 if (fd > 2)
12862                         break;
12863                 if (fd < 0) {
12864                         fprintf(stderr, _("ERROR: Cannot open "
12865                                 "/dev/null (%s)\n"),
12866                                 strerror(errno));
12867                         break;
12868                 }
12869         }
12870         close(fd);
12871 }
12872
12873 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12874 {
12875         e2fsck_t ctx = e2fsck_global_ctx;
12876
12877         if (!ctx)
12878                 return;
12879
12880         ctx->progress = e2fsck_update_progress;
12881         ctx->progress_fd = 0;
12882 }
12883
12884 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12885 {
12886         e2fsck_t ctx = e2fsck_global_ctx;
12887
12888         if (!ctx)
12889                 return;
12890
12891         e2fsck_clear_progbar(ctx);
12892         ctx->progress = 0;
12893 }
12894
12895 static void signal_cancel(int sig FSCK_ATTR((unused)))
12896 {
12897         e2fsck_t ctx = e2fsck_global_ctx;
12898
12899         if (!ctx)
12900                 exit(FSCK_CANCELED);
12901
12902         ctx->flags |= E2F_FLAG_CANCEL;
12903 }
12904
12905 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12906 {
12907         char    *buf, *token, *next, *p, *arg;
12908         int     ea_ver;
12909         int     extended_usage = 0;
12910
12911         buf = string_copy(opts, 0);
12912         for (token = buf; token && *token; token = next) {
12913                 p = strchr(token, ',');
12914                 next = 0;
12915                 if (p) {
12916                         *p = 0;
12917                         next = p+1;
12918                 }
12919                 arg = strchr(token, '=');
12920                 if (arg) {
12921                         *arg = 0;
12922                         arg++;
12923                 }
12924                 if (strcmp(token, "ea_ver") == 0) {
12925                         if (!arg) {
12926                                 extended_usage++;
12927                                 continue;
12928                         }
12929                         ea_ver = strtoul(arg, &p, 0);
12930                         if (*p ||
12931                             ((ea_ver != 1) && (ea_ver != 2))) {
12932                                 fprintf(stderr,
12933                                         _("Invalid EA version.\n"));
12934                                 extended_usage++;
12935                                 continue;
12936                         }
12937                         ctx->ext_attr_ver = ea_ver;
12938                 } else {
12939                         fprintf(stderr, _("Unknown extended option: %s\n"),
12940                                 token);
12941                         extended_usage++;
12942                 }
12943         }
12944         if (extended_usage) {
12945                 bb_error_msg_and_die(
12946                         "Extended options are separated by commas, "
12947                         "and may take an argument which\n"
12948                         "is set off by an equals ('=') sign.  "
12949                         "Valid extended options are:\n"
12950                         "\tea_ver=<ea_version (1 or 2)>\n\n");
12951         }
12952 }
12953
12954
12955 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12956 {
12957         int             flush = 0;
12958         int             c, fd;
12959         e2fsck_t        ctx;
12960         errcode_t       retval;
12961         struct sigaction        sa;
12962         char            *extended_opts = NULL;
12963
12964         retval = e2fsck_allocate_context(&ctx);
12965         if (retval)
12966                 return retval;
12967
12968         *ret_ctx = ctx;
12969
12970         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12971         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12972         if (isatty(0) && isatty(1)) {
12973                 ctx->interactive = 1;
12974         } else {
12975                 ctx->start_meta[0] = '\001';
12976                 ctx->stop_meta[0] = '\002';
12977         }
12978         memset(bar, '=', sizeof(bar)-1);
12979         memset(spaces, ' ', sizeof(spaces)-1);
12980         blkid_get_cache(&ctx->blkid, NULL);
12981
12982         if (argc && *argv)
12983                 ctx->program_name = *argv;
12984         else
12985                 ctx->program_name = "e2fsck";
12986         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
12987                 switch (c) {
12988                 case 'C':
12989                         ctx->progress = e2fsck_update_progress;
12990                         ctx->progress_fd = atoi(optarg);
12991                         if (!ctx->progress_fd)
12992                                 break;
12993                         /* Validate the file descriptor to avoid disasters */
12994                         fd = dup(ctx->progress_fd);
12995                         if (fd < 0) {
12996                                 fprintf(stderr,
12997                                 _("Error validating file descriptor %d: %s\n"),
12998                                         ctx->progress_fd,
12999                                         error_message(errno));
13000                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13001                         } else
13002                                 close(fd);
13003                         break;
13004                 case 'D':
13005                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13006                         break;
13007                 case 'E':
13008                         extended_opts = optarg;
13009                         break;
13010                 case 'p':
13011                 case 'a':
13012                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13013                         conflict_opt:
13014                                 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13015                         }
13016                         ctx->options |= E2F_OPT_PREEN;
13017                         break;
13018                 case 'n':
13019                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13020                                 goto conflict_opt;
13021                         ctx->options |= E2F_OPT_NO;
13022                         break;
13023                 case 'y':
13024                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13025                                 goto conflict_opt;
13026                         ctx->options |= E2F_OPT_YES;
13027                         break;
13028                 case 't':
13029                         /* FIXME - This needs to go away in a future path - will change binary */
13030                         fprintf(stderr, _("The -t option is not "
13031                                 "supported on this version of e2fsck.\n"));
13032                         break;
13033                 case 'c':
13034                         if (cflag++)
13035                                 ctx->options |= E2F_OPT_WRITECHECK;
13036                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13037                         break;
13038                 case 'r':
13039                         /* What we do by default, anyway! */
13040                         break;
13041                 case 'b':
13042                         ctx->use_superblock = atoi(optarg);
13043                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13044                         break;
13045                 case 'B':
13046                         ctx->blocksize = atoi(optarg);
13047                         break;
13048                 case 'I':
13049                         ctx->inode_buffer_blocks = atoi(optarg);
13050                         break;
13051                 case 'j':
13052                         ctx->journal_name = string_copy(optarg, 0);
13053                         break;
13054                 case 'P':
13055                         ctx->process_inode_size = atoi(optarg);
13056                         break;
13057                 case 'd':
13058                         ctx->options |= E2F_OPT_DEBUG;
13059                         break;
13060                 case 'f':
13061                         ctx->options |= E2F_OPT_FORCE;
13062                         break;
13063                 case 'F':
13064                         flush = 1;
13065                         break;
13066                 case 'v':
13067                         verbose = 1;
13068                         break;
13069                 case 'V':
13070                         show_version_only = 1;
13071                         break;
13072                 case 'N':
13073                         ctx->device_name = optarg;
13074                         break;
13075 #ifdef ENABLE_SWAPFS
13076                 case 's':
13077                         normalize_swapfs = 1;
13078                 case 'S':
13079                         swapfs = 1;
13080                         break;
13081 #else
13082                 case 's':
13083                 case 'S':
13084                         fprintf(stderr, _("Byte-swapping filesystems "
13085                                           "not compiled in this version "
13086                                           "of e2fsck\n"));
13087                         exit(1);
13088 #endif
13089                 default:
13090                         bb_show_usage();
13091                 }
13092         if (show_version_only)
13093                 return 0;
13094         if (optind != argc - 1)
13095                 bb_show_usage();
13096         if ((ctx->options & E2F_OPT_NO) &&
13097             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13098                 ctx->options |= E2F_OPT_READONLY;
13099         ctx->io_options = strchr(argv[optind], '?');
13100         if (ctx->io_options)
13101                 *ctx->io_options++ = 0;
13102         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13103         if (!ctx->filesystem_name) {
13104                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13105                 bb_error_msg_and_die(0);
13106         }
13107         if (extended_opts)
13108                 parse_extended_opts(ctx, extended_opts);
13109
13110         if (flush) {
13111                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13112                 if (fd < 0) {
13113                         bb_error_msg(_("while opening %s for flushing"),
13114                                 ctx->filesystem_name);
13115                         bb_error_msg_and_die(0);
13116                 }
13117                 if ((retval = ext2fs_sync_device(fd, 1))) {
13118                         bb_error_msg(_("while trying to flush %s"),
13119                                 ctx->filesystem_name);
13120                         bb_error_msg_and_die(0);
13121                 }
13122                 close(fd);
13123         }
13124 #ifdef ENABLE_SWAPFS
13125         if (swapfs && cflag) {
13126                         fprintf(stderr, _("Incompatible options not "
13127                                           "allowed when byte-swapping.\n"));
13128                         exit(EXIT_USAGE);
13129         }
13130 #endif
13131         /*
13132          * Set up signal action
13133          */
13134         memset(&sa, 0, sizeof(struct sigaction));
13135         sa.sa_handler = signal_cancel;
13136         sigaction(SIGINT, &sa, 0);
13137         sigaction(SIGTERM, &sa, 0);
13138 #ifdef SA_RESTART
13139         sa.sa_flags = SA_RESTART;
13140 #endif
13141         e2fsck_global_ctx = ctx;
13142         sa.sa_handler = signal_progress_on;
13143         sigaction(SIGUSR1, &sa, 0);
13144         sa.sa_handler = signal_progress_off;
13145         sigaction(SIGUSR2, &sa, 0);
13146
13147         /* Update our PATH to include /sbin if we need to run badblocks  */
13148         if (cflag)
13149                 e2fs_set_sbin_path();
13150         return 0;
13151 }
13152
13153 static const char my_ver_string[] = E2FSPROGS_VERSION;
13154 static const char my_ver_date[] = E2FSPROGS_DATE;
13155
13156 int e2fsck_main (int argc, char **argv);
13157 int e2fsck_main (int argc, char **argv)
13158 {
13159         errcode_t       retval;
13160         int             exit_value = EXIT_OK;
13161         ext2_filsys     fs = 0;
13162         io_manager      io_ptr;
13163         struct ext2_super_block *sb;
13164         const char      *lib_ver_date;
13165         int             my_ver, lib_ver;
13166         e2fsck_t        ctx;
13167         struct problem_context pctx;
13168         int flags, run_result;
13169
13170         clear_problem_context(&pctx);
13171
13172         my_ver = ext2fs_parse_version_string(my_ver_string);
13173         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13174         if (my_ver > lib_ver) {
13175                 fprintf( stderr, _("Error: ext2fs library version "
13176                         "out of date!\n"));
13177                 show_version_only++;
13178         }
13179
13180         retval = PRS(argc, argv, &ctx);
13181         if (retval) {
13182                 bb_error_msg(_("while trying to initialize program"));
13183                 exit(EXIT_ERROR);
13184         }
13185         reserve_stdio_fds();
13186
13187         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13188                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13189                          my_ver_date);
13190
13191         if (show_version_only) {
13192                 fprintf(stderr, _("\tUsing %s, %s\n"),
13193                         error_message(EXT2_ET_BASE), lib_ver_date);
13194                 exit(EXIT_OK);
13195         }
13196
13197         check_mount(ctx);
13198
13199         if (!(ctx->options & E2F_OPT_PREEN) &&
13200             !(ctx->options & E2F_OPT_NO) &&
13201             !(ctx->options & E2F_OPT_YES)) {
13202                 if (!ctx->interactive)
13203                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13204         }
13205         ctx->superblock = ctx->use_superblock;
13206 restart:
13207 #ifdef CONFIG_TESTIO_DEBUG
13208         io_ptr = test_io_manager;
13209         test_io_backing_manager = unix_io_manager;
13210 #else
13211         io_ptr = unix_io_manager;
13212 #endif
13213         flags = 0;
13214         if ((ctx->options & E2F_OPT_READONLY) == 0)
13215                 flags |= EXT2_FLAG_RW;
13216
13217         if (ctx->superblock && ctx->blocksize) {
13218                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13219                                       flags, ctx->superblock, ctx->blocksize,
13220                                       io_ptr, &fs);
13221         } else if (ctx->superblock) {
13222                 int blocksize;
13223                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13224                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13225                         retval = ext2fs_open2(ctx->filesystem_name,
13226                                               ctx->io_options, flags,
13227                                               ctx->superblock, blocksize,
13228                                               io_ptr, &fs);
13229                         if (!retval)
13230                                 break;
13231                 }
13232         } else
13233                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13234                                       flags, 0, 0, io_ptr, &fs);
13235         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13236             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13237             ((retval == EXT2_ET_BAD_MAGIC) ||
13238              ((retval == 0) && ext2fs_check_desc(fs)))) {
13239                 if (!fs || (fs->group_desc_count > 1)) {
13240                         printf(_("%s trying backup blocks...\n"),
13241                                retval ? _("Couldn't find ext2 superblock,") :
13242                                _("Group descriptors look bad..."));
13243                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13244                         if (fs)
13245                                 ext2fs_close(fs);
13246                         goto restart;
13247                 }
13248         }
13249         if (retval) {
13250                 bb_error_msg(_("while trying to open %s"),
13251                         ctx->filesystem_name);
13252                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13253                         printf(_("The filesystem revision is apparently "
13254                                "too high for this version of e2fsck.\n"
13255                                "(Or the filesystem superblock "
13256                                "is corrupt)\n\n"));
13257                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13258                 } else if (retval == EXT2_ET_SHORT_READ)
13259                         printf(_("Could this be a zero-length partition?\n"));
13260                 else if ((retval == EPERM) || (retval == EACCES))
13261                         printf(_("You must have %s access to the "
13262                                "filesystem or be root\n"),
13263                                (ctx->options & E2F_OPT_READONLY) ?
13264                                "r/o" : "r/w");
13265                 else if (retval == ENXIO)
13266                         printf(_("Possibly non-existent or swap device?\n"));
13267 #ifdef EROFS
13268                 else if (retval == EROFS)
13269                         printf(_("Disk write-protected; use the -n option "
13270                                "to do a read-only\n"
13271                                "check of the device.\n"));
13272 #endif
13273                 else
13274                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13275                 bb_error_msg_and_die(0);
13276         }
13277         ctx->fs = fs;
13278         fs->priv_data = ctx;
13279         sb = fs->super;
13280         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13281                 bb_error_msg(_("while trying to open %s"),
13282                         ctx->filesystem_name);
13283         get_newer:
13284                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13285         }
13286
13287         /*
13288          * Set the device name, which is used whenever we print error
13289          * or informational messages to the user.
13290          */
13291         if (ctx->device_name == 0 &&
13292             (sb->s_volume_name[0] != 0)) {
13293                 ctx->device_name = string_copy(sb->s_volume_name,
13294                                                sizeof(sb->s_volume_name));
13295         }
13296         if (ctx->device_name == 0)
13297                 ctx->device_name = ctx->filesystem_name;
13298
13299         /*
13300          * Make sure the ext3 superblock fields are consistent.
13301          */
13302         retval = e2fsck_check_ext3_journal(ctx);
13303         if (retval) {
13304                 bb_error_msg(_("while checking ext3 journal for %s"),
13305                         ctx->device_name);
13306                 bb_error_msg_and_die(0);
13307         }
13308
13309         /*
13310          * Check to see if we need to do ext3-style recovery.  If so,
13311          * do it, and then restart the fsck.
13312          */
13313         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13314                 if (ctx->options & E2F_OPT_READONLY) {
13315                         printf(_("Warning: skipping journal recovery "
13316                                  "because doing a read-only filesystem "
13317                                  "check.\n"));
13318                         io_channel_flush(ctx->fs->io);
13319                 } else {
13320                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13321                                 /*
13322                                  * Whoops, we attempted to run the
13323                                  * journal twice.  This should never
13324                                  * happen, unless the hardware or
13325                                  * device driver is being bogus.
13326                                  */
13327                                 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13328                                 bb_error_msg_and_die(0);
13329                         }
13330                         retval = e2fsck_run_ext3_journal(ctx);
13331                         if (retval) {
13332                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13333                                         ctx->device_name);
13334                                 bb_error_msg_and_die(0);
13335                         }
13336                         ext2fs_close(ctx->fs);
13337                         ctx->fs = 0;
13338                         ctx->flags |= E2F_FLAG_RESTARTED;
13339                         goto restart;
13340                 }
13341         }
13342
13343         /*
13344          * Check for compatibility with the feature sets.  We need to
13345          * be more stringent than ext2fs_open().
13346          */
13347         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13348             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13349                 bb_error_msg("(%s)", ctx->device_name);
13350                 goto get_newer;
13351         }
13352         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13353                 bb_error_msg("(%s)", ctx->device_name);
13354                 goto get_newer;
13355         }
13356 #ifdef ENABLE_COMPRESSION
13357         /* FIXME - do we support this at all? */
13358         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13359                 bb_error_msg(_("warning: compression support is experimental"));
13360 #endif
13361 #ifndef ENABLE_HTREE
13362         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13363                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13364                           "but filesystem %s has HTREE directories."),
13365                         ctx->device_name);
13366                 goto get_newer;
13367         }
13368 #endif
13369
13370         /*
13371          * If the user specified a specific superblock, presumably the
13372          * master superblock has been trashed.  So we mark the
13373          * superblock as dirty, so it can be written out.
13374          */
13375         if (ctx->superblock &&
13376             !(ctx->options & E2F_OPT_READONLY))
13377                 ext2fs_mark_super_dirty(fs);
13378
13379         /*
13380          * We only update the master superblock because (a) paranoia;
13381          * we don't want to corrupt the backup superblocks, and (b) we
13382          * don't need to update the mount count and last checked
13383          * fields in the backup superblock (the kernel doesn't
13384          * update the backup superblocks anyway).
13385          */
13386         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13387
13388         ehandler_init(fs->io);
13389
13390         if (ctx->superblock)
13391                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13392         ext2fs_mark_valid(fs);
13393         check_super_block(ctx);
13394         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13395                 bb_error_msg_and_die(0);
13396         check_if_skip(ctx);
13397         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13398                 bb_error_msg_and_die(0);
13399 #ifdef ENABLE_SWAPFS
13400
13401 #ifdef WORDS_BIGENDIAN
13402 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13403 #else
13404 #define NATIVE_FLAG 0
13405 #endif
13406
13407
13408         if (normalize_swapfs) {
13409                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13410                         fprintf(stderr, _("%s: Filesystem byte order "
13411                                 "already normalized.\n"), ctx->device_name);
13412                         bb_error_msg_and_die(0);
13413                 }
13414         }
13415         if (swapfs) {
13416                 swap_filesys(ctx);
13417                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13418                         bb_error_msg_and_die(0);
13419         }
13420 #endif
13421
13422         /*
13423          * Mark the system as valid, 'til proven otherwise
13424          */
13425         ext2fs_mark_valid(fs);
13426
13427         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13428         if (retval) {
13429                 bb_error_msg(_("while reading bad blocks inode"));
13430                 preenhalt(ctx);
13431                 printf(_("This doesn't bode well,"
13432                          " but we'll try to go on...\n"));
13433         }
13434
13435         run_result = e2fsck_run(ctx);
13436         e2fsck_clear_progbar(ctx);
13437         if (run_result == E2F_FLAG_RESTART) {
13438                 printf(_("Restarting e2fsck from the beginning...\n"));
13439                 retval = e2fsck_reset_context(ctx);
13440                 if (retval) {
13441                         bb_error_msg(_("while resetting context"));
13442                         bb_error_msg_and_die(0);
13443                 }
13444                 ext2fs_close(fs);
13445                 goto restart;
13446         }
13447         if (run_result & E2F_FLAG_CANCEL) {
13448                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13449                        ctx->device_name : ctx->filesystem_name);
13450                 exit_value |= FSCK_CANCELED;
13451         }
13452         if (run_result & E2F_FLAG_ABORT)
13453                 bb_error_msg_and_die(_("aborted"));
13454
13455         /* Cleanup */
13456         if (ext2fs_test_changed(fs)) {
13457                 exit_value |= EXIT_NONDESTRUCT;
13458                 if (!(ctx->options & E2F_OPT_PREEN))
13459                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13460                                ctx->device_name);
13461                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13462                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13463                                ctx->device_name);
13464                         exit_value |= EXIT_DESTRUCT;
13465                 }
13466         }
13467         if (!ext2fs_test_valid(fs)) {
13468                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13469                          "errors **********\n\n"), ctx->device_name);
13470                 exit_value |= EXIT_UNCORRECTED;
13471                 exit_value &= ~EXIT_NONDESTRUCT;
13472         }
13473         if (exit_value & FSCK_CANCELED)
13474                 exit_value &= ~EXIT_NONDESTRUCT;
13475         else {
13476                 show_stats(ctx);
13477                 if (!(ctx->options & E2F_OPT_READONLY)) {
13478                         if (ext2fs_test_valid(fs)) {
13479                                 if (!(sb->s_state & EXT2_VALID_FS))
13480                                         exit_value |= EXIT_NONDESTRUCT;
13481                                 sb->s_state = EXT2_VALID_FS;
13482                         } else
13483                                 sb->s_state &= ~EXT2_VALID_FS;
13484                         sb->s_mnt_count = 0;
13485                         sb->s_lastcheck = time(NULL);
13486                         ext2fs_mark_super_dirty(fs);
13487                 }
13488         }
13489
13490         e2fsck_write_bitmaps(ctx);
13491
13492         ext2fs_close(fs);
13493         ctx->fs = NULL;
13494         free(ctx->filesystem_name);
13495         free(ctx->journal_name);
13496         e2fsck_free_context(ctx);
13497
13498         return exit_value;
13499 }