c169ed40dcf839c190449de11299bf90296d9b2a
[oweals/busybox.git] / e2fsprogs / e2fsck.c
1 /*
2  * e2fsck
3  *
4  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5  * Copyright (C) 2006 Garrett Kajmowicz
6  * This file may be
7  * redistributed under the terms of the GNU Public License.
8  *
9  *
10  * Dictionary Abstract Data Type
11  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
12  * Free Software License:
13  * All rights are reserved by the author, with the following exceptions:
14  * Permission is granted to freely reproduce and distribute this software,
15  * possibly in exchange for a fee, provided that this copyright notice appears
16  * intact. Permission is also granted to adapt this software to produce
17  * derivative works, as long as the modified versions carry this copyright
18  * notice and additional notices stating that the work has been modified.
19  * This source code may be translated into executable form and incorporated
20  * into proprietary software; there is no requirement for such software to
21  * contain a copyright notice related to this source.
22  *
23  * linux/fs/recovery  and linux/fs/revoke
24  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
25  *
26  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
27  *
28  * This file is part of the Linux kernel and is made available under
29  * the terms of the GNU General Public License, version 2, or at your
30  * option, any later version, incorporated herein by reference.
31  *
32  * Journal recovery routines for the generic filesystem journaling code;
33  * part of the ext2fs journaling system.
34  */
35
36 #ifndef _GNU_SOURCE
37 #define _GNU_SOURCE 1 /* get strnlen() */
38 #endif
39
40 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
41
42 /*
43  * Procedure declarations
44  */
45
46 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
47
48 /* pass1.c */
49 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
50
51 /* pass2.c */
52 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
53                                     ext2_ino_t ino, char *buf);
54
55 /* pass3.c */
56 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
57 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
58                                          int num, int gauranteed_size);
59 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
60 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
61                                            int adj);
62
63 /* rehash.c */
64 static void e2fsck_rehash_directories(e2fsck_t ctx);
65
66 /* util.c */
67 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
68                                     const char *description);
69 static int ask(e2fsck_t ctx, const char * string, int def);
70 static void e2fsck_read_bitmaps(e2fsck_t ctx);
71 static void preenhalt(e2fsck_t ctx);
72 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
73                               struct ext2_inode * inode, const char * proc);
74 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
75                                struct ext2_inode * inode, const char * proc);
76 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
77                            const char *name, io_manager manager);
78
79 /* unix.c */
80 static void e2fsck_clear_progbar(e2fsck_t ctx);
81 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
82                                   float percent, unsigned int dpynum);
83
84
85 /*
86  * problem.h --- e2fsck problem error codes
87  */
88
89 typedef __u32 problem_t;
90
91 struct problem_context {
92         errcode_t       errcode;
93         ext2_ino_t ino, ino2, dir;
94         struct ext2_inode *inode;
95         struct ext2_dir_entry *dirent;
96         blk_t   blk, blk2;
97         e2_blkcnt_t     blkcount;
98         int             group;
99         __u64   num;
100         const char *str;
101 };
102
103
104 /*
105  * Function declarations
106  */
107 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
108 static int end_problem_latch(e2fsck_t ctx, int mask);
109 static int set_latch_flags(int mask, int setflags, int clearflags);
110 static void clear_problem_context(struct problem_context *ctx);
111
112 /*
113  * Dictionary Abstract Data Type
114  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
115  *
116  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
117  * kazlib_1_20
118  */
119
120 #ifndef DICT_H
121 #define DICT_H
122
123 /*
124  * Blurb for inclusion into C++ translation units
125  */
126
127 typedef unsigned long dictcount_t;
128 #define DICTCOUNT_T_MAX ULONG_MAX
129
130 /*
131  * The dictionary is implemented as a red-black tree
132  */
133
134 typedef enum { dnode_red, dnode_black } dnode_color_t;
135
136 typedef struct dnode_t {
137     struct dnode_t *dict_left;
138     struct dnode_t *dict_right;
139     struct dnode_t *dict_parent;
140     dnode_color_t dict_color;
141     const void *dict_key;
142     void *dict_data;
143 } dnode_t;
144
145 typedef int (*dict_comp_t)(const void *, const void *);
146 typedef void (*dnode_free_t)(dnode_t *);
147
148 typedef struct dict_t {
149     dnode_t dict_nilnode;
150     dictcount_t dict_nodecount;
151     dictcount_t dict_maxcount;
152     dict_comp_t dict_compare;
153     dnode_free_t dict_freenode;
154     int dict_dupes;
155 } dict_t;
156
157 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
158
159 typedef struct dict_load_t {
160     dict_t *dict_dictptr;
161     dnode_t dict_nilnode;
162 } dict_load_t;
163
164 #define dict_count(D) ((D)->dict_nodecount)
165 #define dnode_get(N) ((N)->dict_data)
166 #define dnode_getkey(N) ((N)->dict_key)
167
168 #endif
169
170 /*
171  * Compatibility header file for e2fsck which should be included
172  * instead of linux/jfs.h
173  *
174  * Copyright (C) 2000 Stephen C. Tweedie
175  */
176
177 /*
178  * Pull in the definition of the e2fsck context structure
179  */
180
181 struct buffer_head {
182         char            b_data[8192];
183         e2fsck_t        b_ctx;
184         io_channel      b_io;
185         int             b_size;
186         blk_t           b_blocknr;
187         int             b_dirty;
188         int             b_uptodate;
189         int             b_err;
190 };
191
192
193 #define K_DEV_FS        1
194 #define K_DEV_JOURNAL   2
195
196 #define lock_buffer(bh) do {} while(0)
197 #define unlock_buffer(bh) do {} while(0)
198 #define buffer_req(bh) 1
199 #define do_readahead(journal, start) do {} while(0)
200
201 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
202
203 typedef struct {
204         int     object_length;
205 } kmem_cache_t;
206
207 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
208
209 /*
210  * We use the standard libext2fs portability tricks for inline
211  * functions.
212  */
213
214 static kmem_cache_t * do_cache_create(int len)
215 {
216         kmem_cache_t *new_cache;
217
218         new_cache = malloc(sizeof(*new_cache));
219         if (new_cache)
220                 new_cache->object_length = len;
221         return new_cache;
222 }
223
224 static void do_cache_destroy(kmem_cache_t *cache)
225 {
226         free(cache);
227 }
228
229
230 /*
231  * Dictionary Abstract Data Type
232  */
233
234
235 /*
236  * These macros provide short convenient names for structure members,
237  * which are embellished with dict_ prefixes so that they are
238  * properly confined to the documented namespace. It's legal for a
239  * program which uses dict to define, for instance, a macro called ``parent''.
240  * Such a macro would interfere with the dnode_t struct definition.
241  * In general, highly portable and reusable C modules which expose their
242  * structures need to confine structure member names to well-defined spaces.
243  * The resulting identifiers aren't necessarily convenient to use, nor
244  * readable, in the implementation, however!
245  */
246
247 #define left dict_left
248 #define right dict_right
249 #define parent dict_parent
250 #define color dict_color
251 #define key dict_key
252 #define data dict_data
253
254 #define nilnode dict_nilnode
255 #define maxcount dict_maxcount
256 #define compare dict_compare
257 #define dupes dict_dupes
258
259 #define dict_root(D) ((D)->nilnode.left)
260 #define dict_nil(D) (&(D)->nilnode)
261
262 static void dnode_free(dnode_t *node);
263
264 /*
265  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
266  * its right child C are rearranged so that the P instead becomes the left
267  * child of C.   The left subtree of C is inherited as the new right subtree
268  * for P.  The ordering of the keys within the tree is thus preserved.
269  */
270
271 static void rotate_left(dnode_t *upper)
272 {
273     dnode_t *lower, *lowleft, *upparent;
274
275     lower = upper->right;
276     upper->right = lowleft = lower->left;
277     lowleft->parent = upper;
278
279     lower->parent = upparent = upper->parent;
280
281     /* don't need to check for root node here because root->parent is
282        the sentinel nil node, and root->parent->left points back to root */
283
284     if (upper == upparent->left) {
285         upparent->left = lower;
286     } else {
287         assert (upper == upparent->right);
288         upparent->right = lower;
289     }
290
291     lower->left = upper;
292     upper->parent = lower;
293 }
294
295 /*
296  * This operation is the ``mirror'' image of rotate_left. It is
297  * the same procedure, but with left and right interchanged.
298  */
299
300 static void rotate_right(dnode_t *upper)
301 {
302     dnode_t *lower, *lowright, *upparent;
303
304     lower = upper->left;
305     upper->left = lowright = lower->right;
306     lowright->parent = upper;
307
308     lower->parent = upparent = upper->parent;
309
310     if (upper == upparent->right) {
311         upparent->right = lower;
312     } else {
313         assert (upper == upparent->left);
314         upparent->left = lower;
315     }
316
317     lower->right = upper;
318     upper->parent = lower;
319 }
320
321 /*
322  * Do a postorder traversal of the tree rooted at the specified
323  * node and free everything under it.  Used by dict_free().
324  */
325
326 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
327 {
328     if (node == nil)
329         return;
330     free_nodes(dict, node->left, nil);
331     free_nodes(dict, node->right, nil);
332     dict->dict_freenode(node);
333 }
334
335 /*
336  * Verify that the tree contains the given node. This is done by
337  * traversing all of the nodes and comparing their pointers to the
338  * given pointer. Returns 1 if the node is found, otherwise
339  * returns zero. It is intended for debugging purposes.
340  */
341
342 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
343 {
344     if (root != nil) {
345         return root == node
346                 || verify_dict_has_node(nil, root->left, node)
347                 || verify_dict_has_node(nil, root->right, node);
348     }
349     return 0;
350 }
351
352
353 /*
354  * Select a different set of node allocator routines.
355  */
356
357 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
358 {
359     assert (dict_count(dict) == 0);
360     dict->dict_freenode = fr;
361 }
362
363 /*
364  * Free all the nodes in the dictionary by using the dictionary's
365  * installed free routine. The dictionary is emptied.
366  */
367
368 static void dict_free_nodes(dict_t *dict)
369 {
370     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
371     free_nodes(dict, root, nil);
372     dict->dict_nodecount = 0;
373     dict->nilnode.left = &dict->nilnode;
374     dict->nilnode.right = &dict->nilnode;
375 }
376
377 /*
378  * Initialize a user-supplied dictionary object.
379  */
380
381 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
382 {
383     dict->compare = comp;
384     dict->dict_freenode = dnode_free;
385     dict->dict_nodecount = 0;
386     dict->maxcount = maxcount;
387     dict->nilnode.left = &dict->nilnode;
388     dict->nilnode.right = &dict->nilnode;
389     dict->nilnode.parent = &dict->nilnode;
390     dict->nilnode.color = dnode_black;
391     dict->dupes = 0;
392     return dict;
393 }
394
395 /*
396  * Locate a node in the dictionary having the given key.
397  * If the node is not found, a null a pointer is returned (rather than
398  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
399  * located node is returned.
400  */
401
402 static dnode_t *dict_lookup(dict_t *dict, const void *key)
403 {
404     dnode_t *root = dict_root(dict);
405     dnode_t *nil = dict_nil(dict);
406     dnode_t *saved;
407     int result;
408
409     /* simple binary search adapted for trees that contain duplicate keys */
410
411     while (root != nil) {
412         result = dict->compare(key, root->key);
413         if (result < 0)
414             root = root->left;
415         else if (result > 0)
416             root = root->right;
417         else {
418             if (!dict->dupes) { /* no duplicates, return match          */
419                 return root;
420             } else {            /* could be dupes, find leftmost one    */
421                 do {
422                     saved = root;
423                     root = root->left;
424                     while (root != nil && dict->compare(key, root->key))
425                         root = root->right;
426                 } while (root != nil);
427                 return saved;
428             }
429         }
430     }
431
432     return NULL;
433 }
434
435 /*
436  * Insert a node into the dictionary. The node should have been
437  * initialized with a data field. All other fields are ignored.
438  * The behavior is undefined if the user attempts to insert into
439  * a dictionary that is already full (for which the dict_isfull()
440  * function returns true).
441  */
442
443 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
444 {
445     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
446     dnode_t *parent = nil, *uncle, *grandpa;
447     int result = -1;
448
449     node->key = key;
450
451     /* basic binary tree insert */
452
453     while (where != nil) {
454         parent = where;
455         result = dict->compare(key, where->key);
456         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
457         assert (dict->dupes || result != 0);
458         if (result < 0)
459             where = where->left;
460         else
461             where = where->right;
462     }
463
464     assert (where == nil);
465
466     if (result < 0)
467         parent->left = node;
468     else
469         parent->right = node;
470
471     node->parent = parent;
472     node->left = nil;
473     node->right = nil;
474
475     dict->dict_nodecount++;
476
477     /* red black adjustments */
478
479     node->color = dnode_red;
480
481     while (parent->color == dnode_red) {
482         grandpa = parent->parent;
483         if (parent == grandpa->left) {
484             uncle = grandpa->right;
485             if (uncle->color == dnode_red) {    /* red parent, red uncle */
486                 parent->color = dnode_black;
487                 uncle->color = dnode_black;
488                 grandpa->color = dnode_red;
489                 node = grandpa;
490                 parent = grandpa->parent;
491             } else {                            /* red parent, black uncle */
492                 if (node == parent->right) {
493                     rotate_left(parent);
494                     parent = node;
495                     assert (grandpa == parent->parent);
496                     /* rotation between parent and child preserves grandpa */
497                 }
498                 parent->color = dnode_black;
499                 grandpa->color = dnode_red;
500                 rotate_right(grandpa);
501                 break;
502             }
503         } else {        /* symmetric cases: parent == parent->parent->right */
504             uncle = grandpa->left;
505             if (uncle->color == dnode_red) {
506                 parent->color = dnode_black;
507                 uncle->color = dnode_black;
508                 grandpa->color = dnode_red;
509                 node = grandpa;
510                 parent = grandpa->parent;
511             } else {
512                 if (node == parent->left) {
513                     rotate_right(parent);
514                     parent = node;
515                     assert (grandpa == parent->parent);
516                 }
517                 parent->color = dnode_black;
518                 grandpa->color = dnode_red;
519                 rotate_left(grandpa);
520                 break;
521             }
522         }
523     }
524
525     dict_root(dict)->color = dnode_black;
526
527 }
528
529 /*
530  * Allocate a node using the dictionary's allocator routine, give it
531  * the data item.
532  */
533
534 static dnode_t *dnode_init(dnode_t *dnode, void *data)
535 {
536     dnode->data = data;
537     dnode->parent = NULL;
538     dnode->left = NULL;
539     dnode->right = NULL;
540     return dnode;
541 }
542
543 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
544 {
545     dnode_t *node = malloc(sizeof(dnode_t));
546
547     if (node) {
548         dnode_init(node, data);
549         dict_insert(dict, node, key);
550         return 1;
551     }
552     return 0;
553 }
554
555 /*
556  * Return the node with the lowest (leftmost) key. If the dictionary is empty
557  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
558  */
559
560 static dnode_t *dict_first(dict_t *dict)
561 {
562     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
563
564     if (root != nil)
565         while ((left = root->left) != nil)
566             root = left;
567
568     return (root == nil) ? NULL : root;
569 }
570
571 /*
572  * Return the given node's successor node---the node which has the
573  * next key in the the left to right ordering. If the node has
574  * no successor, a null pointer is returned rather than a pointer to
575  * the nil node.
576  */
577
578 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
579 {
580     dnode_t *nil = dict_nil(dict), *parent, *left;
581
582     if (curr->right != nil) {
583         curr = curr->right;
584         while ((left = curr->left) != nil)
585             curr = left;
586         return curr;
587     }
588
589     parent = curr->parent;
590
591     while (parent != nil && curr == parent->right) {
592         curr = parent;
593         parent = curr->parent;
594     }
595
596     return (parent == nil) ? NULL : parent;
597 }
598
599
600 static void dnode_free(dnode_t *node)
601 {
602     free(node);
603 }
604
605
606 #undef left
607 #undef right
608 #undef parent
609 #undef color
610 #undef key
611 #undef data
612
613 #undef nilnode
614 #undef maxcount
615 #undef compare
616 #undef dupes
617
618
619 /*
620  * dirinfo.c --- maintains the directory information table for e2fsck.
621  */
622
623 /*
624  * This subroutine is called during pass1 to create a directory info
625  * entry.  During pass1, the passed-in parent is 0; it will get filled
626  * in during pass2.
627  */
628 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
629 {
630         struct dir_info *dir;
631         int             i, j;
632         ext2_ino_t      num_dirs;
633         errcode_t       retval;
634         unsigned long   old_size;
635
636         if (!ctx->dir_info) {
637                 ctx->dir_info_count = 0;
638                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
639                 if (retval)
640                         num_dirs = 1024;        /* Guess */
641                 ctx->dir_info_size = num_dirs + 10;
642                 ctx->dir_info  = (struct dir_info *)
643                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
644                                                * sizeof (struct dir_info),
645                                                "directory map");
646         }
647
648         if (ctx->dir_info_count >= ctx->dir_info_size) {
649                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
650                 ctx->dir_info_size += 10;
651                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
652                                            sizeof(struct dir_info),
653                                            &ctx->dir_info);
654                 if (retval) {
655                         ctx->dir_info_size -= 10;
656                         return;
657                 }
658         }
659
660         /*
661          * Normally, add_dir_info is called with each inode in
662          * sequential order; but once in a while (like when pass 3
663          * needs to recreate the root directory or lost+found
664          * directory) it is called out of order.  In those cases, we
665          * need to move the dir_info entries down to make room, since
666          * the dir_info array needs to be sorted by inode number for
667          * get_dir_info()'s sake.
668          */
669         if (ctx->dir_info_count &&
670             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
671                 for (i = ctx->dir_info_count-1; i > 0; i--)
672                         if (ctx->dir_info[i-1].ino < ino)
673                                 break;
674                 dir = &ctx->dir_info[i];
675                 if (dir->ino != ino)
676                         for (j = ctx->dir_info_count++; j > i; j--)
677                                 ctx->dir_info[j] = ctx->dir_info[j-1];
678         } else
679                 dir = &ctx->dir_info[ctx->dir_info_count++];
680
681         dir->ino = ino;
682         dir->dotdot = parent;
683         dir->parent = parent;
684 }
685
686 /*
687  * get_dir_info() --- given an inode number, try to find the directory
688  * information entry for it.
689  */
690 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
691 {
692         int     low, high, mid;
693
694         low = 0;
695         high = ctx->dir_info_count-1;
696         if (!ctx->dir_info)
697                 return 0;
698         if (ino == ctx->dir_info[low].ino)
699                 return &ctx->dir_info[low];
700         if  (ino == ctx->dir_info[high].ino)
701                 return &ctx->dir_info[high];
702
703         while (low < high) {
704                 mid = (low+high)/2;
705                 if (mid == low || mid == high)
706                         break;
707                 if (ino == ctx->dir_info[mid].ino)
708                         return &ctx->dir_info[mid];
709                 if (ino < ctx->dir_info[mid].ino)
710                         high = mid;
711                 else
712                         low = mid;
713         }
714         return 0;
715 }
716
717 /*
718  * Free the dir_info structure when it isn't needed any more.
719  */
720 static void e2fsck_free_dir_info(e2fsck_t ctx)
721 {
722         ext2fs_free_mem(&ctx->dir_info);
723         ctx->dir_info_size = 0;
724         ctx->dir_info_count = 0;
725 }
726
727 /*
728  * Return the count of number of directories in the dir_info structure
729  */
730 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
731 {
732         return ctx->dir_info_count;
733 }
734
735 /*
736  * A simple interator function
737  */
738 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
739 {
740         if (*control >= ctx->dir_info_count)
741                 return 0;
742
743         return(ctx->dir_info + (*control)++);
744 }
745
746 /*
747  * dirinfo.c --- maintains the directory information table for e2fsck.
748  *
749  */
750
751 #ifdef ENABLE_HTREE
752
753 /*
754  * This subroutine is called during pass1 to create a directory info
755  * entry.  During pass1, the passed-in parent is 0; it will get filled
756  * in during pass2.
757  */
758 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
759 {
760         struct dx_dir_info *dir;
761         int             i, j;
762         errcode_t       retval;
763         unsigned long   old_size;
764
765         if (!ctx->dx_dir_info) {
766                 ctx->dx_dir_info_count = 0;
767                 ctx->dx_dir_info_size = 100; /* Guess */
768                 ctx->dx_dir_info  = (struct dx_dir_info *)
769                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
770                                                * sizeof (struct dx_dir_info),
771                                                "directory map");
772         }
773
774         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
775                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
776                 ctx->dx_dir_info_size += 10;
777                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
778                                            sizeof(struct dx_dir_info),
779                                            &ctx->dx_dir_info);
780                 if (retval) {
781                         ctx->dx_dir_info_size -= 10;
782                         return;
783                 }
784         }
785
786         /*
787          * Normally, add_dx_dir_info is called with each inode in
788          * sequential order; but once in a while (like when pass 3
789          * needs to recreate the root directory or lost+found
790          * directory) it is called out of order.  In those cases, we
791          * need to move the dx_dir_info entries down to make room, since
792          * the dx_dir_info array needs to be sorted by inode number for
793          * get_dx_dir_info()'s sake.
794          */
795         if (ctx->dx_dir_info_count &&
796             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
797                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
798                         if (ctx->dx_dir_info[i-1].ino < ino)
799                                 break;
800                 dir = &ctx->dx_dir_info[i];
801                 if (dir->ino != ino)
802                         for (j = ctx->dx_dir_info_count++; j > i; j--)
803                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
804         } else
805                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
806
807         dir->ino = ino;
808         dir->numblocks = num_blocks;
809         dir->hashversion = 0;
810         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
811                                        * sizeof (struct dx_dirblock_info),
812                                        "dx_block info array");
813
814 }
815
816 /*
817  * get_dx_dir_info() --- given an inode number, try to find the directory
818  * information entry for it.
819  */
820 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
821 {
822         int     low, high, mid;
823
824         low = 0;
825         high = ctx->dx_dir_info_count-1;
826         if (!ctx->dx_dir_info)
827                 return 0;
828         if (ino == ctx->dx_dir_info[low].ino)
829                 return &ctx->dx_dir_info[low];
830         if  (ino == ctx->dx_dir_info[high].ino)
831                 return &ctx->dx_dir_info[high];
832
833         while (low < high) {
834                 mid = (low+high)/2;
835                 if (mid == low || mid == high)
836                         break;
837                 if (ino == ctx->dx_dir_info[mid].ino)
838                         return &ctx->dx_dir_info[mid];
839                 if (ino < ctx->dx_dir_info[mid].ino)
840                         high = mid;
841                 else
842                         low = mid;
843         }
844         return 0;
845 }
846
847 /*
848  * Free the dx_dir_info structure when it isn't needed any more.
849  */
850 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
851 {
852         int     i;
853         struct dx_dir_info *dir;
854
855         if (ctx->dx_dir_info) {
856                 dir = ctx->dx_dir_info;
857                 for (i=0; i < ctx->dx_dir_info_count; i++) {
858                         ext2fs_free_mem(&dir->dx_block);
859                 }
860                 ext2fs_free_mem(&ctx->dx_dir_info);
861         }
862         ctx->dx_dir_info_size = 0;
863         ctx->dx_dir_info_count = 0;
864 }
865
866 /*
867  * A simple interator function
868  */
869 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
870 {
871         if (*control >= ctx->dx_dir_info_count)
872                 return 0;
873
874         return(ctx->dx_dir_info + (*control)++);
875 }
876
877 #endif /* ENABLE_HTREE */
878 /*
879  * e2fsck.c - a consistency checker for the new extended file system.
880  *
881  */
882
883 /*
884  * This function allocates an e2fsck context
885  */
886 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
887 {
888         e2fsck_t        context;
889         errcode_t       retval;
890
891         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
892         if (retval)
893                 return retval;
894
895         memset(context, 0, sizeof(struct e2fsck_struct));
896
897         context->process_inode_size = 256;
898         context->ext_attr_ver = 2;
899
900         *ret = context;
901         return 0;
902 }
903
904 struct ea_refcount_el {
905         blk_t   ea_blk;
906         int     ea_count;
907 };
908
909 struct ea_refcount {
910         blk_t           count;
911         blk_t           size;
912         blk_t           cursor;
913         struct ea_refcount_el   *list;
914 };
915
916 static void ea_refcount_free(ext2_refcount_t refcount)
917 {
918         if (!refcount)
919                 return;
920
921         ext2fs_free_mem(&refcount->list);
922         ext2fs_free_mem(&refcount);
923 }
924
925 /*
926  * This function resets an e2fsck context; it is called when e2fsck
927  * needs to be restarted.
928  */
929 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
930 {
931         ctx->flags = 0;
932         ctx->lost_and_found = 0;
933         ctx->bad_lost_and_found = 0;
934         ext2fs_free_inode_bitmap(ctx->inode_used_map);
935         ctx->inode_used_map = 0;
936         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
937         ctx->inode_dir_map = 0;
938         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
939         ctx->inode_reg_map = 0;
940         ext2fs_free_block_bitmap(ctx->block_found_map);
941         ctx->block_found_map = 0;
942         ext2fs_free_icount(ctx->inode_link_info);
943         ctx->inode_link_info = 0;
944         if (ctx->journal_io) {
945                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
946                         io_channel_close(ctx->journal_io);
947                 ctx->journal_io = 0;
948         }
949         if (ctx->fs) {
950                 ext2fs_free_dblist(ctx->fs->dblist);
951                 ctx->fs->dblist = 0;
952         }
953         e2fsck_free_dir_info(ctx);
954 #ifdef ENABLE_HTREE
955         e2fsck_free_dx_dir_info(ctx);
956 #endif
957         ea_refcount_free(ctx->refcount);
958         ctx->refcount = 0;
959         ea_refcount_free(ctx->refcount_extra);
960         ctx->refcount_extra = 0;
961         ext2fs_free_block_bitmap(ctx->block_dup_map);
962         ctx->block_dup_map = 0;
963         ext2fs_free_block_bitmap(ctx->block_ea_map);
964         ctx->block_ea_map = 0;
965         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
966         ctx->inode_bad_map = 0;
967         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
968         ctx->inode_imagic_map = 0;
969         ext2fs_u32_list_free(ctx->dirs_to_hash);
970         ctx->dirs_to_hash = 0;
971
972         /*
973          * Clear the array of invalid meta-data flags
974          */
975         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
976         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
977         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
978
979         /* Clear statistic counters */
980         ctx->fs_directory_count = 0;
981         ctx->fs_regular_count = 0;
982         ctx->fs_blockdev_count = 0;
983         ctx->fs_chardev_count = 0;
984         ctx->fs_links_count = 0;
985         ctx->fs_symlinks_count = 0;
986         ctx->fs_fast_symlinks_count = 0;
987         ctx->fs_fifo_count = 0;
988         ctx->fs_total_count = 0;
989         ctx->fs_sockets_count = 0;
990         ctx->fs_ind_count = 0;
991         ctx->fs_dind_count = 0;
992         ctx->fs_tind_count = 0;
993         ctx->fs_fragmented = 0;
994         ctx->large_files = 0;
995
996         /* Reset the superblock to the user's requested value */
997         ctx->superblock = ctx->use_superblock;
998
999         return 0;
1000 }
1001
1002 static void e2fsck_free_context(e2fsck_t ctx)
1003 {
1004         if (!ctx)
1005                 return;
1006
1007         e2fsck_reset_context(ctx);
1008         if (ctx->blkid)
1009                 blkid_put_cache(ctx->blkid);
1010
1011         ext2fs_free_mem(&ctx);
1012 }
1013
1014 /*
1015  * ea_refcount.c
1016  */
1017
1018 /*
1019  * The strategy we use for keeping track of EA refcounts is as
1020  * follows.  We keep a sorted array of first EA blocks and its
1021  * reference counts.  Once the refcount has dropped to zero, it is
1022  * removed from the array to save memory space.  Once the EA block is
1023  * checked, its bit is set in the block_ea_map bitmap.
1024  */
1025
1026
1027 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1028 {
1029         ext2_refcount_t refcount;
1030         errcode_t       retval;
1031         size_t          bytes;
1032
1033         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1034         if (retval)
1035                 return retval;
1036         memset(refcount, 0, sizeof(struct ea_refcount));
1037
1038         if (!size)
1039                 size = 500;
1040         refcount->size = size;
1041         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1042 #ifdef DEBUG
1043         printf("Refcount allocated %d entries, %d bytes.\n",
1044                refcount->size, bytes);
1045 #endif
1046         retval = ext2fs_get_mem(bytes, &refcount->list);
1047         if (retval)
1048                 goto errout;
1049         memset(refcount->list, 0, bytes);
1050
1051         refcount->count = 0;
1052         refcount->cursor = 0;
1053
1054         *ret = refcount;
1055         return 0;
1056
1057 errout:
1058         ea_refcount_free(refcount);
1059         return(retval);
1060 }
1061
1062 /*
1063  * collapse_refcount() --- go through the refcount array, and get rid
1064  * of any count == zero entries
1065  */
1066 static void refcount_collapse(ext2_refcount_t refcount)
1067 {
1068         unsigned int    i, j;
1069         struct ea_refcount_el   *list;
1070
1071         list = refcount->list;
1072         for (i = 0, j = 0; i < refcount->count; i++) {
1073                 if (list[i].ea_count) {
1074                         if (i != j)
1075                                 list[j] = list[i];
1076                         j++;
1077                 }
1078         }
1079 #if defined(DEBUG) || defined(TEST_PROGRAM)
1080         printf("Refcount_collapse: size was %d, now %d\n",
1081                refcount->count, j);
1082 #endif
1083         refcount->count = j;
1084 }
1085
1086
1087 /*
1088  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1089  *      specified position.
1090  */
1091 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1092                                                  blk_t blk, int pos)
1093 {
1094         struct ea_refcount_el   *el;
1095         errcode_t               retval;
1096         blk_t                   new_size = 0;
1097         int                     num;
1098
1099         if (refcount->count >= refcount->size) {
1100                 new_size = refcount->size + 100;
1101 #ifdef DEBUG
1102                 printf("Reallocating refcount %d entries...\n", new_size);
1103 #endif
1104                 retval = ext2fs_resize_mem((size_t) refcount->size *
1105                                            sizeof(struct ea_refcount_el),
1106                                            (size_t) new_size *
1107                                            sizeof(struct ea_refcount_el),
1108                                            &refcount->list);
1109                 if (retval)
1110                         return 0;
1111                 refcount->size = new_size;
1112         }
1113         num = (int) refcount->count - pos;
1114         if (num < 0)
1115                 return 0;       /* should never happen */
1116         if (num) {
1117                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1118                         sizeof(struct ea_refcount_el) * num);
1119         }
1120         refcount->count++;
1121         el = &refcount->list[pos];
1122         el->ea_count = 0;
1123         el->ea_blk = blk;
1124         return el;
1125 }
1126
1127
1128 /*
1129  * get_refcount_el() --- given an block number, try to find refcount
1130  *      information in the sorted list.  If the create flag is set,
1131  *      and we can't find an entry, create one in the sorted list.
1132  */
1133 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1134                                               blk_t blk, int create)
1135 {
1136         float   range;
1137         int     low, high, mid;
1138         blk_t   lowval, highval;
1139
1140         if (!refcount || !refcount->list)
1141                 return 0;
1142 retry:
1143         low = 0;
1144         high = (int) refcount->count-1;
1145         if (create && ((refcount->count == 0) ||
1146                        (blk > refcount->list[high].ea_blk))) {
1147                 if (refcount->count >= refcount->size)
1148                         refcount_collapse(refcount);
1149
1150                 return insert_refcount_el(refcount, blk,
1151                                           (unsigned) refcount->count);
1152         }
1153         if (refcount->count == 0)
1154                 return 0;
1155
1156         if (refcount->cursor >= refcount->count)
1157                 refcount->cursor = 0;
1158         if (blk == refcount->list[refcount->cursor].ea_blk)
1159                 return &refcount->list[refcount->cursor++];
1160 #ifdef DEBUG
1161         printf("Non-cursor get_refcount_el: %u\n", blk);
1162 #endif
1163         while (low <= high) {
1164                 if (low == high)
1165                         mid = low;
1166                 else {
1167                         /* Interpolate for efficiency */
1168                         lowval = refcount->list[low].ea_blk;
1169                         highval = refcount->list[high].ea_blk;
1170
1171                         if (blk < lowval)
1172                                 range = 0;
1173                         else if (blk > highval)
1174                                 range = 1;
1175                         else
1176                                 range = ((float) (blk - lowval)) /
1177                                         (highval - lowval);
1178                         mid = low + ((int) (range * (high-low)));
1179                 }
1180
1181                 if (blk == refcount->list[mid].ea_blk) {
1182                         refcount->cursor = mid+1;
1183                         return &refcount->list[mid];
1184                 }
1185                 if (blk < refcount->list[mid].ea_blk)
1186                         high = mid-1;
1187                 else
1188                         low = mid+1;
1189         }
1190         /*
1191          * If we need to create a new entry, it should be right at
1192          * low (where high will be left at low-1).
1193          */
1194         if (create) {
1195                 if (refcount->count >= refcount->size) {
1196                         refcount_collapse(refcount);
1197                         if (refcount->count < refcount->size)
1198                                 goto retry;
1199                 }
1200                 return insert_refcount_el(refcount, blk, low);
1201         }
1202         return 0;
1203 }
1204
1205 static errcode_t
1206 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1207 {
1208         struct ea_refcount_el   *el;
1209
1210         el = get_refcount_el(refcount, blk, 1);
1211         if (!el)
1212                 return EXT2_ET_NO_MEMORY;
1213         el->ea_count++;
1214
1215         if (ret)
1216                 *ret = el->ea_count;
1217         return 0;
1218 }
1219
1220 static errcode_t
1221 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1222 {
1223         struct ea_refcount_el   *el;
1224
1225         el = get_refcount_el(refcount, blk, 0);
1226         if (!el || el->ea_count == 0)
1227                 return EXT2_ET_INVALID_ARGUMENT;
1228
1229         el->ea_count--;
1230
1231         if (ret)
1232                 *ret = el->ea_count;
1233         return 0;
1234 }
1235
1236 static errcode_t
1237 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1238 {
1239         struct ea_refcount_el   *el;
1240
1241         /*
1242          * Get the refcount element
1243          */
1244         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1245         if (!el)
1246                 return count ? EXT2_ET_NO_MEMORY : 0;
1247         el->ea_count = count;
1248         return 0;
1249 }
1250
1251 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1252 {
1253         refcount->cursor = 0;
1254 }
1255
1256
1257 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1258 {
1259         struct ea_refcount_el   *list;
1260
1261         while (1) {
1262                 if (refcount->cursor >= refcount->count)
1263                         return 0;
1264                 list = refcount->list;
1265                 if (list[refcount->cursor].ea_count) {
1266                         if (ret)
1267                                 *ret = list[refcount->cursor].ea_count;
1268                         return list[refcount->cursor++].ea_blk;
1269                 }
1270                 refcount->cursor++;
1271         }
1272 }
1273
1274
1275 /*
1276  * ehandler.c --- handle bad block errors which come up during the
1277  *      course of an e2fsck session.
1278  */
1279
1280
1281 static const char *operation;
1282
1283 static errcode_t
1284 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1285                          void *data, size_t size FSCK_ATTR((unused)),
1286                          int actual FSCK_ATTR((unused)), errcode_t error)
1287 {
1288         int     i;
1289         char    *p;
1290         ext2_filsys fs = (ext2_filsys) channel->app_data;
1291         e2fsck_t ctx;
1292
1293         ctx = (e2fsck_t) fs->priv_data;
1294
1295         /*
1296          * If more than one block was read, try reading each block
1297          * separately.  We could use the actual bytes read to figure
1298          * out where to start, but we don't bother.
1299          */
1300         if (count > 1) {
1301                 p = (char *) data;
1302                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1303                         error = io_channel_read_blk(channel, block,
1304                                                     1, p);
1305                         if (error)
1306                                 return error;
1307                 }
1308                 return 0;
1309         }
1310         if (operation)
1311                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1312                        error_message(error), operation);
1313         else
1314                 printf(_("Error reading block %lu (%s).  "), block,
1315                        error_message(error));
1316         preenhalt(ctx);
1317         if (ask(ctx, _("Ignore error"), 1)) {
1318                 if (ask(ctx, _("Force rewrite"), 1))
1319                         io_channel_write_blk(channel, block, 1, data);
1320                 return 0;
1321         }
1322
1323         return error;
1324 }
1325
1326 static errcode_t
1327 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1328                         const void *data, size_t size FSCK_ATTR((unused)),
1329                         int actual FSCK_ATTR((unused)), errcode_t error)
1330 {
1331         int             i;
1332         const char      *p;
1333         ext2_filsys fs = (ext2_filsys) channel->app_data;
1334         e2fsck_t ctx;
1335
1336         ctx = (e2fsck_t) fs->priv_data;
1337
1338         /*
1339          * If more than one block was written, try writing each block
1340          * separately.  We could use the actual bytes read to figure
1341          * out where to start, but we don't bother.
1342          */
1343         if (count > 1) {
1344                 p = (const char *) data;
1345                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1346                         error = io_channel_write_blk(channel, block,
1347                                                      1, p);
1348                         if (error)
1349                                 return error;
1350                 }
1351                 return 0;
1352         }
1353
1354         if (operation)
1355                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1356                        error_message(error), operation);
1357         else
1358                 printf(_("Error writing block %lu (%s).  "), block,
1359                        error_message(error));
1360         preenhalt(ctx);
1361         if (ask(ctx, _("Ignore error"), 1))
1362                 return 0;
1363
1364         return error;
1365 }
1366
1367 static inline const char *ehandler_operation(const char *op)
1368 {
1369         const char *ret = operation;
1370
1371         operation = op;
1372         return ret;
1373 }
1374
1375 static void ehandler_init(io_channel channel)
1376 {
1377         channel->read_error = e2fsck_handle_read_error;
1378         channel->write_error = e2fsck_handle_write_error;
1379 }
1380
1381 /*
1382  * journal.c --- code for handling the "ext3" journal
1383  *
1384  * Copyright (C) 2000 Andreas Dilger
1385  * Copyright (C) 2000 Theodore Ts'o
1386  *
1387  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1388  * Copyright (C) 1999 Red Hat Software
1389  *
1390  * This file may be redistributed under the terms of the
1391  * GNU General Public License version 2 or at your discretion
1392  * any later version.
1393  */
1394
1395 /*
1396  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1397  * This creates a larger static binary, and a smaller binary using
1398  * shared libraries.  It's also probably slightly less CPU-efficient,
1399  * which is why it's not on by default.  But, it's a good way of
1400  * testing the functions in inode_io.c and fileio.c.
1401  */
1402 #undef USE_INODE_IO
1403
1404 /* Kernel compatibility functions for handling the journal.  These allow us
1405  * to use the recovery.c file virtually unchanged from the kernel, so we
1406  * don't have to do much to keep kernel and user recovery in sync.
1407  */
1408 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1409 {
1410 #ifdef USE_INODE_IO
1411         *phys = block;
1412         return 0;
1413 #else
1414         struct inode    *inode = journal->j_inode;
1415         errcode_t       retval;
1416         blk_t           pblk;
1417
1418         if (!inode) {
1419                 *phys = block;
1420                 return 0;
1421         }
1422
1423         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1424                             &inode->i_ext2, NULL, 0, block, &pblk);
1425         *phys = pblk;
1426         return (retval);
1427 #endif
1428 }
1429
1430 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1431 {
1432         struct buffer_head *bh;
1433
1434         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1435         if (!bh)
1436                 return NULL;
1437
1438         bh->b_ctx = kdev->k_ctx;
1439         if (kdev->k_dev == K_DEV_FS)
1440                 bh->b_io = kdev->k_ctx->fs->io;
1441         else
1442                 bh->b_io = kdev->k_ctx->journal_io;
1443         bh->b_size = blocksize;
1444         bh->b_blocknr = blocknr;
1445
1446         return bh;
1447 }
1448
1449 static void sync_blockdev(kdev_t kdev)
1450 {
1451         io_channel      io;
1452
1453         if (kdev->k_dev == K_DEV_FS)
1454                 io = kdev->k_ctx->fs->io;
1455         else
1456                 io = kdev->k_ctx->journal_io;
1457
1458         io_channel_flush(io);
1459 }
1460
1461 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1462 {
1463         int retval;
1464         struct buffer_head *bh;
1465
1466         for (; nr > 0; --nr) {
1467                 bh = *bhp++;
1468                 if (rw == READ && !bh->b_uptodate) {
1469                         retval = io_channel_read_blk(bh->b_io,
1470                                                      bh->b_blocknr,
1471                                                      1, bh->b_data);
1472                         if (retval) {
1473                                 bb_error_msg("while reading block %lu\n",
1474                                         (unsigned long) bh->b_blocknr);
1475                                 bh->b_err = retval;
1476                                 continue;
1477                         }
1478                         bh->b_uptodate = 1;
1479                 } else if (rw == WRITE && bh->b_dirty) {
1480                         retval = io_channel_write_blk(bh->b_io,
1481                                                       bh->b_blocknr,
1482                                                       1, bh->b_data);
1483                         if (retval) {
1484                                 bb_error_msg("while writing block %lu\n",
1485                                         (unsigned long) bh->b_blocknr);
1486                                 bh->b_err = retval;
1487                                 continue;
1488                         }
1489                         bh->b_dirty = 0;
1490                         bh->b_uptodate = 1;
1491                 }
1492         }
1493 }
1494
1495 static inline void mark_buffer_dirty(struct buffer_head *bh)
1496 {
1497         bh->b_dirty = 1;
1498 }
1499
1500 static inline void mark_buffer_clean(struct buffer_head * bh)
1501 {
1502         bh->b_dirty = 0;
1503 }
1504
1505 static void brelse(struct buffer_head *bh)
1506 {
1507         if (bh->b_dirty)
1508                 ll_rw_block(WRITE, 1, &bh);
1509         ext2fs_free_mem(&bh);
1510 }
1511
1512 static inline int buffer_uptodate(struct buffer_head *bh)
1513 {
1514         return bh->b_uptodate;
1515 }
1516
1517 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1518 {
1519         bh->b_uptodate = val;
1520 }
1521
1522 static void wait_on_buffer(struct buffer_head *bh)
1523 {
1524         if (!bh->b_uptodate)
1525                 ll_rw_block(READ, 1, &bh);
1526 }
1527
1528
1529 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1530 {
1531         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1532
1533         /* if we had an error doing journal recovery, we need a full fsck */
1534         if (error)
1535                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1536         ext2fs_mark_super_dirty(ctx->fs);
1537 }
1538
1539 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1540 {
1541         struct ext2_super_block *sb = ctx->fs->super;
1542         struct ext2_super_block jsuper;
1543         struct problem_context  pctx;
1544         struct buffer_head      *bh;
1545         struct inode            *j_inode = NULL;
1546         struct kdev_s           *dev_fs = NULL, *dev_journal;
1547         const char              *journal_name = 0;
1548         journal_t               *journal = NULL;
1549         errcode_t               retval = 0;
1550         io_manager              io_ptr = 0;
1551         unsigned long           start = 0;
1552         blk_t                   blk;
1553         int                     ext_journal = 0;
1554         int                     tried_backup_jnl = 0;
1555         int                     i;
1556
1557         clear_problem_context(&pctx);
1558
1559         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1560         if (!journal) {
1561                 return EXT2_ET_NO_MEMORY;
1562         }
1563
1564         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1565         if (!dev_fs) {
1566                 retval = EXT2_ET_NO_MEMORY;
1567                 goto errout;
1568         }
1569         dev_journal = dev_fs+1;
1570
1571         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1572         dev_fs->k_dev = K_DEV_FS;
1573         dev_journal->k_dev = K_DEV_JOURNAL;
1574
1575         journal->j_dev = dev_journal;
1576         journal->j_fs_dev = dev_fs;
1577         journal->j_inode = NULL;
1578         journal->j_blocksize = ctx->fs->blocksize;
1579
1580         if (uuid_is_null(sb->s_journal_uuid)) {
1581                 if (!sb->s_journal_inum)
1582                         return EXT2_ET_BAD_INODE_NUM;
1583                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1584                                                  "journal inode");
1585                 if (!j_inode) {
1586                         retval = EXT2_ET_NO_MEMORY;
1587                         goto errout;
1588                 }
1589
1590                 j_inode->i_ctx = ctx;
1591                 j_inode->i_ino = sb->s_journal_inum;
1592
1593                 if ((retval = ext2fs_read_inode(ctx->fs,
1594                                                 sb->s_journal_inum,
1595                                                 &j_inode->i_ext2))) {
1596                 try_backup_journal:
1597                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1598                             tried_backup_jnl)
1599                                 goto errout;
1600                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1601                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1602                                EXT2_N_BLOCKS*4);
1603                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1604                         j_inode->i_ext2.i_links_count = 1;
1605                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1606                         tried_backup_jnl++;
1607                 }
1608                 if (!j_inode->i_ext2.i_links_count ||
1609                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1610                         retval = EXT2_ET_NO_JOURNAL;
1611                         goto try_backup_journal;
1612                 }
1613                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1614                     JFS_MIN_JOURNAL_BLOCKS) {
1615                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1616                         goto try_backup_journal;
1617                 }
1618                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1619                         blk = j_inode->i_ext2.i_block[i];
1620                         if (!blk) {
1621                                 if (i < EXT2_NDIR_BLOCKS) {
1622                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1623                                         goto try_backup_journal;
1624                                 }
1625                                 continue;
1626                         }
1627                         if (blk < sb->s_first_data_block ||
1628                             blk >= sb->s_blocks_count) {
1629                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1630                                 goto try_backup_journal;
1631                         }
1632                 }
1633                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1634
1635 #ifdef USE_INODE_IO
1636                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1637                                                  &j_inode->i_ext2,
1638                                                  &journal_name);
1639                 if (retval)
1640                         goto errout;
1641
1642                 io_ptr = inode_io_manager;
1643 #else
1644                 journal->j_inode = j_inode;
1645                 ctx->journal_io = ctx->fs->io;
1646                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1647                         goto errout;
1648 #endif
1649         } else {
1650                 ext_journal = 1;
1651                 if (!ctx->journal_name) {
1652                         char uuid[37];
1653
1654                         uuid_unparse(sb->s_journal_uuid, uuid);
1655                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1656                                                               "UUID", uuid);
1657                         if (!ctx->journal_name)
1658                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1659                 }
1660                 journal_name = ctx->journal_name;
1661
1662                 if (!journal_name) {
1663                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1664                         return EXT2_ET_LOAD_EXT_JOURNAL;
1665                 }
1666
1667                 io_ptr = unix_io_manager;
1668         }
1669
1670 #ifndef USE_INODE_IO
1671         if (ext_journal)
1672 #endif
1673                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1674                                       &ctx->journal_io);
1675         if (retval)
1676                 goto errout;
1677
1678         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1679
1680         if (ext_journal) {
1681                 if (ctx->fs->blocksize == 1024)
1682                         start = 1;
1683                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1684                 if (!bh) {
1685                         retval = EXT2_ET_NO_MEMORY;
1686                         goto errout;
1687                 }
1688                 ll_rw_block(READ, 1, &bh);
1689                 if ((retval = bh->b_err) != 0)
1690                         goto errout;
1691                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1692                        sizeof(jsuper));
1693                 brelse(bh);
1694 #if BB_BIG_ENDIAN
1695                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1696                         ext2fs_swap_super(&jsuper);
1697 #endif
1698                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1699                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1700                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1701                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1702                         goto errout;
1703                 }
1704                 /* Make sure the journal UUID is correct */
1705                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1706                            sizeof(jsuper.s_uuid))) {
1707                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1708                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1709                         goto errout;
1710                 }
1711
1712                 journal->j_maxlen = jsuper.s_blocks_count;
1713                 start++;
1714         }
1715
1716         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1717                 retval = EXT2_ET_NO_MEMORY;
1718                 goto errout;
1719         }
1720
1721         journal->j_sb_buffer = bh;
1722         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1723
1724 #ifdef USE_INODE_IO
1725         ext2fs_free_mem(&j_inode);
1726 #endif
1727
1728         *ret_journal = journal;
1729         return 0;
1730
1731 errout:
1732         ext2fs_free_mem(&dev_fs);
1733         ext2fs_free_mem(&j_inode);
1734         ext2fs_free_mem(&journal);
1735         return retval;
1736
1737 }
1738
1739 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1740                                               struct problem_context *pctx)
1741 {
1742         struct ext2_super_block *sb = ctx->fs->super;
1743         int recover = ctx->fs->super->s_feature_incompat &
1744                 EXT3_FEATURE_INCOMPAT_RECOVER;
1745         int has_journal = ctx->fs->super->s_feature_compat &
1746                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1747
1748         if (has_journal || sb->s_journal_inum) {
1749                 /* The journal inode is bogus, remove and force full fsck */
1750                 pctx->ino = sb->s_journal_inum;
1751                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1752                         if (has_journal && sb->s_journal_inum)
1753                                 printf("*** ext3 journal has been deleted - "
1754                                        "filesystem is now ext2 only ***\n\n");
1755                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1756                         sb->s_journal_inum = 0;
1757                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1758                         e2fsck_clear_recover(ctx, 1);
1759                         return 0;
1760                 }
1761                 return EXT2_ET_BAD_INODE_NUM;
1762         } else if (recover) {
1763                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1764                         e2fsck_clear_recover(ctx, 1);
1765                         return 0;
1766                 }
1767                 return EXT2_ET_UNSUPP_FEATURE;
1768         }
1769         return 0;
1770 }
1771
1772 #define V1_SB_SIZE      0x0024
1773 static void clear_v2_journal_fields(journal_t *journal)
1774 {
1775         e2fsck_t ctx = journal->j_dev->k_ctx;
1776         struct problem_context pctx;
1777
1778         clear_problem_context(&pctx);
1779
1780         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1781                 return;
1782
1783         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1784                ctx->fs->blocksize-V1_SB_SIZE);
1785         mark_buffer_dirty(journal->j_sb_buffer);
1786 }
1787
1788
1789 static errcode_t e2fsck_journal_load(journal_t *journal)
1790 {
1791         e2fsck_t ctx = journal->j_dev->k_ctx;
1792         journal_superblock_t *jsb;
1793         struct buffer_head *jbh = journal->j_sb_buffer;
1794         struct problem_context pctx;
1795
1796         clear_problem_context(&pctx);
1797
1798         ll_rw_block(READ, 1, &jbh);
1799         if (jbh->b_err) {
1800                 bb_error_msg(_("reading journal superblock\n"));
1801                 return jbh->b_err;
1802         }
1803
1804         jsb = journal->j_superblock;
1805         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1806         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1807                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1808
1809         switch (ntohl(jsb->s_header.h_blocktype)) {
1810         case JFS_SUPERBLOCK_V1:
1811                 journal->j_format_version = 1;
1812                 if (jsb->s_feature_compat ||
1813                     jsb->s_feature_incompat ||
1814                     jsb->s_feature_ro_compat ||
1815                     jsb->s_nr_users)
1816                         clear_v2_journal_fields(journal);
1817                 break;
1818
1819         case JFS_SUPERBLOCK_V2:
1820                 journal->j_format_version = 2;
1821                 if (ntohl(jsb->s_nr_users) > 1 &&
1822                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1823                         clear_v2_journal_fields(journal);
1824                 if (ntohl(jsb->s_nr_users) > 1) {
1825                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1826                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1827                 }
1828                 break;
1829
1830         /*
1831          * These should never appear in a journal super block, so if
1832          * they do, the journal is badly corrupted.
1833          */
1834         case JFS_DESCRIPTOR_BLOCK:
1835         case JFS_COMMIT_BLOCK:
1836         case JFS_REVOKE_BLOCK:
1837                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1838
1839         /* If we don't understand the superblock major type, but there
1840          * is a magic number, then it is likely to be a new format we
1841          * just don't understand, so leave it alone. */
1842         default:
1843                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1844         }
1845
1846         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1847                 return EXT2_ET_UNSUPP_FEATURE;
1848
1849         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1850                 return EXT2_ET_RO_UNSUPP_FEATURE;
1851
1852         /* We have now checked whether we know enough about the journal
1853          * format to be able to proceed safely, so any other checks that
1854          * fail we should attempt to recover from. */
1855         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1856                 bb_error_msg(_("%s: no valid journal superblock found\n"),
1857                         ctx->device_name);
1858                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1859         }
1860
1861         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1862                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1863         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1864                 bb_error_msg(_("%s: journal too short\n"),
1865                         ctx->device_name);
1866                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1867         }
1868
1869         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1870         journal->j_transaction_sequence = journal->j_tail_sequence;
1871         journal->j_tail = ntohl(jsb->s_start);
1872         journal->j_first = ntohl(jsb->s_first);
1873         journal->j_last = ntohl(jsb->s_maxlen);
1874
1875         return 0;
1876 }
1877
1878 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1879                                        journal_t *journal)
1880 {
1881         char *p;
1882         union {
1883                 uuid_t uuid;
1884                 __u32 val[4];
1885         } u;
1886         __u32 new_seq = 0;
1887         int i;
1888
1889         /* Leave a valid existing V1 superblock signature alone.
1890          * Anything unrecognisable we overwrite with a new V2
1891          * signature. */
1892
1893         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1894             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1895                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1896                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1897         }
1898
1899         /* Zero out everything else beyond the superblock header */
1900
1901         p = ((char *) jsb) + sizeof(journal_header_t);
1902         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1903
1904         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1905         jsb->s_maxlen = htonl(journal->j_maxlen);
1906         jsb->s_first = htonl(1);
1907
1908         /* Initialize the journal sequence number so that there is "no"
1909          * chance we will find old "valid" transactions in the journal.
1910          * This avoids the need to zero the whole journal (slow to do,
1911          * and risky when we are just recovering the filesystem).
1912          */
1913         uuid_generate(u.uuid);
1914         for (i = 0; i < 4; i ++)
1915                 new_seq ^= u.val[i];
1916         jsb->s_sequence = htonl(new_seq);
1917
1918         mark_buffer_dirty(journal->j_sb_buffer);
1919         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1920 }
1921
1922 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1923                                                   journal_t *journal,
1924                                                   struct problem_context *pctx)
1925 {
1926         struct ext2_super_block *sb = ctx->fs->super;
1927         int recover = ctx->fs->super->s_feature_incompat &
1928                 EXT3_FEATURE_INCOMPAT_RECOVER;
1929
1930         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1931                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1932                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1933                                                    journal);
1934                         journal->j_transaction_sequence = 1;
1935                         e2fsck_clear_recover(ctx, recover);
1936                         return 0;
1937                 }
1938                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1939         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1940                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1941
1942         return 0;
1943 }
1944
1945 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1946                                    int reset, int drop)
1947 {
1948         journal_superblock_t *jsb;
1949
1950         if (drop)
1951                 mark_buffer_clean(journal->j_sb_buffer);
1952         else if (!(ctx->options & E2F_OPT_READONLY)) {
1953                 jsb = journal->j_superblock;
1954                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1955                 if (reset)
1956                         jsb->s_start = 0; /* this marks the journal as empty */
1957                 mark_buffer_dirty(journal->j_sb_buffer);
1958         }
1959         brelse(journal->j_sb_buffer);
1960
1961         if (ctx->journal_io) {
1962                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1963                         io_channel_close(ctx->journal_io);
1964                 ctx->journal_io = 0;
1965         }
1966
1967 #ifndef USE_INODE_IO
1968         ext2fs_free_mem(&journal->j_inode);
1969 #endif
1970         ext2fs_free_mem(&journal->j_fs_dev);
1971         ext2fs_free_mem(&journal);
1972 }
1973
1974 /*
1975  * This function makes sure that the superblock fields regarding the
1976  * journal are consistent.
1977  */
1978 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1979 {
1980         struct ext2_super_block *sb = ctx->fs->super;
1981         journal_t *journal;
1982         int recover = ctx->fs->super->s_feature_incompat &
1983                 EXT3_FEATURE_INCOMPAT_RECOVER;
1984         struct problem_context pctx;
1985         problem_t problem;
1986         int reset = 0, force_fsck = 0;
1987         int retval;
1988
1989         /* If we don't have any journal features, don't do anything more */
1990         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1991             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1992             uuid_is_null(sb->s_journal_uuid))
1993                 return 0;
1994
1995         clear_problem_context(&pctx);
1996         pctx.num = sb->s_journal_inum;
1997
1998         retval = e2fsck_get_journal(ctx, &journal);
1999         if (retval) {
2000                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2001                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2002                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2003                     (retval == EXT2_ET_NO_JOURNAL))
2004                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2005                 return retval;
2006         }
2007
2008         retval = e2fsck_journal_load(journal);
2009         if (retval) {
2010                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2011                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2012                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2013                                   &pctx))) ||
2014                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2015                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2016                                   &pctx))) ||
2017                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2018                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2019                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2020                                                                   &pctx);
2021                 e2fsck_journal_release(ctx, journal, 0, 1);
2022                 return retval;
2023         }
2024
2025         /*
2026          * We want to make the flags consistent here.  We will not leave with
2027          * needs_recovery set but has_journal clear.  We can't get in a loop
2028          * with -y, -n, or -p, only if a user isn't making up their mind.
2029          */
2030 no_has_journal:
2031         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2032                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2033                 pctx.str = "inode";
2034                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2035                         if (recover &&
2036                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2037                                 goto no_has_journal;
2038                         /*
2039                          * Need a full fsck if we are releasing a
2040                          * journal stored on a reserved inode.
2041                          */
2042                         force_fsck = recover ||
2043                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2044                         /* Clear all of the journal fields */
2045                         sb->s_journal_inum = 0;
2046                         sb->s_journal_dev = 0;
2047                         memset(sb->s_journal_uuid, 0,
2048                                sizeof(sb->s_journal_uuid));
2049                         e2fsck_clear_recover(ctx, force_fsck);
2050                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2051                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2052                         ext2fs_mark_super_dirty(ctx->fs);
2053                 }
2054         }
2055
2056         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2057             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2058             journal->j_superblock->s_start != 0) {
2059                 /* Print status information */
2060                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2061                 if (ctx->superblock)
2062                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2063                 else
2064                         problem = PR_0_JOURNAL_RUN;
2065                 if (fix_problem(ctx, problem, &pctx)) {
2066                         ctx->options |= E2F_OPT_FORCE;
2067                         sb->s_feature_incompat |=
2068                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2069                         ext2fs_mark_super_dirty(ctx->fs);
2070                 } else if (fix_problem(ctx,
2071                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2072                         reset = 1;
2073                         sb->s_state &= ~EXT2_VALID_FS;
2074                         ext2fs_mark_super_dirty(ctx->fs);
2075                 }
2076                 /*
2077                  * If the user answers no to the above question, we
2078                  * ignore the fact that journal apparently has data;
2079                  * accidentally replaying over valid data would be far
2080                  * worse than skipping a questionable recovery.
2081                  *
2082                  * XXX should we abort with a fatal error here?  What
2083                  * will the ext3 kernel code do if a filesystem with
2084                  * !NEEDS_RECOVERY but with a non-zero
2085                  * journal->j_superblock->s_start is mounted?
2086                  */
2087         }
2088
2089         e2fsck_journal_release(ctx, journal, reset, 0);
2090         return retval;
2091 }
2092
2093 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2094 {
2095         journal_t *journal;
2096         int retval;
2097
2098         journal_init_revoke_caches();
2099         retval = e2fsck_get_journal(ctx, &journal);
2100         if (retval)
2101                 return retval;
2102
2103         retval = e2fsck_journal_load(journal);
2104         if (retval)
2105                 goto errout;
2106
2107         retval = journal_init_revoke(journal, 1024);
2108         if (retval)
2109                 goto errout;
2110
2111         retval = -journal_recover(journal);
2112         if (retval)
2113                 goto errout;
2114
2115         if (journal->j_superblock->s_errno) {
2116                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2117                 ext2fs_mark_super_dirty(ctx->fs);
2118                 journal->j_superblock->s_errno = 0;
2119                 mark_buffer_dirty(journal->j_sb_buffer);
2120         }
2121
2122 errout:
2123         journal_destroy_revoke(journal);
2124         journal_destroy_revoke_caches();
2125         e2fsck_journal_release(ctx, journal, 1, 0);
2126         return retval;
2127 }
2128
2129 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2130 {
2131         io_manager io_ptr = ctx->fs->io->manager;
2132         int blocksize = ctx->fs->blocksize;
2133         errcode_t       retval, recover_retval;
2134
2135         printf(_("%s: recovering journal\n"), ctx->device_name);
2136         if (ctx->options & E2F_OPT_READONLY) {
2137                 printf(_("%s: won't do journal recovery while read-only\n"),
2138                        ctx->device_name);
2139                 return EXT2_ET_FILE_RO;
2140         }
2141
2142         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2143                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2144
2145         recover_retval = recover_ext3_journal(ctx);
2146
2147         /*
2148          * Reload the filesystem context to get up-to-date data from disk
2149          * because journal recovery will change the filesystem under us.
2150          */
2151         ext2fs_close(ctx->fs);
2152         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2153                              ctx->superblock, blocksize, io_ptr,
2154                              &ctx->fs);
2155
2156         if (retval) {
2157                 bb_error_msg(_("while trying to re-open %s"),
2158                         ctx->device_name);
2159                 bb_error_msg_and_die(0);
2160         }
2161         ctx->fs->priv_data = ctx;
2162
2163         /* Set the superblock flags */
2164         e2fsck_clear_recover(ctx, recover_retval);
2165         return recover_retval;
2166 }
2167
2168 /*
2169  * This function will move the journal inode from a visible file in
2170  * the filesystem directory hierarchy to the reserved inode if necessary.
2171  */
2172 static const char * const journal_names[] = {
2173         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2174
2175 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2176 {
2177         struct ext2_super_block *sb = ctx->fs->super;
2178         struct problem_context  pctx;
2179         struct ext2_inode       inode;
2180         ext2_filsys             fs = ctx->fs;
2181         ext2_ino_t              ino;
2182         errcode_t               retval;
2183         const char * const *    cpp;
2184         int                     group, mount_flags;
2185
2186         clear_problem_context(&pctx);
2187
2188         /*
2189          * If the filesystem is opened read-only, or there is no
2190          * journal, then do nothing.
2191          */
2192         if ((ctx->options & E2F_OPT_READONLY) ||
2193             (sb->s_journal_inum == 0) ||
2194             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2195                 return;
2196
2197         /*
2198          * Read in the journal inode
2199          */
2200         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2201                 return;
2202
2203         /*
2204          * If it's necessary to backup the journal inode, do so.
2205          */
2206         if ((sb->s_jnl_backup_type == 0) ||
2207             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2208              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2209                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2210                         memcpy(sb->s_jnl_blocks, inode.i_block,
2211                                EXT2_N_BLOCKS*4);
2212                         sb->s_jnl_blocks[16] = inode.i_size;
2213                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2214                         ext2fs_mark_super_dirty(fs);
2215                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2216                 }
2217         }
2218
2219         /*
2220          * If the journal is already the hidden inode, then do nothing
2221          */
2222         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2223                 return;
2224
2225         /*
2226          * The journal inode had better have only one link and not be readable.
2227          */
2228         if (inode.i_links_count != 1)
2229                 return;
2230
2231         /*
2232          * If the filesystem is mounted, or we can't tell whether
2233          * or not it's mounted, do nothing.
2234          */
2235         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2236         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2237                 return;
2238
2239         /*
2240          * If we can't find the name of the journal inode, then do
2241          * nothing.
2242          */
2243         for (cpp = journal_names; *cpp; cpp++) {
2244                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2245                                        strlen(*cpp), 0, &ino);
2246                 if ((retval == 0) && (ino == sb->s_journal_inum))
2247                         break;
2248         }
2249         if (*cpp == 0)
2250                 return;
2251
2252         /* We need the inode bitmap to be loaded */
2253         retval = ext2fs_read_bitmaps(fs);
2254         if (retval)
2255                 return;
2256
2257         pctx.str = *cpp;
2258         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2259                 return;
2260
2261         /*
2262          * OK, we've done all the checks, let's actually move the
2263          * journal inode.  Errors at this point mean we need to force
2264          * an ext2 filesystem check.
2265          */
2266         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2267                 goto err_out;
2268         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2269                 goto err_out;
2270         sb->s_journal_inum = EXT2_JOURNAL_INO;
2271         ext2fs_mark_super_dirty(fs);
2272         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2273         inode.i_links_count = 0;
2274         inode.i_dtime = time(0);
2275         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2276                 goto err_out;
2277
2278         group = ext2fs_group_of_ino(fs, ino);
2279         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2280         ext2fs_mark_ib_dirty(fs);
2281         fs->group_desc[group].bg_free_inodes_count++;
2282         fs->super->s_free_inodes_count++;
2283         return;
2284
2285 err_out:
2286         pctx.errcode = retval;
2287         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2288         fs->super->s_state &= ~EXT2_VALID_FS;
2289         ext2fs_mark_super_dirty(fs);
2290         return;
2291 }
2292
2293 /*
2294  * message.c --- print e2fsck messages (with compression)
2295  *
2296  * print_e2fsck_message() prints a message to the user, using
2297  * compression techniques and expansions of abbreviations.
2298  *
2299  * The following % expansions are supported:
2300  *
2301  *      %b      <blk>                   block number
2302  *      %B      <blkcount>              integer
2303  *      %c      <blk2>                  block number
2304  *      %Di     <dirent>->ino           inode number
2305  *      %Dn     <dirent>->name          string
2306  *      %Dr     <dirent>->rec_len
2307  *      %Dl     <dirent>->name_len
2308  *      %Dt     <dirent>->filetype
2309  *      %d      <dir>                   inode number
2310  *      %g      <group>                 integer
2311  *      %i      <ino>                   inode number
2312  *      %Is     <inode> -> i_size
2313  *      %IS     <inode> -> i_extra_isize
2314  *      %Ib     <inode> -> i_blocks
2315  *      %Il     <inode> -> i_links_count
2316  *      %Im     <inode> -> i_mode
2317  *      %IM     <inode> -> i_mtime
2318  *      %IF     <inode> -> i_faddr
2319  *      %If     <inode> -> i_file_acl
2320  *      %Id     <inode> -> i_dir_acl
2321  *      %Iu     <inode> -> i_uid
2322  *      %Ig     <inode> -> i_gid
2323  *      %j      <ino2>                  inode number
2324  *      %m      <com_err error message>
2325  *      %N      <num>
2326  *      %p      ext2fs_get_pathname of directory <ino>
2327  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2328  *                      the containing directory.  (If dirent is NULL
2329  *                      then return the pathname of directory <ino2>)
2330  *      %q      ext2fs_get_pathname of directory <dir>
2331  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2332  *                      the containing directory.
2333  *      %s      <str>                   miscellaneous string
2334  *      %S      backup superblock
2335  *      %X      <num> hexadecimal format
2336  *
2337  * The following '@' expansions are supported:
2338  *
2339  *      @a      extended attribute
2340  *      @A      error allocating
2341  *      @b      block
2342  *      @B      bitmap
2343  *      @c      compress
2344  *      @C      conflicts with some other fs block
2345  *      @D      deleted
2346  *      @d      directory
2347  *      @e      entry
2348  *      @E      Entry '%Dn' in %p (%i)
2349  *      @f      filesystem
2350  *      @F      for @i %i (%Q) is
2351  *      @g      group
2352  *      @h      HTREE directory inode
2353  *      @i      inode
2354  *      @I      illegal
2355  *      @j      journal
2356  *      @l      lost+found
2357  *      @L      is a link
2358  *      @m      multiply-claimed
2359  *      @n      invalid
2360  *      @o      orphaned
2361  *      @p      problem in
2362  *      @r      root inode
2363  *      @s      should be
2364  *      @S      superblock
2365  *      @u      unattached
2366  *      @v      device
2367  *      @z      zero-length
2368  */
2369
2370
2371 /*
2372  * This structure defines the abbreviations used by the text strings
2373  * below.  The first character in the string is the index letter.  An
2374  * abbreviation of the form '@<i>' is expanded by looking up the index
2375  * letter <i> in the table below.
2376  */
2377 static const char * const abbrevs[] = {
2378         N_("aextended attribute"),
2379         N_("Aerror allocating"),
2380         N_("bblock"),
2381         N_("Bbitmap"),
2382         N_("ccompress"),
2383         N_("Cconflicts with some other fs @b"),
2384         N_("iinode"),
2385         N_("Iillegal"),
2386         N_("jjournal"),
2387         N_("Ddeleted"),
2388         N_("ddirectory"),
2389         N_("eentry"),
2390         N_("E@e '%Dn' in %p (%i)"),
2391         N_("ffilesystem"),
2392         N_("Ffor @i %i (%Q) is"),
2393         N_("ggroup"),
2394         N_("hHTREE @d @i"),
2395         N_("llost+found"),
2396         N_("Lis a link"),
2397     N_("mmultiply-claimed"),
2398     N_("ninvalid"),
2399         N_("oorphaned"),
2400         N_("pproblem in"),
2401         N_("rroot @i"),
2402         N_("sshould be"),
2403         N_("Ssuper@b"),
2404         N_("uunattached"),
2405         N_("vdevice"),
2406         N_("zzero-length"),
2407         "@@",
2408         0
2409         };
2410
2411 /*
2412  * Give more user friendly names to the "special" inodes.
2413  */
2414 #define num_special_inodes      11
2415 static const char * const special_inode_name[] =
2416 {
2417         N_("<The NULL inode>"),                 /* 0 */
2418         N_("<The bad blocks inode>"),           /* 1 */
2419         "/",                                    /* 2 */
2420         N_("<The ACL index inode>"),            /* 3 */
2421         N_("<The ACL data inode>"),             /* 4 */
2422         N_("<The boot loader inode>"),          /* 5 */
2423         N_("<The undelete directory inode>"),   /* 6 */
2424         N_("<The group descriptor inode>"),     /* 7 */
2425         N_("<The journal inode>"),              /* 8 */
2426         N_("<Reserved inode 9>"),               /* 9 */
2427         N_("<Reserved inode 10>"),              /* 10 */
2428 };
2429
2430 /*
2431  * This function does "safe" printing.  It will convert non-printable
2432  * ASCII characters using '^' and M- notation.
2433  */
2434 static void safe_print(const char *cp, int len)
2435 {
2436         unsigned char   ch;
2437
2438         if (len < 0)
2439                 len = strlen(cp);
2440
2441         while (len--) {
2442                 ch = *cp++;
2443                 if (ch > 128) {
2444                         fputs("M-", stdout);
2445                         ch -= 128;
2446                 }
2447                 if ((ch < 32) || (ch == 0x7f)) {
2448                         fputc('^', stdout);
2449                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2450                 }
2451                 fputc(ch, stdout);
2452         }
2453 }
2454
2455
2456 /*
2457  * This function prints a pathname, using the ext2fs_get_pathname
2458  * function
2459  */
2460 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2461 {
2462         errcode_t       retval;
2463         char            *path;
2464
2465         if (!dir && (ino < num_special_inodes)) {
2466                 fputs(_(special_inode_name[ino]), stdout);
2467                 return;
2468         }
2469
2470         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2471         if (retval)
2472                 fputs("???", stdout);
2473         else {
2474                 safe_print(path, -1);
2475                 ext2fs_free_mem(&path);
2476         }
2477 }
2478
2479 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2480                           struct problem_context *pctx, int first);
2481 /*
2482  * This function handles the '@' expansion.  We allow recursive
2483  * expansion; an @ expression can contain further '@' and '%'
2484  * expressions.
2485  */
2486 static void expand_at_expression(e2fsck_t ctx, char ch,
2487                                           struct problem_context *pctx,
2488                                           int *first)
2489 {
2490         const char * const *cpp;
2491         const char *str;
2492
2493         /* Search for the abbreviation */
2494         for (cpp = abbrevs; *cpp; cpp++) {
2495                 if (ch == *cpp[0])
2496                         break;
2497         }
2498         if (*cpp) {
2499                 str = _(*cpp) + 1;
2500                 if (*first && islower(*str)) {
2501                         *first = 0;
2502                         fputc(toupper(*str++), stdout);
2503                 }
2504                 print_e2fsck_message(ctx, str, pctx, *first);
2505         } else
2506                 printf("@%c", ch);
2507 }
2508
2509 /*
2510  * This function expands '%IX' expressions
2511  */
2512 static void expand_inode_expression(char ch,
2513                                              struct problem_context *ctx)
2514 {
2515         struct ext2_inode       *inode;
2516         struct ext2_inode_large *large_inode;
2517         char *                  time_str;
2518         time_t                  t;
2519         int                     do_gmt = -1;
2520
2521         if (!ctx || !ctx->inode)
2522                 goto no_inode;
2523
2524         inode = ctx->inode;
2525         large_inode = (struct ext2_inode_large *) inode;
2526
2527         switch (ch) {
2528         case 's':
2529                 if (LINUX_S_ISDIR(inode->i_mode))
2530                         printf("%u", inode->i_size);
2531                 else {
2532 #ifdef EXT2_NO_64_TYPE
2533                         if (inode->i_size_high)
2534                                 printf("0x%x%08x", inode->i_size_high,
2535                                        inode->i_size);
2536                         else
2537                                 printf("%u", inode->i_size);
2538 #else
2539                         printf("%llu", (inode->i_size |
2540                                         ((__u64) inode->i_size_high << 32)));
2541 #endif
2542                 }
2543                 break;
2544         case 'S':
2545                 printf("%u", large_inode->i_extra_isize);
2546                 break;
2547         case 'b':
2548                 printf("%u", inode->i_blocks);
2549                 break;
2550         case 'l':
2551                 printf("%d", inode->i_links_count);
2552                 break;
2553         case 'm':
2554                 printf("0%o", inode->i_mode);
2555                 break;
2556         case 'M':
2557                 /* The diet libc doesn't respect the TZ environemnt variable */
2558                 if (do_gmt == -1) {
2559                         time_str = getenv("TZ");
2560                         if (!time_str)
2561                                 time_str = "";
2562                         do_gmt = !strcmp(time_str, "GMT");
2563                 }
2564                 t = inode->i_mtime;
2565                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2566                 printf("%.24s", time_str);
2567                 break;
2568         case 'F':
2569                 printf("%u", inode->i_faddr);
2570                 break;
2571         case 'f':
2572                 printf("%u", inode->i_file_acl);
2573                 break;
2574         case 'd':
2575                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2576                               inode->i_dir_acl : 0));
2577                 break;
2578         case 'u':
2579                 printf("%d", (inode->i_uid |
2580                               (inode->osd2.linux2.l_i_uid_high << 16)));
2581                 break;
2582         case 'g':
2583                 printf("%d", (inode->i_gid |
2584                               (inode->osd2.linux2.l_i_gid_high << 16)));
2585                 break;
2586         default:
2587         no_inode:
2588                 printf("%%I%c", ch);
2589                 break;
2590         }
2591 }
2592
2593 /*
2594  * This function expands '%dX' expressions
2595  */
2596 static void expand_dirent_expression(char ch,
2597                                               struct problem_context *ctx)
2598 {
2599         struct ext2_dir_entry   *dirent;
2600         int     len;
2601
2602         if (!ctx || !ctx->dirent)
2603                 goto no_dirent;
2604
2605         dirent = ctx->dirent;
2606
2607         switch (ch) {
2608         case 'i':
2609                 printf("%u", dirent->inode);
2610                 break;
2611         case 'n':
2612                 len = dirent->name_len & 0xFF;
2613                 if (len > EXT2_NAME_LEN)
2614                         len = EXT2_NAME_LEN;
2615                 if (len > dirent->rec_len)
2616                         len = dirent->rec_len;
2617                 safe_print(dirent->name, len);
2618                 break;
2619         case 'r':
2620                 printf("%u", dirent->rec_len);
2621                 break;
2622         case 'l':
2623                 printf("%u", dirent->name_len & 0xFF);
2624                 break;
2625         case 't':
2626                 printf("%u", dirent->name_len >> 8);
2627                 break;
2628         default:
2629         no_dirent:
2630                 printf("%%D%c", ch);
2631                 break;
2632         }
2633 }
2634
2635 static void expand_percent_expression(ext2_filsys fs, char ch,
2636                                                struct problem_context *ctx)
2637 {
2638         if (!ctx)
2639                 goto no_context;
2640
2641         switch (ch) {
2642         case '%':
2643                 fputc('%', stdout);
2644                 break;
2645         case 'b':
2646                 printf("%u", ctx->blk);
2647                 break;
2648         case 'B':
2649 #ifdef EXT2_NO_64_TYPE
2650                 printf("%d", ctx->blkcount);
2651 #else
2652                 printf("%lld", ctx->blkcount);
2653 #endif
2654                 break;
2655         case 'c':
2656                 printf("%u", ctx->blk2);
2657                 break;
2658         case 'd':
2659                 printf("%u", ctx->dir);
2660                 break;
2661         case 'g':
2662                 printf("%d", ctx->group);
2663                 break;
2664         case 'i':
2665                 printf("%u", ctx->ino);
2666                 break;
2667         case 'j':
2668                 printf("%u", ctx->ino2);
2669                 break;
2670         case 'm':
2671                 printf("%s", error_message(ctx->errcode));
2672                 break;
2673         case 'N':
2674 #ifdef EXT2_NO_64_TYPE
2675                 printf("%u", ctx->num);
2676 #else
2677                 printf("%llu", ctx->num);
2678 #endif
2679                 break;
2680         case 'p':
2681                 print_pathname(fs, ctx->ino, 0);
2682                 break;
2683         case 'P':
2684                 print_pathname(fs, ctx->ino2,
2685                                ctx->dirent ? ctx->dirent->inode : 0);
2686                 break;
2687         case 'q':
2688                 print_pathname(fs, ctx->dir, 0);
2689                 break;
2690         case 'Q':
2691                 print_pathname(fs, ctx->dir, ctx->ino);
2692                 break;
2693         case 'S':
2694                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2695                 break;
2696         case 's':
2697                 printf("%s", ctx->str ? ctx->str : "NULL");
2698                 break;
2699         case 'X':
2700 #ifdef EXT2_NO_64_TYPE
2701                 printf("0x%x", ctx->num);
2702 #else
2703                 printf("0x%llx", ctx->num);
2704 #endif
2705                 break;
2706         default:
2707         no_context:
2708                 printf("%%%c", ch);
2709                 break;
2710         }
2711 }
2712
2713
2714 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2715                           struct problem_context *pctx, int first)
2716 {
2717         ext2_filsys fs = ctx->fs;
2718         const char *    cp;
2719         int             i;
2720
2721         e2fsck_clear_progbar(ctx);
2722         for (cp = msg; *cp; cp++) {
2723                 if (cp[0] == '@') {
2724                         cp++;
2725                         expand_at_expression(ctx, *cp, pctx, &first);
2726                 } else if (cp[0] == '%' && cp[1] == 'I') {
2727                         cp += 2;
2728                         expand_inode_expression(*cp, pctx);
2729                 } else if (cp[0] == '%' && cp[1] == 'D') {
2730                         cp += 2;
2731                         expand_dirent_expression(*cp, pctx);
2732                 } else if ((cp[0] == '%')) {
2733                         cp++;
2734                         expand_percent_expression(fs, *cp, pctx);
2735                 } else {
2736                         for (i=0; cp[i]; i++)
2737                                 if ((cp[i] == '@') || cp[i] == '%')
2738                                         break;
2739                         printf("%.*s", i, cp);
2740                         cp += i-1;
2741                 }
2742                 first = 0;
2743         }
2744 }
2745
2746
2747 /*
2748  * region.c --- code which manages allocations within a region.
2749  */
2750
2751 struct region_el {
2752         region_addr_t   start;
2753         region_addr_t   end;
2754         struct region_el *next;
2755 };
2756
2757 struct region_struct {
2758         region_addr_t   min;
2759         region_addr_t   max;
2760         struct region_el *allocated;
2761 };
2762
2763 static region_t region_create(region_addr_t min, region_addr_t max)
2764 {
2765         region_t        region;
2766
2767         region = malloc(sizeof(struct region_struct));
2768         if (!region)
2769                 return NULL;
2770         memset(region, 0, sizeof(struct region_struct));
2771         region->min = min;
2772         region->max = max;
2773         return region;
2774 }
2775
2776 static void region_free(region_t region)
2777 {
2778         struct region_el        *r, *next;
2779
2780         for (r = region->allocated; r; r = next) {
2781                 next = r->next;
2782                 free(r);
2783         }
2784         memset(region, 0, sizeof(struct region_struct));
2785         free(region);
2786 }
2787
2788 static int region_allocate(region_t region, region_addr_t start, int n)
2789 {
2790         struct region_el        *r, *new_region, *prev, *next;
2791         region_addr_t end;
2792
2793         end = start+n;
2794         if ((start < region->min) || (end > region->max))
2795                 return -1;
2796         if (n == 0)
2797                 return 1;
2798
2799         /*
2800          * Search through the linked list.  If we find that it
2801          * conflicts witih something that's already allocated, return
2802          * 1; if we can find an existing region which we can grow, do
2803          * so.  Otherwise, stop when we find the appropriate place
2804          * insert a new region element into the linked list.
2805          */
2806         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2807                 if (((start >= r->start) && (start < r->end)) ||
2808                     ((end > r->start) && (end <= r->end)) ||
2809                     ((start <= r->start) && (end >= r->end)))
2810                         return 1;
2811                 if (end == r->start) {
2812                         r->start = start;
2813                         return 0;
2814                 }
2815                 if (start == r->end) {
2816                         if ((next = r->next)) {
2817                                 if (end > next->start)
2818                                         return 1;
2819                                 if (end == next->start) {
2820                                         r->end = next->end;
2821                                         r->next = next->next;
2822                                         free(next);
2823                                         return 0;
2824                                 }
2825                         }
2826                         r->end = end;
2827                         return 0;
2828                 }
2829                 if (start < r->start)
2830                         break;
2831         }
2832         /*
2833          * Insert a new region element structure into the linked list
2834          */
2835         new_region = malloc(sizeof(struct region_el));
2836         if (!new_region)
2837                 return -1;
2838         new_region->start = start;
2839         new_region->end = start + n;
2840         new_region->next = r;
2841         if (prev)
2842                 prev->next = new_region;
2843         else
2844                 region->allocated = new_region;
2845         return 0;
2846 }
2847
2848 /*
2849  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2850  *
2851  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2852  * and applies the following tests to each inode:
2853  *
2854  *      - The mode field of the inode must be legal.
2855  *      - The size and block count fields of the inode are correct.
2856  *      - A data block must not be used by another inode
2857  *
2858  * Pass 1 also gathers the collects the following information:
2859  *
2860  *      - A bitmap of which inodes are in use.          (inode_used_map)
2861  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2862  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2863  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2864  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2865  *      - A bitmap of which blocks are in use.          (block_found_map)
2866  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2867  *      - The data blocks of the directory inodes.      (dir_map)
2868  *
2869  * Pass 1 is designed to stash away enough information so that the
2870  * other passes should not need to read in the inode information
2871  * during the normal course of a filesystem check.  (Althogh if an
2872  * inconsistency is detected, other passes may need to read in an
2873  * inode to fix it.)
2874  *
2875  * Note that pass 1B will be invoked if there are any duplicate blocks
2876  * found.
2877  */
2878
2879
2880 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2881                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2882                          int ref_offset, void *priv_data);
2883 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2884                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2885                              int ref_offset, void *priv_data);
2886 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2887                          char *block_buf);
2888 static void mark_table_blocks(e2fsck_t ctx);
2889 static void alloc_imagic_map(e2fsck_t ctx);
2890 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2891 static void handle_fs_bad_blocks(e2fsck_t ctx);
2892 static void process_inodes(e2fsck_t ctx, char *block_buf);
2893 static int process_inode_cmp(const void *a, const void *b);
2894 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
2895                                   dgrp_t group, void * priv_data);
2896 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2897                                     char *block_buf, int adjust_sign);
2898 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2899
2900 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2901                                struct ext2_inode * inode, int bufsize,
2902                                const char *proc);
2903
2904 struct process_block_struct_1 {
2905         ext2_ino_t      ino;
2906         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2907                                 fragmented:1, compressed:1, bbcheck:1;
2908         blk_t           num_blocks;
2909         blk_t           max_blocks;
2910         e2_blkcnt_t     last_block;
2911         int             num_illegal_blocks;
2912         blk_t           previous_block;
2913         struct ext2_inode *inode;
2914         struct problem_context *pctx;
2915         ext2fs_block_bitmap fs_meta_blocks;
2916         e2fsck_t        ctx;
2917 };
2918
2919 struct process_inode_block {
2920         ext2_ino_t ino;
2921         struct ext2_inode inode;
2922 };
2923
2924 struct scan_callback_struct {
2925         e2fsck_t        ctx;
2926         char            *block_buf;
2927 };
2928
2929 /*
2930  * For the inodes to process list.
2931  */
2932 static struct process_inode_block *inodes_to_process;
2933 static int process_inode_count;
2934
2935 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2936                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2937
2938 /*
2939  * Free all memory allocated by pass1 in preparation for restarting
2940  * things.
2941  */
2942 static void unwind_pass1(void)
2943 {
2944         ext2fs_free_mem(&inodes_to_process);
2945 }
2946
2947 /*
2948  * Check to make sure a device inode is real.  Returns 1 if the device
2949  * checks out, 0 if not.
2950  *
2951  * Note: this routine is now also used to check FIFO's and Sockets,
2952  * since they have the same requirement; the i_block fields should be
2953  * zero.
2954  */
2955 static int
2956 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2957 {
2958         int     i;
2959
2960         /*
2961          * If i_blocks is non-zero, or the index flag is set, then
2962          * this is a bogus device/fifo/socket
2963          */
2964         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2965             (inode->i_flags & EXT2_INDEX_FL))
2966                 return 0;
2967
2968         /*
2969          * We should be able to do the test below all the time, but
2970          * because the kernel doesn't forcibly clear the device
2971          * inode's additional i_block fields, there are some rare
2972          * occasions when a legitimate device inode will have non-zero
2973          * additional i_block fields.  So for now, we only complain
2974          * when the immutable flag is set, which should never happen
2975          * for devices.  (And that's when the problem is caused, since
2976          * you can't set or clear immutable flags for devices.)  Once
2977          * the kernel has been fixed we can change this...
2978          */
2979         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2980                 for (i=4; i < EXT2_N_BLOCKS; i++)
2981                         if (inode->i_block[i])
2982                                 return 0;
2983         }
2984         return 1;
2985 }
2986
2987 /*
2988  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2989  * checks out, 0 if not.
2990  */
2991 static int
2992 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2993 {
2994         unsigned int len;
2995         int i;
2996         blk_t   blocks;
2997
2998         if ((inode->i_size_high || inode->i_size == 0) ||
2999             (inode->i_flags & EXT2_INDEX_FL))
3000                 return 0;
3001
3002         blocks = ext2fs_inode_data_blocks(fs, inode);
3003         if (blocks) {
3004                 if ((inode->i_size >= fs->blocksize) ||
3005                     (blocks != fs->blocksize >> 9) ||
3006                     (inode->i_block[0] < fs->super->s_first_data_block) ||
3007                     (inode->i_block[0] >= fs->super->s_blocks_count))
3008                         return 0;
3009
3010                 for (i = 1; i < EXT2_N_BLOCKS; i++)
3011                         if (inode->i_block[i])
3012                                 return 0;
3013
3014                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
3015                         return 0;
3016
3017                 len = strnlen(buf, fs->blocksize);
3018                 if (len == fs->blocksize)
3019                         return 0;
3020         } else {
3021                 if (inode->i_size >= sizeof(inode->i_block))
3022                         return 0;
3023
3024                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3025                 if (len == sizeof(inode->i_block))
3026                         return 0;
3027         }
3028         if (len != inode->i_size)
3029                 return 0;
3030         return 1;
3031 }
3032
3033 /*
3034  * If the immutable (or append-only) flag is set on the inode, offer
3035  * to clear it.
3036  */
3037 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3038 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3039 {
3040         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3041                 return;
3042
3043         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3044                 return;
3045
3046         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3047         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3048 }
3049
3050 /*
3051  * If device, fifo or socket, check size is zero -- if not offer to
3052  * clear it
3053  */
3054 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3055 {
3056         struct ext2_inode *inode = pctx->inode;
3057
3058         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3059                 return;
3060
3061         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3062                 return;
3063
3064         inode->i_size = 0;
3065         inode->i_size_high = 0;
3066         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3067 }
3068
3069 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3070 {
3071         struct ext2_super_block *sb = ctx->fs->super;
3072         struct ext2_inode_large *inode;
3073         struct ext2_ext_attr_entry *entry;
3074         char *start, *end;
3075         int storage_size, remain, offs;
3076         int problem = 0;
3077
3078         inode = (struct ext2_inode_large *) pctx->inode;
3079         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3080                 inode->i_extra_isize;
3081         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3082                 inode->i_extra_isize + sizeof(__u32);
3083         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3084         entry = (struct ext2_ext_attr_entry *) start;
3085
3086         /* scan all entry's headers first */
3087
3088         /* take finish entry 0UL into account */
3089         remain = storage_size - sizeof(__u32);
3090         offs = end - start;
3091
3092         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3093
3094                 /* header eats this space */
3095                 remain -= sizeof(struct ext2_ext_attr_entry);
3096
3097                 /* is attribute name valid? */
3098                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3099                         pctx->num = entry->e_name_len;
3100                         problem = PR_1_ATTR_NAME_LEN;
3101                         goto fix;
3102                 }
3103
3104                 /* attribute len eats this space */
3105                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3106
3107                 /* check value size */
3108                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3109                         pctx->num = entry->e_value_size;
3110                         problem = PR_1_ATTR_VALUE_SIZE;
3111                         goto fix;
3112                 }
3113
3114                 /* check value placement */
3115                 if (entry->e_value_offs +
3116                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3117                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3118                         pctx->num = entry->e_value_offs;
3119                         problem = PR_1_ATTR_VALUE_OFFSET;
3120                         goto fix;
3121                 }
3122
3123                 /* e_value_block must be 0 in inode's ea */
3124                 if (entry->e_value_block != 0) {
3125                         pctx->num = entry->e_value_block;
3126                         problem = PR_1_ATTR_VALUE_BLOCK;
3127                         goto fix;
3128                 }
3129
3130                 /* e_hash must be 0 in inode's ea */
3131                 if (entry->e_hash != 0) {
3132                         pctx->num = entry->e_hash;
3133                         problem = PR_1_ATTR_HASH;
3134                         goto fix;
3135                 }
3136
3137                 remain -= entry->e_value_size;
3138                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3139
3140                 entry = EXT2_EXT_ATTR_NEXT(entry);
3141         }
3142 fix:
3143         /*
3144          * it seems like a corruption. it's very unlikely we could repair
3145          * EA(s) in automatic fashion -bzzz
3146          */
3147         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3148                 return;
3149
3150         /* simple remove all possible EA(s) */
3151         *((__u32 *)start) = 0UL;
3152         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3153                                 EXT2_INODE_SIZE(sb), "pass1");
3154 }
3155
3156 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3157 {
3158         struct ext2_super_block *sb = ctx->fs->super;
3159         struct ext2_inode_large *inode;
3160         __u32 *eamagic;
3161         int min, max;
3162
3163         inode = (struct ext2_inode_large *) pctx->inode;
3164         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3165                 /* this isn't large inode. so, nothing to check */
3166                 return;
3167         }
3168
3169         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3170         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3171         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3172         /*
3173          * For now we will allow i_extra_isize to be 0, but really
3174          * implementations should never allow i_extra_isize to be 0
3175          */
3176         if (inode->i_extra_isize &&
3177             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3178                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3179                         return;
3180                 inode->i_extra_isize = min;
3181                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3182                                         EXT2_INODE_SIZE(sb), "pass1");
3183                 return;
3184         }
3185
3186         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3187                         inode->i_extra_isize);
3188         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3189                 /* it seems inode has an extended attribute(s) in body */
3190                 check_ea_in_inode(ctx, pctx);
3191         }
3192 }
3193
3194 static void e2fsck_pass1(e2fsck_t ctx)
3195 {
3196         int     i;
3197         __u64   max_sizes;
3198         ext2_filsys fs = ctx->fs;
3199         ext2_ino_t      ino;
3200         struct ext2_inode *inode;
3201         ext2_inode_scan scan;
3202         char            *block_buf;
3203         unsigned char   frag, fsize;
3204         struct          problem_context pctx;
3205         struct          scan_callback_struct scan_struct;
3206         struct ext2_super_block *sb = ctx->fs->super;
3207         int             imagic_fs;
3208         int             busted_fs_time = 0;
3209         int             inode_size;
3210
3211         clear_problem_context(&pctx);
3212
3213         if (!(ctx->options & E2F_OPT_PREEN))
3214                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3215
3216         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3217             !(ctx->options & E2F_OPT_NO)) {
3218                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3219                         ctx->dirs_to_hash = 0;
3220         }
3221
3222         /* Pass 1 */
3223
3224 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3225
3226         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3227                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3228                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3229                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3230                 max_sizes = (max_sizes * (1UL << i)) - 1;
3231                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3232         }
3233 #undef EXT2_BPP
3234
3235         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3236
3237         /*
3238          * Allocate bitmaps structures
3239          */
3240         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3241                                               &ctx->inode_used_map);
3242         if (pctx.errcode) {
3243                 pctx.num = 1;
3244                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3245                 ctx->flags |= E2F_FLAG_ABORT;
3246                 return;
3247         }
3248         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3249                                 _("directory inode map"), &ctx->inode_dir_map);
3250         if (pctx.errcode) {
3251                 pctx.num = 2;
3252                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3253                 ctx->flags |= E2F_FLAG_ABORT;
3254                 return;
3255         }
3256         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3257                         _("regular file inode map"), &ctx->inode_reg_map);
3258         if (pctx.errcode) {
3259                 pctx.num = 6;
3260                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3261                 ctx->flags |= E2F_FLAG_ABORT;
3262                 return;
3263         }
3264         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3265                                               &ctx->block_found_map);
3266         if (pctx.errcode) {
3267                 pctx.num = 1;
3268                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3269                 ctx->flags |= E2F_FLAG_ABORT;
3270                 return;
3271         }
3272         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3273                                              &ctx->inode_link_info);
3274         if (pctx.errcode) {
3275                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3276                 ctx->flags |= E2F_FLAG_ABORT;
3277                 return;
3278         }
3279         inode_size = EXT2_INODE_SIZE(fs->super);
3280         inode = (struct ext2_inode *)
3281                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3282
3283         inodes_to_process = (struct process_inode_block *)
3284                 e2fsck_allocate_memory(ctx,
3285                                        (ctx->process_inode_size *
3286                                         sizeof(struct process_inode_block)),
3287                                        "array of inodes to process");
3288         process_inode_count = 0;
3289
3290         pctx.errcode = ext2fs_init_dblist(fs, 0);
3291         if (pctx.errcode) {
3292                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3293                 ctx->flags |= E2F_FLAG_ABORT;
3294                 return;
3295         }
3296
3297         /*
3298          * If the last orphan field is set, clear it, since the pass1
3299          * processing will automatically find and clear the orphans.
3300          * In the future, we may want to try using the last_orphan
3301          * linked list ourselves, but for now, we clear it so that the
3302          * ext3 mount code won't get confused.
3303          */
3304         if (!(ctx->options & E2F_OPT_READONLY)) {
3305                 if (fs->super->s_last_orphan) {
3306                         fs->super->s_last_orphan = 0;
3307                         ext2fs_mark_super_dirty(fs);
3308                 }
3309         }
3310
3311         mark_table_blocks(ctx);
3312         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3313                                                     "block interate buffer");
3314         e2fsck_use_inode_shortcuts(ctx, 1);
3315         ehandler_operation(_("doing inode scan"));
3316         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3317                                               &scan);
3318         if (pctx.errcode) {
3319                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3320                 ctx->flags |= E2F_FLAG_ABORT;
3321                 return;
3322         }
3323         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3324         ctx->stashed_inode = inode;
3325         scan_struct.ctx = ctx;
3326         scan_struct.block_buf = block_buf;
3327         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3328         if (ctx->progress)
3329                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3330                         return;
3331         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3332             (fs->super->s_mtime < fs->super->s_inodes_count))
3333                 busted_fs_time = 1;
3334
3335         while (1) {
3336                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3337                                                           inode, inode_size);
3338                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3339                         return;
3340                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3341                         continue;
3342                 }
3343                 if (pctx.errcode) {
3344                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3345                         ctx->flags |= E2F_FLAG_ABORT;
3346                         return;
3347                 }
3348                 if (!ino)
3349                         break;
3350                 pctx.ino = ino;
3351                 pctx.inode = inode;
3352                 ctx->stashed_ino = ino;
3353                 if (inode->i_links_count) {
3354                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3355                                            ino, inode->i_links_count);
3356                         if (pctx.errcode) {
3357                                 pctx.num = inode->i_links_count;
3358                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3359                                 ctx->flags |= E2F_FLAG_ABORT;
3360                                 return;
3361                         }
3362                 }
3363                 if (ino == EXT2_BAD_INO) {
3364                         struct process_block_struct_1 pb;
3365
3366                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3367                                                           &pb.fs_meta_blocks);
3368                         if (pctx.errcode) {
3369                                 pctx.num = 4;
3370                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3371                                 ctx->flags |= E2F_FLAG_ABORT;
3372                                 return;
3373                         }
3374                         pb.ino = EXT2_BAD_INO;
3375                         pb.num_blocks = pb.last_block = 0;
3376                         pb.num_illegal_blocks = 0;
3377                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3378                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3379                         pb.inode = inode;
3380                         pb.pctx = &pctx;
3381                         pb.ctx = ctx;
3382                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3383                                      block_buf, process_bad_block, &pb);
3384                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3385                         if (pctx.errcode) {
3386                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3387                                 ctx->flags |= E2F_FLAG_ABORT;
3388                                 return;
3389                         }
3390                         if (pb.bbcheck)
3391                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3392                                 ctx->flags |= E2F_FLAG_ABORT;
3393                                 return;
3394                         }
3395                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3396                         clear_problem_context(&pctx);
3397                         continue;
3398                 } else if (ino == EXT2_ROOT_INO) {
3399                         /*
3400                          * Make sure the root inode is a directory; if
3401                          * not, offer to clear it.  It will be
3402                          * regnerated in pass #3.
3403                          */
3404                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3405                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3406                                         inode->i_dtime = time(0);
3407                                         inode->i_links_count = 0;
3408                                         ext2fs_icount_store(ctx->inode_link_info,
3409                                                             ino, 0);
3410                                         e2fsck_write_inode(ctx, ino, inode,
3411                                                            "pass1");
3412                                 }
3413
3414                         }
3415                         /*
3416                          * If dtime is set, offer to clear it.  mke2fs
3417                          * version 0.2b created filesystems with the
3418                          * dtime field set for the root and lost+found
3419                          * directories.  We won't worry about
3420                          * /lost+found, since that can be regenerated
3421                          * easily.  But we will fix the root directory
3422                          * as a special case.
3423                          */
3424                         if (inode->i_dtime && inode->i_links_count) {
3425                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3426                                         inode->i_dtime = 0;
3427                                         e2fsck_write_inode(ctx, ino, inode,
3428                                                            "pass1");
3429                                 }
3430                         }
3431                 } else if (ino == EXT2_JOURNAL_INO) {
3432                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3433                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3434                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3435                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3436                                                 &pctx)) {
3437                                         inode->i_mode = LINUX_S_IFREG;
3438                                         e2fsck_write_inode(ctx, ino, inode,
3439                                                            "pass1");
3440                                 }
3441                                 check_blocks(ctx, &pctx, block_buf);
3442                                 continue;
3443                         }
3444                         if ((inode->i_links_count || inode->i_blocks ||
3445                              inode->i_blocks || inode->i_block[0]) &&
3446                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3447                                         &pctx)) {
3448                                 memset(inode, 0, inode_size);
3449                                 ext2fs_icount_store(ctx->inode_link_info,
3450                                                     ino, 0);
3451                                 e2fsck_write_inode_full(ctx, ino, inode,
3452                                                         inode_size, "pass1");
3453                         }
3454                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3455                         int     problem = 0;
3456
3457                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3458                         if (ino == EXT2_BOOT_LOADER_INO) {
3459                                 if (LINUX_S_ISDIR(inode->i_mode))
3460                                         problem = PR_1_RESERVED_BAD_MODE;
3461                         } else if (ino == EXT2_RESIZE_INO) {
3462                                 if (inode->i_mode &&
3463                                     !LINUX_S_ISREG(inode->i_mode))
3464                                         problem = PR_1_RESERVED_BAD_MODE;
3465                         } else {
3466                                 if (inode->i_mode != 0)
3467                                         problem = PR_1_RESERVED_BAD_MODE;
3468                         }
3469                         if (problem) {
3470                                 if (fix_problem(ctx, problem, &pctx)) {
3471                                         inode->i_mode = 0;
3472                                         e2fsck_write_inode(ctx, ino, inode,
3473                                                            "pass1");
3474                                 }
3475                         }
3476                         check_blocks(ctx, &pctx, block_buf);
3477                         continue;
3478                 }
3479                 /*
3480                  * Check for inodes who might have been part of the
3481                  * orphaned list linked list.  They should have gotten
3482                  * dealt with by now, unless the list had somehow been
3483                  * corrupted.
3484                  *
3485                  * FIXME: In the future, inodes which are still in use
3486                  * (and which are therefore) pending truncation should
3487                  * be handled specially.  Right now we just clear the
3488                  * dtime field, and the normal e2fsck handling of
3489                  * inodes where i_size and the inode blocks are
3490                  * inconsistent is to fix i_size, instead of releasing
3491                  * the extra blocks.  This won't catch the inodes that
3492                  * was at the end of the orphan list, but it's better
3493                  * than nothing.  The right answer is that there
3494                  * shouldn't be any bugs in the orphan list handling.  :-)
3495                  */
3496                 if (inode->i_dtime && !busted_fs_time &&
3497                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3498                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3499                                 inode->i_dtime = inode->i_links_count ?
3500                                         0 : time(0);
3501                                 e2fsck_write_inode(ctx, ino, inode,
3502                                                    "pass1");
3503                         }
3504                 }
3505
3506                 /*
3507                  * This code assumes that deleted inodes have
3508                  * i_links_count set to 0.
3509                  */
3510                 if (!inode->i_links_count) {
3511                         if (!inode->i_dtime && inode->i_mode) {
3512                                 if (fix_problem(ctx,
3513                                             PR_1_ZERO_DTIME, &pctx)) {
3514                                         inode->i_dtime = time(0);
3515                                         e2fsck_write_inode(ctx, ino, inode,
3516                                                            "pass1");
3517                                 }
3518                         }
3519                         continue;
3520                 }
3521                 /*
3522                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3523                  * deleted files.  Oops.
3524                  *
3525                  * Since all new ext2 implementations get this right,
3526                  * we now assume that the case of non-zero
3527                  * i_links_count and non-zero dtime means that we
3528                  * should keep the file, not delete it.
3529                  *
3530                  */
3531                 if (inode->i_dtime) {
3532                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3533                                 inode->i_dtime = 0;
3534                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3535                         }
3536                 }
3537
3538                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3539                 switch (fs->super->s_creator_os) {
3540                     case EXT2_OS_LINUX:
3541                         frag = inode->osd2.linux2.l_i_frag;
3542                         fsize = inode->osd2.linux2.l_i_fsize;
3543                         break;
3544                     case EXT2_OS_HURD:
3545                         frag = inode->osd2.hurd2.h_i_frag;
3546                         fsize = inode->osd2.hurd2.h_i_fsize;
3547                         break;
3548                     case EXT2_OS_MASIX:
3549                         frag = inode->osd2.masix2.m_i_frag;
3550                         fsize = inode->osd2.masix2.m_i_fsize;
3551                         break;
3552                     default:
3553                         frag = fsize = 0;
3554                 }
3555
3556                 if (inode->i_faddr || frag || fsize ||
3557                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3558                         mark_inode_bad(ctx, ino);
3559                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3560                         if (imagic_fs) {
3561                                 if (!ctx->inode_imagic_map)
3562                                         alloc_imagic_map(ctx);
3563                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3564                                                          ino);
3565                         } else {
3566                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3567                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3568                                         e2fsck_write_inode(ctx, ino,
3569                                                            inode, "pass1");
3570                                 }
3571                         }
3572                 }
3573
3574                 check_inode_extra_space(ctx, &pctx);
3575
3576                 if (LINUX_S_ISDIR(inode->i_mode)) {
3577                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3578                         e2fsck_add_dir_info(ctx, ino, 0);
3579                         ctx->fs_directory_count++;
3580                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3581                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3582                         ctx->fs_regular_count++;
3583                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3584                            e2fsck_pass1_check_device_inode(fs, inode)) {
3585                         check_immutable(ctx, &pctx);
3586                         check_size(ctx, &pctx);
3587                         ctx->fs_chardev_count++;
3588                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3589                            e2fsck_pass1_check_device_inode(fs, inode)) {
3590                         check_immutable(ctx, &pctx);
3591                         check_size(ctx, &pctx);
3592                         ctx->fs_blockdev_count++;
3593                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3594                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3595                         check_immutable(ctx, &pctx);
3596                         ctx->fs_symlinks_count++;
3597                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3598                                 ctx->fs_fast_symlinks_count++;
3599                                 check_blocks(ctx, &pctx, block_buf);
3600                                 continue;
3601                         }
3602                 }
3603                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3604                          e2fsck_pass1_check_device_inode(fs, inode)) {
3605                         check_immutable(ctx, &pctx);
3606                         check_size(ctx, &pctx);
3607                         ctx->fs_fifo_count++;
3608                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3609                            e2fsck_pass1_check_device_inode(fs, inode)) {
3610                         check_immutable(ctx, &pctx);
3611                         check_size(ctx, &pctx);
3612                         ctx->fs_sockets_count++;
3613                 } else
3614                         mark_inode_bad(ctx, ino);
3615                 if (inode->i_block[EXT2_IND_BLOCK])
3616                         ctx->fs_ind_count++;
3617                 if (inode->i_block[EXT2_DIND_BLOCK])
3618                         ctx->fs_dind_count++;
3619                 if (inode->i_block[EXT2_TIND_BLOCK])
3620                         ctx->fs_tind_count++;
3621                 if (inode->i_block[EXT2_IND_BLOCK] ||
3622                     inode->i_block[EXT2_DIND_BLOCK] ||
3623                     inode->i_block[EXT2_TIND_BLOCK] ||
3624                     inode->i_file_acl) {
3625                         inodes_to_process[process_inode_count].ino = ino;
3626                         inodes_to_process[process_inode_count].inode = *inode;
3627                         process_inode_count++;
3628                 } else
3629                         check_blocks(ctx, &pctx, block_buf);
3630
3631                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3632                         return;
3633
3634                 if (process_inode_count >= ctx->process_inode_size) {
3635                         process_inodes(ctx, block_buf);
3636
3637                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3638                                 return;
3639                 }
3640         }
3641         process_inodes(ctx, block_buf);
3642         ext2fs_close_inode_scan(scan);
3643         ehandler_operation(0);
3644
3645         /*
3646          * If any extended attribute blocks' reference counts need to
3647          * be adjusted, either up (ctx->refcount_extra), or down
3648          * (ctx->refcount), then fix them.
3649          */
3650         if (ctx->refcount) {
3651                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3652                 ea_refcount_free(ctx->refcount);
3653                 ctx->refcount = 0;
3654         }
3655         if (ctx->refcount_extra) {
3656                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3657                                         block_buf, +1);
3658                 ea_refcount_free(ctx->refcount_extra);
3659                 ctx->refcount_extra = 0;
3660         }
3661
3662         if (ctx->invalid_bitmaps)
3663                 handle_fs_bad_blocks(ctx);
3664
3665         /* We don't need the block_ea_map any more */
3666         ext2fs_free_block_bitmap(ctx->block_ea_map);
3667         ctx->block_ea_map = 0;
3668
3669         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3670                 ext2fs_block_bitmap save_bmap;
3671
3672                 save_bmap = fs->block_map;
3673                 fs->block_map = ctx->block_found_map;
3674                 clear_problem_context(&pctx);
3675                 pctx.errcode = ext2fs_create_resize_inode(fs);
3676                 if (pctx.errcode) {
3677                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3678                         /* Should never get here */
3679                         ctx->flags |= E2F_FLAG_ABORT;
3680                         return;
3681                 }
3682                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3683                                   "recreate inode");
3684                 inode->i_mtime = time(0);
3685                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, 
3686                                   "recreate inode");
3687                 fs->block_map = save_bmap;
3688                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3689         }
3690
3691         if (ctx->flags & E2F_FLAG_RESTART) {
3692                 /*
3693                  * Only the master copy of the superblock and block
3694                  * group descriptors are going to be written during a
3695                  * restart, so set the superblock to be used to be the
3696                  * master superblock.
3697                  */
3698                 ctx->use_superblock = 0;
3699                 unwind_pass1();
3700                 goto endit;
3701         }
3702
3703         if (ctx->block_dup_map) {
3704                 if (ctx->options & E2F_OPT_PREEN) {
3705                         clear_problem_context(&pctx);
3706                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3707                 }
3708                 e2fsck_pass1_dupblocks(ctx, block_buf);
3709         }
3710         ext2fs_free_mem(&inodes_to_process);
3711 endit:
3712         e2fsck_use_inode_shortcuts(ctx, 0);
3713
3714         ext2fs_free_mem(&block_buf);
3715         ext2fs_free_mem(&inode);
3716
3717 }
3718
3719 /*
3720  * When the inode_scan routines call this callback at the end of the
3721  * glock group, call process_inodes.
3722  */
3723 static errcode_t scan_callback(ext2_filsys fs,
3724                                ext2_inode_scan scan FSCK_ATTR((unused)),
3725                                dgrp_t group, void * priv_data)
3726 {
3727         struct scan_callback_struct *scan_struct;
3728         e2fsck_t ctx;
3729
3730         scan_struct = (struct scan_callback_struct *) priv_data;
3731         ctx = scan_struct->ctx;
3732
3733         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3734
3735         if (ctx->progress)
3736                 if ((ctx->progress)(ctx, 1, group+1,
3737                                     ctx->fs->group_desc_count))
3738                         return EXT2_ET_CANCEL_REQUESTED;
3739
3740         return 0;
3741 }
3742
3743 /*
3744  * Process the inodes in the "inodes to process" list.
3745  */
3746 static void process_inodes(e2fsck_t ctx, char *block_buf)
3747 {
3748         int                     i;
3749         struct ext2_inode       *old_stashed_inode;
3750         ext2_ino_t              old_stashed_ino;
3751         const char              *old_operation;
3752         char                    buf[80];
3753         struct problem_context  pctx;
3754
3755         /* begin process_inodes */
3756         if (process_inode_count == 0)
3757                 return;
3758         old_operation = ehandler_operation(0);
3759         old_stashed_inode = ctx->stashed_inode;
3760         old_stashed_ino = ctx->stashed_ino;
3761         qsort(inodes_to_process, process_inode_count,
3762                       sizeof(struct process_inode_block), process_inode_cmp);
3763         clear_problem_context(&pctx);
3764         for (i=0; i < process_inode_count; i++) {
3765                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3766                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3767                 sprintf(buf, _("reading indirect blocks of inode %u"),
3768                         pctx.ino);
3769                 ehandler_operation(buf);
3770                 check_blocks(ctx, &pctx, block_buf);
3771                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3772                         break;
3773         }
3774         ctx->stashed_inode = old_stashed_inode;
3775         ctx->stashed_ino = old_stashed_ino;
3776         process_inode_count = 0;
3777         /* end process inodes */
3778
3779         ehandler_operation(old_operation);
3780 }
3781
3782 static int process_inode_cmp(const void *a, const void *b)
3783 {
3784         const struct process_inode_block *ib_a =
3785                 (const struct process_inode_block *) a;
3786         const struct process_inode_block *ib_b =
3787                 (const struct process_inode_block *) b;
3788         int     ret;
3789
3790         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3791                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3792         if (ret == 0)
3793                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3794         return ret;
3795 }
3796
3797 /*
3798  * Mark an inode as being bad in some what
3799  */
3800 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3801 {
3802         struct          problem_context pctx;
3803
3804         if (!ctx->inode_bad_map) {
3805                 clear_problem_context(&pctx);
3806
3807                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3808                             _("bad inode map"), &ctx->inode_bad_map);
3809                 if (pctx.errcode) {
3810                         pctx.num = 3;
3811                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3812                         /* Should never get here */
3813                         ctx->flags |= E2F_FLAG_ABORT;
3814                         return;
3815                 }
3816         }
3817         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3818 }
3819
3820
3821 /*
3822  * This procedure will allocate the inode imagic table
3823  */
3824 static void alloc_imagic_map(e2fsck_t ctx)
3825 {
3826         struct          problem_context pctx;
3827
3828         clear_problem_context(&pctx);
3829         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3830                                               _("imagic inode map"),
3831                                               &ctx->inode_imagic_map);
3832         if (pctx.errcode) {
3833                 pctx.num = 5;
3834                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3835                 /* Should never get here */
3836                 ctx->flags |= E2F_FLAG_ABORT;
3837                 return;
3838         }
3839 }
3840
3841 /*
3842  * Marks a block as in use, setting the dup_map if it's been set
3843  * already.  Called by process_block and process_bad_block.
3844  *
3845  * WARNING: Assumes checks have already been done to make sure block
3846  * is valid.  This is true in both process_block and process_bad_block.
3847  */
3848 static void mark_block_used(e2fsck_t ctx, blk_t block)
3849 {
3850         struct          problem_context pctx;
3851
3852         clear_problem_context(&pctx);
3853
3854         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3855                 if (!ctx->block_dup_map) {
3856                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3857                               _("multiply claimed block map"),
3858                               &ctx->block_dup_map);
3859                         if (pctx.errcode) {
3860                                 pctx.num = 3;
3861                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3862                                             &pctx);
3863                                 /* Should never get here */
3864                                 ctx->flags |= E2F_FLAG_ABORT;
3865                                 return;
3866                         }
3867                 }
3868                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3869         } else {
3870                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3871         }
3872 }
3873
3874 /*
3875  * Adjust the extended attribute block's reference counts at the end
3876  * of pass 1, either by subtracting out references for EA blocks that
3877  * are still referenced in ctx->refcount, or by adding references for
3878  * EA blocks that had extra references as accounted for in
3879  * ctx->refcount_extra.
3880  */
3881 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3882                                     char *block_buf, int adjust_sign)
3883 {
3884         struct ext2_ext_attr_header     *header;
3885         struct problem_context          pctx;
3886         ext2_filsys                     fs = ctx->fs;
3887         blk_t                           blk;
3888         __u32                           should_be;
3889         int                             count;
3890
3891         clear_problem_context(&pctx);
3892
3893         ea_refcount_intr_begin(refcount);
3894         while (1) {
3895                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3896                         break;
3897                 pctx.blk = blk;
3898                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3899                 if (pctx.errcode) {
3900                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3901                         return;
3902                 }
3903                 header = (struct ext2_ext_attr_header *) block_buf;
3904                 pctx.blkcount = header->h_refcount;
3905                 should_be = header->h_refcount + adjust_sign * count;
3906                 pctx.num = should_be;
3907                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3908                         header->h_refcount = should_be;
3909                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3910                                                              block_buf);
3911                         if (pctx.errcode) {
3912                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3913                                 continue;
3914                         }
3915                 }
3916         }
3917 }
3918
3919 /*
3920  * Handle processing the extended attribute blocks
3921  */
3922 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3923                            char *block_buf)
3924 {
3925         ext2_filsys fs = ctx->fs;
3926         ext2_ino_t      ino = pctx->ino;
3927         struct ext2_inode *inode = pctx->inode;
3928         blk_t           blk;
3929         char *          end;
3930         struct ext2_ext_attr_header *header;
3931         struct ext2_ext_attr_entry *entry;
3932         int             count;
3933         region_t        region;
3934
3935         blk = inode->i_file_acl;
3936         if (blk == 0)
3937                 return 0;
3938
3939         /*
3940          * If the Extended attribute flag isn't set, then a non-zero
3941          * file acl means that the inode is corrupted.
3942          *
3943          * Or if the extended attribute block is an invalid block,
3944          * then the inode is also corrupted.
3945          */
3946         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3947             (blk < fs->super->s_first_data_block) ||
3948             (blk >= fs->super->s_blocks_count)) {
3949                 mark_inode_bad(ctx, ino);
3950                 return 0;
3951         }
3952
3953         /* If ea bitmap hasn't been allocated, create it */
3954         if (!ctx->block_ea_map) {
3955                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3956                                                       _("ext attr block map"),
3957                                                       &ctx->block_ea_map);
3958                 if (pctx->errcode) {
3959                         pctx->num = 2;
3960                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3961                         ctx->flags |= E2F_FLAG_ABORT;
3962                         return 0;
3963                 }
3964         }
3965
3966         /* Create the EA refcount structure if necessary */
3967         if (!ctx->refcount) {
3968                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3969                 if (pctx->errcode) {
3970                         pctx->num = 1;
3971                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3972                         ctx->flags |= E2F_FLAG_ABORT;
3973                         return 0;
3974                 }
3975         }
3976
3977         /* Have we seen this EA block before? */
3978         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3979                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3980                         return 1;
3981                 /* Ooops, this EA was referenced more than it stated */
3982                 if (!ctx->refcount_extra) {
3983                         pctx->errcode = ea_refcount_create(0,
3984                                            &ctx->refcount_extra);
3985                         if (pctx->errcode) {
3986                                 pctx->num = 2;
3987                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3988                                 ctx->flags |= E2F_FLAG_ABORT;
3989                                 return 0;
3990                         }
3991                 }
3992                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3993                 return 1;
3994         }
3995
3996         /*
3997          * OK, we haven't seen this EA block yet.  So we need to
3998          * validate it
3999          */
4000         pctx->blk = blk;
4001         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
4002         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
4003                 goto clear_extattr;
4004         header = (struct ext2_ext_attr_header *) block_buf;
4005         pctx->blk = inode->i_file_acl;
4006         if (((ctx->ext_attr_ver == 1) &&
4007              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
4008             ((ctx->ext_attr_ver == 2) &&
4009              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
4010                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
4011                         goto clear_extattr;
4012         }
4013
4014         if (header->h_blocks != 1) {
4015                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
4016                         goto clear_extattr;
4017         }
4018
4019         region = region_create(0, fs->blocksize);
4020         if (!region) {
4021                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4022                 ctx->flags |= E2F_FLAG_ABORT;
4023                 return 0;
4024         }
4025         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4026                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4027                         goto clear_extattr;
4028         }
4029
4030         entry = (struct ext2_ext_attr_entry *)(header+1);
4031         end = block_buf + fs->blocksize;
4032         while ((char *)entry < end && *(__u32 *)entry) {
4033                 if (region_allocate(region, (char *)entry - (char *)header,
4034                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4035                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4036                                 goto clear_extattr;
4037                 }
4038                 if ((ctx->ext_attr_ver == 1 &&
4039                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4040                     (ctx->ext_attr_ver == 2 &&
4041                      entry->e_name_index == 0)) {
4042                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4043                                 goto clear_extattr;
4044                 }
4045                 if (entry->e_value_block != 0) {
4046                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4047                                 goto clear_extattr;
4048                 }
4049                 if (entry->e_value_size &&
4050                     region_allocate(region, entry->e_value_offs,
4051                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4052                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4053                                 goto clear_extattr;
4054                 }
4055                 entry = EXT2_EXT_ATTR_NEXT(entry);
4056         }
4057         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4058                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4059                         goto clear_extattr;
4060         }
4061         region_free(region);
4062
4063         count = header->h_refcount - 1;
4064         if (count)
4065                 ea_refcount_store(ctx->refcount, blk, count);
4066         mark_block_used(ctx, blk);
4067         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4068
4069         return 1;
4070
4071 clear_extattr:
4072         inode->i_file_acl = 0;
4073         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4074         return 0;
4075 }
4076
4077 /* Returns 1 if bad htree, 0 if OK */
4078 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4079                         ext2_ino_t ino FSCK_ATTR((unused)),
4080                         struct ext2_inode *inode,
4081                         char *block_buf)
4082 {
4083         struct ext2_dx_root_info        *root;
4084         ext2_filsys                     fs = ctx->fs;
4085         errcode_t                       retval;
4086         blk_t                           blk;
4087
4088         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4089              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4090             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4091              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4092                 return 1;
4093
4094         blk = inode->i_block[0];
4095         if (((blk == 0) ||
4096              (blk < fs->super->s_first_data_block) ||
4097              (blk >= fs->super->s_blocks_count)) &&
4098             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4099                 return 1;
4100
4101         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4102         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4103                 return 1;
4104
4105         /* XXX should check that beginning matches a directory */
4106         root = (struct ext2_dx_root_info *) (block_buf + 24);
4107
4108         if ((root->reserved_zero || root->info_length < 8) &&
4109             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4110                 return 1;
4111
4112         pctx->num = root->hash_version;
4113         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4114             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4115             (root->hash_version != EXT2_HASH_TEA) &&
4116             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4117                 return 1;
4118
4119         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4120             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4121                 return 1;
4122
4123         pctx->num = root->indirect_levels;
4124         if ((root->indirect_levels > 1) &&
4125             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4126                 return 1;
4127
4128         return 0;
4129 }
4130
4131 /*
4132  * This subroutine is called on each inode to account for all of the
4133  * blocks used by that inode.
4134  */
4135 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4136                          char *block_buf)
4137 {
4138         ext2_filsys fs = ctx->fs;
4139         struct process_block_struct_1 pb;
4140         ext2_ino_t      ino = pctx->ino;
4141         struct ext2_inode *inode = pctx->inode;
4142         int             bad_size = 0;
4143         int             dirty_inode = 0;
4144         __u64           size;
4145
4146         pb.ino = ino;
4147         pb.num_blocks = 0;
4148         pb.last_block = -1;
4149         pb.num_illegal_blocks = 0;
4150         pb.suppress = 0; pb.clear = 0;
4151         pb.fragmented = 0;
4152         pb.compressed = 0;
4153         pb.previous_block = 0;
4154         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4155         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4156         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4157         pb.inode = inode;
4158         pb.pctx = pctx;
4159         pb.ctx = ctx;
4160         pctx->ino = ino;
4161         pctx->errcode = 0;
4162
4163         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4164                 if (fs->super->s_feature_incompat &
4165                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4166                         pb.compressed = 1;
4167                 else {
4168                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4169                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4170                                 dirty_inode++;
4171                         }
4172                 }
4173         }
4174
4175         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4176                 pb.num_blocks++;
4177
4178         if (ext2fs_inode_has_valid_blocks(inode))
4179                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4180                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4181                                        block_buf, process_block, &pb);
4182         end_problem_latch(ctx, PR_LATCH_BLOCK);
4183         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4184         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4185                 goto out;
4186         if (pctx->errcode)
4187                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4188
4189         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4190                 ctx->fs_fragmented++;
4191
4192         if (pb.clear) {
4193                 inode->i_links_count = 0;
4194                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4195                 inode->i_dtime = time(0);
4196                 dirty_inode++;
4197                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4198                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4199                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4200                 /*
4201                  * The inode was probably partially accounted for
4202                  * before processing was aborted, so we need to
4203                  * restart the pass 1 scan.
4204                  */
4205                 ctx->flags |= E2F_FLAG_RESTART;
4206                 goto out;
4207         }
4208
4209         if (inode->i_flags & EXT2_INDEX_FL) {
4210                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4211                         inode->i_flags &= ~EXT2_INDEX_FL;
4212                         dirty_inode++;
4213                 } else {
4214 #ifdef ENABLE_HTREE
4215                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4216 #endif
4217                 }
4218         }
4219         if (ctx->dirs_to_hash && pb.is_dir &&
4220             !(inode->i_flags & EXT2_INDEX_FL) &&
4221             ((inode->i_size / fs->blocksize) >= 3))
4222                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4223
4224         if (!pb.num_blocks && pb.is_dir) {
4225                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4226                         inode->i_links_count = 0;
4227                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4228                         inode->i_dtime = time(0);
4229                         dirty_inode++;
4230                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4231                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4232                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4233                         ctx->fs_directory_count--;
4234                         goto out;
4235                 }
4236         }
4237
4238         pb.num_blocks *= (fs->blocksize / 512);
4239
4240         if (pb.is_dir) {
4241                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4242                 if (nblock > (pb.last_block + 1))
4243                         bad_size = 1;
4244                 else if (nblock < (pb.last_block + 1)) {
4245                         if (((pb.last_block + 1) - nblock) >
4246                             fs->super->s_prealloc_dir_blocks)
4247                                 bad_size = 2;
4248                 }
4249         } else {
4250                 size = EXT2_I_SIZE(inode);
4251                 if ((pb.last_block >= 0) &&
4252                     (size < (__u64) pb.last_block * fs->blocksize))
4253                         bad_size = 3;
4254                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4255                         bad_size = 4;
4256         }
4257         /* i_size for symlinks is checked elsewhere */
4258         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4259                 pctx->num = (pb.last_block+1) * fs->blocksize;
4260                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4261                         inode->i_size = pctx->num;
4262                         if (!LINUX_S_ISDIR(inode->i_mode))
4263                                 inode->i_size_high = pctx->num >> 32;
4264                         dirty_inode++;
4265                 }
4266                 pctx->num = 0;
4267         }
4268         if (LINUX_S_ISREG(inode->i_mode) &&
4269             (inode->i_size_high || inode->i_size & 0x80000000UL))
4270                 ctx->large_files++;
4271         if (pb.num_blocks != inode->i_blocks) {
4272                 pctx->num = pb.num_blocks;
4273                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4274                         inode->i_blocks = pb.num_blocks;
4275                         dirty_inode++;
4276                 }
4277                 pctx->num = 0;
4278         }
4279 out:
4280         if (dirty_inode)
4281                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4282 }
4283
4284
4285 /*
4286  * This is a helper function for check_blocks().
4287  */
4288 static int process_block(ext2_filsys fs,
4289                   blk_t *block_nr,
4290                   e2_blkcnt_t blockcnt,
4291                   blk_t ref_block FSCK_ATTR((unused)),
4292                   int ref_offset FSCK_ATTR((unused)),
4293                   void *priv_data)
4294 {
4295         struct process_block_struct_1 *p;
4296         struct problem_context *pctx;
4297         blk_t   blk = *block_nr;
4298         int     ret_code = 0;
4299         int     problem = 0;
4300         e2fsck_t        ctx;
4301
4302         p = (struct process_block_struct_1 *) priv_data;
4303         pctx = p->pctx;
4304         ctx = p->ctx;
4305
4306         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4307                 /* todo: Check that the comprblk_fl is high, that the
4308                    blkaddr pattern looks right (all non-holes up to
4309                    first EXT2FS_COMPRESSED_BLKADDR, then all
4310                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4311                    that the feature_incompat bit is high, and that the
4312                    inode is a regular file.  If we're doing a "full
4313                    check" (a concept introduced to e2fsck by e2compr,
4314                    meaning that we look at data blocks as well as
4315                    metadata) then call some library routine that
4316                    checks the compressed data.  I'll have to think
4317                    about this, because one particularly important
4318                    problem to be able to fix is to recalculate the
4319                    cluster size if necessary.  I think that perhaps
4320                    we'd better do most/all e2compr-specific checks
4321                    separately, after the non-e2compr checks.  If not
4322                    doing a full check, it may be useful to test that
4323                    the personality is linux; e.g. if it isn't then
4324                    perhaps this really is just an illegal block. */
4325                 return 0;
4326         }
4327
4328         if (blk == 0) {
4329                 if (p->is_dir == 0) {
4330                         /*
4331                          * Should never happen, since only directories
4332                          * get called with BLOCK_FLAG_HOLE
4333                          */
4334 #if DEBUG_E2FSCK
4335                         printf("process_block() called with blk == 0, "
4336                                "blockcnt=%d, inode %lu???\n",
4337                                blockcnt, p->ino);
4338 #endif
4339                         return 0;
4340                 }
4341                 if (blockcnt < 0)
4342                         return 0;
4343                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4344                         goto mark_dir;
4345                 }
4346                 return 0;
4347         }
4348
4349         /*
4350          * Simplistic fragmentation check.  We merely require that the
4351          * file be contiguous.  (Which can never be true for really
4352          * big files that are greater than a block group.)
4353          */
4354         if (!HOLE_BLKADDR(p->previous_block)) {
4355                 if (p->previous_block+1 != blk)
4356                         p->fragmented = 1;
4357         }
4358         p->previous_block = blk;
4359
4360         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4361                 problem = PR_1_TOOBIG_DIR;
4362         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4363                 problem = PR_1_TOOBIG_REG;
4364         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4365                 problem = PR_1_TOOBIG_SYMLINK;
4366
4367         if (blk < fs->super->s_first_data_block ||
4368             blk >= fs->super->s_blocks_count)
4369                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4370
4371         if (problem) {
4372                 p->num_illegal_blocks++;
4373                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4374                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4375                                 p->clear = 1;
4376                                 return BLOCK_ABORT;
4377                         }
4378                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4379                                 p->suppress = 1;
4380                                 set_latch_flags(PR_LATCH_BLOCK,
4381                                                 PRL_SUPPRESS, 0);
4382                         }
4383                 }
4384                 pctx->blk = blk;
4385                 pctx->blkcount = blockcnt;
4386                 if (fix_problem(ctx, problem, pctx)) {
4387                         blk = *block_nr = 0;
4388                         ret_code = BLOCK_CHANGED;
4389                         goto mark_dir;
4390                 } else
4391                         return 0;
4392         }
4393
4394         if (p->ino == EXT2_RESIZE_INO) {
4395                 /*
4396                  * The resize inode has already be sanity checked
4397                  * during pass #0 (the superblock checks).  All we
4398                  * have to do is mark the double indirect block as
4399                  * being in use; all of the other blocks are handled
4400                  * by mark_table_blocks()).
4401                  */
4402                 if (blockcnt == BLOCK_COUNT_DIND)
4403                         mark_block_used(ctx, blk);
4404         } else
4405                 mark_block_used(ctx, blk);
4406         p->num_blocks++;
4407         if (blockcnt >= 0)
4408                 p->last_block = blockcnt;
4409 mark_dir:
4410         if (p->is_dir && (blockcnt >= 0)) {
4411                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4412                                                     blk, blockcnt);
4413                 if (pctx->errcode) {
4414                         pctx->blk = blk;
4415                         pctx->num = blockcnt;
4416                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4417                         /* Should never get here */
4418                         ctx->flags |= E2F_FLAG_ABORT;
4419                         return BLOCK_ABORT;
4420                 }
4421         }
4422         return ret_code;
4423 }
4424
4425 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4426                       blk_t *block_nr,
4427                       e2_blkcnt_t blockcnt,
4428                       blk_t ref_block FSCK_ATTR((unused)),
4429                       int ref_offset FSCK_ATTR((unused)),
4430                       void *priv_data EXT2FS_ATTR((unused)))
4431 {
4432         /*
4433          * Note: This function processes blocks for the bad blocks
4434          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4435          */
4436
4437         printf("Unrecoverable Error: Found %lli bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4438         return BLOCK_ERROR;
4439 }
4440
4441 /*
4442  * This routine gets called at the end of pass 1 if bad blocks are
4443  * detected in the superblock, group descriptors, inode_bitmaps, or
4444  * block bitmaps.  At this point, all of the blocks have been mapped
4445  * out, so we can try to allocate new block(s) to replace the bad
4446  * blocks.
4447  */
4448 static void handle_fs_bad_blocks(e2fsck_t ctx)
4449 {
4450         printf("Bad blocks detected on your filesystem\n"
4451                 "You should get your data off as the device will soon die\n");
4452 }
4453
4454 /*
4455  * This routine marks all blocks which are used by the superblock,
4456  * group descriptors, inode bitmaps, and block bitmaps.
4457  */
4458 static void mark_table_blocks(e2fsck_t ctx)
4459 {
4460         ext2_filsys fs = ctx->fs;
4461         blk_t   block, b;
4462         dgrp_t  i;
4463         int     j;
4464         struct problem_context pctx;
4465
4466         clear_problem_context(&pctx);
4467
4468         block = fs->super->s_first_data_block;
4469         for (i = 0; i < fs->group_desc_count; i++) {
4470                 pctx.group = i;
4471
4472                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4473
4474                 /*
4475                  * Mark the blocks used for the inode table
4476                  */
4477                 if (fs->group_desc[i].bg_inode_table) {
4478                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4479                              j < fs->inode_blocks_per_group;
4480                              j++, b++) {
4481                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4482                                                              b)) {
4483                                         pctx.blk = b;
4484                                         if (fix_problem(ctx,
4485                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4486                                                 ctx->invalid_inode_table_flag[i]++;
4487                                                 ctx->invalid_bitmaps++;
4488                                         }
4489                                 } else {
4490                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
4491                                                              b);
4492                                 }
4493                         }
4494                 }
4495
4496                 /*
4497                  * Mark block used for the block bitmap
4498                  */
4499                 if (fs->group_desc[i].bg_block_bitmap) {
4500                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4501                                      fs->group_desc[i].bg_block_bitmap)) {
4502                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4503                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4504                                         ctx->invalid_block_bitmap_flag[i]++;
4505                                         ctx->invalid_bitmaps++;
4506                                 }
4507                         } else {
4508                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4509                                      fs->group_desc[i].bg_block_bitmap);
4510                     }
4511
4512                 }
4513                 /*
4514                  * Mark block used for the inode bitmap
4515                  */
4516                 if (fs->group_desc[i].bg_inode_bitmap) {
4517                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4518                                      fs->group_desc[i].bg_inode_bitmap)) {
4519                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4520                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4521                                         ctx->invalid_inode_bitmap_flag[i]++;
4522                                         ctx->invalid_bitmaps++;
4523                                 }
4524                         } else {
4525                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4526                                      fs->group_desc[i].bg_inode_bitmap);
4527                         }
4528                 }
4529                 block += fs->super->s_blocks_per_group;
4530         }
4531 }
4532
4533 /*
4534  * Thes subroutines short circuits ext2fs_get_blocks and
4535  * ext2fs_check_directory; we use them since we already have the inode
4536  * structure, so there's no point in letting the ext2fs library read
4537  * the inode again.
4538  */
4539 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4540                                   blk_t *blocks)
4541 {
4542         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4543         int     i;
4544
4545         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4546                 return EXT2_ET_CALLBACK_NOTHANDLED;
4547
4548         for (i=0; i < EXT2_N_BLOCKS; i++)
4549                 blocks[i] = ctx->stashed_inode->i_block[i];
4550         return 0;
4551 }
4552
4553 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4554                                   struct ext2_inode *inode)
4555 {
4556         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4557
4558         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4559                 return EXT2_ET_CALLBACK_NOTHANDLED;
4560         *inode = *ctx->stashed_inode;
4561         return 0;
4562 }
4563
4564 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4565                             struct ext2_inode *inode)
4566 {
4567         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4568
4569         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4570                 *ctx->stashed_inode = *inode;
4571         return EXT2_ET_CALLBACK_NOTHANDLED;
4572 }
4573
4574 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4575 {
4576         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4577
4578         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4579                 return EXT2_ET_CALLBACK_NOTHANDLED;
4580
4581         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4582                 return EXT2_ET_NO_DIRECTORY;
4583         return 0;
4584 }
4585
4586 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4587 {
4588         ext2_filsys fs = ctx->fs;
4589
4590         if (bool) {
4591                 fs->get_blocks = pass1_get_blocks;
4592                 fs->check_directory = pass1_check_directory;
4593                 fs->read_inode = pass1_read_inode;
4594                 fs->write_inode = pass1_write_inode;
4595                 ctx->stashed_ino = 0;
4596         } else {
4597                 fs->get_blocks = 0;
4598                 fs->check_directory = 0;
4599                 fs->read_inode = 0;
4600                 fs->write_inode = 0;
4601         }
4602 }
4603
4604 /*
4605  * pass1b.c --- Pass #1b of e2fsck
4606  *
4607  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4608  * only invoked if pass 1 discovered blocks which are in use by more
4609  * than one inode.
4610  *
4611  * Pass1B scans the data blocks of all the inodes again, generating a
4612  * complete list of duplicate blocks and which inodes have claimed
4613  * them.
4614  *
4615  * Pass1C does a tree-traversal of the filesystem, to determine the
4616  * parent directories of these inodes.  This step is necessary so that
4617  * e2fsck can print out the pathnames of affected inodes.
4618  *
4619  * Pass1D is a reconciliation pass.  For each inode with duplicate
4620  * blocks, the user is prompted if s/he would like to clone the file
4621  * (so that the file gets a fresh copy of the duplicated blocks) or
4622  * simply to delete the file.
4623  *
4624  */
4625
4626
4627 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4628 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4629 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4630
4631 /* Define an extension to the ext2 library's block count information */
4632 #define BLOCK_COUNT_EXTATTR     (-5)
4633
4634 struct block_el {
4635         blk_t   block;
4636         struct block_el *next;
4637 };
4638
4639 struct inode_el {
4640         ext2_ino_t      inode;
4641         struct inode_el *next;
4642 };
4643
4644 struct dup_block {
4645         int             num_bad;
4646         struct inode_el *inode_list;
4647 };
4648
4649 /*
4650  * This structure stores information about a particular inode which
4651  * is sharing blocks with other inodes.  This information is collected
4652  * to display to the user, so that the user knows what files he or she
4653  * is dealing with, when trying to decide how to resolve the conflict
4654  * of multiply-claimed blocks.
4655  */
4656 struct dup_inode {
4657         ext2_ino_t              dir;
4658         int                     num_dupblocks;
4659         struct ext2_inode       inode;
4660         struct block_el         *block_list;
4661 };
4662
4663 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4664                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4665                                 int ref_offset, void *priv_data);
4666 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4667                         struct dup_inode *dp, char *block_buf);
4668 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4669                       struct dup_inode *dp, char* block_buf);
4670 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4671
4672 static void pass1b(e2fsck_t ctx, char *block_buf);
4673 static void pass1c(e2fsck_t ctx, char *block_buf);
4674 static void pass1d(e2fsck_t ctx, char *block_buf);
4675
4676 static int dup_inode_count = 0;
4677
4678 static dict_t blk_dict, ino_dict;
4679
4680 static ext2fs_inode_bitmap inode_dup_map;
4681
4682 static int dict_int_cmp(const void *a, const void *b)
4683 {
4684         intptr_t        ia, ib;
4685
4686         ia = (intptr_t)a;
4687         ib = (intptr_t)b;
4688
4689         return (ia-ib);
4690 }
4691
4692 /*
4693  * Add a duplicate block record
4694  */
4695 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4696                      struct ext2_inode *inode)
4697 {
4698         dnode_t *n;
4699         struct dup_block        *db;
4700         struct dup_inode        *di;
4701         struct block_el         *blk_el;
4702         struct inode_el         *ino_el;
4703
4704         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4705         if (n)
4706                 db = (struct dup_block *) dnode_get(n);
4707         else {
4708                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4709                          sizeof(struct dup_block), "duplicate block header");
4710                 db->num_bad = 0;
4711                 db->inode_list = 0;
4712                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4713         }
4714         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4715                          sizeof(struct inode_el), "inode element");
4716         ino_el->inode = ino;
4717         ino_el->next = db->inode_list;
4718         db->inode_list = ino_el;
4719         db->num_bad++;
4720
4721         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4722         if (n)
4723                 di = (struct dup_inode *) dnode_get(n);
4724         else {
4725                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4726                          sizeof(struct dup_inode), "duplicate inode header");
4727                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
4728                 di->num_dupblocks = 0;
4729                 di->block_list = 0;
4730                 di->inode = *inode;
4731                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4732         }
4733         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4734                          sizeof(struct block_el), "block element");
4735         blk_el->block = blk;
4736         blk_el->next = di->block_list;
4737         di->block_list = blk_el;
4738         di->num_dupblocks++;
4739 }
4740
4741 /*
4742  * Free a duplicate inode record
4743  */
4744 static void inode_dnode_free(dnode_t *node)
4745 {
4746         struct dup_inode        *di;
4747         struct block_el         *p, *next;
4748
4749         di = (struct dup_inode *) dnode_get(node);
4750         for (p = di->block_list; p; p = next) {
4751                 next = p->next;
4752                 free(p);
4753         }
4754         free(node);
4755 }
4756
4757 /*
4758  * Free a duplicate block record
4759  */
4760 static void block_dnode_free(dnode_t *node)
4761 {
4762         struct dup_block        *db;
4763         struct inode_el         *p, *next;
4764
4765         db = (struct dup_block *) dnode_get(node);
4766         for (p = db->inode_list; p; p = next) {
4767                 next = p->next;
4768                 free(p);
4769         }
4770         free(node);
4771 }
4772
4773
4774 /*
4775  * Main procedure for handling duplicate blocks
4776  */
4777 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4778 {
4779         ext2_filsys             fs = ctx->fs;
4780         struct problem_context  pctx;
4781
4782         clear_problem_context(&pctx);
4783
4784         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4785                       _("multiply claimed inode map"), &inode_dup_map);
4786         if (pctx.errcode) {
4787                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4788                 ctx->flags |= E2F_FLAG_ABORT;
4789                 return;
4790         }
4791
4792         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4793         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4794         dict_set_allocator(&ino_dict, inode_dnode_free);
4795         dict_set_allocator(&blk_dict, block_dnode_free);
4796
4797         pass1b(ctx, block_buf);
4798         pass1c(ctx, block_buf);
4799         pass1d(ctx, block_buf);
4800
4801         /*
4802          * Time to free all of the accumulated data structures that we
4803          * don't need anymore.
4804          */
4805         dict_free_nodes(&ino_dict);
4806         dict_free_nodes(&blk_dict);
4807 }
4808
4809 /*
4810  * Scan the inodes looking for inodes that contain duplicate blocks.
4811  */
4812 struct process_block_struct_1b {
4813         e2fsck_t        ctx;
4814         ext2_ino_t      ino;
4815         int             dup_blocks;
4816         struct ext2_inode *inode;
4817         struct problem_context *pctx;
4818 };
4819
4820 static void pass1b(e2fsck_t ctx, char *block_buf)
4821 {
4822         ext2_filsys fs = ctx->fs;
4823         ext2_ino_t ino;
4824         struct ext2_inode inode;
4825         ext2_inode_scan scan;
4826         struct process_block_struct_1b pb;
4827         struct problem_context pctx;
4828
4829         clear_problem_context(&pctx);
4830
4831         if (!(ctx->options & E2F_OPT_PREEN))
4832                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4833         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4834                                               &scan);
4835         if (pctx.errcode) {
4836                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4837                 ctx->flags |= E2F_FLAG_ABORT;
4838                 return;
4839         }
4840         ctx->stashed_inode = &inode;
4841         pb.ctx = ctx;
4842         pb.pctx = &pctx;
4843         pctx.str = "pass1b";
4844         while (1) {
4845                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4846                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4847                         continue;
4848                 if (pctx.errcode) {
4849                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4850                         ctx->flags |= E2F_FLAG_ABORT;
4851                         return;
4852                 }
4853                 if (!ino)
4854                         break;
4855                 pctx.ino = ctx->stashed_ino = ino;
4856                 if ((ino != EXT2_BAD_INO) &&
4857                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4858                         continue;
4859
4860                 pb.ino = ino;
4861                 pb.dup_blocks = 0;
4862                 pb.inode = &inode;
4863
4864                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4865                     (ino == EXT2_BAD_INO))
4866                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4867                                      0, block_buf, process_pass1b_block, &pb);
4868                 if (inode.i_file_acl)
4869                         process_pass1b_block(fs, &inode.i_file_acl,
4870                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4871                 if (pb.dup_blocks) {
4872                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4873                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4874                             ino == EXT2_ROOT_INO)
4875                                 dup_inode_count++;
4876                 }
4877                 if (pctx.errcode)
4878                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4879         }
4880         ext2fs_close_inode_scan(scan);
4881         e2fsck_use_inode_shortcuts(ctx, 0);
4882 }
4883
4884 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4885                                 blk_t   *block_nr,
4886                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4887                                 blk_t ref_blk FSCK_ATTR((unused)),
4888                                 int ref_offset FSCK_ATTR((unused)),
4889                                 void *priv_data)
4890 {
4891         struct process_block_struct_1b *p;
4892         e2fsck_t ctx;
4893
4894         if (HOLE_BLKADDR(*block_nr))
4895                 return 0;
4896         p = (struct process_block_struct_1b *) priv_data;
4897         ctx = p->ctx;
4898
4899         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4900                 return 0;
4901
4902         /* OK, this is a duplicate block */
4903         if (p->ino != EXT2_BAD_INO) {
4904                 p->pctx->blk = *block_nr;
4905                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4906         }
4907         p->dup_blocks++;
4908         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4909
4910         add_dupe(ctx, p->ino, *block_nr, p->inode);
4911
4912         return 0;
4913 }
4914
4915 /*
4916  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4917  * is used so that we can print pathnames when prompting the user for
4918  * what to do.
4919  */
4920 struct search_dir_struct {
4921         int             count;
4922         ext2_ino_t      first_inode;
4923         ext2_ino_t      max_inode;
4924 };
4925
4926 static int search_dirent_proc(ext2_ino_t dir, int entry,
4927                               struct ext2_dir_entry *dirent,
4928                               int offset FSCK_ATTR((unused)),
4929                               int blocksize FSCK_ATTR((unused)),
4930                               char *buf FSCK_ATTR((unused)),
4931                               void *priv_data)
4932 {
4933         struct search_dir_struct *sd;
4934         struct dup_inode        *p;
4935         dnode_t                 *n;
4936
4937         sd = (struct search_dir_struct *) priv_data;
4938
4939         if (dirent->inode > sd->max_inode)
4940                 /* Should abort this inode, but not everything */
4941                 return 0;
4942
4943         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4944             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4945                 return 0;
4946
4947         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4948         if (!n)
4949                 return 0;
4950         p = (struct dup_inode *) dnode_get(n);
4951         p->dir = dir;
4952         sd->count--;
4953
4954         return(sd->count ? 0 : DIRENT_ABORT);
4955 }
4956
4957
4958 static void pass1c(e2fsck_t ctx, char *block_buf)
4959 {
4960         ext2_filsys fs = ctx->fs;
4961         struct search_dir_struct sd;
4962         struct problem_context pctx;
4963
4964         clear_problem_context(&pctx);
4965
4966         if (!(ctx->options & E2F_OPT_PREEN))
4967                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4968
4969         /*
4970          * Search through all directories to translate inodes to names
4971          * (by searching for the containing directory for that inode.)
4972          */
4973         sd.count = dup_inode_count;
4974         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4975         sd.max_inode = fs->super->s_inodes_count;
4976         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4977                                   search_dirent_proc, &sd);
4978 }
4979
4980 static void pass1d(e2fsck_t ctx, char *block_buf)
4981 {
4982         ext2_filsys fs = ctx->fs;
4983         struct dup_inode        *p, *t;
4984         struct dup_block        *q;
4985         ext2_ino_t              *shared, ino;
4986         int     shared_len;
4987         int     i;
4988         int     file_ok;
4989         int     meta_data = 0;
4990         struct problem_context pctx;
4991         dnode_t *n, *m;
4992         struct block_el *s;
4993         struct inode_el *r;
4994
4995         clear_problem_context(&pctx);
4996
4997         if (!(ctx->options & E2F_OPT_PREEN))
4998                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4999         e2fsck_read_bitmaps(ctx);
5000
5001         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
5002         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
5003         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
5004                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
5005                                 "Shared inode list");
5006         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
5007                 p = (struct dup_inode *) dnode_get(n);
5008                 shared_len = 0;
5009                 file_ok = 1;
5010                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
5011                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
5012                         continue;
5013
5014                 /*
5015                  * Find all of the inodes which share blocks with this
5016                  * one.  First we find all of the duplicate blocks
5017                  * belonging to this inode, and then search each block
5018                  * get the list of inodes, and merge them together.
5019                  */
5020                 for (s = p->block_list; s; s = s->next) {
5021                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5022                         if (!m)
5023                                 continue; /* Should never happen... */
5024                         q = (struct dup_block *) dnode_get(m);
5025                         if (q->num_bad > 1)
5026                                 file_ok = 0;
5027                         if (check_if_fs_block(ctx, s->block)) {
5028                                 file_ok = 0;
5029                                 meta_data = 1;
5030                         }
5031
5032                         /*
5033                          * Add all inodes used by this block to the
5034                          * shared[] --- which is a unique list, so
5035                          * if an inode is already in shared[], don't
5036                          * add it again.
5037                          */
5038                         for (r = q->inode_list; r; r = r->next) {
5039                                 if (r->inode == ino)
5040                                         continue;
5041                                 for (i = 0; i < shared_len; i++)
5042                                         if (shared[i] == r->inode)
5043                                                 break;
5044                                 if (i == shared_len) {
5045                                         shared[shared_len++] = r->inode;
5046                                 }
5047                         }
5048                 }
5049
5050                 /*
5051                  * Report the inode that we are working on
5052                  */
5053                 pctx.inode = &p->inode;
5054                 pctx.ino = ino;
5055                 pctx.dir = p->dir;
5056                 pctx.blkcount = p->num_dupblocks;
5057                 pctx.num = meta_data ? shared_len+1 : shared_len;
5058                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5059                 pctx.blkcount = 0;
5060                 pctx.num = 0;
5061
5062                 if (meta_data)
5063                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5064
5065                 for (i = 0; i < shared_len; i++) {
5066                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5067                         if (!m)
5068                                 continue; /* should never happen */
5069                         t = (struct dup_inode *) dnode_get(m);
5070                         /*
5071                          * Report the inode that we are sharing with
5072                          */
5073                         pctx.inode = &t->inode;
5074                         pctx.ino = shared[i];
5075                         pctx.dir = t->dir;
5076                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5077                 }
5078                 if (file_ok) {
5079                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5080                         continue;
5081                 }
5082                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5083                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5084                         if (pctx.errcode)
5085                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5086                         else
5087                                 continue;
5088                 }
5089                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5090                         delete_file(ctx, ino, p, block_buf);
5091                 else
5092                         ext2fs_unmark_valid(fs);
5093         }
5094         ext2fs_free_mem(&shared);
5095 }
5096
5097 /*
5098  * Drop the refcount on the dup_block structure, and clear the entry
5099  * in the block_dup_map if appropriate.
5100  */
5101 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5102 {
5103         p->num_bad--;
5104         if (p->num_bad <= 0 ||
5105             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5106                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5107 }
5108
5109 static int delete_file_block(ext2_filsys fs,
5110                              blk_t      *block_nr,
5111                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5112                              blk_t ref_block FSCK_ATTR((unused)),
5113                              int ref_offset FSCK_ATTR((unused)),
5114                              void *priv_data)
5115 {
5116         struct process_block_struct_1b *pb;
5117         struct dup_block *p;
5118         dnode_t *n;
5119         e2fsck_t ctx;
5120
5121         pb = (struct process_block_struct_1b *) priv_data;
5122         ctx = pb->ctx;
5123
5124         if (HOLE_BLKADDR(*block_nr))
5125                 return 0;
5126
5127         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5128                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5129                 if (n) {
5130                         p = (struct dup_block *) dnode_get(n);
5131                         decrement_badcount(ctx, *block_nr, p);
5132                 } else
5133                         bb_error_msg(_("internal error; can't find dup_blk for %d\n"),
5134                                 *block_nr);
5135         } else {
5136                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5137                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5138         }
5139
5140         return 0;
5141 }
5142
5143 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5144                         struct dup_inode *dp, char* block_buf)
5145 {
5146         ext2_filsys fs = ctx->fs;
5147         struct process_block_struct_1b pb;
5148         struct ext2_inode       inode;
5149         struct problem_context  pctx;
5150         unsigned int            count;
5151
5152         clear_problem_context(&pctx);
5153         pctx.ino = pb.ino = ino;
5154         pb.dup_blocks = dp->num_dupblocks;
5155         pb.ctx = ctx;
5156         pctx.str = "delete_file";
5157
5158         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5159         if (ext2fs_inode_has_valid_blocks(&inode))
5160                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5161                                                      delete_file_block, &pb);
5162         if (pctx.errcode)
5163                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5164         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5165         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5166         if (ctx->inode_bad_map)
5167                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5168         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5169
5170         /* Inode may have changed by block_iterate, so reread it */
5171         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5172         inode.i_links_count = 0;
5173         inode.i_dtime = time(0);
5174         if (inode.i_file_acl &&
5175             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5176                 count = 1;
5177                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5178                                                    block_buf, -1, &count);
5179                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5180                         pctx.errcode = 0;
5181                         count = 1;
5182                 }
5183                 if (pctx.errcode) {
5184                         pctx.blk = inode.i_file_acl;
5185                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5186                 }
5187                 /*
5188                  * If the count is zero, then arrange to have the
5189                  * block deleted.  If the block is in the block_dup_map,
5190                  * also call delete_file_block since it will take care
5191                  * of keeping the accounting straight.
5192                  */
5193                 if ((count == 0) ||
5194                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5195                                              inode.i_file_acl))
5196                         delete_file_block(fs, &inode.i_file_acl,
5197                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5198         }
5199         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5200 }
5201
5202 struct clone_struct {
5203         errcode_t       errcode;
5204         ext2_ino_t      dir;
5205         char    *buf;
5206         e2fsck_t ctx;
5207 };
5208
5209 static int clone_file_block(ext2_filsys fs,
5210                             blk_t       *block_nr,
5211                             e2_blkcnt_t blockcnt,
5212                             blk_t ref_block FSCK_ATTR((unused)),
5213                             int ref_offset FSCK_ATTR((unused)),
5214                             void *priv_data)
5215 {
5216         struct dup_block *p;
5217         blk_t   new_block;
5218         errcode_t       retval;
5219         struct clone_struct *cs = (struct clone_struct *) priv_data;
5220         dnode_t *n;
5221         e2fsck_t ctx;
5222
5223         ctx = cs->ctx;
5224
5225         if (HOLE_BLKADDR(*block_nr))
5226                 return 0;
5227
5228         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5229                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5230                 if (n) {
5231                         p = (struct dup_block *) dnode_get(n);
5232                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5233                                                   &new_block);
5234                         if (retval) {
5235                                 cs->errcode = retval;
5236                                 return BLOCK_ABORT;
5237                         }
5238                         if (cs->dir && (blockcnt >= 0)) {
5239                                 retval = ext2fs_set_dir_block(fs->dblist,
5240                                       cs->dir, new_block, blockcnt);
5241                                 if (retval) {
5242                                         cs->errcode = retval;
5243                                         return BLOCK_ABORT;
5244                                 }
5245                         }
5246
5247                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5248                                                      cs->buf);
5249                         if (retval) {
5250                                 cs->errcode = retval;
5251                                 return BLOCK_ABORT;
5252                         }
5253                         retval = io_channel_write_blk(fs->io, new_block, 1,
5254                                                       cs->buf);
5255                         if (retval) {
5256                                 cs->errcode = retval;
5257                                 return BLOCK_ABORT;
5258                         }
5259                         decrement_badcount(ctx, *block_nr, p);
5260                         *block_nr = new_block;
5261                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5262                                                  new_block);
5263                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5264                         return BLOCK_CHANGED;
5265                 } else
5266                         bb_error_msg(_("internal error; can't find dup_blk for %d\n"),
5267                                 *block_nr);
5268         }
5269         return 0;
5270 }
5271
5272 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5273                       struct dup_inode *dp, char* block_buf)
5274 {
5275         ext2_filsys fs = ctx->fs;
5276         errcode_t       retval;
5277         struct clone_struct cs;
5278         struct problem_context  pctx;
5279         blk_t           blk;
5280         dnode_t         *n;
5281         struct inode_el *ino_el;
5282         struct dup_block        *db;
5283         struct dup_inode        *di;
5284
5285         clear_problem_context(&pctx);
5286         cs.errcode = 0;
5287         cs.dir = 0;
5288         cs.ctx = ctx;
5289         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5290         if (retval)
5291                 return retval;
5292
5293         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5294                 cs.dir = ino;
5295
5296         pctx.ino = ino;
5297         pctx.str = "clone_file";
5298         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5299                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5300                                                      clone_file_block, &cs);
5301         ext2fs_mark_bb_dirty(fs);
5302         if (pctx.errcode) {
5303                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5304                 retval = pctx.errcode;
5305                 goto errout;
5306         }
5307         if (cs.errcode) {
5308                 bb_error_msg(_("returned from clone_file_block"));
5309                 retval = cs.errcode;
5310                 goto errout;
5311         }
5312         /* The inode may have changed on disk, so we have to re-read it */
5313         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5314         blk = dp->inode.i_file_acl;
5315         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5316                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5317                     BLOCK_CHANGED)) {
5318                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5319                 /*
5320                  * If we cloned the EA block, find all other inodes
5321                  * which refered to that EA block, and modify
5322                  * them to point to the new EA block.
5323                  */
5324                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5325                 db = (struct dup_block *) dnode_get(n);
5326                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5327                         if (ino_el->inode == ino)
5328                                 continue;
5329                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5330                         di = (struct dup_inode *) dnode_get(n);
5331                         if (di->inode.i_file_acl == blk) {
5332                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5333                                 e2fsck_write_inode(ctx, ino_el->inode,
5334                                            &di->inode, "clone file EA");
5335                                 decrement_badcount(ctx, blk, db);
5336                         }
5337                 }
5338         }
5339         retval = 0;
5340 errout:
5341         ext2fs_free_mem(&cs.buf);
5342         return retval;
5343 }
5344
5345 /*
5346  * This routine returns 1 if a block overlaps with one of the superblocks,
5347  * group descriptors, inode bitmaps, or block bitmaps.
5348  */
5349 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5350 {
5351         ext2_filsys fs = ctx->fs;
5352         blk_t   block;
5353         dgrp_t  i;
5354
5355         block = fs->super->s_first_data_block;
5356         for (i = 0; i < fs->group_desc_count; i++) {
5357
5358                 /* Check superblocks/block group descriptros */
5359                 if (ext2fs_bg_has_super(fs, i)) {
5360                         if (test_block >= block &&
5361                             (test_block <= block + fs->desc_blocks))
5362                                 return 1;
5363                 }
5364
5365                 /* Check the inode table */
5366                 if ((fs->group_desc[i].bg_inode_table) &&
5367                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5368                     (test_block < (fs->group_desc[i].bg_inode_table +
5369                                    fs->inode_blocks_per_group)))
5370                         return 1;
5371
5372                 /* Check the bitmap blocks */
5373                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5374                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5375                         return 1;
5376
5377                 block += fs->super->s_blocks_per_group;
5378         }
5379         return 0;
5380 }
5381 /*
5382  * pass2.c --- check directory structure
5383  *
5384  * Pass 2 of e2fsck iterates through all active directory inodes, and
5385  * applies to following tests to each directory entry in the directory
5386  * blocks in the inodes:
5387  *
5388  *      - The length of the directory entry (rec_len) should be at
5389  *              least 8 bytes, and no more than the remaining space
5390  *              left in the directory block.
5391  *      - The length of the name in the directory entry (name_len)
5392  *              should be less than (rec_len - 8).
5393  *      - The inode number in the directory entry should be within
5394  *              legal bounds.
5395  *      - The inode number should refer to a in-use inode.
5396  *      - The first entry should be '.', and its inode should be
5397  *              the inode of the directory.
5398  *      - The second entry should be '..'.
5399  *
5400  * To minimize disk seek time, the directory blocks are processed in
5401  * sorted order of block numbers.
5402  *
5403  * Pass 2 also collects the following information:
5404  *      - The inode numbers of the subdirectories for each directory.
5405  *
5406  * Pass 2 relies on the following information from previous passes:
5407  *      - The directory information collected in pass 1.
5408  *      - The inode_used_map bitmap
5409  *      - The inode_bad_map bitmap
5410  *      - The inode_dir_map bitmap
5411  *
5412  * Pass 2 frees the following data structures
5413  *      - The inode_bad_map bitmap
5414  *      - The inode_reg_map bitmap
5415  */
5416
5417 /*
5418  * Keeps track of how many times an inode is referenced.
5419  */
5420 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5421 static int check_dir_block(ext2_filsys fs,
5422                            struct ext2_db_entry *dir_blocks_info,
5423                            void *priv_data);
5424 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5425                               struct problem_context *pctx);
5426 static int update_dir_block(ext2_filsys fs,
5427                             blk_t       *block_nr,
5428                             e2_blkcnt_t blockcnt,
5429                             blk_t       ref_block,
5430                             int         ref_offset,
5431                             void        *priv_data);
5432 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5433 static int htree_depth(struct dx_dir_info *dx_dir,
5434                        struct dx_dirblock_info *dx_db);
5435 static int special_dir_block_cmp(const void *a, const void *b);
5436
5437 struct check_dir_struct {
5438         char *buf;
5439         struct problem_context  pctx;
5440         int     count, max;
5441         e2fsck_t ctx;
5442 };
5443
5444 static void e2fsck_pass2(e2fsck_t ctx)
5445 {
5446         struct ext2_super_block *sb = ctx->fs->super;
5447         struct problem_context  pctx;
5448         ext2_filsys             fs = ctx->fs;
5449         char                    *buf;
5450         struct dir_info         *dir;
5451         struct check_dir_struct cd;
5452         struct dx_dir_info      *dx_dir;
5453         struct dx_dirblock_info *dx_db, *dx_parent;
5454         int                     b;
5455         int                     i, depth;
5456         problem_t               code;
5457         int                     bad_dir;
5458
5459         clear_problem_context(&cd.pctx);
5460
5461         /* Pass 2 */
5462
5463         if (!(ctx->options & E2F_OPT_PREEN))
5464                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5465
5466         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5467                                                 0, ctx->inode_link_info,
5468                                                 &ctx->inode_count);
5469         if (cd.pctx.errcode) {
5470                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5471                 ctx->flags |= E2F_FLAG_ABORT;
5472                 return;
5473         }
5474         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5475                                               "directory scan buffer");
5476
5477         /*
5478          * Set up the parent pointer for the root directory, if
5479          * present.  (If the root directory is not present, we will
5480          * create it in pass 3.)
5481          */
5482         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5483         if (dir)
5484                 dir->parent = EXT2_ROOT_INO;
5485
5486         cd.buf = buf;
5487         cd.ctx = ctx;
5488         cd.count = 1;
5489         cd.max = ext2fs_dblist_count(fs->dblist);
5490
5491         if (ctx->progress)
5492                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5493
5494         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5495                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5496
5497         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5498                                                 &cd);
5499         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5500                 return;
5501         if (cd.pctx.errcode) {
5502                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5503                 ctx->flags |= E2F_FLAG_ABORT;
5504                 return;
5505         }
5506
5507 #ifdef ENABLE_HTREE
5508         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5509                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5510                         return;
5511                 if (dx_dir->numblocks == 0)
5512                         continue;
5513                 clear_problem_context(&pctx);
5514                 bad_dir = 0;
5515                 pctx.dir = dx_dir->ino;
5516                 dx_db = dx_dir->dx_block;
5517                 if (dx_db->flags & DX_FLAG_REFERENCED)
5518                         dx_db->flags |= DX_FLAG_DUP_REF;
5519                 else
5520                         dx_db->flags |= DX_FLAG_REFERENCED;
5521                 /*
5522                  * Find all of the first and last leaf blocks, and
5523                  * update their parent's min and max hash values
5524                  */
5525                 for (b=0, dx_db = dx_dir->dx_block;
5526                      b < dx_dir->numblocks;
5527                      b++, dx_db++) {
5528                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5529                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5530                                 continue;
5531                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5532                         /*
5533                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5534                          */
5535                         if (dx_db->flags & DX_FLAG_FIRST)
5536                                 dx_parent->min_hash = dx_db->min_hash;
5537                         /*
5538                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5539                          */
5540                         if (dx_db->flags & DX_FLAG_LAST)
5541                                 dx_parent->max_hash = dx_db->max_hash;
5542                 }
5543
5544                 for (b=0, dx_db = dx_dir->dx_block;
5545                      b < dx_dir->numblocks;
5546                      b++, dx_db++) {
5547                         pctx.blkcount = b;
5548                         pctx.group = dx_db->parent;
5549                         code = 0;
5550                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5551                             (dx_db->min_hash < dx_db->node_min_hash)) {
5552                                 pctx.blk = dx_db->min_hash;
5553                                 pctx.blk2 = dx_db->node_min_hash;
5554                                 code = PR_2_HTREE_MIN_HASH;
5555                                 fix_problem(ctx, code, &pctx);
5556                                 bad_dir++;
5557                         }
5558                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5559                                 depth = htree_depth(dx_dir, dx_db);
5560                                 if (depth != dx_dir->depth) {
5561                                         code = PR_2_HTREE_BAD_DEPTH;
5562                                         fix_problem(ctx, code, &pctx);
5563                                         bad_dir++;
5564                                 }
5565                         }
5566                         /*
5567                          * This test doesn't apply for the root block
5568                          * at block #0
5569                          */
5570                         if (b &&
5571                             (dx_db->max_hash > dx_db->node_max_hash)) {
5572                                 pctx.blk = dx_db->max_hash;
5573                                 pctx.blk2 = dx_db->node_max_hash;
5574                                 code = PR_2_HTREE_MAX_HASH;
5575                                 fix_problem(ctx, code, &pctx);
5576                                 bad_dir++;
5577                         }
5578                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5579                                 code = PR_2_HTREE_NOTREF;
5580                                 fix_problem(ctx, code, &pctx);
5581                                 bad_dir++;
5582                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5583                                 code = PR_2_HTREE_DUPREF;
5584                                 fix_problem(ctx, code, &pctx);
5585                                 bad_dir++;
5586                         }
5587                         if (code == 0)
5588                                 continue;
5589                 }
5590                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5591                         clear_htree(ctx, dx_dir->ino);
5592                         dx_dir->numblocks = 0;
5593                 }
5594         }
5595 #endif
5596         ext2fs_free_mem(&buf);
5597         ext2fs_free_dblist(fs->dblist);
5598
5599         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5600         ctx->inode_bad_map = 0;
5601         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5602         ctx->inode_reg_map = 0;
5603
5604         clear_problem_context(&pctx);
5605         if (ctx->large_files) {
5606                 if (!(sb->s_feature_ro_compat &
5607                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5608                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5609                         sb->s_feature_ro_compat |=
5610                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5611                         ext2fs_mark_super_dirty(fs);
5612                 }
5613                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5614                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5615                         ext2fs_update_dynamic_rev(fs);
5616                         ext2fs_mark_super_dirty(fs);
5617                 }
5618         } else if (!ctx->large_files &&
5619             (sb->s_feature_ro_compat &
5620               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5621                 if (fs->flags & EXT2_FLAG_RW) {
5622                         sb->s_feature_ro_compat &=
5623                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5624                         ext2fs_mark_super_dirty(fs);
5625                 }
5626         }
5627
5628 }
5629
5630 #define MAX_DEPTH 32000
5631 static int htree_depth(struct dx_dir_info *dx_dir,
5632                        struct dx_dirblock_info *dx_db)
5633 {
5634         int     depth = 0;
5635
5636         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5637                 dx_db = &dx_dir->dx_block[dx_db->parent];
5638                 depth++;
5639         }
5640         return depth;
5641 }
5642
5643 static int dict_de_cmp(const void *a, const void *b)
5644 {
5645         const struct ext2_dir_entry *de_a, *de_b;
5646         int     a_len, b_len;
5647
5648         de_a = (const struct ext2_dir_entry *) a;
5649         a_len = de_a->name_len & 0xFF;
5650         de_b = (const struct ext2_dir_entry *) b;
5651         b_len = de_b->name_len & 0xFF;
5652
5653         if (a_len != b_len)
5654                 return (a_len - b_len);
5655
5656         return strncmp(de_a->name, de_b->name, a_len);
5657 }
5658
5659 /*
5660  * This is special sort function that makes sure that directory blocks
5661  * with a dirblock of zero are sorted to the beginning of the list.
5662  * This guarantees that the root node of the htree directories are
5663  * processed first, so we know what hash version to use.
5664  */
5665 static int special_dir_block_cmp(const void *a, const void *b)
5666 {
5667         const struct ext2_db_entry *db_a =
5668                 (const struct ext2_db_entry *) a;
5669         const struct ext2_db_entry *db_b =
5670                 (const struct ext2_db_entry *) b;
5671
5672         if (db_a->blockcnt && !db_b->blockcnt)
5673                 return 1;
5674
5675         if (!db_a->blockcnt && db_b->blockcnt)
5676                 return -1;
5677
5678         if (db_a->blk != db_b->blk)
5679                 return (int) (db_a->blk - db_b->blk);
5680
5681         if (db_a->ino != db_b->ino)
5682                 return (int) (db_a->ino - db_b->ino);
5683
5684         return (int) (db_a->blockcnt - db_b->blockcnt);
5685 }
5686
5687
5688 /*
5689  * Make sure the first entry in the directory is '.', and that the
5690  * directory entry is sane.
5691  */
5692 static int check_dot(e2fsck_t ctx,
5693                      struct ext2_dir_entry *dirent,
5694                      ext2_ino_t ino, struct problem_context *pctx)
5695 {
5696         struct ext2_dir_entry *nextdir;
5697         int     status = 0;
5698         int     created = 0;
5699         int     new_len;
5700         int     problem = 0;
5701
5702         if (!dirent->inode)
5703                 problem = PR_2_MISSING_DOT;
5704         else if (((dirent->name_len & 0xFF) != 1) ||
5705                  (dirent->name[0] != '.'))
5706                 problem = PR_2_1ST_NOT_DOT;
5707         else if (dirent->name[1] != '\0')
5708                 problem = PR_2_DOT_NULL_TERM;
5709
5710         if (problem) {
5711                 if (fix_problem(ctx, problem, pctx)) {
5712                         if (dirent->rec_len < 12)
5713                                 dirent->rec_len = 12;
5714                         dirent->inode = ino;
5715                         dirent->name_len = 1;
5716                         dirent->name[0] = '.';
5717                         dirent->name[1] = '\0';
5718                         status = 1;
5719                         created = 1;
5720                 }
5721         }
5722         if (dirent->inode != ino) {
5723                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5724                         dirent->inode = ino;
5725                         status = 1;
5726                 }
5727         }
5728         if (dirent->rec_len > 12) {
5729                 new_len = dirent->rec_len - 12;
5730                 if (new_len > 12) {
5731                         if (created ||
5732                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5733                                 nextdir = (struct ext2_dir_entry *)
5734                                         ((char *) dirent + 12);
5735                                 dirent->rec_len = 12;
5736                                 nextdir->rec_len = new_len;
5737                                 nextdir->inode = 0;
5738                                 nextdir->name_len = 0;
5739                                 status = 1;
5740                         }
5741                 }
5742         }
5743         return status;
5744 }
5745
5746 /*
5747  * Make sure the second entry in the directory is '..', and that the
5748  * directory entry is sane.  We do not check the inode number of '..'
5749  * here; this gets done in pass 3.
5750  */
5751 static int check_dotdot(e2fsck_t ctx,
5752                         struct ext2_dir_entry *dirent,
5753                         struct dir_info *dir, struct problem_context *pctx)
5754 {
5755         int             problem = 0;
5756
5757         if (!dirent->inode)
5758                 problem = PR_2_MISSING_DOT_DOT;
5759         else if (((dirent->name_len & 0xFF) != 2) ||
5760                  (dirent->name[0] != '.') ||
5761                  (dirent->name[1] != '.'))
5762                 problem = PR_2_2ND_NOT_DOT_DOT;
5763         else if (dirent->name[2] != '\0')
5764                 problem = PR_2_DOT_DOT_NULL_TERM;
5765
5766         if (problem) {
5767                 if (fix_problem(ctx, problem, pctx)) {
5768                         if (dirent->rec_len < 12)
5769                                 dirent->rec_len = 12;
5770                         /*
5771                          * Note: we don't have the parent inode just
5772                          * yet, so we will fill it in with the root
5773                          * inode.  This will get fixed in pass 3.
5774                          */
5775                         dirent->inode = EXT2_ROOT_INO;
5776                         dirent->name_len = 2;
5777                         dirent->name[0] = '.';
5778                         dirent->name[1] = '.';
5779                         dirent->name[2] = '\0';
5780                         return 1;
5781                 }
5782                 return 0;
5783         }
5784         dir->dotdot = dirent->inode;
5785         return 0;
5786 }
5787
5788 /*
5789  * Check to make sure a directory entry doesn't contain any illegal
5790  * characters.
5791  */
5792 static int check_name(e2fsck_t ctx,
5793                       struct ext2_dir_entry *dirent,
5794                       struct problem_context *pctx)
5795 {
5796         int     i;
5797         int     fixup = -1;
5798         int     ret = 0;
5799
5800         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5801                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5802                         if (fixup < 0) {
5803                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5804                         }
5805                         if (fixup) {
5806                                 dirent->name[i] = '.';
5807                                 ret = 1;
5808                         }
5809                 }
5810         }
5811         return ret;
5812 }
5813
5814 /*
5815  * Check the directory filetype (if present)
5816  */
5817
5818 /*
5819  * Given a mode, return the ext2 file type
5820  */
5821 static int ext2_file_type(unsigned int mode)
5822 {
5823         if (LINUX_S_ISREG(mode))
5824                 return EXT2_FT_REG_FILE;
5825
5826         if (LINUX_S_ISDIR(mode))
5827                 return EXT2_FT_DIR;
5828
5829         if (LINUX_S_ISCHR(mode))
5830                 return EXT2_FT_CHRDEV;
5831
5832         if (LINUX_S_ISBLK(mode))
5833                 return EXT2_FT_BLKDEV;
5834
5835         if (LINUX_S_ISLNK(mode))
5836                 return EXT2_FT_SYMLINK;
5837
5838         if (LINUX_S_ISFIFO(mode))
5839                 return EXT2_FT_FIFO;
5840
5841         if (LINUX_S_ISSOCK(mode))
5842                 return EXT2_FT_SOCK;
5843
5844         return 0;
5845 }
5846
5847 static int check_filetype(e2fsck_t ctx,
5848                                    struct ext2_dir_entry *dirent,
5849                                    struct problem_context *pctx)
5850 {
5851         int     filetype = dirent->name_len >> 8;
5852         int     should_be = EXT2_FT_UNKNOWN;
5853         struct ext2_inode       inode;
5854
5855         if (!(ctx->fs->super->s_feature_incompat &
5856               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5857                 if (filetype == 0 ||
5858                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5859                         return 0;
5860                 dirent->name_len = dirent->name_len & 0xFF;
5861                 return 1;
5862         }
5863
5864         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5865                 should_be = EXT2_FT_DIR;
5866         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5867                                             dirent->inode)) {
5868                 should_be = EXT2_FT_REG_FILE;
5869         } else if (ctx->inode_bad_map &&
5870                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5871                                             dirent->inode))
5872                 should_be = 0;
5873         else {
5874                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5875                                   "check_filetype");
5876                 should_be = ext2_file_type(inode.i_mode);
5877         }
5878         if (filetype == should_be)
5879                 return 0;
5880         pctx->num = should_be;
5881
5882         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5883                         pctx) == 0)
5884                 return 0;
5885
5886         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5887         return 1;
5888 }
5889
5890 #ifdef ENABLE_HTREE
5891 static void parse_int_node(ext2_filsys fs,
5892                            struct ext2_db_entry *db,
5893                            struct check_dir_struct *cd,
5894                            struct dx_dir_info   *dx_dir,
5895                            char *block_buf)
5896 {
5897         struct          ext2_dx_root_info  *root;
5898         struct          ext2_dx_entry *ent;
5899         struct          ext2_dx_countlimit *limit;
5900         struct dx_dirblock_info *dx_db;
5901         int             i, expect_limit, count;
5902         blk_t           blk;
5903         ext2_dirhash_t  min_hash = 0xffffffff;
5904         ext2_dirhash_t  max_hash = 0;
5905         ext2_dirhash_t  hash = 0, prev_hash;
5906
5907         if (db->blockcnt == 0) {
5908                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5909                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5910         } else {
5911                 ent = (struct ext2_dx_entry *) (block_buf+8);
5912         }
5913         limit = (struct ext2_dx_countlimit *) ent;
5914
5915         count = ext2fs_le16_to_cpu(limit->count);
5916         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5917                 sizeof(struct ext2_dx_entry);
5918         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5919                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5920                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5921                         goto clear_and_exit;
5922         }
5923         if (count > expect_limit) {
5924                 cd->pctx.num = count;
5925                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5926                         goto clear_and_exit;
5927                 count = expect_limit;
5928         }
5929
5930         for (i=0; i < count; i++) {
5931                 prev_hash = hash;
5932                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5933                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5934                 /* Check to make sure the block is valid */
5935                 if (blk > (blk_t) dx_dir->numblocks) {
5936                         cd->pctx.blk = blk;
5937                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5938                                         &cd->pctx))
5939                                 goto clear_and_exit;
5940                 }
5941                 if (hash < prev_hash &&
5942                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5943                         goto clear_and_exit;
5944                 dx_db = &dx_dir->dx_block[blk];
5945                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5946                         dx_db->flags |= DX_FLAG_DUP_REF;
5947                 } else {
5948                         dx_db->flags |= DX_FLAG_REFERENCED;
5949                         dx_db->parent = db->blockcnt;
5950                 }
5951                 if (hash < min_hash)
5952                         min_hash = hash;
5953                 if (hash > max_hash)
5954                         max_hash = hash;
5955                 dx_db->node_min_hash = hash;
5956                 if ((i+1) < count)
5957                         dx_db->node_max_hash =
5958                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5959                 else {
5960                         dx_db->node_max_hash = 0xfffffffe;
5961                         dx_db->flags |= DX_FLAG_LAST;
5962                 }
5963                 if (i == 0)
5964                         dx_db->flags |= DX_FLAG_FIRST;
5965         }
5966         dx_db = &dx_dir->dx_block[db->blockcnt];
5967         dx_db->min_hash = min_hash;
5968         dx_db->max_hash = max_hash;
5969         return;
5970
5971 clear_and_exit:
5972         clear_htree(cd->ctx, cd->pctx.ino);
5973         dx_dir->numblocks = 0;
5974 }
5975 #endif /* ENABLE_HTREE */
5976
5977 /*
5978  * Given a busted directory, try to salvage it somehow.
5979  *
5980  */
5981 static void salvage_directory(ext2_filsys fs,
5982                               struct ext2_dir_entry *dirent,
5983                               struct ext2_dir_entry *prev,
5984                               unsigned int *offset)
5985 {
5986         char    *cp = (char *) dirent;
5987         int left = fs->blocksize - *offset - dirent->rec_len;
5988         int name_len = dirent->name_len & 0xFF;
5989
5990         /*
5991          * Special case of directory entry of size 8: copy what's left
5992          * of the directory block up to cover up the invalid hole.
5993          */
5994         if ((left >= 12) && (dirent->rec_len == 8)) {
5995                 memmove(cp, cp+8, left);
5996                 memset(cp + left, 0, 8);
5997                 return;
5998         }
5999         /*
6000          * If the directory entry overruns the end of the directory
6001          * block, and the name is small enough to fit, then adjust the
6002          * record length.
6003          */
6004         if ((left < 0) &&
6005             (name_len + 8 <= dirent->rec_len + left) &&
6006             dirent->inode <= fs->super->s_inodes_count &&
6007             strnlen(dirent->name, name_len) == name_len) {
6008                 dirent->rec_len += left;
6009                 return;
6010         }
6011         /*
6012          * If the directory entry is a multiple of four, so it is
6013          * valid, let the previous directory entry absorb the invalid
6014          * one.
6015          */
6016         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
6017                 prev->rec_len += dirent->rec_len;
6018                 *offset += dirent->rec_len;
6019                 return;
6020         }
6021         /*
6022          * Default salvage method --- kill all of the directory
6023          * entries for the rest of the block.  We will either try to
6024          * absorb it into the previous directory entry, or create a
6025          * new empty directory entry the rest of the directory block.
6026          */
6027         if (prev) {
6028                 prev->rec_len += fs->blocksize - *offset;
6029                 *offset = fs->blocksize;
6030         } else {
6031                 dirent->rec_len = fs->blocksize - *offset;
6032                 dirent->name_len = 0;
6033                 dirent->inode = 0;
6034         }
6035 }
6036
6037 static int check_dir_block(ext2_filsys fs,
6038                            struct ext2_db_entry *db,
6039                            void *priv_data)
6040 {
6041         struct dir_info         *subdir, *dir;
6042         struct dx_dir_info      *dx_dir;
6043 #ifdef ENABLE_HTREE
6044         struct dx_dirblock_info *dx_db = 0;
6045 #endif /* ENABLE_HTREE */
6046         struct ext2_dir_entry   *dirent, *prev;
6047         ext2_dirhash_t          hash;
6048         unsigned int            offset = 0;
6049         int                     dir_modified = 0;
6050         int                     dot_state;
6051         blk_t                   block_nr = db->blk;
6052         ext2_ino_t              ino = db->ino;
6053         __u16                   links;
6054         struct check_dir_struct *cd;
6055         char                    *buf;
6056         e2fsck_t                ctx;
6057         int                     problem;
6058         struct ext2_dx_root_info *root;
6059         struct ext2_dx_countlimit *limit;
6060         static dict_t de_dict;
6061         struct problem_context  pctx;
6062         int     dups_found = 0;
6063
6064         cd = (struct check_dir_struct *) priv_data;
6065         buf = cd->buf;
6066         ctx = cd->ctx;
6067
6068         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6069                 return DIRENT_ABORT;
6070
6071         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6072                 return DIRENT_ABORT;
6073
6074         /*
6075          * Make sure the inode is still in use (could have been
6076          * deleted in the duplicate/bad blocks pass.
6077          */
6078         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6079                 return 0;
6080
6081         cd->pctx.ino = ino;
6082         cd->pctx.blk = block_nr;
6083         cd->pctx.blkcount = db->blockcnt;
6084         cd->pctx.ino2 = 0;
6085         cd->pctx.dirent = 0;
6086         cd->pctx.num = 0;
6087
6088         if (db->blk == 0) {
6089                 if (allocate_dir_block(ctx, db, &cd->pctx))
6090                         return 0;
6091                 block_nr = db->blk;
6092         }
6093
6094         if (db->blockcnt)
6095                 dot_state = 2;
6096         else
6097                 dot_state = 0;
6098
6099         if (ctx->dirs_to_hash &&
6100             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6101                 dups_found++;
6102
6103         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6104         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6105                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6106         if (cd->pctx.errcode) {
6107                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6108                         ctx->flags |= E2F_FLAG_ABORT;
6109                         return DIRENT_ABORT;
6110                 }
6111                 memset(buf, 0, fs->blocksize);
6112         }
6113 #ifdef ENABLE_HTREE
6114         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6115         if (dx_dir && dx_dir->numblocks) {
6116                 if (db->blockcnt >= dx_dir->numblocks) {
6117                         printf("XXX should never happen!!!\n");
6118                         abort();
6119                 }
6120                 dx_db = &dx_dir->dx_block[db->blockcnt];
6121                 dx_db->type = DX_DIRBLOCK_LEAF;
6122                 dx_db->phys = block_nr;
6123                 dx_db->min_hash = ~0;
6124                 dx_db->max_hash = 0;
6125
6126                 dirent = (struct ext2_dir_entry *) buf;
6127                 limit = (struct ext2_dx_countlimit *) (buf+8);
6128                 if (db->blockcnt == 0) {
6129                         root = (struct ext2_dx_root_info *) (buf + 24);
6130                         dx_db->type = DX_DIRBLOCK_ROOT;
6131                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6132                         if ((root->reserved_zero ||
6133                              root->info_length < 8 ||
6134                              root->indirect_levels > 1) &&
6135                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6136                                 clear_htree(ctx, ino);
6137                                 dx_dir->numblocks = 0;
6138                                 dx_db = 0;
6139                         }
6140                         dx_dir->hashversion = root->hash_version;
6141                         dx_dir->depth = root->indirect_levels + 1;
6142                 } else if ((dirent->inode == 0) &&
6143                            (dirent->rec_len == fs->blocksize) &&
6144                            (dirent->name_len == 0) &&
6145                            (ext2fs_le16_to_cpu(limit->limit) ==
6146                             ((fs->blocksize-8) /
6147                              sizeof(struct ext2_dx_entry))))
6148                         dx_db->type = DX_DIRBLOCK_NODE;
6149         }
6150 #endif /* ENABLE_HTREE */
6151
6152         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6153         prev = 0;
6154         do {
6155                 problem = 0;
6156                 dirent = (struct ext2_dir_entry *) (buf + offset);
6157                 cd->pctx.dirent = dirent;
6158                 cd->pctx.num = offset;
6159                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6160                     (dirent->rec_len < 12) ||
6161                     ((dirent->rec_len % 4) != 0) ||
6162                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6163                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6164                                 salvage_directory(fs, dirent, prev, &offset);
6165                                 dir_modified++;
6166                                 continue;
6167                         } else
6168                                 goto abort_free_dict;
6169                 }
6170                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6171                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6172                                 dirent->name_len = EXT2_NAME_LEN;
6173                                 dir_modified++;
6174                         }
6175                 }
6176
6177                 if (dot_state == 0) {
6178                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6179                                 dir_modified++;
6180                 } else if (dot_state == 1) {
6181                         dir = e2fsck_get_dir_info(ctx, ino);
6182                         if (!dir) {
6183                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6184                                 goto abort_free_dict;
6185                         }
6186                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6187                                 dir_modified++;
6188                 } else if (dirent->inode == ino) {
6189                         problem = PR_2_LINK_DOT;
6190                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6191                                 dirent->inode = 0;
6192                                 dir_modified++;
6193                                 goto next;
6194                         }
6195                 }
6196                 if (!dirent->inode)
6197                         goto next;
6198
6199                 /*
6200                  * Make sure the inode listed is a legal one.
6201                  */
6202                 if (((dirent->inode != EXT2_ROOT_INO) &&
6203                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6204                     (dirent->inode > fs->super->s_inodes_count)) {
6205                         problem = PR_2_BAD_INO;
6206                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6207                                                dirent->inode))) {
6208                         /*
6209                          * If the inode is unused, offer to clear it.
6210                          */
6211                         problem = PR_2_UNUSED_INODE;
6212                 } else if ((dot_state > 1) &&
6213                            ((dirent->name_len & 0xFF) == 1) &&
6214                            (dirent->name[0] == '.')) {
6215                         /*
6216                          * If there's a '.' entry in anything other
6217                          * than the first directory entry, it's a
6218                          * duplicate entry that should be removed.
6219                          */
6220                         problem = PR_2_DUP_DOT;
6221                 } else if ((dot_state > 1) &&
6222                            ((dirent->name_len & 0xFF) == 2) &&
6223                            (dirent->name[0] == '.') &&
6224                            (dirent->name[1] == '.')) {
6225                         /*
6226                          * If there's a '..' entry in anything other
6227                          * than the second directory entry, it's a
6228                          * duplicate entry that should be removed.
6229                          */
6230                         problem = PR_2_DUP_DOT_DOT;
6231                 } else if ((dot_state > 1) &&
6232                            (dirent->inode == EXT2_ROOT_INO)) {
6233                         /*
6234                          * Don't allow links to the root directory.
6235                          * We check this specially to make sure we
6236                          * catch this error case even if the root
6237                          * directory hasn't been created yet.
6238                          */
6239                         problem = PR_2_LINK_ROOT;
6240                 } else if ((dot_state > 1) &&
6241                            (dirent->name_len & 0xFF) == 0) {
6242                         /*
6243                          * Don't allow zero-length directory names.
6244                          */
6245                         problem = PR_2_NULL_NAME;
6246                 }
6247
6248                 if (problem) {
6249                         if (fix_problem(ctx, problem, &cd->pctx)) {
6250                                 dirent->inode = 0;
6251                                 dir_modified++;
6252                                 goto next;
6253                         } else {
6254                                 ext2fs_unmark_valid(fs);
6255                                 if (problem == PR_2_BAD_INO)
6256                                         goto next;
6257                         }
6258                 }
6259
6260                 /*
6261                  * If the inode was marked as having bad fields in
6262                  * pass1, process it and offer to fix/clear it.
6263                  * (We wait until now so that we can display the
6264                  * pathname to the user.)
6265                  */
6266                 if (ctx->inode_bad_map &&
6267                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6268                                              dirent->inode)) {
6269                         if (e2fsck_process_bad_inode(ctx, ino,
6270                                                      dirent->inode,
6271                                                      buf + fs->blocksize)) {
6272                                 dirent->inode = 0;
6273                                 dir_modified++;
6274                                 goto next;
6275                         }
6276                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6277                                 return DIRENT_ABORT;
6278                 }
6279
6280                 if (check_name(ctx, dirent, &cd->pctx))
6281                         dir_modified++;
6282
6283                 if (check_filetype(ctx, dirent, &cd->pctx))
6284                         dir_modified++;
6285
6286 #ifdef ENABLE_HTREE
6287                 if (dx_db) {
6288                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6289                                        (dirent->name_len & 0xFF),
6290                                        fs->super->s_hash_seed, &hash, 0);
6291                         if (hash < dx_db->min_hash)
6292                                 dx_db->min_hash = hash;
6293                         if (hash > dx_db->max_hash)
6294                                 dx_db->max_hash = hash;
6295                 }
6296 #endif
6297
6298                 /*
6299                  * If this is a directory, then mark its parent in its
6300                  * dir_info structure.  If the parent field is already
6301                  * filled in, then this directory has more than one
6302                  * hard link.  We assume the first link is correct,
6303                  * and ask the user if he/she wants to clear this one.
6304                  */
6305                 if ((dot_state > 1) &&
6306                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6307                                               dirent->inode))) {
6308                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6309                         if (!subdir) {
6310                                 cd->pctx.ino = dirent->inode;
6311                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6312                                 goto abort_free_dict;
6313                         }
6314                         if (subdir->parent) {
6315                                 cd->pctx.ino2 = subdir->parent;
6316                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6317                                                 &cd->pctx)) {
6318                                         dirent->inode = 0;
6319                                         dir_modified++;
6320                                         goto next;
6321                                 }
6322                                 cd->pctx.ino2 = 0;
6323                         } else
6324                                 subdir->parent = ino;
6325                 }
6326
6327                 if (dups_found) {
6328                         ;
6329                 } else if (dict_lookup(&de_dict, dirent)) {
6330                         clear_problem_context(&pctx);
6331                         pctx.ino = ino;
6332                         pctx.dirent = dirent;
6333                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6334                         if (!ctx->dirs_to_hash)
6335                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6336                         if (ctx->dirs_to_hash)
6337                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6338                         dups_found++;
6339                 } else
6340                         dict_alloc_insert(&de_dict, dirent, dirent);
6341
6342                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6343                                         &links);
6344                 if (links > 1)
6345                         ctx->fs_links_count++;
6346                 ctx->fs_total_count++;
6347         next:
6348                 prev = dirent;
6349                 offset += dirent->rec_len;
6350                 dot_state++;
6351         } while (offset < fs->blocksize);
6352 #ifdef ENABLE_HTREE
6353         if (dx_db) {
6354                 cd->pctx.dir = cd->pctx.ino;
6355                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6356                     (dx_db->type == DX_DIRBLOCK_NODE))
6357                         parse_int_node(fs, db, cd, dx_dir, buf);
6358         }
6359 #endif /* ENABLE_HTREE */
6360         if (offset != fs->blocksize) {
6361                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6362                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6363                         dirent->rec_len = cd->pctx.num;
6364                         dir_modified++;
6365                 }
6366         }
6367         if (dir_modified) {
6368                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6369                 if (cd->pctx.errcode) {
6370                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6371                                          &cd->pctx))
6372                                 goto abort_free_dict;
6373                 }
6374                 ext2fs_mark_changed(fs);
6375         }
6376         dict_free_nodes(&de_dict);
6377         return 0;
6378 abort_free_dict:
6379         dict_free_nodes(&de_dict);
6380         ctx->flags |= E2F_FLAG_ABORT;
6381         return DIRENT_ABORT;
6382 }
6383
6384 /*
6385  * This function is called to deallocate a block, and is an interator
6386  * functioned called by deallocate inode via ext2fs_iterate_block().
6387  */
6388 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6389                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6390                                   blk_t ref_block FSCK_ATTR((unused)),
6391                                   int ref_offset FSCK_ATTR((unused)),
6392                                   void *priv_data)
6393 {
6394         e2fsck_t        ctx = (e2fsck_t) priv_data;
6395
6396         if (HOLE_BLKADDR(*block_nr))
6397                 return 0;
6398         if ((*block_nr < fs->super->s_first_data_block) ||
6399             (*block_nr >= fs->super->s_blocks_count))
6400                 return 0;
6401         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6402         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6403         return 0;
6404 }
6405
6406 /*
6407  * This fuction deallocates an inode
6408  */
6409 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6410 {
6411         ext2_filsys fs = ctx->fs;
6412         struct ext2_inode       inode;
6413         struct problem_context  pctx;
6414         __u32                   count;
6415
6416         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6417         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6418         inode.i_links_count = 0;
6419         inode.i_dtime = time(0);
6420         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6421         clear_problem_context(&pctx);
6422         pctx.ino = ino;
6423
6424         /*
6425          * Fix up the bitmaps...
6426          */
6427         e2fsck_read_bitmaps(ctx);
6428         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6429         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6430         if (ctx->inode_bad_map)
6431                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6432         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6433
6434         if (inode.i_file_acl &&
6435             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6436                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6437                                                    block_buf, -1, &count);
6438                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6439                         pctx.errcode = 0;
6440                         count = 1;
6441                 }
6442                 if (pctx.errcode) {
6443                         pctx.blk = inode.i_file_acl;
6444                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6445                         ctx->flags |= E2F_FLAG_ABORT;
6446                         return;
6447                 }
6448                 if (count == 0) {
6449                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6450                                                    inode.i_file_acl);
6451                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6452                 }
6453                 inode.i_file_acl = 0;
6454         }
6455
6456         if (!ext2fs_inode_has_valid_blocks(&inode))
6457                 return;
6458
6459         if (LINUX_S_ISREG(inode.i_mode) &&
6460             (inode.i_size_high || inode.i_size & 0x80000000UL))
6461                 ctx->large_files--;
6462
6463         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6464                                             deallocate_inode_block, ctx);
6465         if (pctx.errcode) {
6466                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6467                 ctx->flags |= E2F_FLAG_ABORT;
6468                 return;
6469         }
6470 }
6471
6472 /*
6473  * This fuction clears the htree flag on an inode
6474  */
6475 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6476 {
6477         struct ext2_inode       inode;
6478
6479         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6480         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6481         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6482         if (ctx->dirs_to_hash)
6483                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6484 }
6485
6486
6487 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6488                                     ext2_ino_t ino, char *buf)
6489 {
6490         ext2_filsys fs = ctx->fs;
6491         struct ext2_inode       inode;
6492         int                     inode_modified = 0;
6493         int                     not_fixed = 0;
6494         unsigned char           *frag, *fsize;
6495         struct problem_context  pctx;
6496         int     problem = 0;
6497
6498         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6499
6500         clear_problem_context(&pctx);
6501         pctx.ino = ino;
6502         pctx.dir = dir;
6503         pctx.inode = &inode;
6504
6505         if (inode.i_file_acl &&
6506             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6507             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6508                 inode.i_file_acl = 0;
6509 #if BB_BIG_ENDIAN
6510                 /*
6511                  * This is a special kludge to deal with long symlinks
6512                  * on big endian systems.  i_blocks had already been
6513                  * decremented earlier in pass 1, but since i_file_acl
6514                  * hadn't yet been cleared, ext2fs_read_inode()
6515                  * assumed that the file was short symlink and would
6516                  * not have byte swapped i_block[0].  Hence, we have
6517                  * to byte-swap it here.
6518                  */
6519                 if (LINUX_S_ISLNK(inode.i_mode) &&
6520                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6521                     (inode.i_blocks == fs->blocksize >> 9))
6522                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6523 #endif
6524                 inode_modified++;
6525         } else
6526                 not_fixed++;
6527
6528         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6529             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6530             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6531             !(LINUX_S_ISSOCK(inode.i_mode)))
6532                 problem = PR_2_BAD_MODE;
6533         else if (LINUX_S_ISCHR(inode.i_mode)
6534                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6535                 problem = PR_2_BAD_CHAR_DEV;
6536         else if (LINUX_S_ISBLK(inode.i_mode)
6537                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6538                 problem = PR_2_BAD_BLOCK_DEV;
6539         else if (LINUX_S_ISFIFO(inode.i_mode)
6540                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6541                 problem = PR_2_BAD_FIFO;
6542         else if (LINUX_S_ISSOCK(inode.i_mode)
6543                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6544                 problem = PR_2_BAD_SOCKET;
6545         else if (LINUX_S_ISLNK(inode.i_mode)
6546                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6547                 problem = PR_2_INVALID_SYMLINK;
6548         }
6549
6550         if (problem) {
6551                 if (fix_problem(ctx, problem, &pctx)) {
6552                         deallocate_inode(ctx, ino, 0);
6553                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6554                                 return 0;
6555                         return 1;
6556                 } else
6557                         not_fixed++;
6558                 problem = 0;
6559         }
6560
6561         if (inode.i_faddr) {
6562                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6563                         inode.i_faddr = 0;
6564                         inode_modified++;
6565                 } else
6566                         not_fixed++;
6567         }
6568
6569         switch (fs->super->s_creator_os) {
6570             case EXT2_OS_LINUX:
6571                 frag = &inode.osd2.linux2.l_i_frag;
6572                 fsize = &inode.osd2.linux2.l_i_fsize;
6573                 break;
6574             case EXT2_OS_HURD:
6575                 frag = &inode.osd2.hurd2.h_i_frag;
6576                 fsize = &inode.osd2.hurd2.h_i_fsize;
6577                 break;
6578             case EXT2_OS_MASIX:
6579                 frag = &inode.osd2.masix2.m_i_frag;
6580                 fsize = &inode.osd2.masix2.m_i_fsize;
6581                 break;
6582             default:
6583                 frag = fsize = 0;
6584         }
6585         if (frag && *frag) {
6586                 pctx.num = *frag;
6587                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6588                         *frag = 0;
6589                         inode_modified++;
6590                 } else
6591                         not_fixed++;
6592                 pctx.num = 0;
6593         }
6594         if (fsize && *fsize) {
6595                 pctx.num = *fsize;
6596                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6597                         *fsize = 0;
6598                         inode_modified++;
6599                 } else
6600                         not_fixed++;
6601                 pctx.num = 0;
6602         }
6603
6604         if (inode.i_file_acl &&
6605             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6606              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6607                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6608                         inode.i_file_acl = 0;
6609                         inode_modified++;
6610                 } else
6611                         not_fixed++;
6612         }
6613         if (inode.i_dir_acl &&
6614             LINUX_S_ISDIR(inode.i_mode)) {
6615                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6616                         inode.i_dir_acl = 0;
6617                         inode_modified++;
6618                 } else
6619                         not_fixed++;
6620         }
6621
6622         if (inode_modified)
6623                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6624         if (!not_fixed)
6625                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6626         return 0;
6627 }
6628
6629
6630 /*
6631  * allocate_dir_block --- this function allocates a new directory
6632  *      block for a particular inode; this is done if a directory has
6633  *      a "hole" in it, or if a directory has a illegal block number
6634  *      that was zeroed out and now needs to be replaced.
6635  */
6636 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6637                               struct problem_context *pctx)
6638 {
6639         ext2_filsys fs = ctx->fs;
6640         blk_t                   blk;
6641         char                    *block;
6642         struct ext2_inode       inode;
6643
6644         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6645                 return 1;
6646
6647         /*
6648          * Read the inode and block bitmaps in; we'll be messing with
6649          * them.
6650          */
6651         e2fsck_read_bitmaps(ctx);
6652
6653         /*
6654          * First, find a free block
6655          */
6656         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6657         if (pctx->errcode) {
6658                 pctx->str = "ext2fs_new_block";
6659                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6660                 return 1;
6661         }
6662         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6663         ext2fs_mark_block_bitmap(fs->block_map, blk);
6664         ext2fs_mark_bb_dirty(fs);
6665
6666         /*
6667          * Now let's create the actual data block for the inode
6668          */
6669         if (db->blockcnt)
6670                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6671         else
6672                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6673                                                      EXT2_ROOT_INO, &block);
6674
6675         if (pctx->errcode) {
6676                 pctx->str = "ext2fs_new_dir_block";
6677                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6678                 return 1;
6679         }
6680
6681         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6682         ext2fs_free_mem(&block);
6683         if (pctx->errcode) {
6684                 pctx->str = "ext2fs_write_dir_block";
6685                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6686                 return 1;
6687         }
6688
6689         /*
6690          * Update the inode block count
6691          */
6692         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6693         inode.i_blocks += fs->blocksize / 512;
6694         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6695                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6696         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6697
6698         /*
6699          * Finally, update the block pointers for the inode
6700          */
6701         db->blk = blk;
6702         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6703                                       0, update_dir_block, db);
6704         if (pctx->errcode) {
6705                 pctx->str = "ext2fs_block_iterate";
6706                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6707                 return 1;
6708         }
6709
6710         return 0;
6711 }
6712
6713 /*
6714  * This is a helper function for allocate_dir_block().
6715  */
6716 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6717                             blk_t       *block_nr,
6718                             e2_blkcnt_t blockcnt,
6719                             blk_t ref_block FSCK_ATTR((unused)),
6720                             int ref_offset FSCK_ATTR((unused)),
6721                             void *priv_data)
6722 {
6723         struct ext2_db_entry *db;
6724
6725         db = (struct ext2_db_entry *) priv_data;
6726         if (db->blockcnt == (int) blockcnt) {
6727                 *block_nr = db->blk;
6728                 return BLOCK_CHANGED;
6729         }
6730         return 0;
6731 }
6732
6733 /*
6734  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6735  *
6736  * Pass #3 assures that all directories are connected to the
6737  * filesystem tree, using the following algorithm:
6738  *
6739  * First, the root directory is checked to make sure it exists; if
6740  * not, e2fsck will offer to create a new one.  It is then marked as
6741  * "done".
6742  *
6743  * Then, pass3 interates over all directory inodes; for each directory
6744  * it attempts to trace up the filesystem tree, using dirinfo.parent
6745  * until it reaches a directory which has been marked "done".  If it
6746  * can not do so, then the directory must be disconnected, and e2fsck
6747  * will offer to reconnect it to /lost+found.  While it is chasing
6748  * parent pointers up the filesystem tree, if pass3 sees a directory
6749  * twice, then it has detected a filesystem loop, and it will again
6750  * offer to reconnect the directory to /lost+found in to break the
6751  * filesystem loop.
6752  *
6753  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6754  * reconnect inodes to /lost+found; this subroutine is also used by
6755  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6756  * is responsible for creating /lost+found if it does not exist.
6757  *
6758  * Pass 3 frees the following data structures:
6759  *      - The dirinfo directory information cache.
6760  */
6761
6762 static void check_root(e2fsck_t ctx);
6763 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6764                            struct problem_context *pctx);
6765 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6766
6767 static ext2fs_inode_bitmap inode_loop_detect;
6768 static ext2fs_inode_bitmap inode_done_map;
6769
6770 static void e2fsck_pass3(e2fsck_t ctx)
6771 {
6772         ext2_filsys fs = ctx->fs;
6773         int             i;
6774         struct problem_context  pctx;
6775         struct dir_info *dir;
6776         unsigned long maxdirs, count;
6777
6778         clear_problem_context(&pctx);
6779
6780         /* Pass 3 */
6781
6782         if (!(ctx->options & E2F_OPT_PREEN))
6783                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6784
6785         /*
6786          * Allocate some bitmaps to do loop detection.
6787          */
6788         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6789                                                     &inode_done_map);
6790         if (pctx.errcode) {
6791                 pctx.num = 2;
6792                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6793                 ctx->flags |= E2F_FLAG_ABORT;
6794                 goto abort_exit;
6795         }
6796         check_root(ctx);
6797         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6798                 goto abort_exit;
6799
6800         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6801
6802         maxdirs = e2fsck_get_num_dirinfo(ctx);
6803         count = 1;
6804
6805         if (ctx->progress)
6806                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6807                         goto abort_exit;
6808
6809         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6810                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6811                         goto abort_exit;
6812                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6813                         goto abort_exit;
6814                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6815                         if (check_directory(ctx, dir, &pctx))
6816                                 goto abort_exit;
6817         }
6818
6819         /*
6820          * Force the creation of /lost+found if not present
6821          */
6822         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6823                 e2fsck_get_lost_and_found(ctx, 1);
6824
6825         /*
6826          * If there are any directories that need to be indexed or
6827          * optimized, do it here.
6828          */
6829         e2fsck_rehash_directories(ctx);
6830
6831 abort_exit:
6832         e2fsck_free_dir_info(ctx);
6833         ext2fs_free_inode_bitmap(inode_loop_detect);
6834         inode_loop_detect = 0;
6835         ext2fs_free_inode_bitmap(inode_done_map);
6836         inode_done_map = 0;
6837 }
6838
6839 /*
6840  * This makes sure the root inode is present; if not, we ask if the
6841  * user wants us to create it.  Not creating it is a fatal error.
6842  */
6843 static void check_root(e2fsck_t ctx)
6844 {
6845         ext2_filsys fs = ctx->fs;
6846         blk_t                   blk;
6847         struct ext2_inode       inode;
6848         char *                  block;
6849         struct problem_context  pctx;
6850
6851         clear_problem_context(&pctx);
6852
6853         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6854                 /*
6855                  * If the root inode is not a directory, die here.  The
6856                  * user must have answered 'no' in pass1 when we
6857                  * offered to clear it.
6858                  */
6859                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6860                                                EXT2_ROOT_INO))) {
6861                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6862                         ctx->flags |= E2F_FLAG_ABORT;
6863                 }
6864                 return;
6865         }
6866
6867         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6868                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6869                 ctx->flags |= E2F_FLAG_ABORT;
6870                 return;
6871         }
6872
6873         e2fsck_read_bitmaps(ctx);
6874
6875         /*
6876          * First, find a free block
6877          */
6878         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6879         if (pctx.errcode) {
6880                 pctx.str = "ext2fs_new_block";
6881                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882                 ctx->flags |= E2F_FLAG_ABORT;
6883                 return;
6884         }
6885         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6886         ext2fs_mark_block_bitmap(fs->block_map, blk);
6887         ext2fs_mark_bb_dirty(fs);
6888
6889         /*
6890          * Now let's create the actual data block for the inode
6891          */
6892         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6893                                             &block);
6894         if (pctx.errcode) {
6895                 pctx.str = "ext2fs_new_dir_block";
6896                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6897                 ctx->flags |= E2F_FLAG_ABORT;
6898                 return;
6899         }
6900
6901         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6902         if (pctx.errcode) {
6903                 pctx.str = "ext2fs_write_dir_block";
6904                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905                 ctx->flags |= E2F_FLAG_ABORT;
6906                 return;
6907         }
6908         ext2fs_free_mem(&block);
6909
6910         /*
6911          * Set up the inode structure
6912          */
6913         memset(&inode, 0, sizeof(inode));
6914         inode.i_mode = 040755;
6915         inode.i_size = fs->blocksize;
6916         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
6917         inode.i_links_count = 2;
6918         inode.i_blocks = fs->blocksize / 512;
6919         inode.i_block[0] = blk;
6920
6921         /*
6922          * Write out the inode.
6923          */
6924         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6925         if (pctx.errcode) {
6926                 pctx.str = "ext2fs_write_inode";
6927                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6928                 ctx->flags |= E2F_FLAG_ABORT;
6929                 return;
6930         }
6931
6932         /*
6933          * Miscellaneous bookkeeping...
6934          */
6935         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6936         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6937         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6938
6939         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6940         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6941         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6942         ext2fs_mark_ib_dirty(fs);
6943 }
6944
6945 /*
6946  * This subroutine is responsible for making sure that a particular
6947  * directory is connected to the root; if it isn't we trace it up as
6948  * far as we can go, and then offer to connect the resulting parent to
6949  * the lost+found.  We have to do loop detection; if we ever discover
6950  * a loop, we treat that as a disconnected directory and offer to
6951  * reparent it to lost+found.
6952  *
6953  * However, loop detection is expensive, because for very large
6954  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6955  * is non-trivial.  Loops in filesystems are also a rare error case,
6956  * and we shouldn't optimize for error cases.  So we try two passes of
6957  * the algorithm.  The first time, we ignore loop detection and merely
6958  * increment a counter; if the counter exceeds some extreme threshold,
6959  * then we try again with the loop detection bitmap enabled.
6960  */
6961 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6962                            struct problem_context *pctx)
6963 {
6964         ext2_filsys     fs = ctx->fs;
6965         struct dir_info *p = dir;
6966         int             loop_pass = 0, parent_count = 0;
6967
6968         if (!p)
6969                 return 0;
6970
6971         while (1) {
6972                 /*
6973                  * Mark this inode as being "done"; by the time we
6974                  * return from this function, the inode we either be
6975                  * verified as being connected to the directory tree,
6976                  * or we will have offered to reconnect this to
6977                  * lost+found.
6978                  *
6979                  * If it was marked done already, then we've reached a
6980                  * parent we've already checked.
6981                  */
6982                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6983                         break;
6984
6985                 /*
6986                  * If this directory doesn't have a parent, or we've
6987                  * seen the parent once already, then offer to
6988                  * reparent it to lost+found
6989                  */
6990                 if (!p->parent ||
6991                     (loop_pass &&
6992                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6993                                               p->parent)))) {
6994                         pctx->ino = p->ino;
6995                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6996                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6997                                         ext2fs_unmark_valid(fs);
6998                                 else {
6999                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
7000                                         p->parent = ctx->lost_and_found;
7001                                         fix_dotdot(ctx, p, ctx->lost_and_found);
7002                                 }
7003                         }
7004                         break;
7005                 }
7006                 p = e2fsck_get_dir_info(ctx, p->parent);
7007                 if (!p) {
7008                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
7009                         return 0;
7010                 }
7011                 if (loop_pass) {
7012                         ext2fs_mark_inode_bitmap(inode_loop_detect,
7013                                                  p->ino);
7014                 } else if (parent_count++ > 2048) {
7015                         /*
7016                          * If we've run into a path depth that's
7017                          * greater than 2048, try again with the inode
7018                          * loop bitmap turned on and start from the
7019                          * top.
7020                          */
7021                         loop_pass = 1;
7022                         if (inode_loop_detect)
7023                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
7024                         else {
7025                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7026                                 if (pctx->errcode) {
7027                                         pctx->num = 1;
7028                                         fix_problem(ctx,
7029                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7030                                         ctx->flags |= E2F_FLAG_ABORT;
7031                                         return -1;
7032                                 }
7033                         }
7034                         p = dir;
7035                 }
7036         }
7037
7038         /*
7039          * Make sure that .. and the parent directory are the same;
7040          * offer to fix it if not.
7041          */
7042         if (dir->parent != dir->dotdot) {
7043                 pctx->ino = dir->ino;
7044                 pctx->ino2 = dir->dotdot;
7045                 pctx->dir = dir->parent;
7046                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7047                         fix_dotdot(ctx, dir, dir->parent);
7048         }
7049         return 0;
7050 }
7051
7052 /*
7053  * This routine gets the lost_and_found inode, making it a directory
7054  * if necessary
7055  */
7056 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7057 {
7058         ext2_filsys fs = ctx->fs;
7059         ext2_ino_t                      ino;
7060         blk_t                   blk;
7061         errcode_t               retval;
7062         struct ext2_inode       inode;
7063         char *                  block;
7064         static const char       name[] = "lost+found";
7065         struct  problem_context pctx;
7066         struct dir_info         *dirinfo;
7067
7068         if (ctx->lost_and_found)
7069                 return ctx->lost_and_found;
7070
7071         clear_problem_context(&pctx);
7072
7073         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7074                                sizeof(name)-1, 0, &ino);
7075         if (retval && !fix)
7076                 return 0;
7077         if (!retval) {
7078                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7079                         ctx->lost_and_found = ino;
7080                         return ino;
7081                 }
7082
7083                 /* Lost+found isn't a directory! */
7084                 if (!fix)
7085                         return 0;
7086                 pctx.ino = ino;
7087                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7088                         return 0;
7089
7090                 /* OK, unlink the old /lost+found file. */
7091                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7092                 if (pctx.errcode) {
7093                         pctx.str = "ext2fs_unlink";
7094                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7095                         return 0;
7096                 }
7097                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7098                 if (dirinfo)
7099                         dirinfo->parent = 0;
7100                 e2fsck_adjust_inode_count(ctx, ino, -1);
7101         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7102                 pctx.errcode = retval;
7103                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7104         }
7105         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7106                 return 0;
7107
7108         /*
7109          * Read the inode and block bitmaps in; we'll be messing with
7110          * them.
7111          */
7112         e2fsck_read_bitmaps(ctx);
7113
7114         /*
7115          * First, find a free block
7116          */
7117         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7118         if (retval) {
7119                 pctx.errcode = retval;
7120                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7121                 return 0;
7122         }
7123         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7124         ext2fs_block_alloc_stats(fs, blk, +1);
7125
7126         /*
7127          * Next find a free inode.
7128          */
7129         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7130                                   ctx->inode_used_map, &ino);
7131         if (retval) {
7132                 pctx.errcode = retval;
7133                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7134                 return 0;
7135         }
7136         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7137         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7138         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7139
7140         /*
7141          * Now let's create the actual data block for the inode
7142          */
7143         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7144         if (retval) {
7145                 pctx.errcode = retval;
7146                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7147                 return 0;
7148         }
7149
7150         retval = ext2fs_write_dir_block(fs, blk, block);
7151         ext2fs_free_mem(&block);
7152         if (retval) {
7153                 pctx.errcode = retval;
7154                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7155                 return 0;
7156         }
7157
7158         /*
7159          * Set up the inode structure
7160          */
7161         memset(&inode, 0, sizeof(inode));
7162         inode.i_mode = 040700;
7163         inode.i_size = fs->blocksize;
7164         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
7165         inode.i_links_count = 2;
7166         inode.i_blocks = fs->blocksize / 512;
7167         inode.i_block[0] = blk;
7168
7169         /*
7170          * Next, write out the inode.
7171          */
7172         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7173         if (pctx.errcode) {
7174                 pctx.str = "ext2fs_write_inode";
7175                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7176                 return 0;
7177         }
7178         /*
7179          * Finally, create the directory link
7180          */
7181         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7182         if (pctx.errcode) {
7183                 pctx.str = "ext2fs_link";
7184                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7185                 return 0;
7186         }
7187
7188         /*
7189          * Miscellaneous bookkeeping that needs to be kept straight.
7190          */
7191         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7192         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7193         ext2fs_icount_store(ctx->inode_count, ino, 2);
7194         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7195         ctx->lost_and_found = ino;
7196         return ino;
7197 }
7198
7199 /*
7200  * This routine will connect a file to lost+found
7201  */
7202 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7203 {
7204         ext2_filsys fs = ctx->fs;
7205         errcode_t       retval;
7206         char            name[80];
7207         struct problem_context  pctx;
7208         struct ext2_inode       inode;
7209         int             file_type = 0;
7210
7211         clear_problem_context(&pctx);
7212         pctx.ino = ino;
7213
7214         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7215                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7216                         ctx->bad_lost_and_found++;
7217         }
7218         if (ctx->bad_lost_and_found) {
7219                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7220                 return 1;
7221         }
7222
7223         sprintf(name, "#%u", ino);
7224         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7225                 file_type = ext2_file_type(inode.i_mode);
7226         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7227         if (retval == EXT2_ET_DIR_NO_SPACE) {
7228                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7229                         return 1;
7230                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7231                                                  1, 0);
7232                 if (retval) {
7233                         pctx.errcode = retval;
7234                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7235                         return 1;
7236                 }
7237                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7238                                      ino, file_type);
7239         }
7240         if (retval) {
7241                 pctx.errcode = retval;
7242                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7243                 return 1;
7244         }
7245         e2fsck_adjust_inode_count(ctx, ino, 1);
7246
7247         return 0;
7248 }
7249
7250 /*
7251  * Utility routine to adjust the inode counts on an inode.
7252  */
7253 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7254 {
7255         ext2_filsys fs = ctx->fs;
7256         errcode_t               retval;
7257         struct ext2_inode       inode;
7258
7259         if (!ino)
7260                 return 0;
7261
7262         retval = ext2fs_read_inode(fs, ino, &inode);
7263         if (retval)
7264                 return retval;
7265
7266         if (adj == 1) {
7267                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7268                 if (inode.i_links_count == (__u16) ~0)
7269                         return 0;
7270                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7271                 inode.i_links_count++;
7272         } else if (adj == -1) {
7273                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7274                 if (inode.i_links_count == 0)
7275                         return 0;
7276                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7277                 inode.i_links_count--;
7278         }
7279
7280         retval = ext2fs_write_inode(fs, ino, &inode);
7281         if (retval)
7282                 return retval;
7283
7284         return 0;
7285 }
7286
7287 /*
7288  * Fix parent --- this routine fixes up the parent of a directory.
7289  */
7290 struct fix_dotdot_struct {
7291         ext2_filsys     fs;
7292         ext2_ino_t      parent;
7293         int             done;
7294         e2fsck_t        ctx;
7295 };
7296
7297 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7298                            int  offset FSCK_ATTR((unused)),
7299                            int  blocksize FSCK_ATTR((unused)),
7300                            char *buf FSCK_ATTR((unused)),
7301                            void *priv_data)
7302 {
7303         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7304         errcode_t       retval;
7305         struct problem_context pctx;
7306
7307         if ((dirent->name_len & 0xFF) != 2)
7308                 return 0;
7309         if (strncmp(dirent->name, "..", 2))
7310                 return 0;
7311
7312         clear_problem_context(&pctx);
7313
7314         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7315         if (retval) {
7316                 pctx.errcode = retval;
7317                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7318         }
7319         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7320         if (retval) {
7321                 pctx.errcode = retval;
7322                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7323         }
7324         dirent->inode = fp->parent;
7325
7326         fp->done++;
7327         return DIRENT_ABORT | DIRENT_CHANGED;
7328 }
7329
7330 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7331 {
7332         ext2_filsys fs = ctx->fs;
7333         errcode_t       retval;
7334         struct fix_dotdot_struct fp;
7335         struct problem_context pctx;
7336
7337         fp.fs = fs;
7338         fp.parent = parent;
7339         fp.done = 0;
7340         fp.ctx = ctx;
7341
7342         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7343                                     0, fix_dotdot_proc, &fp);
7344         if (retval || !fp.done) {
7345                 clear_problem_context(&pctx);
7346                 pctx.ino = dir->ino;
7347                 pctx.errcode = retval;
7348                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7349                             PR_3_FIX_PARENT_NOFIND, &pctx);
7350                 ext2fs_unmark_valid(fs);
7351         }
7352         dir->dotdot = parent;
7353
7354         return;
7355 }
7356
7357 /*
7358  * These routines are responsible for expanding a /lost+found if it is
7359  * too small.
7360  */
7361
7362 struct expand_dir_struct {
7363         int                     num;
7364         int                     guaranteed_size;
7365         int                     newblocks;
7366         int                     last_block;
7367         errcode_t               err;
7368         e2fsck_t                ctx;
7369 };
7370
7371 static int expand_dir_proc(ext2_filsys fs,
7372                            blk_t        *blocknr,
7373                            e2_blkcnt_t  blockcnt,
7374                            blk_t ref_block FSCK_ATTR((unused)),
7375                            int ref_offset FSCK_ATTR((unused)),
7376                            void *priv_data)
7377 {
7378         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7379         blk_t   new_blk;
7380         static blk_t    last_blk = 0;
7381         char            *block;
7382         errcode_t       retval;
7383         e2fsck_t        ctx;
7384
7385         ctx = es->ctx;
7386
7387         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7388                 return BLOCK_ABORT;
7389
7390         if (blockcnt > 0)
7391                 es->last_block = blockcnt;
7392         if (*blocknr) {
7393                 last_blk = *blocknr;
7394                 return 0;
7395         }
7396         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7397                                   &new_blk);
7398         if (retval) {
7399                 es->err = retval;
7400                 return BLOCK_ABORT;
7401         }
7402         if (blockcnt > 0) {
7403                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7404                 if (retval) {
7405                         es->err = retval;
7406                         return BLOCK_ABORT;
7407                 }
7408                 es->num--;
7409                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7410         } else {
7411                 retval = ext2fs_get_mem(fs->blocksize, &block);
7412                 if (retval) {
7413                         es->err = retval;
7414                         return BLOCK_ABORT;
7415                 }
7416                 memset(block, 0, fs->blocksize);
7417                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7418         }
7419         if (retval) {
7420                 es->err = retval;
7421                 return BLOCK_ABORT;
7422         }
7423         ext2fs_free_mem(&block);
7424         *blocknr = new_blk;
7425         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7426         ext2fs_block_alloc_stats(fs, new_blk, +1);
7427         es->newblocks++;
7428
7429         if (es->num == 0)
7430                 return (BLOCK_CHANGED | BLOCK_ABORT);
7431         else
7432                 return BLOCK_CHANGED;
7433 }
7434
7435 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7436                                   int num, int guaranteed_size)
7437 {
7438         ext2_filsys fs = ctx->fs;
7439         errcode_t       retval;
7440         struct expand_dir_struct es;
7441         struct ext2_inode       inode;
7442
7443         if (!(fs->flags & EXT2_FLAG_RW))
7444                 return EXT2_ET_RO_FILSYS;
7445
7446         /*
7447          * Read the inode and block bitmaps in; we'll be messing with
7448          * them.
7449          */
7450         e2fsck_read_bitmaps(ctx);
7451
7452         retval = ext2fs_check_directory(fs, dir);
7453         if (retval)
7454                 return retval;
7455
7456         es.num = num;
7457         es.guaranteed_size = guaranteed_size;
7458         es.last_block = 0;
7459         es.err = 0;
7460         es.newblocks = 0;
7461         es.ctx = ctx;
7462
7463         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7464                                        0, expand_dir_proc, &es);
7465
7466         if (es.err)
7467                 return es.err;
7468
7469         /*
7470          * Update the size and block count fields in the inode.
7471          */
7472         retval = ext2fs_read_inode(fs, dir, &inode);
7473         if (retval)
7474                 return retval;
7475
7476         inode.i_size = (es.last_block + 1) * fs->blocksize;
7477         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7478
7479         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7480
7481         return 0;
7482 }
7483
7484 /*
7485  * pass4.c -- pass #4 of e2fsck: Check reference counts
7486  *
7487  * Pass 4 frees the following data structures:
7488  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7489  */
7490
7491 /*
7492  * This routine is called when an inode is not connected to the
7493  * directory tree.
7494  *
7495  * This subroutine returns 1 then the caller shouldn't bother with the
7496  * rest of the pass 4 tests.
7497  */
7498 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7499 {
7500         ext2_filsys fs = ctx->fs;
7501         struct ext2_inode       inode;
7502         struct problem_context  pctx;
7503
7504         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7505         clear_problem_context(&pctx);
7506         pctx.ino = i;
7507         pctx.inode = &inode;
7508
7509         /*
7510          * Offer to delete any zero-length files that does not have
7511          * blocks.  If there is an EA block, it might have useful
7512          * information, so we won't prompt to delete it, but let it be
7513          * reconnected to lost+found.
7514          */
7515         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7516                                 LINUX_S_ISDIR(inode.i_mode))) {
7517                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7518                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7519                         inode.i_links_count = 0;
7520                         inode.i_dtime = time(0);
7521                         e2fsck_write_inode(ctx, i, &inode,
7522                                            "disconnect_inode");
7523                         /*
7524                          * Fix up the bitmaps...
7525                          */
7526                         e2fsck_read_bitmaps(ctx);
7527                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7528                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7529                         ext2fs_inode_alloc_stats2(fs, i, -1,
7530                                                   LINUX_S_ISDIR(inode.i_mode));
7531                         return 0;
7532                 }
7533         }
7534
7535         /*
7536          * Prompt to reconnect.
7537          */
7538         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7539                 if (e2fsck_reconnect_file(ctx, i))
7540                         ext2fs_unmark_valid(fs);
7541         } else {
7542                 /*
7543                  * If we don't attach the inode, then skip the
7544                  * i_links_test since there's no point in trying to
7545                  * force i_links_count to zero.
7546                  */
7547                 ext2fs_unmark_valid(fs);
7548                 return 1;
7549         }
7550         return 0;
7551 }
7552
7553
7554 static void e2fsck_pass4(e2fsck_t ctx)
7555 {
7556         ext2_filsys fs = ctx->fs;
7557         ext2_ino_t      i;
7558         struct ext2_inode       inode;
7559         struct problem_context  pctx;
7560         __u16   link_count, link_counted;
7561         char    *buf = 0;
7562         int     group, maxgroup;
7563
7564         /* Pass 4 */
7565
7566         clear_problem_context(&pctx);
7567
7568         if (!(ctx->options & E2F_OPT_PREEN))
7569                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7570
7571         group = 0;
7572         maxgroup = fs->group_desc_count;
7573         if (ctx->progress)
7574                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7575                         return;
7576
7577         for (i=1; i <= fs->super->s_inodes_count; i++) {
7578                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7579                         return;
7580                 if ((i % fs->super->s_inodes_per_group) == 0) {
7581                         group++;
7582                         if (ctx->progress)
7583                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7584                                         return;
7585                 }
7586                 if (i == EXT2_BAD_INO ||
7587                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7588                         continue;
7589                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7590                     (ctx->inode_imagic_map &&
7591                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7592                         continue;
7593                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7594                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7595                 if (link_counted == 0) {
7596                         if (!buf)
7597                                 buf = e2fsck_allocate_memory(ctx,
7598                                      fs->blocksize, "bad_inode buffer");
7599                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7600                                 continue;
7601                         if (disconnect_inode(ctx, i))
7602                                 continue;
7603                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7604                                             &link_count);
7605                         ext2fs_icount_fetch(ctx->inode_count, i,
7606                                             &link_counted);
7607                 }
7608                 if (link_counted != link_count) {
7609                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7610                         pctx.ino = i;
7611                         pctx.inode = &inode;
7612                         if (link_count != inode.i_links_count) {
7613                                 pctx.num = link_count;
7614                                 fix_problem(ctx,
7615                                             PR_4_INCONSISTENT_COUNT, &pctx);
7616                         }
7617                         pctx.num = link_counted;
7618                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7619                                 inode.i_links_count = link_counted;
7620                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7621                         }
7622                 }
7623         }
7624         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7625         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7626         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7627         ctx->inode_imagic_map = 0;
7628         ext2fs_free_mem(&buf);
7629 }
7630
7631 /*
7632  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7633  */
7634
7635 #define NO_BLK ((blk_t) -1)
7636
7637 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7638                             struct problem_context *pctx)
7639 {
7640         switch (problem) {
7641         case PR_5_BLOCK_UNUSED:
7642                 if (pctx->blk == pctx->blk2)
7643                         pctx->blk2 = 0;
7644                 else
7645                         problem = PR_5_BLOCK_RANGE_UNUSED;
7646                 break;
7647         case PR_5_BLOCK_USED:
7648                 if (pctx->blk == pctx->blk2)
7649                         pctx->blk2 = 0;
7650                 else
7651                         problem = PR_5_BLOCK_RANGE_USED;
7652                 break;
7653         case PR_5_INODE_UNUSED:
7654                 if (pctx->ino == pctx->ino2)
7655                         pctx->ino2 = 0;
7656                 else
7657                         problem = PR_5_INODE_RANGE_UNUSED;
7658                 break;
7659         case PR_5_INODE_USED:
7660                 if (pctx->ino == pctx->ino2)
7661                         pctx->ino2 = 0;
7662                 else
7663                         problem = PR_5_INODE_RANGE_USED;
7664                 break;
7665         }
7666         fix_problem(ctx, problem, pctx);
7667         pctx->blk = pctx->blk2 = NO_BLK;
7668         pctx->ino = pctx->ino2 = 0;
7669 }
7670
7671 static void check_block_bitmaps(e2fsck_t ctx)
7672 {
7673         ext2_filsys fs = ctx->fs;
7674         blk_t   i;
7675         int     *free_array;
7676         int     group = 0;
7677         unsigned int    blocks = 0;
7678         unsigned int    free_blocks = 0;
7679         int     group_free = 0;
7680         int     actual, bitmap;
7681         struct problem_context  pctx;
7682         int     problem, save_problem, fixit, had_problem;
7683         errcode_t       retval;
7684
7685         clear_problem_context(&pctx);
7686         free_array = (int *) e2fsck_allocate_memory(ctx,
7687             fs->group_desc_count * sizeof(int), "free block count array");
7688
7689         if ((fs->super->s_first_data_block <
7690              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7691             (fs->super->s_blocks_count-1 >
7692              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7693                 pctx.num = 1;
7694                 pctx.blk = fs->super->s_first_data_block;
7695                 pctx.blk2 = fs->super->s_blocks_count -1;
7696                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7697                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7698                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7699
7700                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7701                 return;
7702         }
7703
7704         if ((fs->super->s_first_data_block <
7705              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7706             (fs->super->s_blocks_count-1 >
7707              ext2fs_get_block_bitmap_end(fs->block_map))) {
7708                 pctx.num = 2;
7709                 pctx.blk = fs->super->s_first_data_block;
7710                 pctx.blk2 = fs->super->s_blocks_count -1;
7711                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7712                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7713                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7714
7715                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7716                 return;
7717         }
7718
7719 redo_counts:
7720         had_problem = 0;
7721         save_problem = 0;
7722         pctx.blk = pctx.blk2 = NO_BLK;
7723         for (i = fs->super->s_first_data_block;
7724              i < fs->super->s_blocks_count;
7725              i++) {
7726                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7727                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7728
7729                 if (actual == bitmap)
7730                         goto do_counts;
7731
7732                 if (!actual && bitmap) {
7733                         /*
7734                          * Block not used, but marked in use in the bitmap.
7735                          */
7736                         problem = PR_5_BLOCK_UNUSED;
7737                 } else {
7738                         /*
7739                          * Block used, but not marked in use in the bitmap.
7740                          */
7741                         problem = PR_5_BLOCK_USED;
7742                 }
7743                 if (pctx.blk == NO_BLK) {
7744                         pctx.blk = pctx.blk2 = i;
7745                         save_problem = problem;
7746                 } else {
7747                         if ((problem == save_problem) &&
7748                             (pctx.blk2 == i-1))
7749                                 pctx.blk2++;
7750                         else {
7751                                 print_bitmap_problem(ctx, save_problem, &pctx);
7752                                 pctx.blk = pctx.blk2 = i;
7753                                 save_problem = problem;
7754                         }
7755                 }
7756                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7757                 had_problem++;
7758
7759         do_counts:
7760                 if (!bitmap) {
7761                         group_free++;
7762                         free_blocks++;
7763                 }
7764                 blocks ++;
7765                 if ((blocks == fs->super->s_blocks_per_group) ||
7766                     (i == fs->super->s_blocks_count-1)) {
7767                         free_array[group] = group_free;
7768                         group ++;
7769                         blocks = 0;
7770                         group_free = 0;
7771                         if (ctx->progress)
7772                                 if ((ctx->progress)(ctx, 5, group,
7773                                                     fs->group_desc_count*2))
7774                                         return;
7775                 }
7776         }
7777         if (pctx.blk != NO_BLK)
7778                 print_bitmap_problem(ctx, save_problem, &pctx);
7779         if (had_problem)
7780                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7781         else
7782                 fixit = -1;
7783         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7784
7785         if (fixit == 1) {
7786                 ext2fs_free_block_bitmap(fs->block_map);
7787                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7788                                                   &fs->block_map);
7789                 if (retval) {
7790                         clear_problem_context(&pctx);
7791                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7792                         ctx->flags |= E2F_FLAG_ABORT;
7793                         return;
7794                 }
7795                 ext2fs_set_bitmap_padding(fs->block_map);
7796                 ext2fs_mark_bb_dirty(fs);
7797
7798                 /* Redo the counts */
7799                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7800                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7801                 goto redo_counts;
7802         } else if (fixit == 0)
7803                 ext2fs_unmark_valid(fs);
7804
7805         for (i = 0; i < fs->group_desc_count; i++) {
7806                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7807                         pctx.group = i;
7808                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7809                         pctx.blk2 = free_array[i];
7810
7811                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7812                                         &pctx)) {
7813                                 fs->group_desc[i].bg_free_blocks_count =
7814                                         free_array[i];
7815                                 ext2fs_mark_super_dirty(fs);
7816                         } else
7817                                 ext2fs_unmark_valid(fs);
7818                 }
7819         }
7820         if (free_blocks != fs->super->s_free_blocks_count) {
7821                 pctx.group = 0;
7822                 pctx.blk = fs->super->s_free_blocks_count;
7823                 pctx.blk2 = free_blocks;
7824
7825                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7826                         fs->super->s_free_blocks_count = free_blocks;
7827                         ext2fs_mark_super_dirty(fs);
7828                 } else
7829                         ext2fs_unmark_valid(fs);
7830         }
7831         ext2fs_free_mem(&free_array);
7832 }
7833
7834 static void check_inode_bitmaps(e2fsck_t ctx)
7835 {
7836         ext2_filsys fs = ctx->fs;
7837         ext2_ino_t      i;
7838         unsigned int    free_inodes = 0;
7839         int             group_free = 0;
7840         int             dirs_count = 0;
7841         int             group = 0;
7842         unsigned int    inodes = 0;
7843         int             *free_array;
7844         int             *dir_array;
7845         int             actual, bitmap;
7846         errcode_t       retval;
7847         struct problem_context  pctx;
7848         int             problem, save_problem, fixit, had_problem;
7849
7850         clear_problem_context(&pctx);
7851         free_array = (int *) e2fsck_allocate_memory(ctx,
7852             fs->group_desc_count * sizeof(int), "free inode count array");
7853
7854         dir_array = (int *) e2fsck_allocate_memory(ctx,
7855            fs->group_desc_count * sizeof(int), "directory count array");
7856
7857         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7858             (fs->super->s_inodes_count >
7859              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7860                 pctx.num = 3;
7861                 pctx.blk = 1;
7862                 pctx.blk2 = fs->super->s_inodes_count;
7863                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7864                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7865                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7866
7867                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7868                 return;
7869         }
7870         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7871             (fs->super->s_inodes_count >
7872              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7873                 pctx.num = 4;
7874                 pctx.blk = 1;
7875                 pctx.blk2 = fs->super->s_inodes_count;
7876                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7877                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7878                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7879
7880                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7881                 return;
7882         }
7883
7884 redo_counts:
7885         had_problem = 0;
7886         save_problem = 0;
7887         pctx.ino = pctx.ino2 = 0;
7888         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7889                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7890                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7891
7892                 if (actual == bitmap)
7893                         goto do_counts;
7894
7895                 if (!actual && bitmap) {
7896                         /*
7897                          * Inode wasn't used, but marked in bitmap
7898                          */
7899                         problem = PR_5_INODE_UNUSED;
7900                 } else /* if (actual && !bitmap) */ {
7901                         /*
7902                          * Inode used, but not in bitmap
7903                          */
7904                         problem = PR_5_INODE_USED;
7905                 }
7906                 if (pctx.ino == 0) {
7907                         pctx.ino = pctx.ino2 = i;
7908                         save_problem = problem;
7909                 } else {
7910                         if ((problem == save_problem) &&
7911                             (pctx.ino2 == i-1))
7912                                 pctx.ino2++;
7913                         else {
7914                                 print_bitmap_problem(ctx, save_problem, &pctx);
7915                                 pctx.ino = pctx.ino2 = i;
7916                                 save_problem = problem;
7917                         }
7918                 }
7919                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7920                 had_problem++;
7921
7922 do_counts:
7923                 if (!bitmap) {
7924                         group_free++;
7925                         free_inodes++;
7926                 } else {
7927                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7928                                 dirs_count++;
7929                 }
7930                 inodes++;
7931                 if ((inodes == fs->super->s_inodes_per_group) ||
7932                     (i == fs->super->s_inodes_count)) {
7933                         free_array[group] = group_free;
7934                         dir_array[group] = dirs_count;
7935                         group ++;
7936                         inodes = 0;
7937                         group_free = 0;
7938                         dirs_count = 0;
7939                         if (ctx->progress)
7940                                 if ((ctx->progress)(ctx, 5,
7941                                             group + fs->group_desc_count,
7942                                             fs->group_desc_count*2))
7943                                         return;
7944                 }
7945         }
7946         if (pctx.ino)
7947                 print_bitmap_problem(ctx, save_problem, &pctx);
7948
7949         if (had_problem)
7950                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7951         else
7952                 fixit = -1;
7953         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7954
7955         if (fixit == 1) {
7956                 ext2fs_free_inode_bitmap(fs->inode_map);
7957                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7958                                                   &fs->inode_map);
7959                 if (retval) {
7960                         clear_problem_context(&pctx);
7961                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7962                         ctx->flags |= E2F_FLAG_ABORT;
7963                         return;
7964                 }
7965                 ext2fs_set_bitmap_padding(fs->inode_map);
7966                 ext2fs_mark_ib_dirty(fs);
7967
7968                 /* redo counts */
7969                 inodes = 0; free_inodes = 0; group_free = 0;
7970                 dirs_count = 0; group = 0;
7971                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7972                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7973                 goto redo_counts;
7974         } else if (fixit == 0)
7975                 ext2fs_unmark_valid(fs);
7976
7977         for (i = 0; i < fs->group_desc_count; i++) {
7978                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7979                         pctx.group = i;
7980                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7981                         pctx.ino2 = free_array[i];
7982                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7983                                         &pctx)) {
7984                                 fs->group_desc[i].bg_free_inodes_count =
7985                                         free_array[i];
7986                                 ext2fs_mark_super_dirty(fs);
7987                         } else
7988                                 ext2fs_unmark_valid(fs);
7989                 }
7990                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7991                         pctx.group = i;
7992                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7993                         pctx.ino2 = dir_array[i];
7994
7995                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7996                                         &pctx)) {
7997                                 fs->group_desc[i].bg_used_dirs_count =
7998                                         dir_array[i];
7999                                 ext2fs_mark_super_dirty(fs);
8000                         } else
8001                                 ext2fs_unmark_valid(fs);
8002                 }
8003         }
8004         if (free_inodes != fs->super->s_free_inodes_count) {
8005                 pctx.group = -1;
8006                 pctx.ino = fs->super->s_free_inodes_count;
8007                 pctx.ino2 = free_inodes;
8008
8009                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
8010                         fs->super->s_free_inodes_count = free_inodes;
8011                         ext2fs_mark_super_dirty(fs);
8012                 } else
8013                         ext2fs_unmark_valid(fs);
8014         }
8015         ext2fs_free_mem(&free_array);
8016         ext2fs_free_mem(&dir_array);
8017 }
8018
8019 static void check_inode_end(e2fsck_t ctx)
8020 {
8021         ext2_filsys fs = ctx->fs;
8022         ext2_ino_t      end, save_inodes_count, i;
8023         struct problem_context  pctx;
8024
8025         clear_problem_context(&pctx);
8026
8027         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8028         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8029                                                      &save_inodes_count);
8030         if (pctx.errcode) {
8031                 pctx.num = 1;
8032                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8033                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8034                 return;
8035         }
8036         if (save_inodes_count == end)
8037                 return;
8038
8039         for (i = save_inodes_count + 1; i <= end; i++) {
8040                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8041                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8042                                 for (i = save_inodes_count + 1; i <= end; i++)
8043                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8044                                                                  i);
8045                                 ext2fs_mark_ib_dirty(fs);
8046                         } else
8047                                 ext2fs_unmark_valid(fs);
8048                         break;
8049                 }
8050         }
8051
8052         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8053                                                      save_inodes_count, 0);
8054         if (pctx.errcode) {
8055                 pctx.num = 2;
8056                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8057                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8058                 return;
8059         }
8060 }
8061
8062 static void check_block_end(e2fsck_t ctx)
8063 {
8064         ext2_filsys fs = ctx->fs;
8065         blk_t   end, save_blocks_count, i;
8066         struct problem_context  pctx;
8067
8068         clear_problem_context(&pctx);
8069
8070         end = fs->block_map->start +
8071                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8072         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8073                                                      &save_blocks_count);
8074         if (pctx.errcode) {
8075                 pctx.num = 3;
8076                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8077                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8078                 return;
8079         }
8080         if (save_blocks_count == end)
8081                 return;
8082
8083         for (i = save_blocks_count + 1; i <= end; i++) {
8084                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8085                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8086                                 for (i = save_blocks_count + 1; i <= end; i++)
8087                                         ext2fs_mark_block_bitmap(fs->block_map,
8088                                                                  i);
8089                                 ext2fs_mark_bb_dirty(fs);
8090                         } else
8091                                 ext2fs_unmark_valid(fs);
8092                         break;
8093                 }
8094         }
8095
8096         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8097                                                      save_blocks_count, 0);
8098         if (pctx.errcode) {
8099                 pctx.num = 4;
8100                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8101                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8102                 return;
8103         }
8104 }
8105
8106 static void e2fsck_pass5(e2fsck_t ctx)
8107 {
8108         struct problem_context  pctx;
8109
8110         /* Pass 5 */
8111
8112         clear_problem_context(&pctx);
8113
8114         if (!(ctx->options & E2F_OPT_PREEN))
8115                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8116
8117         if (ctx->progress)
8118                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8119                         return;
8120
8121         e2fsck_read_bitmaps(ctx);
8122
8123         check_block_bitmaps(ctx);
8124         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8125                 return;
8126         check_inode_bitmaps(ctx);
8127         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8128                 return;
8129         check_inode_end(ctx);
8130         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8131                 return;
8132         check_block_end(ctx);
8133         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8134                 return;
8135
8136         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8137         ctx->inode_used_map = 0;
8138         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8139         ctx->inode_dir_map = 0;
8140         ext2fs_free_block_bitmap(ctx->block_found_map);
8141         ctx->block_found_map = 0;
8142 }
8143
8144 /*
8145  * problem.c --- report filesystem problems to the user
8146  */
8147
8148 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8149 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8150 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8151 #define PR_MSG_ONLY     0x000008 /* Print message only */
8152
8153 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8154
8155 #define PR_FATAL        0x001000 /* Fatal error */
8156 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8157                                  /* ask another */
8158 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8159 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8160 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8161 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8162 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8163
8164
8165 #define PROMPT_NONE     0
8166 #define PROMPT_FIX      1
8167 #define PROMPT_CLEAR    2
8168 #define PROMPT_RELOCATE 3
8169 #define PROMPT_ALLOCATE 4
8170 #define PROMPT_EXPAND   5
8171 #define PROMPT_CONNECT  6
8172 #define PROMPT_CREATE   7
8173 #define PROMPT_SALVAGE  8
8174 #define PROMPT_TRUNCATE 9
8175 #define PROMPT_CLEAR_INODE 10
8176 #define PROMPT_ABORT    11
8177 #define PROMPT_SPLIT    12
8178 #define PROMPT_CONTINUE 13
8179 #define PROMPT_CLONE    14
8180 #define PROMPT_DELETE   15
8181 #define PROMPT_SUPPRESS 16
8182 #define PROMPT_UNLINK   17
8183 #define PROMPT_CLEAR_HTREE 18
8184 #define PROMPT_RECREATE 19
8185 #define PROMPT_NULL     20
8186
8187 struct e2fsck_problem {
8188         problem_t       e2p_code;
8189         const char *    e2p_description;
8190         char            prompt;
8191         int             flags;
8192         problem_t       second_code;
8193 };
8194
8195 struct latch_descr {
8196         int             latch_code;
8197         problem_t       question;
8198         problem_t       end_message;
8199         int             flags;
8200 };
8201
8202 /*
8203  * These are the prompts which are used to ask the user if they want
8204  * to fix a problem.
8205  */
8206 static const char * const prompt[] = {
8207         N_("(no prompt)"),      /* 0 */
8208         N_("Fix"),              /* 1 */
8209         N_("Clear"),            /* 2 */
8210         N_("Relocate"),         /* 3 */
8211         N_("Allocate"),         /* 4 */
8212         N_("Expand"),           /* 5 */
8213         N_("Connect to /lost+found"), /* 6 */
8214         N_("Create"),           /* 7 */
8215         N_("Salvage"),          /* 8 */
8216         N_("Truncate"),         /* 9 */
8217         N_("Clear inode"),      /* 10 */
8218         N_("Abort"),            /* 11 */
8219         N_("Split"),            /* 12 */
8220         N_("Continue"),         /* 13 */
8221         N_("Clone multiply-claimed blocks"), /* 14 */
8222         N_("Delete file"),      /* 15 */
8223         N_("Suppress messages"),/* 16 */
8224         N_("Unlink"),           /* 17 */
8225         N_("Clear HTree index"),/* 18 */
8226         N_("Recreate"),         /* 19 */
8227         "",                     /* 20 */
8228 };
8229
8230 /*
8231  * These messages are printed when we are preen mode and we will be
8232  * automatically fixing the problem.
8233  */
8234 static const char * const preen_msg[] = {
8235         N_("(NONE)"),           /* 0 */
8236         N_("FIXED"),            /* 1 */
8237         N_("CLEARED"),          /* 2 */
8238         N_("RELOCATED"),        /* 3 */
8239         N_("ALLOCATED"),        /* 4 */
8240         N_("EXPANDED"),         /* 5 */
8241         N_("RECONNECTED"),      /* 6 */
8242         N_("CREATED"),          /* 7 */
8243         N_("SALVAGED"),         /* 8 */
8244         N_("TRUNCATED"),        /* 9 */
8245         N_("INODE CLEARED"),    /* 10 */
8246         N_("ABORTED"),          /* 11 */
8247         N_("SPLIT"),            /* 12 */
8248         N_("CONTINUING"),       /* 13 */
8249         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8250         N_("FILE DELETED"),     /* 15 */
8251         N_("SUPPRESSED"),       /* 16 */
8252         N_("UNLINKED"),         /* 17 */
8253         N_("HTREE INDEX CLEARED"),/* 18 */
8254         N_("WILL RECREATE"),    /* 19 */
8255         "",                     /* 20 */
8256 };
8257
8258 static const struct e2fsck_problem problem_table[] = {
8259
8260         /* Pre-Pass 1 errors */
8261
8262         /* Block bitmap not in group */
8263         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8264           PROMPT_RELOCATE, PR_LATCH_RELOC },
8265
8266         /* Inode bitmap not in group */
8267         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8268           PROMPT_RELOCATE, PR_LATCH_RELOC },
8269
8270         /* Inode table not in group */
8271         { PR_0_ITABLE_NOT_GROUP,
8272           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8273           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8274           PROMPT_RELOCATE, PR_LATCH_RELOC },
8275
8276         /* Superblock corrupt */
8277         { PR_0_SB_CORRUPT,
8278           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8279           "@f.  If the @v is valid and it really contains an ext2\n"
8280           "@f (and not swap or ufs or something else), then the @S\n"
8281           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8282           "    e2fsck -b %S <@v>\n\n"),
8283           PROMPT_NONE, PR_FATAL },
8284
8285         /* Filesystem size is wrong */
8286         { PR_0_FS_SIZE_WRONG,
8287           N_("The @f size (according to the @S) is %b @bs\n"
8288           "The physical size of the @v is %c @bs\n"
8289           "Either the @S or the partition table is likely to be corrupt!\n"),
8290           PROMPT_ABORT, 0 },
8291
8292         /* Fragments not supported */
8293         { PR_0_NO_FRAGMENTS,
8294           N_("@S @b_size = %b, fragsize = %c.\n"
8295           "This version of e2fsck does not support fragment sizes different\n"
8296           "from the @b size.\n"),
8297           PROMPT_NONE, PR_FATAL },
8298
8299           /* Bad blocks_per_group */
8300         { PR_0_BLOCKS_PER_GROUP,
8301           N_("@S @bs_per_group = %b, should have been %c\n"),
8302           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8303
8304         /* Bad first_data_block */
8305         { PR_0_FIRST_DATA_BLOCK,
8306           N_("@S first_data_@b = %b, should have been %c\n"),
8307           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8308
8309         /* Adding UUID to filesystem */
8310         { PR_0_ADD_UUID,
8311           N_("@f did not have a UUID; generating one.\n\n"),
8312           PROMPT_NONE, 0 },
8313
8314         /* Relocate hint */
8315         { PR_0_RELOCATE_HINT,
8316           N_("Note: if several inode or block bitmap blocks or part\n"
8317           "of the inode table require relocation, you may wish to try\n"
8318           "running e2fsck with the '-b %S' option first.  The problem\n"
8319           "may lie only with the primary block group descriptors, and\n"
8320           "the backup block group descriptors may be OK.\n\n"),
8321           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8322
8323         /* Miscellaneous superblock corruption */
8324         { PR_0_MISC_CORRUPT_SUPER,
8325           N_("Corruption found in @S.  (%s = %N).\n"),
8326           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8327
8328         /* Error determing physical device size of filesystem */
8329         { PR_0_GETSIZE_ERROR,
8330           N_("Error determining size of the physical @v: %m\n"),
8331           PROMPT_NONE, PR_FATAL },
8332
8333         /* Inode count in superblock is incorrect */
8334         { PR_0_INODE_COUNT_WRONG,
8335           N_("@i count in @S is %i, @s %j.\n"),
8336           PROMPT_FIX, 0 },
8337
8338         { PR_0_HURD_CLEAR_FILETYPE,
8339           N_("The Hurd does not support the filetype feature.\n"),
8340           PROMPT_CLEAR, 0 },
8341
8342         /* Journal inode is invalid */
8343         { PR_0_JOURNAL_BAD_INODE,
8344           N_("@S has an @n ext3 @j (@i %i).\n"),
8345           PROMPT_CLEAR, PR_PREEN_OK },
8346
8347         /* The external journal has (unsupported) multiple filesystems */
8348         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8349           N_("External @j has multiple @f users (unsupported).\n"),
8350           PROMPT_NONE, PR_FATAL },
8351
8352         /* Can't find external journal */
8353         { PR_0_CANT_FIND_JOURNAL,
8354           N_("Can't find external @j\n"),
8355           PROMPT_NONE, PR_FATAL },
8356
8357         /* External journal has bad superblock */
8358         { PR_0_EXT_JOURNAL_BAD_SUPER,
8359           N_("External @j has bad @S\n"),
8360           PROMPT_NONE, PR_FATAL },
8361
8362         /* Superblock has a bad journal UUID */
8363         { PR_0_JOURNAL_BAD_UUID,
8364           N_("External @j does not support this @f\n"),
8365           PROMPT_NONE, PR_FATAL },
8366
8367         /* Journal has an unknown superblock type */
8368         { PR_0_JOURNAL_UNSUPP_SUPER,
8369           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8370              "It is likely that your copy of e2fsck is old and/or doesn't "
8371              "support this @j format.\n"
8372              "It is also possible the @j @S is corrupt.\n"),
8373           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8374
8375         /* Journal superblock is corrupt */
8376         { PR_0_JOURNAL_BAD_SUPER,
8377           N_("Ext3 @j @S is corrupt.\n"),
8378           PROMPT_FIX, PR_PREEN_OK },
8379
8380         /* Superblock flag should be cleared */
8381         { PR_0_JOURNAL_HAS_JOURNAL,
8382           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8383           PROMPT_CLEAR, PR_PREEN_OK },
8384
8385         /* Superblock flag is incorrect */
8386         { PR_0_JOURNAL_RECOVER_SET,
8387           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8388           PROMPT_CLEAR, PR_PREEN_OK },
8389
8390         /* Journal has data, but recovery flag is clear */
8391         { PR_0_JOURNAL_RECOVERY_CLEAR,
8392           N_("ext3 recovery flag is clear, but @j has data.\n"),
8393           PROMPT_NONE, 0 },
8394
8395         /* Ask if we should clear the journal */
8396         { PR_0_JOURNAL_RESET_JOURNAL,
8397           N_("Clear @j"),
8398           PROMPT_NULL, PR_PREEN_NOMSG },
8399
8400         /* Ask if we should run the journal anyway */
8401         { PR_0_JOURNAL_RUN,
8402           N_("Run @j anyway"),
8403           PROMPT_NULL, 0 },
8404
8405         /* Run the journal by default */
8406         { PR_0_JOURNAL_RUN_DEFAULT,
8407           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8408           PROMPT_NONE, 0 },
8409
8410         /* Clearing orphan inode */
8411         { PR_0_ORPHAN_CLEAR_INODE,
8412           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8413           PROMPT_NONE, 0 },
8414
8415         /* Illegal block found in orphaned inode */
8416         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8417            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8418           PROMPT_NONE, 0 },
8419
8420         /* Already cleared block found in orphaned inode */
8421         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8422            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8423           PROMPT_NONE, 0 },
8424
8425         /* Illegal orphan inode in superblock */
8426         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8427           N_("@I @o @i %i in @S.\n"),
8428           PROMPT_NONE, 0 },
8429
8430         /* Illegal inode in orphaned inode list */
8431         { PR_0_ORPHAN_ILLEGAL_INODE,
8432           N_("@I @i %i in @o @i list.\n"),
8433           PROMPT_NONE, 0 },
8434
8435         /* Filesystem revision is 0, but feature flags are set */
8436         { PR_0_FS_REV_LEVEL,
8437           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8438           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8439
8440         /* Journal superblock has an unknown read-only feature flag set */
8441         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8442           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8443           PROMPT_ABORT, 0 },
8444
8445         /* Journal superblock has an unknown incompatible feature flag set */
8446         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8447           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8448           PROMPT_ABORT, 0 },
8449
8450         /* Journal has unsupported version number */
8451         { PR_0_JOURNAL_UNSUPP_VERSION,
8452           N_("@j version not supported by this e2fsck.\n"),
8453           PROMPT_ABORT, 0 },
8454
8455         /* Moving journal to hidden file */
8456         { PR_0_MOVE_JOURNAL,
8457           N_("Moving @j from /%s to hidden @i.\n\n"),
8458           PROMPT_NONE, 0 },
8459
8460         /* Error moving journal to hidden file */
8461         { PR_0_ERR_MOVE_JOURNAL,
8462           N_("Error moving @j: %m\n\n"),
8463           PROMPT_NONE, 0 },
8464
8465         /* Clearing V2 journal superblock */
8466         { PR_0_CLEAR_V2_JOURNAL,
8467           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8468              "Clearing fields beyond the V1 @j @S...\n\n"),
8469           PROMPT_NONE, 0 },
8470
8471         /* Backup journal inode blocks */
8472         { PR_0_BACKUP_JNL,
8473           N_("Backing up @j @i @b information.\n\n"),
8474           PROMPT_NONE, 0 },
8475
8476         /* Reserved blocks w/o resize_inode */
8477         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8478           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8479              "is %N; @s zero.  "),
8480           PROMPT_FIX, 0 },
8481
8482         /* Resize_inode not enabled, but resize inode is non-zero */
8483         { PR_0_CLEAR_RESIZE_INODE,
8484           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8485           PROMPT_CLEAR, 0 },
8486
8487         /* Resize inode invalid */
8488         { PR_0_RESIZE_INODE_INVALID,
8489           N_("Resize @i not valid.  "),
8490           PROMPT_RECREATE, 0 },
8491
8492         /* Pass 1 errors */
8493
8494         /* Pass 1: Checking inodes, blocks, and sizes */
8495         { PR_1_PASS_HEADER,
8496           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8497           PROMPT_NONE, 0 },
8498
8499         /* Root directory is not an inode */
8500         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8501           PROMPT_CLEAR, 0 },
8502
8503         /* Root directory has dtime set */
8504         { PR_1_ROOT_DTIME,
8505           N_("@r has dtime set (probably due to old mke2fs).  "),
8506           PROMPT_FIX, PR_PREEN_OK },
8507
8508         /* Reserved inode has bad mode */
8509         { PR_1_RESERVED_BAD_MODE,
8510           N_("Reserved @i %i (%Q) has @n mode.  "),
8511           PROMPT_CLEAR, PR_PREEN_OK },
8512
8513         /* Deleted inode has zero dtime */
8514         { PR_1_ZERO_DTIME,
8515           N_("@D @i %i has zero dtime.  "),
8516           PROMPT_FIX, PR_PREEN_OK },
8517
8518         /* Inode in use, but dtime set */
8519         { PR_1_SET_DTIME,
8520           N_("@i %i is in use, but has dtime set.  "),
8521           PROMPT_FIX, PR_PREEN_OK },
8522
8523         /* Zero-length directory */
8524         { PR_1_ZERO_LENGTH_DIR,
8525           N_("@i %i is a @z @d.  "),
8526           PROMPT_CLEAR, PR_PREEN_OK },
8527
8528         /* Block bitmap conflicts with some other fs block */
8529         { PR_1_BB_CONFLICT,
8530           N_("@g %g's @b @B at %b @C.\n"),
8531           PROMPT_RELOCATE, 0 },
8532
8533         /* Inode bitmap conflicts with some other fs block */
8534         { PR_1_IB_CONFLICT,
8535           N_("@g %g's @i @B at %b @C.\n"),
8536           PROMPT_RELOCATE, 0 },
8537
8538         /* Inode table conflicts with some other fs block */
8539         { PR_1_ITABLE_CONFLICT,
8540           N_("@g %g's @i table at %b @C.\n"),
8541           PROMPT_RELOCATE, 0 },
8542
8543         /* Block bitmap is on a bad block */
8544         { PR_1_BB_BAD_BLOCK,
8545           N_("@g %g's @b @B (%b) is bad.  "),
8546           PROMPT_RELOCATE, 0 },
8547
8548         /* Inode bitmap is on a bad block */
8549         { PR_1_IB_BAD_BLOCK,
8550           N_("@g %g's @i @B (%b) is bad.  "),
8551           PROMPT_RELOCATE, 0 },
8552
8553         /* Inode has incorrect i_size */
8554         { PR_1_BAD_I_SIZE,
8555           N_("@i %i, i_size is %Is, @s %N.  "),
8556           PROMPT_FIX, PR_PREEN_OK },
8557
8558         /* Inode has incorrect i_blocks */
8559         { PR_1_BAD_I_BLOCKS,
8560           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8561           PROMPT_FIX, PR_PREEN_OK },
8562
8563         /* Illegal blocknumber in inode */
8564         { PR_1_ILLEGAL_BLOCK_NUM,
8565           N_("@I @b #%B (%b) in @i %i.  "),
8566           PROMPT_CLEAR, PR_LATCH_BLOCK },
8567
8568         /* Block number overlaps fs metadata */
8569         { PR_1_BLOCK_OVERLAPS_METADATA,
8570           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8571           PROMPT_CLEAR, PR_LATCH_BLOCK },
8572
8573         /* Inode has illegal blocks (latch question) */
8574         { PR_1_INODE_BLOCK_LATCH,
8575           N_("@i %i has illegal @b(s).  "),
8576           PROMPT_CLEAR, 0 },
8577
8578         /* Too many bad blocks in inode */
8579         { PR_1_TOO_MANY_BAD_BLOCKS,
8580           N_("Too many illegal @bs in @i %i.\n"),
8581           PROMPT_CLEAR_INODE, PR_NO_OK },
8582
8583         /* Illegal block number in bad block inode */
8584         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8585           N_("@I @b #%B (%b) in bad @b @i.  "),
8586           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8587
8588         /* Bad block inode has illegal blocks (latch question) */
8589         { PR_1_INODE_BBLOCK_LATCH,
8590           N_("Bad @b @i has illegal @b(s).  "),
8591           PROMPT_CLEAR, 0 },
8592
8593         /* Duplicate or bad blocks in use! */
8594         { PR_1_DUP_BLOCKS_PREENSTOP,
8595           N_("Duplicate or bad @b in use!\n"),
8596           PROMPT_NONE, 0 },
8597
8598         /* Bad block used as bad block indirect block */
8599         { PR_1_BBINODE_BAD_METABLOCK,
8600           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8601           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8602
8603         /* Inconsistency can't be fixed prompt */
8604         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8605           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8606              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8607              "in the @f.\n"),
8608           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8609
8610         /* Bad primary block */
8611         { PR_1_BAD_PRIMARY_BLOCK,
8612           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
8613           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8614
8615         /* Bad primary block prompt */
8616         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8617           N_("You can remove this @b from the bad @b list and hope\n"
8618              "that the @b is really OK.  But there are no guarantees.\n\n"),
8619           PROMPT_CLEAR, PR_PREEN_NOMSG },
8620
8621         /* Bad primary superblock */
8622         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8623           N_("The primary @S (%b) is on the bad @b list.\n"),
8624           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8625
8626         /* Bad primary block group descriptors */
8627         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8628           N_("Block %b in the primary @g descriptors "
8629           "is on the bad @b list\n"),
8630           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8631
8632         /* Bad superblock in group */
8633         { PR_1_BAD_SUPERBLOCK,
8634           N_("Warning: Group %g's @S (%b) is bad.\n"),
8635           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8636
8637         /* Bad block group descriptors in group */
8638         { PR_1_BAD_GROUP_DESCRIPTORS,
8639           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8640           "@b (%b).\n"),
8641           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8642
8643         /* Block claimed for no reason */
8644         { PR_1_PROGERR_CLAIMED_BLOCK,
8645           N_("Programming error?  @b #%b claimed for no reason in "
8646           "process_bad_@b.\n"),
8647           PROMPT_NONE, PR_PREEN_OK },
8648
8649         /* Error allocating blocks for relocating metadata */
8650         { PR_1_RELOC_BLOCK_ALLOCATE,
8651           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8652           PROMPT_NONE, PR_PREEN_OK },
8653
8654         /* Error allocating block buffer during relocation process */
8655         { PR_1_RELOC_MEMORY_ALLOCATE,
8656           N_("@A @b buffer for relocating %s\n"),
8657           PROMPT_NONE, PR_PREEN_OK },
8658
8659         /* Relocating metadata group information from X to Y */
8660         { PR_1_RELOC_FROM_TO,
8661           N_("Relocating @g %g's %s from %b to %c...\n"),
8662           PROMPT_NONE, PR_PREEN_OK },
8663
8664         /* Relocating metatdata group information to X */
8665         { PR_1_RELOC_TO,
8666           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8667           PROMPT_NONE, PR_PREEN_OK },
8668
8669         /* Block read error during relocation process */
8670         { PR_1_RELOC_READ_ERR,
8671           N_("Warning: could not read @b %b of %s: %m\n"),
8672           PROMPT_NONE, PR_PREEN_OK },
8673
8674         /* Block write error during relocation process */
8675         { PR_1_RELOC_WRITE_ERR,
8676           N_("Warning: could not write @b %b for %s: %m\n"),
8677           PROMPT_NONE, PR_PREEN_OK },
8678
8679         /* Error allocating inode bitmap */
8680         { PR_1_ALLOCATE_IBITMAP_ERROR,
8681           N_("@A @i @B (%N): %m\n"),
8682           PROMPT_NONE, PR_FATAL },
8683
8684         /* Error allocating block bitmap */
8685         { PR_1_ALLOCATE_BBITMAP_ERROR,
8686           N_("@A @b @B (%N): %m\n"),
8687           PROMPT_NONE, PR_FATAL },
8688
8689         /* Error allocating icount structure */
8690         { PR_1_ALLOCATE_ICOUNT,
8691           N_("@A icount link information: %m\n"),
8692           PROMPT_NONE, PR_FATAL },
8693
8694         /* Error allocating dbcount */
8695         { PR_1_ALLOCATE_DBCOUNT,
8696           N_("@A @d @b array: %m\n"),
8697           PROMPT_NONE, PR_FATAL },
8698
8699         /* Error while scanning inodes */
8700         { PR_1_ISCAN_ERROR,
8701           N_("Error while scanning @is (%i): %m\n"),
8702           PROMPT_NONE, PR_FATAL },
8703
8704         /* Error while iterating over blocks */
8705         { PR_1_BLOCK_ITERATE,
8706           N_("Error while iterating over @bs in @i %i: %m\n"),
8707           PROMPT_NONE, PR_FATAL },
8708
8709         /* Error while storing inode count information */
8710         { PR_1_ICOUNT_STORE,
8711           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8712           PROMPT_NONE, PR_FATAL },
8713
8714         /* Error while storing directory block information */
8715         { PR_1_ADD_DBLOCK,
8716           N_("Error storing @d @b information "
8717           "(@i=%i, @b=%b, num=%N): %m\n"),
8718           PROMPT_NONE, PR_FATAL },
8719
8720         /* Error while reading inode (for clearing) */
8721         { PR_1_READ_INODE,
8722           N_("Error reading @i %i: %m\n"),
8723           PROMPT_NONE, PR_FATAL },
8724
8725         /* Suppress messages prompt */
8726         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8727
8728         /* Imagic flag set on an inode when filesystem doesn't support it */
8729         { PR_1_SET_IMAGIC,
8730           N_("@i %i has imagic flag set.  "),
8731           PROMPT_CLEAR, 0 },
8732
8733         /* Immutable flag set on a device or socket inode */
8734         { PR_1_SET_IMMUTABLE,
8735           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8736              "or append-only flag set.  "),
8737           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8738
8739         /* Compression flag set on an inode when filesystem doesn't support it */
8740         { PR_1_COMPR_SET,
8741           N_("@i %i has @cion flag set on @f without @cion support.  "),
8742           PROMPT_CLEAR, 0 },
8743
8744         /* Non-zero size for device, fifo or socket inode */
8745         { PR_1_SET_NONZSIZE,
8746           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8747           PROMPT_FIX, PR_PREEN_OK },
8748
8749         /* Filesystem revision is 0, but feature flags are set */
8750         { PR_1_FS_REV_LEVEL,
8751           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8752           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8753
8754         /* Journal inode is not in use, but contains data */
8755         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8756           N_("@j @i is not in use, but contains data.  "),
8757           PROMPT_CLEAR, PR_PREEN_OK },
8758
8759         /* Journal has bad mode */
8760         { PR_1_JOURNAL_BAD_MODE,
8761           N_("@j is not regular file.  "),
8762           PROMPT_FIX, PR_PREEN_OK },
8763
8764         /* Deal with inodes that were part of orphan linked list */
8765         { PR_1_LOW_DTIME,
8766           N_("@i %i was part of the @o @i list.  "),
8767           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8768
8769         /* Deal with inodes that were part of corrupted orphan linked
8770            list (latch question) */
8771         { PR_1_ORPHAN_LIST_REFUGEES,
8772           N_("@is that were part of a corrupted orphan linked list found.  "),
8773           PROMPT_FIX, 0 },
8774
8775         /* Error allocating refcount structure */
8776         { PR_1_ALLOCATE_REFCOUNT,
8777           N_("@A refcount structure (%N): %m\n"),
8778           PROMPT_NONE, PR_FATAL },
8779
8780         /* Error reading extended attribute block */
8781         { PR_1_READ_EA_BLOCK,
8782           N_("Error reading @a @b %b for @i %i.  "),
8783           PROMPT_CLEAR, 0 },
8784
8785         /* Invalid extended attribute block */
8786         { PR_1_BAD_EA_BLOCK,
8787           N_("@i %i has a bad @a @b %b.  "),
8788           PROMPT_CLEAR, 0 },
8789
8790         /* Error reading Extended Attribute block while fixing refcount */
8791         { PR_1_EXTATTR_READ_ABORT,
8792           N_("Error reading @a @b %b (%m).  "),
8793           PROMPT_ABORT, 0 },
8794
8795         /* Extended attribute reference count incorrect */
8796         { PR_1_EXTATTR_REFCOUNT,
8797           N_("@a @b %b has reference count %B, @s %N.  "),
8798           PROMPT_FIX, 0 },
8799
8800         /* Error writing Extended Attribute block while fixing refcount */
8801         { PR_1_EXTATTR_WRITE,
8802           N_("Error writing @a @b %b (%m).  "),
8803           PROMPT_ABORT, 0 },
8804
8805         /* Multiple EA blocks not supported */
8806         { PR_1_EA_MULTI_BLOCK,
8807           N_("@a @b %b has h_@bs > 1.  "),
8808           PROMPT_CLEAR, 0},
8809
8810         /* Error allocating EA region allocation structure */
8811         { PR_1_EA_ALLOC_REGION,
8812           N_("@A @a @b %b.  "),
8813           PROMPT_ABORT, 0},
8814
8815         /* Error EA allocation collision */
8816         { PR_1_EA_ALLOC_COLLISION,
8817           N_("@a @b %b is corrupt (allocation collision).  "),
8818           PROMPT_CLEAR, 0},
8819
8820         /* Bad extended attribute name */
8821         { PR_1_EA_BAD_NAME,
8822           N_("@a @b %b is corrupt (@n name).  "),
8823           PROMPT_CLEAR, 0},
8824
8825         /* Bad extended attribute value */
8826         { PR_1_EA_BAD_VALUE,
8827           N_("@a @b %b is corrupt (@n value).  "),
8828           PROMPT_CLEAR, 0},
8829
8830         /* Inode too big (latch question) */
8831         { PR_1_INODE_TOOBIG,
8832           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8833
8834         /* Directory too big */
8835         { PR_1_TOOBIG_DIR,
8836           N_("@b #%B (%b) causes @d to be too big.  "),
8837           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8838
8839         /* Regular file too big */
8840         { PR_1_TOOBIG_REG,
8841           N_("@b #%B (%b) causes file to be too big.  "),
8842           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8843
8844         /* Symlink too big */
8845         { PR_1_TOOBIG_SYMLINK,
8846           N_("@b #%B (%b) causes symlink to be too big.  "),
8847           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8848
8849         /* INDEX_FL flag set on a non-HTREE filesystem */
8850         { PR_1_HTREE_SET,
8851           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8852           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853
8854         /* INDEX_FL flag set on a non-directory */
8855         { PR_1_HTREE_NODIR,
8856           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8857           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8858
8859         /* Invalid root node in HTREE directory */
8860         { PR_1_HTREE_BADROOT,
8861           N_("@h %i has an @n root node.\n"),
8862           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8863
8864         /* Unsupported hash version in HTREE directory */
8865         { PR_1_HTREE_HASHV,
8866           N_("@h %i has an unsupported hash version (%N)\n"),
8867           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8868
8869         /* Incompatible flag in HTREE root node */
8870         { PR_1_HTREE_INCOMPAT,
8871           N_("@h %i uses an incompatible htree root node flag.\n"),
8872           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8873
8874         /* HTREE too deep */
8875         { PR_1_HTREE_DEPTH,
8876           N_("@h %i has a tree depth (%N) which is too big\n"),
8877           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8878
8879         /* Bad block has indirect block that conflicts with filesystem block */
8880         { PR_1_BB_FS_BLOCK,
8881           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8882              "@f metadata.  "),
8883           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8884
8885         /* Resize inode failed */
8886         { PR_1_RESIZE_INODE_CREATE,
8887           N_("Resize @i (re)creation failed: %m."),
8888           PROMPT_ABORT, 0 },
8889
8890         /* invalid inode->i_extra_isize */
8891         { PR_1_EXTRA_ISIZE,
8892           N_("@i %i has a extra size (%IS) which is @n\n"),
8893           PROMPT_FIX, PR_PREEN_OK },
8894
8895         /* invalid ea entry->e_name_len */
8896         { PR_1_ATTR_NAME_LEN,
8897           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8898           PROMPT_CLEAR, PR_PREEN_OK },
8899
8900         /* invalid ea entry->e_value_size */
8901         { PR_1_ATTR_VALUE_SIZE,
8902           N_("@a in @i %i has a value size (%N) which is @n\n"),
8903           PROMPT_CLEAR, PR_PREEN_OK },
8904
8905         /* invalid ea entry->e_value_offs */
8906         { PR_1_ATTR_VALUE_OFFSET,
8907           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8908           PROMPT_CLEAR, PR_PREEN_OK },
8909
8910         /* invalid ea entry->e_value_block */
8911         { PR_1_ATTR_VALUE_BLOCK,
8912           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8913           PROMPT_CLEAR, PR_PREEN_OK },
8914
8915         /* invalid ea entry->e_hash */
8916         { PR_1_ATTR_HASH,
8917           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8918           PROMPT_CLEAR, PR_PREEN_OK },
8919
8920         /* Pass 1b errors */
8921
8922         /* Pass 1B: Rescan for duplicate/bad blocks */
8923         { PR_1B_PASS_HEADER,
8924           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8925           "Pass 1B: Rescanning for @m @bs\n"),
8926           PROMPT_NONE, 0 },
8927
8928         /* Duplicate/bad block(s) header */
8929         { PR_1B_DUP_BLOCK_HEADER,
8930           N_("@m @b(s) in @i %i:"),
8931           PROMPT_NONE, 0 },
8932
8933         /* Duplicate/bad block(s) in inode */
8934         { PR_1B_DUP_BLOCK,
8935           " %b",
8936           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8937
8938         /* Duplicate/bad block(s) end */
8939         { PR_1B_DUP_BLOCK_END,
8940           "\n",
8941           PROMPT_NONE, PR_PREEN_NOHDR },
8942
8943         /* Error while scanning inodes */
8944         { PR_1B_ISCAN_ERROR,
8945           N_("Error while scanning inodes (%i): %m\n"),
8946           PROMPT_NONE, PR_FATAL },
8947
8948         /* Error allocating inode bitmap */
8949         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8950           N_("@A @i @B (@i_dup_map): %m\n"),
8951           PROMPT_NONE, PR_FATAL },
8952
8953         /* Error while iterating over blocks */
8954         { PR_1B_BLOCK_ITERATE,
8955           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8956           PROMPT_NONE, 0 },
8957
8958         /* Error adjusting EA refcount */
8959         { PR_1B_ADJ_EA_REFCOUNT,
8960           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8961           PROMPT_NONE, 0 },
8962
8963
8964         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8965         { PR_1C_PASS_HEADER,
8966           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8967           PROMPT_NONE, 0 },
8968
8969
8970         /* Pass 1D: Reconciling multiply-claimed blocks */
8971         { PR_1D_PASS_HEADER,
8972           N_("Pass 1D: Reconciling @m @bs\n"),
8973           PROMPT_NONE, 0 },
8974
8975         /* File has duplicate blocks */
8976         { PR_1D_DUP_FILE,
8977           N_("File %Q (@i #%i, mod time %IM) \n"
8978           "  has %B @m @b(s), shared with %N file(s):\n"),
8979           PROMPT_NONE, 0 },
8980
8981         /* List of files sharing duplicate blocks */
8982         { PR_1D_DUP_FILE_LIST,
8983           N_("\t%Q (@i #%i, mod time %IM)\n"),
8984           PROMPT_NONE, 0 },
8985
8986         /* File sharing blocks with filesystem metadata  */
8987         { PR_1D_SHARE_METADATA,
8988           N_("\t<@f metadata>\n"),
8989           PROMPT_NONE, 0 },
8990
8991         /* Report of how many duplicate/bad inodes */
8992         { PR_1D_NUM_DUP_INODES,
8993           N_("(There are %N @is containing @m @bs.)\n\n"),
8994           PROMPT_NONE, 0 },
8995
8996         /* Duplicated blocks already reassigned or cloned. */
8997         { PR_1D_DUP_BLOCKS_DEALT,
8998           N_("@m @bs already reassigned or cloned.\n\n"),
8999           PROMPT_NONE, 0 },
9000
9001         /* Clone duplicate/bad blocks? */
9002         { PR_1D_CLONE_QUESTION,
9003           "", PROMPT_CLONE, PR_NO_OK },
9004
9005         /* Delete file? */
9006         { PR_1D_DELETE_QUESTION,
9007           "", PROMPT_DELETE, 0 },
9008
9009         /* Couldn't clone file (error) */
9010         { PR_1D_CLONE_ERROR,
9011           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
9012
9013         /* Pass 2 errors */
9014
9015         /* Pass 2: Checking directory structure */
9016         { PR_2_PASS_HEADER,
9017           N_("Pass 2: Checking @d structure\n"),
9018           PROMPT_NONE, 0 },
9019
9020         /* Bad inode number for '.' */
9021         { PR_2_BAD_INODE_DOT,
9022           N_("@n @i number for '.' in @d @i %i.\n"),
9023           PROMPT_FIX, 0 },
9024
9025         /* Directory entry has bad inode number */
9026         { PR_2_BAD_INO,
9027           N_("@E has @n @i #: %Di.\n"),
9028           PROMPT_CLEAR, 0 },
9029
9030         /* Directory entry has deleted or unused inode */
9031         { PR_2_UNUSED_INODE,
9032           N_("@E has @D/unused @i %Di.  "),
9033           PROMPT_CLEAR, PR_PREEN_OK },
9034
9035         /* Directry entry is link to '.' */
9036         { PR_2_LINK_DOT,
9037           N_("@E @L to '.'  "),
9038           PROMPT_CLEAR, 0 },
9039
9040         /* Directory entry points to inode now located in a bad block */
9041         { PR_2_BB_INODE,
9042           N_("@E points to @i (%Di) located in a bad @b.\n"),
9043           PROMPT_CLEAR, 0 },
9044
9045         /* Directory entry contains a link to a directory */
9046         { PR_2_LINK_DIR,
9047           N_("@E @L to @d %P (%Di).\n"),
9048           PROMPT_CLEAR, 0 },
9049
9050         /* Directory entry contains a link to the root directry */
9051         { PR_2_LINK_ROOT,
9052           N_("@E @L to the @r.\n"),
9053           PROMPT_CLEAR, 0 },
9054
9055         /* Directory entry has illegal characters in its name */
9056         { PR_2_BAD_NAME,
9057           N_("@E has illegal characters in its name.\n"),
9058           PROMPT_FIX, 0 },
9059
9060         /* Missing '.' in directory inode */
9061         { PR_2_MISSING_DOT,
9062           N_("Missing '.' in @d @i %i.\n"),
9063           PROMPT_FIX, 0 },
9064
9065         /* Missing '..' in directory inode */
9066         { PR_2_MISSING_DOT_DOT,
9067           N_("Missing '..' in @d @i %i.\n"),
9068           PROMPT_FIX, 0 },
9069
9070         /* First entry in directory inode doesn't contain '.' */
9071         { PR_2_1ST_NOT_DOT,
9072           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9073           PROMPT_FIX, 0 },
9074
9075         /* Second entry in directory inode doesn't contain '..' */
9076         { PR_2_2ND_NOT_DOT_DOT,
9077           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9078           PROMPT_FIX, 0 },
9079
9080         /* i_faddr should be zero */
9081         { PR_2_FADDR_ZERO,
9082           N_("i_faddr @F %IF, @s zero.\n"),
9083           PROMPT_CLEAR, 0 },
9084
9085         /* i_file_acl should be zero */
9086         { PR_2_FILE_ACL_ZERO,
9087           N_("i_file_acl @F %If, @s zero.\n"),
9088           PROMPT_CLEAR, 0 },
9089
9090         /* i_dir_acl should be zero */
9091         { PR_2_DIR_ACL_ZERO,
9092           N_("i_dir_acl @F %Id, @s zero.\n"),
9093           PROMPT_CLEAR, 0 },
9094
9095         /* i_frag should be zero */
9096         { PR_2_FRAG_ZERO,
9097           N_("i_frag @F %N, @s zero.\n"),
9098           PROMPT_CLEAR, 0 },
9099
9100         /* i_fsize should be zero */
9101         { PR_2_FSIZE_ZERO,
9102           N_("i_fsize @F %N, @s zero.\n"),
9103           PROMPT_CLEAR, 0 },
9104
9105         /* inode has bad mode */
9106         { PR_2_BAD_MODE,
9107           N_("@i %i (%Q) has @n mode (%Im).\n"),
9108           PROMPT_CLEAR, 0 },
9109
9110         /* directory corrupted */
9111         { PR_2_DIR_CORRUPTED,
9112           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9113           PROMPT_SALVAGE, 0 },
9114
9115         /* filename too long */
9116         { PR_2_FILENAME_LONG,
9117           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9118           PROMPT_TRUNCATE, 0 },
9119
9120         /* Directory inode has a missing block (hole) */
9121         { PR_2_DIRECTORY_HOLE,
9122           N_("@d @i %i has an unallocated @b #%B.  "),
9123           PROMPT_ALLOCATE, 0 },
9124
9125         /* '.' is not NULL terminated */
9126         { PR_2_DOT_NULL_TERM,
9127           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9128           PROMPT_FIX, 0 },
9129
9130         /* '..' is not NULL terminated */
9131         { PR_2_DOT_DOT_NULL_TERM,
9132           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9133           PROMPT_FIX, 0 },
9134
9135         /* Illegal character device inode */
9136         { PR_2_BAD_CHAR_DEV,
9137           N_("@i %i (%Q) is an @I character @v.\n"),
9138           PROMPT_CLEAR, 0 },
9139
9140         /* Illegal block device inode */
9141         { PR_2_BAD_BLOCK_DEV,
9142           N_("@i %i (%Q) is an @I @b @v.\n"),
9143           PROMPT_CLEAR, 0 },
9144
9145         /* Duplicate '.' entry */
9146         { PR_2_DUP_DOT,
9147           N_("@E is duplicate '.' @e.\n"),
9148           PROMPT_FIX, 0 },
9149
9150         /* Duplicate '..' entry */
9151         { PR_2_DUP_DOT_DOT,
9152           N_("@E is duplicate '..' @e.\n"),
9153           PROMPT_FIX, 0 },
9154
9155         /* Internal error: couldn't find dir_info */
9156         { PR_2_NO_DIRINFO,
9157           N_("Internal error: couldn't find dir_info for %i.\n"),
9158           PROMPT_NONE, PR_FATAL },
9159
9160         /* Final rec_len is wrong */
9161         { PR_2_FINAL_RECLEN,
9162           N_("@E has rec_len of %Dr, @s %N.\n"),
9163           PROMPT_FIX, 0 },
9164
9165         /* Error allocating icount structure */
9166         { PR_2_ALLOCATE_ICOUNT,
9167           N_("@A icount structure: %m\n"),
9168           PROMPT_NONE, PR_FATAL },
9169
9170         /* Error iterating over directory blocks */
9171         { PR_2_DBLIST_ITERATE,
9172           N_("Error iterating over @d @bs: %m\n"),
9173           PROMPT_NONE, PR_FATAL },
9174
9175         /* Error reading directory block */
9176         { PR_2_READ_DIRBLOCK,
9177           N_("Error reading @d @b %b (@i %i): %m\n"),
9178           PROMPT_CONTINUE, 0 },
9179
9180         /* Error writing directory block */
9181         { PR_2_WRITE_DIRBLOCK,
9182           N_("Error writing @d @b %b (@i %i): %m\n"),
9183           PROMPT_CONTINUE, 0 },
9184
9185         /* Error allocating new directory block */
9186         { PR_2_ALLOC_DIRBOCK,
9187           N_("@A new @d @b for @i %i (%s): %m\n"),
9188           PROMPT_NONE, 0 },
9189
9190         /* Error deallocating inode */
9191         { PR_2_DEALLOC_INODE,
9192           N_("Error deallocating @i %i: %m\n"),
9193           PROMPT_NONE, PR_FATAL },
9194
9195         /* Directory entry for '.' is big.  Split? */
9196         { PR_2_SPLIT_DOT,
9197           N_("@d @e for '.' is big.  "),
9198           PROMPT_SPLIT, PR_NO_OK },
9199
9200         /* Illegal FIFO inode */
9201         { PR_2_BAD_FIFO,
9202           N_("@i %i (%Q) is an @I FIFO.\n"),
9203           PROMPT_CLEAR, 0 },
9204
9205         /* Illegal socket inode */
9206         { PR_2_BAD_SOCKET,
9207           N_("@i %i (%Q) is an @I socket.\n"),
9208           PROMPT_CLEAR, 0 },
9209
9210         /* Directory filetype not set */
9211         { PR_2_SET_FILETYPE,
9212           N_("Setting filetype for @E to %N.\n"),
9213           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9214
9215         /* Directory filetype incorrect */
9216         { PR_2_BAD_FILETYPE,
9217           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9218           PROMPT_FIX, 0 },
9219
9220         /* Directory filetype set on filesystem */
9221         { PR_2_CLEAR_FILETYPE,
9222           N_("@E has filetype set.\n"),
9223           PROMPT_CLEAR, PR_PREEN_OK },
9224
9225         /* Directory filename is null */
9226         { PR_2_NULL_NAME,
9227           N_("@E has a @z name.\n"),
9228           PROMPT_CLEAR, 0 },
9229
9230         /* Invalid symlink */
9231         { PR_2_INVALID_SYMLINK,
9232           N_("Symlink %Q (@i #%i) is @n.\n"),
9233           PROMPT_CLEAR, 0 },
9234
9235         /* i_file_acl (extended attribute block) is bad */
9236         { PR_2_FILE_ACL_BAD,
9237           N_("@a @b @F @n (%If).\n"),
9238           PROMPT_CLEAR, 0 },
9239
9240         /* Filesystem contains large files, but has no such flag in sb */
9241         { PR_2_FEATURE_LARGE_FILES,
9242           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9243           PROMPT_FIX, 0 },
9244
9245         /* Node in HTREE directory not referenced */
9246         { PR_2_HTREE_NOTREF,
9247           N_("@p @h %d: node (%B) not referenced\n"),
9248           PROMPT_NONE, 0 },
9249
9250         /* Node in HTREE directory referenced twice */
9251         { PR_2_HTREE_DUPREF,
9252           N_("@p @h %d: node (%B) referenced twice\n"),
9253           PROMPT_NONE, 0 },
9254
9255         /* Node in HTREE directory has bad min hash */
9256         { PR_2_HTREE_MIN_HASH,
9257           N_("@p @h %d: node (%B) has bad min hash\n"),
9258           PROMPT_NONE, 0 },
9259
9260         /* Node in HTREE directory has bad max hash */
9261         { PR_2_HTREE_MAX_HASH,
9262           N_("@p @h %d: node (%B) has bad max hash\n"),
9263           PROMPT_NONE, 0 },
9264
9265         /* Clear invalid HTREE directory */
9266         { PR_2_HTREE_CLEAR,
9267           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9268
9269         /* Bad block in htree interior node */
9270         { PR_2_HTREE_BADBLK,
9271           N_("@p @h %d (%q): bad @b number %b.\n"),
9272           PROMPT_CLEAR_HTREE, 0 },
9273
9274         /* Error adjusting EA refcount */
9275         { PR_2_ADJ_EA_REFCOUNT,
9276           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9277           PROMPT_NONE, PR_FATAL },
9278
9279         /* Invalid HTREE root node */
9280         { PR_2_HTREE_BAD_ROOT,
9281           N_("@p @h %d: root node is @n\n"),
9282           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9283
9284         /* Invalid HTREE limit */
9285         { PR_2_HTREE_BAD_LIMIT,
9286           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9287           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9288
9289         /* Invalid HTREE count */
9290         { PR_2_HTREE_BAD_COUNT,
9291           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9292           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9293
9294         /* HTREE interior node has out-of-order hashes in table */
9295         { PR_2_HTREE_HASH_ORDER,
9296           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9297           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9298
9299         /* Node in HTREE directory has invalid depth */
9300         { PR_2_HTREE_BAD_DEPTH,
9301           N_("@p @h %d: node (%B) has @n depth\n"),
9302           PROMPT_NONE, 0 },
9303
9304         /* Duplicate directory entry found */
9305         { PR_2_DUPLICATE_DIRENT,
9306           N_("Duplicate @E found.  "),
9307           PROMPT_CLEAR, 0 },
9308
9309         /* Non-unique filename found */
9310         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9311           N_("@E has a non-unique filename.\nRename to %s"),
9312           PROMPT_NULL, 0 },
9313
9314         /* Duplicate directory entry found */
9315         { PR_2_REPORT_DUP_DIRENT,
9316           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9317           PROMPT_NONE, 0 },
9318
9319         /* Pass 3 errors */
9320
9321         /* Pass 3: Checking directory connectivity */
9322         { PR_3_PASS_HEADER,
9323           N_("Pass 3: Checking @d connectivity\n"),
9324           PROMPT_NONE, 0 },
9325
9326         /* Root inode not allocated */
9327         { PR_3_NO_ROOT_INODE,
9328           N_("@r not allocated.  "),
9329           PROMPT_ALLOCATE, 0 },
9330
9331         /* No room in lost+found */
9332         { PR_3_EXPAND_LF_DIR,
9333           N_("No room in @l @d.  "),
9334           PROMPT_EXPAND, 0 },
9335
9336         /* Unconnected directory inode */
9337         { PR_3_UNCONNECTED_DIR,
9338           N_("Unconnected @d @i %i (%p)\n"),
9339           PROMPT_CONNECT, 0 },
9340
9341         /* /lost+found not found */
9342         { PR_3_NO_LF_DIR,
9343           N_("/@l not found.  "),
9344           PROMPT_CREATE, PR_PREEN_OK },
9345
9346         /* .. entry is incorrect */
9347         { PR_3_BAD_DOT_DOT,
9348           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9349           PROMPT_FIX, 0 },
9350
9351         /* Bad or non-existent /lost+found.  Cannot reconnect */
9352         { PR_3_NO_LPF,
9353           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9354           PROMPT_NONE, 0 },
9355
9356         /* Could not expand /lost+found */
9357         { PR_3_CANT_EXPAND_LPF,
9358           N_("Could not expand /@l: %m\n"),
9359           PROMPT_NONE, 0 },
9360
9361         /* Could not reconnect inode */
9362         { PR_3_CANT_RECONNECT,
9363           N_("Could not reconnect %i: %m\n"),
9364           PROMPT_NONE, 0 },
9365
9366         /* Error while trying to find /lost+found */
9367         { PR_3_ERR_FIND_LPF,
9368           N_("Error while trying to find /@l: %m\n"),
9369           PROMPT_NONE, 0 },
9370
9371         /* Error in ext2fs_new_block while creating /lost+found */
9372         { PR_3_ERR_LPF_NEW_BLOCK,
9373           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9374           PROMPT_NONE, 0 },
9375
9376         /* Error in ext2fs_new_inode while creating /lost+found */
9377         { PR_3_ERR_LPF_NEW_INODE,
9378           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9379           PROMPT_NONE, 0 },
9380
9381         /* Error in ext2fs_new_dir_block while creating /lost+found */
9382         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9383           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9384           PROMPT_NONE, 0 },
9385
9386         /* Error while writing directory block for /lost+found */
9387         { PR_3_ERR_LPF_WRITE_BLOCK,
9388           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9389           PROMPT_NONE, 0 },
9390
9391         /* Error while adjusting inode count */
9392         { PR_3_ADJUST_INODE,
9393           N_("Error while adjusting @i count on @i %i\n"),
9394           PROMPT_NONE, 0 },
9395
9396         /* Couldn't fix parent directory -- error */
9397         { PR_3_FIX_PARENT_ERR,
9398           N_("Couldn't fix parent of @i %i: %m\n\n"),
9399           PROMPT_NONE, 0 },
9400
9401         /* Couldn't fix parent directory -- couldn't find it */
9402         { PR_3_FIX_PARENT_NOFIND,
9403           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9404           PROMPT_NONE, 0 },
9405
9406         /* Error allocating inode bitmap */
9407         { PR_3_ALLOCATE_IBITMAP_ERROR,
9408           N_("@A @i @B (%N): %m\n"),
9409           PROMPT_NONE, PR_FATAL },
9410
9411         /* Error creating root directory */
9412         { PR_3_CREATE_ROOT_ERROR,
9413           N_("Error creating root @d (%s): %m\n"),
9414           PROMPT_NONE, PR_FATAL },
9415
9416         /* Error creating lost and found directory */
9417         { PR_3_CREATE_LPF_ERROR,
9418           N_("Error creating /@l @d (%s): %m\n"),
9419           PROMPT_NONE, PR_FATAL },
9420
9421         /* Root inode is not directory; aborting */
9422         { PR_3_ROOT_NOT_DIR_ABORT,
9423           N_("@r is not a @d; aborting.\n"),
9424           PROMPT_NONE, PR_FATAL },
9425
9426         /* Cannot proceed without a root inode. */
9427         { PR_3_NO_ROOT_INODE_ABORT,
9428           N_("Cannot proceed without a @r.\n"),
9429           PROMPT_NONE, PR_FATAL },
9430
9431         /* Internal error: couldn't find dir_info */
9432         { PR_3_NO_DIRINFO,
9433           N_("Internal error: couldn't find dir_info for %i.\n"),
9434           PROMPT_NONE, PR_FATAL },
9435
9436         /* Lost+found not a directory */
9437         { PR_3_LPF_NOTDIR,
9438           N_("/@l is not a @d (ino=%i)\n"),
9439           PROMPT_UNLINK, 0 },
9440
9441         /* Pass 3A Directory Optimization       */
9442
9443         /* Pass 3A: Optimizing directories */
9444         { PR_3A_PASS_HEADER,
9445           N_("Pass 3A: Optimizing directories\n"),
9446           PROMPT_NONE, PR_PREEN_NOMSG },
9447
9448         /* Error iterating over directories */
9449         { PR_3A_OPTIMIZE_ITER,
9450           N_("Failed to create dirs_to_hash iterator: %m"),
9451           PROMPT_NONE, 0 },
9452
9453         /* Error rehash directory */
9454         { PR_3A_OPTIMIZE_DIR_ERR,
9455           N_("Failed to optimize directory %q (%d): %m"),
9456           PROMPT_NONE, 0 },
9457
9458         /* Rehashing dir header */
9459         { PR_3A_OPTIMIZE_DIR_HEADER,
9460           N_("Optimizing directories: "),
9461           PROMPT_NONE, PR_MSG_ONLY },
9462
9463         /* Rehashing directory %d */
9464         { PR_3A_OPTIMIZE_DIR,
9465           " %d",
9466           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9467
9468         /* Rehashing dir end */
9469         { PR_3A_OPTIMIZE_DIR_END,
9470           "\n",
9471           PROMPT_NONE, PR_PREEN_NOHDR },
9472
9473         /* Pass 4 errors */
9474
9475         /* Pass 4: Checking reference counts */
9476         { PR_4_PASS_HEADER,
9477           N_("Pass 4: Checking reference counts\n"),
9478           PROMPT_NONE, 0 },
9479
9480         /* Unattached zero-length inode */
9481         { PR_4_ZERO_LEN_INODE,
9482           N_("@u @z @i %i.  "),
9483           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9484
9485         /* Unattached inode */
9486         { PR_4_UNATTACHED_INODE,
9487           N_("@u @i %i\n"),
9488           PROMPT_CONNECT, 0 },
9489
9490         /* Inode ref count wrong */
9491         { PR_4_BAD_REF_COUNT,
9492           N_("@i %i ref count is %Il, @s %N.  "),
9493           PROMPT_FIX, PR_PREEN_OK },
9494
9495         { PR_4_INCONSISTENT_COUNT,
9496           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9497           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9498           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9499           "They @s the same!\n"),
9500           PROMPT_NONE, 0 },
9501
9502         /* Pass 5 errors */
9503
9504         /* Pass 5: Checking group summary information */
9505         { PR_5_PASS_HEADER,
9506           N_("Pass 5: Checking @g summary information\n"),
9507           PROMPT_NONE, 0 },
9508
9509         /* Padding at end of inode bitmap is not set. */
9510         { PR_5_INODE_BMAP_PADDING,
9511           N_("Padding at end of @i @B is not set. "),
9512           PROMPT_FIX, PR_PREEN_OK },
9513
9514         /* Padding at end of block bitmap is not set. */
9515         { PR_5_BLOCK_BMAP_PADDING,
9516           N_("Padding at end of @b @B is not set. "),
9517           PROMPT_FIX, PR_PREEN_OK },
9518
9519         /* Block bitmap differences header */
9520         { PR_5_BLOCK_BITMAP_HEADER,
9521           N_("@b @B differences: "),
9522           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9523
9524         /* Block not used, but marked in bitmap */
9525         { PR_5_BLOCK_UNUSED,
9526           " -%b",
9527           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528
9529         /* Block used, but not marked used in bitmap */
9530         { PR_5_BLOCK_USED,
9531           " +%b",
9532           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9533
9534         /* Block bitmap differences end */
9535         { PR_5_BLOCK_BITMAP_END,
9536           "\n",
9537           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538
9539         /* Inode bitmap differences header */
9540         { PR_5_INODE_BITMAP_HEADER,
9541           N_("@i @B differences: "),
9542           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9543
9544         /* Inode not used, but marked in bitmap */
9545         { PR_5_INODE_UNUSED,
9546           " -%i",
9547           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9548
9549         /* Inode used, but not marked used in bitmap */
9550         { PR_5_INODE_USED,
9551           " +%i",
9552           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9553
9554         /* Inode bitmap differences end */
9555         { PR_5_INODE_BITMAP_END,
9556           "\n",
9557           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558
9559         /* Free inodes count for group wrong */
9560         { PR_5_FREE_INODE_COUNT_GROUP,
9561           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9562           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9563
9564         /* Directories count for group wrong */
9565         { PR_5_FREE_DIR_COUNT_GROUP,
9566           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9567           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9568
9569         /* Free inodes count wrong */
9570         { PR_5_FREE_INODE_COUNT,
9571           N_("Free @is count wrong (%i, counted=%j).\n"),
9572           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9573
9574         /* Free blocks count for group wrong */
9575         { PR_5_FREE_BLOCK_COUNT_GROUP,
9576           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9577           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9578
9579         /* Free blocks count wrong */
9580         { PR_5_FREE_BLOCK_COUNT,
9581           N_("Free @bs count wrong (%b, counted=%c).\n"),
9582           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9583
9584         /* Programming error: bitmap endpoints don't match */
9585         { PR_5_BMAP_ENDPOINTS,
9586           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9587           "match calculated @B endpoints (%i, %j)\n"),
9588           PROMPT_NONE, PR_FATAL },
9589
9590         /* Internal error: fudging end of bitmap */
9591         { PR_5_FUDGE_BITMAP_ERROR,
9592           N_("Internal error: fudging end of bitmap (%N)\n"),
9593           PROMPT_NONE, PR_FATAL },
9594
9595         /* Error copying in replacement inode bitmap */
9596         { PR_5_COPY_IBITMAP_ERROR,
9597           N_("Error copying in replacement @i @B: %m\n"),
9598           PROMPT_NONE, PR_FATAL },
9599
9600         /* Error copying in replacement block bitmap */
9601         { PR_5_COPY_BBITMAP_ERROR,
9602           N_("Error copying in replacement @b @B: %m\n"),
9603           PROMPT_NONE, PR_FATAL },
9604
9605         /* Block range not used, but marked in bitmap */
9606         { PR_5_BLOCK_RANGE_UNUSED,
9607           " -(%b--%c)",
9608           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9609
9610         /* Block range used, but not marked used in bitmap */
9611         { PR_5_BLOCK_RANGE_USED,
9612           " +(%b--%c)",
9613           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9614
9615         /* Inode range not used, but marked in bitmap */
9616         { PR_5_INODE_RANGE_UNUSED,
9617           " -(%i--%j)",
9618           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9619
9620         /* Inode range used, but not marked used in bitmap */
9621         { PR_5_INODE_RANGE_USED,
9622           " +(%i--%j)",
9623           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9624
9625         { 0 }
9626 };
9627
9628 /*
9629  * This is the latch flags register.  It allows several problems to be
9630  * "latched" together.  This means that the user has to answer but one
9631  * question for the set of problems, and all of the associated
9632  * problems will be either fixed or not fixed.
9633  */
9634 static struct latch_descr pr_latch_info[] = {
9635         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9636         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9637         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9638         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9639         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9640         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9641         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9642         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9643         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9644         { -1, 0, 0 },
9645 };
9646
9647 static const struct e2fsck_problem *find_problem(problem_t code)
9648 {
9649         int     i;
9650
9651         for (i=0; problem_table[i].e2p_code; i++) {
9652                 if (problem_table[i].e2p_code == code)
9653                         return &problem_table[i];
9654         }
9655         return 0;
9656 }
9657
9658 static struct latch_descr *find_latch(int code)
9659 {
9660         int     i;
9661
9662         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9663                 if (pr_latch_info[i].latch_code == code)
9664                         return &pr_latch_info[i];
9665         }
9666         return 0;
9667 }
9668
9669 int end_problem_latch(e2fsck_t ctx, int mask)
9670 {
9671         struct latch_descr *ldesc;
9672         struct problem_context pctx;
9673         int answer = -1;
9674
9675         ldesc = find_latch(mask);
9676         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9677                 clear_problem_context(&pctx);
9678                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9679         }
9680         ldesc->flags &= ~(PRL_VARIABLE);
9681         return answer;
9682 }
9683
9684 int set_latch_flags(int mask, int setflags, int clearflags)
9685 {
9686         struct latch_descr *ldesc;
9687
9688         ldesc = find_latch(mask);
9689         if (!ldesc)
9690                 return -1;
9691         ldesc->flags |= setflags;
9692         ldesc->flags &= ~clearflags;
9693         return 0;
9694 }
9695
9696 void clear_problem_context(struct problem_context *ctx)
9697 {
9698         memset(ctx, 0, sizeof(struct problem_context));
9699         ctx->blkcount = -1;
9700         ctx->group = -1;
9701 }
9702
9703 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9704 {
9705         ext2_filsys fs = ctx->fs;
9706         const struct e2fsck_problem *ptr;
9707         struct latch_descr *ldesc = 0;
9708         const char *message;
9709         int             def_yn, answer, ans;
9710         int             print_answer = 0;
9711         int             suppress = 0;
9712
9713         ptr = find_problem(code);
9714         if (!ptr) {
9715                 printf(_("Unhandled error code (0x%x)!\n"), code);
9716                 return 0;
9717         }
9718         def_yn = 1;
9719         if ((ptr->flags & PR_NO_DEFAULT) ||
9720             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9721             (ctx->options & E2F_OPT_NO))
9722                 def_yn= 0;
9723
9724         /*
9725          * Do special latch processing.  This is where we ask the
9726          * latch question, if it exists
9727          */
9728         if (ptr->flags & PR_LATCH_MASK) {
9729                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9730                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9731                         ans = fix_problem(ctx, ldesc->question, pctx);
9732                         if (ans == 1)
9733                                 ldesc->flags |= PRL_YES;
9734                         if (ans == 0)
9735                                 ldesc->flags |= PRL_NO;
9736                         ldesc->flags |= PRL_LATCHED;
9737                 }
9738                 if (ldesc->flags & PRL_SUPPRESS)
9739                         suppress++;
9740         }
9741         if ((ptr->flags & PR_PREEN_NOMSG) &&
9742             (ctx->options & E2F_OPT_PREEN))
9743                 suppress++;
9744         if ((ptr->flags & PR_NO_NOMSG) &&
9745             (ctx->options & E2F_OPT_NO))
9746                 suppress++;
9747         if (!suppress) {
9748                 message = ptr->e2p_description;
9749                 if ((ctx->options & E2F_OPT_PREEN) &&
9750                     !(ptr->flags & PR_PREEN_NOHDR)) {
9751                         printf("%s: ", ctx->device_name ?
9752                                ctx->device_name : ctx->filesystem_name);
9753                 }
9754                 if (*message)
9755                         print_e2fsck_message(ctx, _(message), pctx, 1);
9756         }
9757         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9758                 preenhalt(ctx);
9759
9760         if (ptr->flags & PR_FATAL)
9761                 bb_error_msg_and_die(0);
9762
9763         if (ptr->prompt == PROMPT_NONE) {
9764                 if (ptr->flags & PR_NOCOLLATE)
9765                         answer = -1;
9766                 else
9767                         answer = def_yn;
9768         } else {
9769                 if (ctx->options & E2F_OPT_PREEN) {
9770                         answer = def_yn;
9771                         if (!(ptr->flags & PR_PREEN_NOMSG))
9772                                 print_answer = 1;
9773                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9774                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9775                         if (!suppress)
9776                                 print_answer = 1;
9777                         if (ldesc->flags & PRL_YES)
9778                                 answer = 1;
9779                         else
9780                                 answer = 0;
9781                 } else
9782                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9783                 if (!answer && !(ptr->flags & PR_NO_OK))
9784                         ext2fs_unmark_valid(fs);
9785
9786                 if (print_answer)
9787                         printf("%s.\n", answer ?
9788                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9789
9790         }
9791
9792         if ((ptr->prompt == PROMPT_ABORT) && answer)
9793                 bb_error_msg_and_die(0);
9794
9795         if (ptr->flags & PR_AFTER_CODE)
9796                 answer = fix_problem(ctx, ptr->second_code, pctx);
9797
9798         return answer;
9799 }
9800
9801 /*
9802  * linux/fs/recovery.c
9803  *
9804  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9805  */
9806
9807 /*
9808  * Maintain information about the progress of the recovery job, so that
9809  * the different passes can carry information between them.
9810  */
9811 struct recovery_info
9812 {
9813         tid_t           start_transaction;
9814         tid_t           end_transaction;
9815
9816         int             nr_replays;
9817         int             nr_revokes;
9818         int             nr_revoke_hits;
9819 };
9820
9821 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9822 static int do_one_pass(journal_t *journal,
9823                                 struct recovery_info *info, enum passtype pass);
9824 static int scan_revoke_records(journal_t *, struct buffer_head *,
9825                                 tid_t, struct recovery_info *);
9826
9827 /*
9828  * Read a block from the journal
9829  */
9830
9831 static int jread(struct buffer_head **bhp, journal_t *journal,
9832                  unsigned int offset)
9833 {
9834         int err;
9835         unsigned long blocknr;
9836         struct buffer_head *bh;
9837
9838         *bhp = NULL;
9839
9840         err = journal_bmap(journal, offset, &blocknr);
9841
9842         if (err) {
9843                 printf ("JBD: bad block at offset %u\n", offset);
9844                 return err;
9845         }
9846
9847         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9848         if (!bh)
9849                 return -ENOMEM;
9850
9851         if (!buffer_uptodate(bh)) {
9852                 /* If this is a brand new buffer, start readahead.
9853                    Otherwise, we assume we are already reading it.  */
9854                 if (!buffer_req(bh))
9855                         do_readahead(journal, offset);
9856                 wait_on_buffer(bh);
9857         }
9858
9859         if (!buffer_uptodate(bh)) {
9860                 printf ("JBD: Failed to read block at offset %u\n", offset);
9861                 brelse(bh);
9862                 return -EIO;
9863         }
9864
9865         *bhp = bh;
9866         return 0;
9867 }
9868
9869
9870 /*
9871  * Count the number of in-use tags in a journal descriptor block.
9872  */
9873
9874 static int count_tags(struct buffer_head *bh, int size)
9875 {
9876         char *                  tagp;
9877         journal_block_tag_t *   tag;
9878         int                     nr = 0;
9879
9880         tagp = &bh->b_data[sizeof(journal_header_t)];
9881
9882         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9883                 tag = (journal_block_tag_t *) tagp;
9884
9885                 nr++;
9886                 tagp += sizeof(journal_block_tag_t);
9887                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9888                         tagp += 16;
9889
9890                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9891                         break;
9892         }
9893
9894         return nr;
9895 }
9896
9897
9898 /* Make sure we wrap around the log correctly! */
9899 #define wrap(journal, var)                                            \
9900 do {                                                                \
9901         if (var >= (journal)->j_last)                                   \
9902                 var -= ((journal)->j_last - (journal)->j_first);        \
9903 } while (0)
9904
9905 /**
9906  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9907  * @journal: the journal to recover
9908  *
9909  * The primary function for recovering the log contents when mounting a
9910  * journaled device.
9911  *
9912  * Recovery is done in three passes.  In the first pass, we look for the
9913  * end of the log.  In the second, we assemble the list of revoke
9914  * blocks.  In the third and final pass, we replay any un-revoked blocks
9915  * in the log.
9916  */
9917 int journal_recover(journal_t *journal)
9918 {
9919         int                     err;
9920         journal_superblock_t *  sb;
9921
9922         struct recovery_info    info;
9923
9924         memset(&info, 0, sizeof(info));
9925         sb = journal->j_superblock;
9926
9927         /*
9928          * The journal superblock's s_start field (the current log head)
9929          * is always zero if, and only if, the journal was cleanly
9930          * unmounted.
9931          */
9932
9933         if (!sb->s_start) {
9934                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9935                 return 0;
9936         }
9937
9938         err = do_one_pass(journal, &info, PASS_SCAN);
9939         if (!err)
9940                 err = do_one_pass(journal, &info, PASS_REVOKE);
9941         if (!err)
9942                 err = do_one_pass(journal, &info, PASS_REPLAY);
9943
9944         /* Restart the log at the next transaction ID, thus invalidating
9945          * any existing commit records in the log. */
9946         journal->j_transaction_sequence = ++info.end_transaction;
9947
9948         journal_clear_revoke(journal);
9949         sync_blockdev(journal->j_fs_dev);
9950         return err;
9951 }
9952
9953 static int do_one_pass(journal_t *journal,
9954                         struct recovery_info *info, enum passtype pass)
9955 {
9956         unsigned int            first_commit_ID, next_commit_ID;
9957         unsigned long           next_log_block;
9958         int                     err, success = 0;
9959         journal_superblock_t *  sb;
9960         journal_header_t *      tmp;
9961         struct buffer_head *    bh;
9962         unsigned int            sequence;
9963         int                     blocktype;
9964
9965         /* Precompute the maximum metadata descriptors in a descriptor block */
9966         int                     MAX_BLOCKS_PER_DESC;
9967         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9968                                / sizeof(journal_block_tag_t));
9969
9970         /*
9971          * First thing is to establish what we expect to find in the log
9972          * (in terms of transaction IDs), and where (in terms of log
9973          * block offsets): query the superblock.
9974          */
9975
9976         sb = journal->j_superblock;
9977         next_commit_ID = ntohl(sb->s_sequence);
9978         next_log_block = ntohl(sb->s_start);
9979
9980         first_commit_ID = next_commit_ID;
9981         if (pass == PASS_SCAN)
9982                 info->start_transaction = first_commit_ID;
9983
9984         /*
9985          * Now we walk through the log, transaction by transaction,
9986          * making sure that each transaction has a commit block in the
9987          * expected place.  Each complete transaction gets replayed back
9988          * into the main filesystem.
9989          */
9990
9991         while (1) {
9992                 int                     flags;
9993                 char *                  tagp;
9994                 journal_block_tag_t *   tag;
9995                 struct buffer_head *    obh;
9996                 struct buffer_head *    nbh;
9997
9998                 /* If we already know where to stop the log traversal,
9999                  * check right now that we haven't gone past the end of
10000                  * the log. */
10001
10002                 if (pass != PASS_SCAN)
10003                         if (tid_geq(next_commit_ID, info->end_transaction))
10004                                 break;
10005
10006                 /* Skip over each chunk of the transaction looking
10007                  * either the next descriptor block or the final commit
10008                  * record. */
10009
10010                 err = jread(&bh, journal, next_log_block);
10011                 if (err)
10012                         goto failed;
10013
10014                 next_log_block++;
10015                 wrap(journal, next_log_block);
10016
10017                 /* What kind of buffer is it?
10018                  *
10019                  * If it is a descriptor block, check that it has the
10020                  * expected sequence number.  Otherwise, we're all done
10021                  * here. */
10022
10023                 tmp = (journal_header_t *)bh->b_data;
10024
10025                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10026                         brelse(bh);
10027                         break;
10028                 }
10029
10030                 blocktype = ntohl(tmp->h_blocktype);
10031                 sequence = ntohl(tmp->h_sequence);
10032
10033                 if (sequence != next_commit_ID) {
10034                         brelse(bh);
10035                         break;
10036                 }
10037
10038                 /* OK, we have a valid descriptor block which matches
10039                  * all of the sequence number checks.  What are we going
10040                  * to do with it?  That depends on the pass... */
10041
10042                 switch(blocktype) {
10043                 case JFS_DESCRIPTOR_BLOCK:
10044                         /* If it is a valid descriptor block, replay it
10045                          * in pass REPLAY; otherwise, just skip over the
10046                          * blocks it describes. */
10047                         if (pass != PASS_REPLAY) {
10048                                 next_log_block +=
10049                                         count_tags(bh, journal->j_blocksize);
10050                                 wrap(journal, next_log_block);
10051                                 brelse(bh);
10052                                 continue;
10053                         }
10054
10055                         /* A descriptor block: we can now write all of
10056                          * the data blocks.  Yay, useful work is finally
10057                          * getting done here! */
10058
10059                         tagp = &bh->b_data[sizeof(journal_header_t)];
10060                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10061                                <= journal->j_blocksize) {
10062                                 unsigned long io_block;
10063
10064                                 tag = (journal_block_tag_t *) tagp;
10065                                 flags = ntohl(tag->t_flags);
10066
10067                                 io_block = next_log_block++;
10068                                 wrap(journal, next_log_block);
10069                                 err = jread(&obh, journal, io_block);
10070                                 if (err) {
10071                                         /* Recover what we can, but
10072                                          * report failure at the end. */
10073                                         success = err;
10074                                         printf ("JBD: IO error %d recovering "
10075                                                 "block %ld in log\n",
10076                                                 err, io_block);
10077                                 } else {
10078                                         unsigned long blocknr;
10079
10080                                         blocknr = ntohl(tag->t_blocknr);
10081
10082                                         /* If the block has been
10083                                          * revoked, then we're all done
10084                                          * here. */
10085                                         if (journal_test_revoke
10086                                             (journal, blocknr,
10087                                              next_commit_ID)) {
10088                                                 brelse(obh);
10089                                                 ++info->nr_revoke_hits;
10090                                                 goto skip_write;
10091                                         }
10092
10093                                         /* Find a buffer for the new
10094                                          * data being restored */
10095                                         nbh = getblk(journal->j_fs_dev,
10096                                                        blocknr,
10097                                                      journal->j_blocksize);
10098                                         if (nbh == NULL) {
10099                                                 printf ("JBD: Out of memory "
10100                                                        "during recovery.\n");
10101                                                 err = -ENOMEM;
10102                                                 brelse(bh);
10103                                                 brelse(obh);
10104                                                 goto failed;
10105                                         }
10106
10107                                         lock_buffer(nbh);
10108                                         memcpy(nbh->b_data, obh->b_data,
10109                                                         journal->j_blocksize);
10110                                         if (flags & JFS_FLAG_ESCAPE) {
10111                                                 *((unsigned int *)bh->b_data) =
10112                                                         htonl(JFS_MAGIC_NUMBER);
10113                                         }
10114
10115                                         mark_buffer_uptodate(nbh, 1);
10116                                         mark_buffer_dirty(nbh);
10117                                         ++info->nr_replays;
10118                                         /* ll_rw_block(WRITE, 1, &nbh); */
10119                                         unlock_buffer(nbh);
10120                                         brelse(obh);
10121                                         brelse(nbh);
10122                                 }
10123
10124                         skip_write:
10125                                 tagp += sizeof(journal_block_tag_t);
10126                                 if (!(flags & JFS_FLAG_SAME_UUID))
10127                                         tagp += 16;
10128
10129                                 if (flags & JFS_FLAG_LAST_TAG)
10130                                         break;
10131                         }
10132
10133                         brelse(bh);
10134                         continue;
10135
10136                 case JFS_COMMIT_BLOCK:
10137                         /* Found an expected commit block: not much to
10138                          * do other than move on to the next sequence
10139                          * number. */
10140                         brelse(bh);
10141                         next_commit_ID++;
10142                         continue;
10143
10144                 case JFS_REVOKE_BLOCK:
10145                         /* If we aren't in the REVOKE pass, then we can
10146                          * just skip over this block. */
10147                         if (pass != PASS_REVOKE) {
10148                                 brelse(bh);
10149                                 continue;
10150                         }
10151
10152                         err = scan_revoke_records(journal, bh,
10153                                                   next_commit_ID, info);
10154                         brelse(bh);
10155                         if (err)
10156                                 goto failed;
10157                         continue;
10158
10159                 default:
10160                         goto done;
10161                 }
10162         }
10163
10164  done:
10165         /*
10166          * We broke out of the log scan loop: either we came to the
10167          * known end of the log or we found an unexpected block in the
10168          * log.  If the latter happened, then we know that the "current"
10169          * transaction marks the end of the valid log.
10170          */
10171
10172         if (pass == PASS_SCAN)
10173                 info->end_transaction = next_commit_ID;
10174         else {
10175                 /* It's really bad news if different passes end up at
10176                  * different places (but possible due to IO errors). */
10177                 if (info->end_transaction != next_commit_ID) {
10178                         printf ("JBD: recovery pass %d ended at "
10179                                 "transaction %u, expected %u\n",
10180                                 pass, next_commit_ID, info->end_transaction);
10181                         if (!success)
10182                                 success = -EIO;
10183                 }
10184         }
10185
10186         return success;
10187
10188  failed:
10189         return err;
10190 }
10191
10192
10193 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10194
10195 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10196                                tid_t sequence, struct recovery_info *info)
10197 {
10198         journal_revoke_header_t *header;
10199         int offset, max;
10200
10201         header = (journal_revoke_header_t *) bh->b_data;
10202         offset = sizeof(journal_revoke_header_t);
10203         max = ntohl(header->r_count);
10204
10205         while (offset < max) {
10206                 unsigned long blocknr;
10207                 int err;
10208
10209                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10210                 offset += 4;
10211                 err = journal_set_revoke(journal, blocknr, sequence);
10212                 if (err)
10213                         return err;
10214                 ++info->nr_revokes;
10215         }
10216         return 0;
10217 }
10218
10219
10220 /*
10221  * rehash.c --- rebuild hash tree directories
10222  *
10223  * This algorithm is designed for simplicity of implementation and to
10224  * pack the directory as much as possible.  It however requires twice
10225  * as much memory as the size of the directory.  The maximum size
10226  * directory supported using a 4k blocksize is roughly a gigabyte, and
10227  * so there may very well be problems with machines that don't have
10228  * virtual memory, and obscenely large directories.
10229  *
10230  * An alternate algorithm which is much more disk intensive could be
10231  * written, and probably will need to be written in the future.  The
10232  * design goals of such an algorithm are: (a) use (roughly) constant
10233  * amounts of memory, no matter how large the directory, (b) the
10234  * directory must be safe at all times, even if e2fsck is interrupted
10235  * in the middle, (c) we must use minimal amounts of extra disk
10236  * blocks.  This pretty much requires an incremental approach, where
10237  * we are reading from one part of the directory, and inserting into
10238  * the front half.  So the algorithm will have to keep track of a
10239  * moving block boundary between the new tree and the old tree, and
10240  * files will need to be moved from the old directory and inserted
10241  * into the new tree.  If the new directory requires space which isn't
10242  * yet available, blocks from the beginning part of the old directory
10243  * may need to be moved to the end of the directory to make room for
10244  * the new tree:
10245  *
10246  *    --------------------------------------------------------
10247  *    |  new tree   |        | old tree                      |
10248  *    --------------------------------------------------------
10249  *                  ^ ptr    ^ptr
10250  *                tail new   head old
10251  *
10252  * This is going to be a pain in the tuckus to implement, and will
10253  * require a lot more disk accesses.  So I'm going to skip it for now;
10254  * it's only really going to be an issue for really, really big
10255  * filesystems (when we reach the level of tens of millions of files
10256  * in a single directory).  It will probably be easier to simply
10257  * require that e2fsck use VM first.
10258  */
10259
10260 struct fill_dir_struct {
10261         char *buf;
10262         struct ext2_inode *inode;
10263         int err;
10264         e2fsck_t ctx;
10265         struct hash_entry *harray;
10266         int max_array, num_array;
10267         int dir_size;
10268         int compress;
10269         ino_t parent;
10270 };
10271
10272 struct hash_entry {
10273         ext2_dirhash_t  hash;
10274         ext2_dirhash_t  minor_hash;
10275         struct ext2_dir_entry   *dir;
10276 };
10277
10278 struct out_dir {
10279         int             num;
10280         int             max;
10281         char            *buf;
10282         ext2_dirhash_t  *hashes;
10283 };
10284
10285 static int fill_dir_block(ext2_filsys fs,
10286                           blk_t *block_nr,
10287                           e2_blkcnt_t blockcnt,
10288                           blk_t ref_block FSCK_ATTR((unused)),
10289                           int ref_offset FSCK_ATTR((unused)),
10290                           void *priv_data)
10291 {
10292         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10293         struct hash_entry       *new_array, *ent;
10294         struct ext2_dir_entry   *dirent;
10295         char                    *dir;
10296         unsigned int            offset, dir_offset;
10297
10298         if (blockcnt < 0)
10299                 return 0;
10300
10301         offset = blockcnt * fs->blocksize;
10302         if (offset + fs->blocksize > fd->inode->i_size) {
10303                 fd->err = EXT2_ET_DIR_CORRUPTED;
10304                 return BLOCK_ABORT;
10305         }
10306         dir = (fd->buf+offset);
10307         if (HOLE_BLKADDR(*block_nr)) {
10308                 memset(dir, 0, fs->blocksize);
10309                 dirent = (struct ext2_dir_entry *) dir;
10310                 dirent->rec_len = fs->blocksize;
10311         } else {
10312                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10313                 if (fd->err)
10314                         return BLOCK_ABORT;
10315         }
10316         /* While the directory block is "hot", index it. */
10317         dir_offset = 0;
10318         while (dir_offset < fs->blocksize) {
10319                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10320                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10321                     (dirent->rec_len < 8) ||
10322                     ((dirent->rec_len % 4) != 0) ||
10323                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10324                         fd->err = EXT2_ET_DIR_CORRUPTED;
10325                         return BLOCK_ABORT;
10326                 }
10327                 dir_offset += dirent->rec_len;
10328                 if (dirent->inode == 0)
10329                         continue;
10330                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10331                     (dirent->name[0] == '.'))
10332                         continue;
10333                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10334                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10335                         fd->parent = dirent->inode;
10336                         continue;
10337                 }
10338                 if (fd->num_array >= fd->max_array) {
10339                         new_array = realloc(fd->harray,
10340                             sizeof(struct hash_entry) * (fd->max_array+500));
10341                         if (!new_array) {
10342                                 fd->err = ENOMEM;
10343                                 return BLOCK_ABORT;
10344                         }
10345                         fd->harray = new_array;
10346                         fd->max_array += 500;
10347                 }
10348                 ent = fd->harray + fd->num_array++;
10349                 ent->dir = dirent;
10350                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10351                 if (fd->compress)
10352                         ent->hash = ent->minor_hash = 0;
10353                 else {
10354                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10355                                                  dirent->name,
10356                                                  dirent->name_len & 0xFF,
10357                                                  fs->super->s_hash_seed,
10358                                                  &ent->hash, &ent->minor_hash);
10359                         if (fd->err)
10360                                 return BLOCK_ABORT;
10361                 }
10362         }
10363
10364         return 0;
10365 }
10366
10367 /* Used for sorting the hash entry */
10368 static int name_cmp(const void *a, const void *b)
10369 {
10370         const struct hash_entry *he_a = (const struct hash_entry *) a;
10371         const struct hash_entry *he_b = (const struct hash_entry *) b;
10372         int     ret;
10373         int     min_len;
10374
10375         min_len = he_a->dir->name_len;
10376         if (min_len > he_b->dir->name_len)
10377                 min_len = he_b->dir->name_len;
10378
10379         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10380         if (ret == 0) {
10381                 if (he_a->dir->name_len > he_b->dir->name_len)
10382                         ret = 1;
10383                 else if (he_a->dir->name_len < he_b->dir->name_len)
10384                         ret = -1;
10385                 else
10386                         ret = he_b->dir->inode - he_a->dir->inode;
10387         }
10388         return ret;
10389 }
10390
10391 /* Used for sorting the hash entry */
10392 static int hash_cmp(const void *a, const void *b)
10393 {
10394         const struct hash_entry *he_a = (const struct hash_entry *) a;
10395         const struct hash_entry *he_b = (const struct hash_entry *) b;
10396         int     ret;
10397
10398         if (he_a->hash > he_b->hash)
10399                 ret = 1;
10400         else if (he_a->hash < he_b->hash)
10401                 ret = -1;
10402         else {
10403                 if (he_a->minor_hash > he_b->minor_hash)
10404                         ret = 1;
10405                 else if (he_a->minor_hash < he_b->minor_hash)
10406                         ret = -1;
10407                 else
10408                         ret = name_cmp(a, b);
10409         }
10410         return ret;
10411 }
10412
10413 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10414                                 int blocks)
10415 {
10416         void                    *new_mem;
10417
10418         if (outdir->max) {
10419                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
10420                 if (!new_mem)
10421                         return ENOMEM;
10422                 outdir->buf = new_mem;
10423                 new_mem = realloc(outdir->hashes,
10424                                   blocks * sizeof(ext2_dirhash_t));
10425                 if (!new_mem)
10426                         return ENOMEM;
10427                 outdir->hashes = new_mem;
10428         } else {
10429                 outdir->buf = malloc(blocks * fs->blocksize);
10430                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
10431                 outdir->num = 0;
10432         }
10433         outdir->max = blocks;
10434         return 0;
10435 }
10436
10437 static void free_out_dir(struct out_dir *outdir)
10438 {
10439         free(outdir->buf);
10440         free(outdir->hashes);
10441         outdir->max = 0;
10442         outdir->num =0;
10443 }
10444
10445 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10446                          char ** ret)
10447 {
10448         errcode_t       retval;
10449
10450         if (outdir->num >= outdir->max) {
10451                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10452                 if (retval)
10453                         return retval;
10454         }
10455         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10456         memset(*ret, 0, fs->blocksize);
10457         return 0;
10458 }
10459
10460 /*
10461  * This function is used to make a unique filename.  We do this by
10462  * appending ~0, and then incrementing the number.  However, we cannot
10463  * expand the length of the filename beyond the padding available in
10464  * the directory entry.
10465  */
10466 static void mutate_name(char *str, __u16 *len)
10467 {
10468         int     i;
10469         __u16   l = *len & 0xFF, h = *len & 0xff00;
10470
10471         /*
10472          * First check to see if it looks the name has been mutated
10473          * already
10474          */
10475         for (i = l-1; i > 0; i--) {
10476                 if (!isdigit(str[i]))
10477                         break;
10478         }
10479         if ((i == l-1) || (str[i] != '~')) {
10480                 if (((l-1) & 3) < 2)
10481                         l += 2;
10482                 else
10483                         l = (l+3) & ~3;
10484                 str[l-2] = '~';
10485                 str[l-1] = '0';
10486                 *len = l | h;
10487                 return;
10488         }
10489         for (i = l-1; i >= 0; i--) {
10490                 if (isdigit(str[i])) {
10491                         if (str[i] == '9')
10492                                 str[i] = '0';
10493                         else {
10494                                 str[i]++;
10495                                 return;
10496                         }
10497                         continue;
10498                 }
10499                 if (i == 1) {
10500                         if (str[0] == 'z')
10501                                 str[0] = 'A';
10502                         else if (str[0] == 'Z') {
10503                                 str[0] = '~';
10504                                 str[1] = '0';
10505                         } else
10506                                 str[0]++;
10507                 } else if (i > 0) {
10508                         str[i] = '1';
10509                         str[i-1] = '~';
10510                 } else {
10511                         if (str[0] == '~')
10512                                 str[0] = 'a';
10513                         else
10514                                 str[0]++;
10515                 }
10516                 break;
10517         }
10518 }
10519
10520 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10521                                     ext2_ino_t ino,
10522                                     struct fill_dir_struct *fd)
10523 {
10524         struct problem_context  pctx;
10525         struct hash_entry       *ent, *prev;
10526         int                     i, j;
10527         int                     fixed = 0;
10528         char                    new_name[256];
10529         __u16                   new_len;
10530
10531         clear_problem_context(&pctx);
10532         pctx.ino = ino;
10533
10534         for (i=1; i < fd->num_array; i++) {
10535                 ent = fd->harray + i;
10536                 prev = ent - 1;
10537                 if (!ent->dir->inode ||
10538                     ((ent->dir->name_len & 0xFF) !=
10539                      (prev->dir->name_len & 0xFF)) ||
10540                     (strncmp(ent->dir->name, prev->dir->name,
10541                              ent->dir->name_len & 0xFF)))
10542                         continue;
10543                 pctx.dirent = ent->dir;
10544                 if ((ent->dir->inode == prev->dir->inode) &&
10545                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10546                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10547                         ent->dir->inode = 0;
10548                         fixed++;
10549                         continue;
10550                 }
10551                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10552                 new_len = ent->dir->name_len;
10553                 mutate_name(new_name, &new_len);
10554                 for (j=0; j < fd->num_array; j++) {
10555                         if ((i==j) ||
10556                             ((ent->dir->name_len & 0xFF) !=
10557                              (fd->harray[j].dir->name_len & 0xFF)) ||
10558                             (strncmp(new_name, fd->harray[j].dir->name,
10559                                      new_len & 0xFF)))
10560                                 continue;
10561                         mutate_name(new_name, &new_len);
10562
10563                         j = -1;
10564                 }
10565                 new_name[new_len & 0xFF] = 0;
10566                 pctx.str = new_name;
10567                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10568                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10569                         ent->dir->name_len = new_len;
10570                         ext2fs_dirhash(fs->super->s_def_hash_version,
10571                                        ent->dir->name,
10572                                        ent->dir->name_len & 0xFF,
10573                                        fs->super->s_hash_seed,
10574                                        &ent->hash, &ent->minor_hash);
10575                         fixed++;
10576                 }
10577         }
10578         return fixed;
10579 }
10580
10581
10582 static errcode_t copy_dir_entries(ext2_filsys fs,
10583                                   struct fill_dir_struct *fd,
10584                                   struct out_dir *outdir)
10585 {
10586         errcode_t               retval;
10587         char                    *block_start;
10588         struct hash_entry       *ent;
10589         struct ext2_dir_entry   *dirent;
10590         int                     i, rec_len, left;
10591         ext2_dirhash_t          prev_hash;
10592         int                     offset;
10593
10594         outdir->max = 0;
10595         retval = alloc_size_dir(fs, outdir,
10596                                 (fd->dir_size / fs->blocksize) + 2);
10597         if (retval)
10598                 return retval;
10599         outdir->num = fd->compress ? 0 : 1;
10600         offset = 0;
10601         outdir->hashes[0] = 0;
10602         prev_hash = 1;
10603         if ((retval = get_next_block(fs, outdir, &block_start)))
10604                 return retval;
10605         dirent = (struct ext2_dir_entry *) block_start;
10606         left = fs->blocksize;
10607         for (i=0; i < fd->num_array; i++) {
10608                 ent = fd->harray + i;
10609                 if (ent->dir->inode == 0)
10610                         continue;
10611                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10612                 if (rec_len > left) {
10613                         if (left)
10614                                 dirent->rec_len += left;
10615                         if ((retval = get_next_block(fs, outdir,
10616                                                       &block_start)))
10617                                 return retval;
10618                         offset = 0;
10619                 }
10620                 left = fs->blocksize - offset;
10621                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10622                 if (offset == 0) {
10623                         if (ent->hash == prev_hash)
10624                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10625                         else
10626                                 outdir->hashes[outdir->num-1] = ent->hash;
10627                 }
10628                 dirent->inode = ent->dir->inode;
10629                 dirent->name_len = ent->dir->name_len;
10630                 dirent->rec_len = rec_len;
10631                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10632                 offset += rec_len;
10633                 left -= rec_len;
10634                 if (left < 12) {
10635                         dirent->rec_len += left;
10636                         offset += left;
10637                         left = 0;
10638                 }
10639                 prev_hash = ent->hash;
10640         }
10641         if (left)
10642                 dirent->rec_len += left;
10643
10644         return 0;
10645 }
10646
10647
10648 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10649                                     ext2_ino_t ino, ext2_ino_t parent)
10650 {
10651         struct ext2_dir_entry           *dir;
10652         struct ext2_dx_root_info        *root;
10653         struct ext2_dx_countlimit       *limits;
10654         int                             filetype = 0;
10655
10656         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10657                 filetype = EXT2_FT_DIR << 8;
10658
10659         memset(buf, 0, fs->blocksize);
10660         dir = (struct ext2_dir_entry *) buf;
10661         dir->inode = ino;
10662         dir->name[0] = '.';
10663         dir->name_len = 1 | filetype;
10664         dir->rec_len = 12;
10665         dir = (struct ext2_dir_entry *) (buf + 12);
10666         dir->inode = parent;
10667         dir->name[0] = '.';
10668         dir->name[1] = '.';
10669         dir->name_len = 2 | filetype;
10670         dir->rec_len = fs->blocksize - 12;
10671
10672         root = (struct ext2_dx_root_info *) (buf+24);
10673         root->reserved_zero = 0;
10674         root->hash_version = fs->super->s_def_hash_version;
10675         root->info_length = 8;
10676         root->indirect_levels = 0;
10677         root->unused_flags = 0;
10678
10679         limits = (struct ext2_dx_countlimit *) (buf+32);
10680         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10681         limits->count = 0;
10682
10683         return root;
10684 }
10685
10686
10687 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10688 {
10689         struct ext2_dir_entry           *dir;
10690         struct ext2_dx_countlimit       *limits;
10691
10692         memset(buf, 0, fs->blocksize);
10693         dir = (struct ext2_dir_entry *) buf;
10694         dir->inode = 0;
10695         dir->rec_len = fs->blocksize;
10696
10697         limits = (struct ext2_dx_countlimit *) (buf+8);
10698         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10699         limits->count = 0;
10700
10701         return (struct ext2_dx_entry *) limits;
10702 }
10703
10704 /*
10705  * This function takes the leaf nodes which have been written in
10706  * outdir, and populates the root node and any necessary interior nodes.
10707  */
10708 static errcode_t calculate_tree(ext2_filsys fs,
10709                                 struct out_dir *outdir,
10710                                 ext2_ino_t ino,
10711                                 ext2_ino_t parent)
10712 {
10713         struct ext2_dx_root_info        *root_info;
10714         struct ext2_dx_entry            *root, *dx_ent = 0;
10715         struct ext2_dx_countlimit       *root_limit, *limit;
10716         errcode_t                       retval;
10717         char                            * block_start;
10718         int                             i, c1, c2, nblks;
10719         int                             limit_offset, root_offset;
10720
10721         root_info = set_root_node(fs, outdir->buf, ino, parent);
10722         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10723                 root_info->info_length;
10724         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10725         c1 = root_limit->limit;
10726         nblks = outdir->num;
10727
10728         /* Write out the pointer blocks */
10729         if (nblks-1 <= c1) {
10730                 /* Just write out the root block, and we're done */
10731                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10732                 for (i=1; i < nblks; i++) {
10733                         root->block = ext2fs_cpu_to_le32(i);
10734                         if (i != 1)
10735                                 root->hash =
10736                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10737                         root++;
10738                         c1--;
10739                 }
10740         } else {
10741                 c2 = 0;
10742                 limit = 0;
10743                 root_info->indirect_levels = 1;
10744                 for (i=1; i < nblks; i++) {
10745                         if (c1 == 0)
10746                                 return ENOSPC;
10747                         if (c2 == 0) {
10748                                 if (limit)
10749                                         limit->limit = limit->count =
10750                 ext2fs_cpu_to_le16(limit->limit);
10751                                 root = (struct ext2_dx_entry *)
10752                                         (outdir->buf + root_offset);
10753                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10754                                 if (i != 1)
10755                                         root->hash =
10756                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10757                                 if ((retval =  get_next_block(fs, outdir,
10758                                                               &block_start)))
10759                                         return retval;
10760                                 dx_ent = set_int_node(fs, block_start);
10761                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10762                                 c2 = limit->limit;
10763                                 root_offset += sizeof(struct ext2_dx_entry);
10764                                 c1--;
10765                         }
10766                         dx_ent->block = ext2fs_cpu_to_le32(i);
10767                         if (c2 != limit->limit)
10768                                 dx_ent->hash =
10769                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10770                         dx_ent++;
10771                         c2--;
10772                 }
10773                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10774                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10775         }
10776         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10777         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10778         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10779
10780         return 0;
10781 }
10782
10783 struct write_dir_struct {
10784         struct out_dir *outdir;
10785         errcode_t       err;
10786         e2fsck_t        ctx;
10787         int             cleared;
10788 };
10789
10790 /*
10791  * Helper function which writes out a directory block.
10792  */
10793 static int write_dir_block(ext2_filsys fs,
10794                            blk_t        *block_nr,
10795                            e2_blkcnt_t blockcnt,
10796                            blk_t ref_block FSCK_ATTR((unused)),
10797                            int ref_offset FSCK_ATTR((unused)),
10798                            void *priv_data)
10799 {
10800         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10801         blk_t   blk;
10802         char    *dir;
10803
10804         if (*block_nr == 0)
10805                 return 0;
10806         if (blockcnt >= wd->outdir->num) {
10807                 e2fsck_read_bitmaps(wd->ctx);
10808                 blk = *block_nr;
10809                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10810                 ext2fs_block_alloc_stats(fs, blk, -1);
10811                 *block_nr = 0;
10812                 wd->cleared++;
10813                 return BLOCK_CHANGED;
10814         }
10815         if (blockcnt < 0)
10816                 return 0;
10817
10818         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10819         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10820         if (wd->err)
10821                 return BLOCK_ABORT;
10822         return 0;
10823 }
10824
10825 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10826                                  struct out_dir *outdir,
10827                                  ext2_ino_t ino, int compress)
10828 {
10829         struct write_dir_struct wd;
10830         errcode_t       retval;
10831         struct ext2_inode       inode;
10832
10833         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10834         if (retval)
10835                 return retval;
10836
10837         wd.outdir = outdir;
10838         wd.err = 0;
10839         wd.ctx = ctx;
10840         wd.cleared = 0;
10841
10842         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10843                                        write_dir_block, &wd);
10844         if (retval)
10845                 return retval;
10846         if (wd.err)
10847                 return wd.err;
10848
10849         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10850         if (compress)
10851                 inode.i_flags &= ~EXT2_INDEX_FL;
10852         else
10853                 inode.i_flags |= EXT2_INDEX_FL;
10854         inode.i_size = outdir->num * fs->blocksize;
10855         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10856         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10857
10858         return 0;
10859 }
10860
10861 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10862 {
10863         ext2_filsys             fs = ctx->fs;
10864         errcode_t               retval;
10865         struct ext2_inode       inode;
10866         char                    *dir_buf = 0;
10867         struct fill_dir_struct  fd;
10868         struct out_dir          outdir;
10869
10870         outdir.max = outdir.num = 0;
10871         outdir.buf = 0;
10872         outdir.hashes = 0;
10873         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10874
10875         retval = ENOMEM;
10876         fd.harray = 0;
10877         dir_buf = malloc(inode.i_size);
10878         if (!dir_buf)
10879                 goto errout;
10880
10881         fd.max_array = inode.i_size / 32;
10882         fd.num_array = 0;
10883         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
10884         if (!fd.harray)
10885                 goto errout;
10886
10887         fd.ctx = ctx;
10888         fd.buf = dir_buf;
10889         fd.inode = &inode;
10890         fd.err = 0;
10891         fd.dir_size = 0;
10892         fd.compress = 0;
10893         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10894             (inode.i_size / fs->blocksize) < 2)
10895                 fd.compress = 1;
10896         fd.parent = 0;
10897
10898         /* Read in the entire directory into memory */
10899         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10900                                        fill_dir_block, &fd);
10901         if (fd.err) {
10902                 retval = fd.err;
10903                 goto errout;
10904         }
10905
10906         /* Sort the list */
10907 resort:
10908         if (fd.compress)
10909                 qsort(fd.harray+2, fd.num_array-2,
10910                       sizeof(struct hash_entry), name_cmp);
10911         else
10912                 qsort(fd.harray, fd.num_array,
10913                       sizeof(struct hash_entry), hash_cmp);
10914
10915         /*
10916          * Look for duplicates
10917          */
10918         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10919                 goto resort;
10920
10921         if (ctx->options & E2F_OPT_NO) {
10922                 retval = 0;
10923                 goto errout;
10924         }
10925
10926         /*
10927          * Copy the directory entries.  In a htree directory these
10928          * will become the leaf nodes.
10929          */
10930         retval = copy_dir_entries(fs, &fd, &outdir);
10931         if (retval)
10932                 goto errout;
10933
10934         free(dir_buf); dir_buf = 0;
10935
10936         if (!fd.compress) {
10937                 /* Calculate the interior nodes */
10938                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10939                 if (retval)
10940                         goto errout;
10941         }
10942
10943         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10944
10945 errout:
10946         free(dir_buf);
10947         free(fd.harray);
10948
10949         free_out_dir(&outdir);
10950         return retval;
10951 }
10952
10953 void e2fsck_rehash_directories(e2fsck_t ctx)
10954 {
10955         struct problem_context  pctx;
10956         struct dir_info         *dir;
10957         ext2_u32_iterate        iter;
10958         ext2_ino_t              ino;
10959         errcode_t               retval;
10960         int                     i, cur, max, all_dirs, dir_index, first = 1;
10961
10962         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10963
10964         if (!ctx->dirs_to_hash && !all_dirs)
10965                 return;
10966
10967         e2fsck_get_lost_and_found(ctx, 0);
10968
10969         clear_problem_context(&pctx);
10970
10971         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10972         cur = 0;
10973         if (all_dirs) {
10974                 i = 0;
10975                 max = e2fsck_get_num_dirinfo(ctx);
10976         } else {
10977                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10978                                                        &iter);
10979                 if (retval) {
10980                         pctx.errcode = retval;
10981                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10982                         return;
10983                 }
10984                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10985         }
10986         while (1) {
10987                 if (all_dirs) {
10988                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10989                                 break;
10990                         ino = dir->ino;
10991                 } else {
10992                         if (!ext2fs_u32_list_iterate(iter, &ino))
10993                                 break;
10994                 }
10995                 if (ino == ctx->lost_and_found)
10996                         continue;
10997                 pctx.dir = ino;
10998                 if (first) {
10999                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
11000                         first = 0;
11001                 }
11002                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
11003                 if (pctx.errcode) {
11004                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
11005                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
11006                 }
11007                 if (ctx->progress && !ctx->progress_fd)
11008                         e2fsck_simple_progress(ctx, "Rebuilding directory",
11009                                100.0 * (float) (++cur) / (float) max, ino);
11010         }
11011         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
11012         if (!all_dirs)
11013                 ext2fs_u32_list_iterate_end(iter);
11014
11015         ext2fs_u32_list_free(ctx->dirs_to_hash);
11016         ctx->dirs_to_hash = 0;
11017 }
11018
11019 /*
11020  * linux/fs/revoke.c
11021  *
11022  * Journal revoke routines for the generic filesystem journaling code;
11023  * part of the ext2fs journaling system.
11024  *
11025  * Revoke is the mechanism used to prevent old log records for deleted
11026  * metadata from being replayed on top of newer data using the same
11027  * blocks.  The revoke mechanism is used in two separate places:
11028  *
11029  * + Commit: during commit we write the entire list of the current
11030  *   transaction's revoked blocks to the journal
11031  *
11032  * + Recovery: during recovery we record the transaction ID of all
11033  *   revoked blocks.  If there are multiple revoke records in the log
11034  *   for a single block, only the last one counts, and if there is a log
11035  *   entry for a block beyond the last revoke, then that log entry still
11036  *   gets replayed.
11037  *
11038  * We can get interactions between revokes and new log data within a
11039  * single transaction:
11040  *
11041  * Block is revoked and then journaled:
11042  *   The desired end result is the journaling of the new block, so we
11043  *   cancel the revoke before the transaction commits.
11044  *
11045  * Block is journaled and then revoked:
11046  *   The revoke must take precedence over the write of the block, so we
11047  *   need either to cancel the journal entry or to write the revoke
11048  *   later in the log than the log block.  In this case, we choose the
11049  *   latter: journaling a block cancels any revoke record for that block
11050  *   in the current transaction, so any revoke for that block in the
11051  *   transaction must have happened after the block was journaled and so
11052  *   the revoke must take precedence.
11053  *
11054  * Block is revoked and then written as data:
11055  *   The data write is allowed to succeed, but the revoke is _not_
11056  *   cancelled.  We still need to prevent old log records from
11057  *   overwriting the new data.  We don't even need to clear the revoke
11058  *   bit here.
11059  *
11060  * Revoke information on buffers is a tri-state value:
11061  *
11062  * RevokeValid clear:   no cached revoke status, need to look it up
11063  * RevokeValid set, Revoked clear:
11064  *                      buffer has not been revoked, and cancel_revoke
11065  *                      need do nothing.
11066  * RevokeValid set, Revoked set:
11067  *                      buffer has been revoked.
11068  */
11069
11070 static kmem_cache_t *revoke_record_cache;
11071 static kmem_cache_t *revoke_table_cache;
11072
11073 /* Each revoke record represents one single revoked block.  During
11074    journal replay, this involves recording the transaction ID of the
11075    last transaction to revoke this block. */
11076
11077 struct jbd_revoke_record_s
11078 {
11079         struct list_head  hash;
11080         tid_t             sequence;     /* Used for recovery only */
11081         unsigned long     blocknr;
11082 };
11083
11084
11085 /* The revoke table is just a simple hash table of revoke records. */
11086 struct jbd_revoke_table_s
11087 {
11088         /* It is conceivable that we might want a larger hash table
11089          * for recovery.  Must be a power of two. */
11090         int               hash_size;
11091         int               hash_shift;
11092         struct list_head *hash_table;
11093 };
11094
11095
11096 /* Utility functions to maintain the revoke table */
11097
11098 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11099 static inline int hash(journal_t *journal, unsigned long block)
11100 {
11101         struct jbd_revoke_table_s *table = journal->j_revoke;
11102         int hash_shift = table->hash_shift;
11103
11104         return ((block << (hash_shift - 6)) ^
11105                 (block >> 13) ^
11106                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11107 }
11108
11109 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11110                               tid_t seq)
11111 {
11112         struct list_head *hash_list;
11113         struct jbd_revoke_record_s *record;
11114
11115         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11116         if (!record)
11117                 goto oom;
11118
11119         record->sequence = seq;
11120         record->blocknr = blocknr;
11121         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11122         list_add(&record->hash, hash_list);
11123         return 0;
11124
11125 oom:
11126         return -ENOMEM;
11127 }
11128
11129 /* Find a revoke record in the journal's hash table. */
11130
11131 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11132                                                       unsigned long blocknr)
11133 {
11134         struct list_head *hash_list;
11135         struct jbd_revoke_record_s *record;
11136
11137         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11138
11139         record = (struct jbd_revoke_record_s *) hash_list->next;
11140         while (&(record->hash) != hash_list) {
11141                 if (record->blocknr == blocknr)
11142                         return record;
11143                 record = (struct jbd_revoke_record_s *) record->hash.next;
11144         }
11145         return NULL;
11146 }
11147
11148 int journal_init_revoke_caches(void)
11149 {
11150         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11151         if (revoke_record_cache == 0)
11152                 return -ENOMEM;
11153
11154         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11155         if (revoke_table_cache == 0) {
11156                 do_cache_destroy(revoke_record_cache);
11157                 revoke_record_cache = NULL;
11158                 return -ENOMEM;
11159         }
11160         return 0;
11161 }
11162
11163 void journal_destroy_revoke_caches(void)
11164 {
11165         do_cache_destroy(revoke_record_cache);
11166         revoke_record_cache = 0;
11167         do_cache_destroy(revoke_table_cache);
11168         revoke_table_cache = 0;
11169 }
11170
11171 /* Initialise the revoke table for a given journal to a given size. */
11172
11173 int journal_init_revoke(journal_t *journal, int hash_size)
11174 {
11175         int shift, tmp;
11176
11177         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11178         if (!journal->j_revoke)
11179                 return -ENOMEM;
11180
11181         /* Check that the hash_size is a power of two */
11182         journal->j_revoke->hash_size = hash_size;
11183
11184         shift = 0;
11185         tmp = hash_size;
11186         while((tmp >>= 1UL) != 0UL)
11187                 shift++;
11188         journal->j_revoke->hash_shift = shift;
11189
11190         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
11191         if (!journal->j_revoke->hash_table) {
11192                 free(journal->j_revoke);
11193                 journal->j_revoke = NULL;
11194                 return -ENOMEM;
11195         }
11196
11197         for (tmp = 0; tmp < hash_size; tmp++)
11198                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11199
11200         return 0;
11201 }
11202
11203 /* Destoy a journal's revoke table.  The table must already be empty! */
11204
11205 void journal_destroy_revoke(journal_t *journal)
11206 {
11207         struct jbd_revoke_table_s *table;
11208         struct list_head *hash_list;
11209         int i;
11210
11211         table = journal->j_revoke;
11212         if (!table)
11213                 return;
11214
11215         for (i=0; i<table->hash_size; i++) {
11216                 hash_list = &table->hash_table[i];
11217         }
11218
11219         free(table->hash_table);
11220         free(table);
11221         journal->j_revoke = NULL;
11222 }
11223
11224 /*
11225  * Revoke support for recovery.
11226  *
11227  * Recovery needs to be able to:
11228  *
11229  *  record all revoke records, including the tid of the latest instance
11230  *  of each revoke in the journal
11231  *
11232  *  check whether a given block in a given transaction should be replayed
11233  *  (ie. has not been revoked by a revoke record in that or a subsequent
11234  *  transaction)
11235  *
11236  *  empty the revoke table after recovery.
11237  */
11238
11239 /*
11240  * First, setting revoke records.  We create a new revoke record for
11241  * every block ever revoked in the log as we scan it for recovery, and
11242  * we update the existing records if we find multiple revokes for a
11243  * single block.
11244  */
11245
11246 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11247                        tid_t sequence)
11248 {
11249         struct jbd_revoke_record_s *record;
11250
11251         record = find_revoke_record(journal, blocknr);
11252         if (record) {
11253                 /* If we have multiple occurences, only record the
11254                  * latest sequence number in the hashed record */
11255                 if (tid_gt(sequence, record->sequence))
11256                         record->sequence = sequence;
11257                 return 0;
11258         }
11259         return insert_revoke_hash(journal, blocknr, sequence);
11260 }
11261
11262 /*
11263  * Test revoke records.  For a given block referenced in the log, has
11264  * that block been revoked?  A revoke record with a given transaction
11265  * sequence number revokes all blocks in that transaction and earlier
11266  * ones, but later transactions still need replayed.
11267  */
11268
11269 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11270                         tid_t sequence)
11271 {
11272         struct jbd_revoke_record_s *record;
11273
11274         record = find_revoke_record(journal, blocknr);
11275         if (!record)
11276                 return 0;
11277         if (tid_gt(sequence, record->sequence))
11278                 return 0;
11279         return 1;
11280 }
11281
11282 /*
11283  * Finally, once recovery is over, we need to clear the revoke table so
11284  * that it can be reused by the running filesystem.
11285  */
11286
11287 void journal_clear_revoke(journal_t *journal)
11288 {
11289         int i;
11290         struct list_head *hash_list;
11291         struct jbd_revoke_record_s *record;
11292         struct jbd_revoke_table_s *revoke_var;
11293
11294         revoke_var = journal->j_revoke;
11295
11296         for (i = 0; i < revoke_var->hash_size; i++) {
11297                 hash_list = &revoke_var->hash_table[i];
11298                 while (!list_empty(hash_list)) {
11299                         record = (struct jbd_revoke_record_s*) hash_list->next;
11300                         list_del(&record->hash);
11301                         free(record);
11302                 }
11303         }
11304 }
11305
11306 /*
11307  * e2fsck.c - superblock checks
11308  */
11309
11310 #define MIN_CHECK 1
11311 #define MAX_CHECK 2
11312
11313 static void check_super_value(e2fsck_t ctx, const char *descr,
11314                               unsigned long value, int flags,
11315                               unsigned long min_val, unsigned long max_val)
11316 {
11317         struct          problem_context pctx;
11318
11319         if (((flags & MIN_CHECK) && (value < min_val)) ||
11320             ((flags & MAX_CHECK) && (value > max_val))) {
11321                 clear_problem_context(&pctx);
11322                 pctx.num = value;
11323                 pctx.str = descr;
11324                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11325                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11326         }
11327 }
11328
11329 /*
11330  * This routine may get stubbed out in special compilations of the
11331  * e2fsck code..
11332  */
11333 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11334 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11335 {
11336         return (ext2fs_get_device_size(ctx->filesystem_name,
11337                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11338                                        &ctx->num_blocks));
11339 }
11340 #endif
11341
11342 /*
11343  * helper function to release an inode
11344  */
11345 struct process_block_struct {
11346         e2fsck_t        ctx;
11347         char            *buf;
11348         struct problem_context *pctx;
11349         int             truncating;
11350         int             truncate_offset;
11351         e2_blkcnt_t     truncate_block;
11352         int             truncated_blocks;
11353         int             abort;
11354         errcode_t       errcode;
11355 };
11356
11357 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11358                                e2_blkcnt_t blockcnt,
11359                                blk_t    ref_blk FSCK_ATTR((unused)),
11360                                int      ref_offset FSCK_ATTR((unused)),
11361                                void *priv_data)
11362 {
11363         struct process_block_struct *pb;
11364         e2fsck_t                ctx;
11365         struct problem_context  *pctx;
11366         blk_t                   blk = *block_nr;
11367         int                     retval = 0;
11368
11369         pb = (struct process_block_struct *) priv_data;
11370         ctx = pb->ctx;
11371         pctx = pb->pctx;
11372
11373         pctx->blk = blk;
11374         pctx->blkcount = blockcnt;
11375
11376         if (HOLE_BLKADDR(blk))
11377                 return 0;
11378
11379         if ((blk < fs->super->s_first_data_block) ||
11380             (blk >= fs->super->s_blocks_count)) {
11381                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11382         return_abort:
11383                 pb->abort = 1;
11384                 return BLOCK_ABORT;
11385         }
11386
11387         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11388                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11389                 goto return_abort;
11390         }
11391
11392         /*
11393          * If we are deleting an orphan, then we leave the fields alone.
11394          * If we are truncating an orphan, then update the inode fields
11395          * and clean up any partial block data.
11396          */
11397         if (pb->truncating) {
11398                 /*
11399                  * We only remove indirect blocks if they are
11400                  * completely empty.
11401                  */
11402                 if (blockcnt < 0) {
11403                         int     i, limit;
11404                         blk_t   *bp;
11405
11406                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11407                                                         pb->buf);
11408                         if (pb->errcode)
11409                                 goto return_abort;
11410
11411                         limit = fs->blocksize >> 2;
11412                         for (i = 0, bp = (blk_t *) pb->buf;
11413                              i < limit;  i++, bp++)
11414                                 if (*bp)
11415                                         return 0;
11416                 }
11417                 /*
11418                  * We don't remove direct blocks until we've reached
11419                  * the truncation block.
11420                  */
11421                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11422                         return 0;
11423                 /*
11424                  * If part of the last block needs truncating, we do
11425                  * it here.
11426                  */
11427                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11428                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11429                                                         pb->buf);
11430                         if (pb->errcode)
11431                                 goto return_abort;
11432                         memset(pb->buf + pb->truncate_offset, 0,
11433                                fs->blocksize - pb->truncate_offset);
11434                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11435                                                          pb->buf);
11436                         if (pb->errcode)
11437                                 goto return_abort;
11438                 }
11439                 pb->truncated_blocks++;
11440                 *block_nr = 0;
11441                 retval |= BLOCK_CHANGED;
11442         }
11443
11444         ext2fs_block_alloc_stats(fs, blk, -1);
11445         return retval;
11446 }
11447
11448 /*
11449  * This function releases an inode.  Returns 1 if an inconsistency was
11450  * found.  If the inode has a link count, then it is being truncated and
11451  * not deleted.
11452  */
11453 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11454                                 struct ext2_inode *inode, char *block_buf,
11455                                 struct problem_context *pctx)
11456 {
11457         struct process_block_struct     pb;
11458         ext2_filsys                     fs = ctx->fs;
11459         errcode_t                       retval;
11460         __u32                           count;
11461
11462         if (!ext2fs_inode_has_valid_blocks(inode))
11463                 return 0;
11464
11465         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11466         pb.ctx = ctx;
11467         pb.abort = 0;
11468         pb.errcode = 0;
11469         pb.pctx = pctx;
11470         if (inode->i_links_count) {
11471                 pb.truncating = 1;
11472                 pb.truncate_block = (e2_blkcnt_t)
11473                         ((((long long)inode->i_size_high << 32) +
11474                           inode->i_size + fs->blocksize - 1) /
11475                          fs->blocksize);
11476                 pb.truncate_offset = inode->i_size % fs->blocksize;
11477         } else {
11478                 pb.truncating = 0;
11479                 pb.truncate_block = 0;
11480                 pb.truncate_offset = 0;
11481         }
11482         pb.truncated_blocks = 0;
11483         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11484                                       block_buf, release_inode_block, &pb);
11485         if (retval) {
11486                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11487                         ino);
11488                 return 1;
11489         }
11490         if (pb.abort)
11491                 return 1;
11492
11493         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11494         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11495
11496         if (pb.truncated_blocks)
11497                 inode->i_blocks -= pb.truncated_blocks *
11498                         (fs->blocksize / 512);
11499
11500         if (inode->i_file_acl) {
11501                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11502                                                    block_buf, -1, &count);
11503                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11504                         retval = 0;
11505                         count = 1;
11506                 }
11507                 if (retval) {
11508                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11509                                 ino);
11510                         return 1;
11511                 }
11512                 if (count == 0)
11513                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11514                 inode->i_file_acl = 0;
11515         }
11516         return 0;
11517 }
11518
11519 /*
11520  * This function releases all of the orphan inodes.  It returns 1 if
11521  * it hit some error, and 0 on success.
11522  */
11523 static int release_orphan_inodes(e2fsck_t ctx)
11524 {
11525         ext2_filsys fs = ctx->fs;
11526         ext2_ino_t      ino, next_ino;
11527         struct ext2_inode inode;
11528         struct problem_context pctx;
11529         char *block_buf;
11530
11531         if ((ino = fs->super->s_last_orphan) == 0)
11532                 return 0;
11533
11534         /*
11535          * Win or lose, we won't be using the head of the orphan inode
11536          * list again.
11537          */
11538         fs->super->s_last_orphan = 0;
11539         ext2fs_mark_super_dirty(fs);
11540
11541         /*
11542          * If the filesystem contains errors, don't run the orphan
11543          * list, since the orphan list can't be trusted; and we're
11544          * going to be running a full e2fsck run anyway...
11545          */
11546         if (fs->super->s_state & EXT2_ERROR_FS)
11547                 return 0;
11548
11549         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11550             (ino > fs->super->s_inodes_count)) {
11551                 clear_problem_context(&pctx);
11552                 pctx.ino = ino;
11553                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11554                 return 1;
11555         }
11556
11557         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11558                                                     "block iterate buffer");
11559         e2fsck_read_bitmaps(ctx);
11560
11561         while (ino) {
11562                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11563                 clear_problem_context(&pctx);
11564                 pctx.ino = ino;
11565                 pctx.inode = &inode;
11566                 pctx.str = inode.i_links_count ? _("Truncating") :
11567                         _("Clearing");
11568
11569                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11570
11571                 next_ino = inode.i_dtime;
11572                 if (next_ino &&
11573                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11574                      (next_ino > fs->super->s_inodes_count))) {
11575                         pctx.ino = next_ino;
11576                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11577                         goto return_abort;
11578                 }
11579
11580                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11581                         goto return_abort;
11582
11583                 if (!inode.i_links_count) {
11584                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11585                                                   LINUX_S_ISDIR(inode.i_mode));
11586                         inode.i_dtime = time(0);
11587                 } else {
11588                         inode.i_dtime = 0;
11589                 }
11590                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11591                 ino = next_ino;
11592         }
11593         ext2fs_free_mem(&block_buf);
11594         return 0;
11595 return_abort:
11596         ext2fs_free_mem(&block_buf);
11597         return 1;
11598 }
11599
11600 /*
11601  * Check the resize inode to make sure it is sane.  We check both for
11602  * the case where on-line resizing is not enabled (in which case the
11603  * resize inode should be cleared) as well as the case where on-line
11604  * resizing is enabled.
11605  */
11606 static void check_resize_inode(e2fsck_t ctx)
11607 {
11608         ext2_filsys fs = ctx->fs;
11609         struct ext2_inode inode;
11610         struct problem_context  pctx;
11611         int             i, j, gdt_off, ind_off;
11612         blk_t           blk, pblk, expect;
11613         __u32           *dind_buf = 0, *ind_buf;
11614         errcode_t       retval;
11615
11616         clear_problem_context(&pctx);
11617
11618         /*
11619          * If the resize inode feature isn't set, then
11620          * s_reserved_gdt_blocks must be zero.
11621          */
11622         if (!(fs->super->s_feature_compat &
11623               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11624                 if (fs->super->s_reserved_gdt_blocks) {
11625                         pctx.num = fs->super->s_reserved_gdt_blocks;
11626                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11627                                         &pctx)) {
11628                                 fs->super->s_reserved_gdt_blocks = 0;
11629                                 ext2fs_mark_super_dirty(fs);
11630                         }
11631                 }
11632         }
11633
11634         /* Read the resize inode */
11635         pctx.ino = EXT2_RESIZE_INO;
11636         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11637         if (retval) {
11638                 if (fs->super->s_feature_compat &
11639                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11640                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11641                 return;
11642         }
11643
11644         /*
11645          * If the resize inode feature isn't set, check to make sure
11646          * the resize inode is cleared; then we're done.
11647          */
11648         if (!(fs->super->s_feature_compat &
11649               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11650                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11651                         if (inode.i_block[i])
11652                                 break;
11653                 }
11654                 if ((i < EXT2_N_BLOCKS) &&
11655                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11656                         memset(&inode, 0, sizeof(inode));
11657                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11658                                            "clear_resize");
11659                 }
11660                 return;
11661         }
11662
11663         /*
11664          * The resize inode feature is enabled; check to make sure the
11665          * only block in use is the double indirect block
11666          */
11667         blk = inode.i_block[EXT2_DIND_BLOCK];
11668         for (i=0; i < EXT2_N_BLOCKS; i++) {
11669                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11670                         break;
11671         }
11672         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11673             !(inode.i_mode & LINUX_S_IFREG) ||
11674             (blk < fs->super->s_first_data_block ||
11675              blk >= fs->super->s_blocks_count)) {
11676         resize_inode_invalid:
11677                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11678                         memset(&inode, 0, sizeof(inode));
11679                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11680                                            "clear_resize");
11681                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11682                 }
11683                 if (!(ctx->options & E2F_OPT_READONLY)) {
11684                         fs->super->s_state &= ~EXT2_VALID_FS;
11685                         ext2fs_mark_super_dirty(fs);
11686                 }
11687                 goto cleanup;
11688         }
11689         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11690                                                     "resize dind buffer");
11691         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11692
11693         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11694         if (retval)
11695                 goto resize_inode_invalid;
11696
11697         gdt_off = fs->desc_blocks;
11698         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11699         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11700              i++, gdt_off++, pblk++) {
11701                 gdt_off %= fs->blocksize/4;
11702                 if (dind_buf[gdt_off] != pblk)
11703                         goto resize_inode_invalid;
11704                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11705                 if (retval)
11706                         goto resize_inode_invalid;
11707                 ind_off = 0;
11708                 for (j = 1; j < fs->group_desc_count; j++) {
11709                         if (!ext2fs_bg_has_super(fs, j))
11710                                 continue;
11711                         expect = pblk + (j * fs->super->s_blocks_per_group);
11712                         if (ind_buf[ind_off] != expect)
11713                                 goto resize_inode_invalid;
11714                         ind_off++;
11715                 }
11716         }
11717
11718 cleanup:
11719         ext2fs_free_mem(&dind_buf);
11720
11721  }
11722
11723 static void check_super_block(e2fsck_t ctx)
11724 {
11725         ext2_filsys fs = ctx->fs;
11726         blk_t   first_block, last_block;
11727         struct ext2_super_block *sb = fs->super;
11728         struct ext2_group_desc *gd;
11729         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11730         blk_t   bpg_max;
11731         int     inodes_per_block;
11732         int     ipg_max;
11733         int     inode_size;
11734         dgrp_t  i;
11735         blk_t   should_be;
11736         struct problem_context  pctx;
11737         __u32   free_blocks = 0, free_inodes = 0;
11738
11739         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11740         ipg_max = inodes_per_block * (blocks_per_group - 4);
11741         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11742                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11743         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11744         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11745                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11746
11747         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11748                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11749         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11750                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11751         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11752                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11753
11754         clear_problem_context(&pctx);
11755
11756         /*
11757          * Verify the super block constants...
11758          */
11759         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11760                           MIN_CHECK, 1, 0);
11761         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11762                           MIN_CHECK, 1, 0);
11763         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11764                           MAX_CHECK, 0, sb->s_blocks_count);
11765         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11766                           MIN_CHECK | MAX_CHECK, 0,
11767                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11768         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11769                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11770         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11771                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11772                           bpg_max);
11773         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11774                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11775         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11776                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11777         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11778                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11779         check_super_value(ctx, "reserved_gdt_blocks",
11780                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11781                           fs->blocksize/4);
11782         inode_size = EXT2_INODE_SIZE(sb);
11783         check_super_value(ctx, "inode_size",
11784                           inode_size, MIN_CHECK | MAX_CHECK,
11785                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11786         if (inode_size & (inode_size - 1)) {
11787                 pctx.num = inode_size;
11788                 pctx.str = "inode_size";
11789                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11790                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11791                 return;
11792         }
11793
11794         if (!ctx->num_blocks) {
11795                 pctx.errcode = e2fsck_get_device_size(ctx);
11796                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11797                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11798                         ctx->flags |= E2F_FLAG_ABORT;
11799                         return;
11800                 }
11801                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11802                     (ctx->num_blocks < sb->s_blocks_count)) {
11803                         pctx.blk = sb->s_blocks_count;
11804                         pctx.blk2 = ctx->num_blocks;
11805                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11806                                 ctx->flags |= E2F_FLAG_ABORT;
11807                                 return;
11808                         }
11809                 }
11810         }
11811
11812         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11813                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11814                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11815                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11816                 ctx->flags |= E2F_FLAG_ABORT;
11817                 return;
11818         }
11819
11820         should_be = sb->s_frags_per_group >>
11821                 (sb->s_log_block_size - sb->s_log_frag_size);
11822         if (sb->s_blocks_per_group != should_be) {
11823                 pctx.blk = sb->s_blocks_per_group;
11824                 pctx.blk2 = should_be;
11825                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11826                 ctx->flags |= E2F_FLAG_ABORT;
11827                 return;
11828         }
11829
11830         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11831         if (sb->s_first_data_block != should_be) {
11832                 pctx.blk = sb->s_first_data_block;
11833                 pctx.blk2 = should_be;
11834                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11835                 ctx->flags |= E2F_FLAG_ABORT;
11836                 return;
11837         }
11838
11839         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11840         if (sb->s_inodes_count != should_be) {
11841                 pctx.ino = sb->s_inodes_count;
11842                 pctx.ino2 = should_be;
11843                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11844                         sb->s_inodes_count = should_be;
11845                         ext2fs_mark_super_dirty(fs);
11846                 }
11847         }
11848
11849         /*
11850          * Verify the group descriptors....
11851          */
11852         first_block =  sb->s_first_data_block;
11853         last_block = first_block + blocks_per_group;
11854
11855         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11856                 pctx.group = i;
11857
11858                 if (i == fs->group_desc_count - 1)
11859                         last_block = sb->s_blocks_count;
11860                 if ((gd->bg_block_bitmap < first_block) ||
11861                     (gd->bg_block_bitmap >= last_block)) {
11862                         pctx.blk = gd->bg_block_bitmap;
11863                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11864                                 gd->bg_block_bitmap = 0;
11865                 }
11866                 if (gd->bg_block_bitmap == 0) {
11867                         ctx->invalid_block_bitmap_flag[i]++;
11868                         ctx->invalid_bitmaps++;
11869                 }
11870                 if ((gd->bg_inode_bitmap < first_block) ||
11871                     (gd->bg_inode_bitmap >= last_block)) {
11872                         pctx.blk = gd->bg_inode_bitmap;
11873                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11874                                 gd->bg_inode_bitmap = 0;
11875                 }
11876                 if (gd->bg_inode_bitmap == 0) {
11877                         ctx->invalid_inode_bitmap_flag[i]++;
11878                         ctx->invalid_bitmaps++;
11879                 }
11880                 if ((gd->bg_inode_table < first_block) ||
11881                     ((gd->bg_inode_table +
11882                       fs->inode_blocks_per_group - 1) >= last_block)) {
11883                         pctx.blk = gd->bg_inode_table;
11884                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11885                                 gd->bg_inode_table = 0;
11886                 }
11887                 if (gd->bg_inode_table == 0) {
11888                         ctx->invalid_inode_table_flag[i]++;
11889                         ctx->invalid_bitmaps++;
11890                 }
11891                 free_blocks += gd->bg_free_blocks_count;
11892                 free_inodes += gd->bg_free_inodes_count;
11893                 first_block += sb->s_blocks_per_group;
11894                 last_block += sb->s_blocks_per_group;
11895
11896                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11897                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11898                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11899                         ext2fs_unmark_valid(fs);
11900
11901         }
11902
11903         /*
11904          * Update the global counts from the block group counts.  This
11905          * is needed for an experimental patch which eliminates
11906          * locking the entire filesystem when allocating blocks or
11907          * inodes; if the filesystem is not unmounted cleanly, the
11908          * global counts may not be accurate.
11909          */
11910         if ((free_blocks != sb->s_free_blocks_count) ||
11911             (free_inodes != sb->s_free_inodes_count)) {
11912                 if (ctx->options & E2F_OPT_READONLY)
11913                         ext2fs_unmark_valid(fs);
11914                 else {
11915                         sb->s_free_blocks_count = free_blocks;
11916                         sb->s_free_inodes_count = free_inodes;
11917                         ext2fs_mark_super_dirty(fs);
11918                 }
11919         }
11920
11921         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11922             (sb->s_free_inodes_count > sb->s_inodes_count))
11923                 ext2fs_unmark_valid(fs);
11924
11925
11926         /*
11927          * If we have invalid bitmaps, set the error state of the
11928          * filesystem.
11929          */
11930         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11931                 sb->s_state &= ~EXT2_VALID_FS;
11932                 ext2fs_mark_super_dirty(fs);
11933         }
11934
11935         clear_problem_context(&pctx);
11936
11937         /*
11938          * If the UUID field isn't assigned, assign it.
11939          */
11940         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11941                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11942                         uuid_generate(sb->s_uuid);
11943                         ext2fs_mark_super_dirty(fs);
11944                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11945                 }
11946         }
11947
11948         /* FIXME - HURD support?
11949          * For the Hurd, check to see if the filetype option is set,
11950          * since it doesn't support it.
11951          */
11952         if (!(ctx->options & E2F_OPT_READONLY) &&
11953             fs->super->s_creator_os == EXT2_OS_HURD &&
11954             (fs->super->s_feature_incompat &
11955              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11956                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11957                         fs->super->s_feature_incompat &=
11958                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11959                         ext2fs_mark_super_dirty(fs);
11960
11961                 }
11962         }
11963
11964         /*
11965          * If we have any of the compatibility flags set, we need to have a
11966          * revision 1 filesystem.  Most kernels will not check the flags on
11967          * a rev 0 filesystem and we may have corruption issues because of
11968          * the incompatible changes to the filesystem.
11969          */
11970         if (!(ctx->options & E2F_OPT_READONLY) &&
11971             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11972             (fs->super->s_feature_compat ||
11973              fs->super->s_feature_ro_compat ||
11974              fs->super->s_feature_incompat) &&
11975             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11976                 ext2fs_update_dynamic_rev(fs);
11977                 ext2fs_mark_super_dirty(fs);
11978         }
11979
11980         check_resize_inode(ctx);
11981
11982         /*
11983          * Clean up any orphan inodes, if present.
11984          */
11985         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11986                 fs->super->s_state &= ~EXT2_VALID_FS;
11987                 ext2fs_mark_super_dirty(fs);
11988         }
11989
11990         /*
11991          * Move the ext3 journal file, if necessary.
11992          */
11993         e2fsck_move_ext3_journal(ctx);
11994         return;
11995 }
11996
11997 /*
11998  * swapfs.c --- byte-swap an ext2 filesystem
11999  */
12000
12001 #ifdef ENABLE_SWAPFS
12002
12003 struct swap_block_struct {
12004         ext2_ino_t      ino;
12005         int             isdir;
12006         errcode_t       errcode;
12007         char            *dir_buf;
12008         struct ext2_inode *inode;
12009 };
12010
12011 /*
12012  * This is a helper function for block_iterate.  We mark all of the
12013  * indirect and direct blocks as changed, so that block_iterate will
12014  * write them out.
12015  */
12016 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
12017                       void *priv_data)
12018 {
12019         errcode_t       retval;
12020
12021         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
12022
12023         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
12024                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
12025                 if (retval) {
12026                         sb->errcode = retval;
12027                         return BLOCK_ABORT;
12028                 }
12029                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
12030                 if (retval) {
12031                         sb->errcode = retval;
12032                         return BLOCK_ABORT;
12033                 }
12034         }
12035         if (blockcnt >= 0) {
12036                 if (blockcnt < EXT2_NDIR_BLOCKS)
12037                         return 0;
12038                 return BLOCK_CHANGED;
12039         }
12040         if (blockcnt == BLOCK_COUNT_IND) {
12041                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
12042                         return 0;
12043                 return BLOCK_CHANGED;
12044         }
12045         if (blockcnt == BLOCK_COUNT_DIND) {
12046                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12047                         return 0;
12048                 return BLOCK_CHANGED;
12049         }
12050         if (blockcnt == BLOCK_COUNT_TIND) {
12051                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12052                         return 0;
12053                 return BLOCK_CHANGED;
12054         }
12055         return BLOCK_CHANGED;
12056 }
12057
12058 /*
12059  * This function is responsible for byte-swapping all of the indirect,
12060  * block pointers.  It is also responsible for byte-swapping directories.
12061  */
12062 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12063                               struct ext2_inode *inode)
12064 {
12065         errcode_t                       retval;
12066         struct swap_block_struct        sb;
12067
12068         sb.ino = ino;
12069         sb.inode = inode;
12070         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12071         sb.errcode = 0;
12072         sb.isdir = 0;
12073         if (LINUX_S_ISDIR(inode->i_mode))
12074                 sb.isdir = 1;
12075
12076         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12077                                       swap_block, &sb);
12078         if (retval) {
12079                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12080                 ctx->flags |= E2F_FLAG_ABORT;
12081                 return;
12082         }
12083         if (sb.errcode) {
12084                 bb_error_msg(_("while calling iterator function"));
12085                 ctx->flags |= E2F_FLAG_ABORT;
12086                 return;
12087         }
12088 }
12089
12090 static void swap_inodes(e2fsck_t ctx)
12091 {
12092         ext2_filsys fs = ctx->fs;
12093         dgrp_t                  group;
12094         unsigned int            i;
12095         ext2_ino_t              ino = 1;
12096         char                    *buf, *block_buf;
12097         errcode_t               retval;
12098         struct ext2_inode *     inode;
12099
12100         e2fsck_use_inode_shortcuts(ctx, 1);
12101
12102         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12103                                 &buf);
12104         if (retval) {
12105                 bb_error_msg(_("while allocating inode buffer"));
12106                 ctx->flags |= E2F_FLAG_ABORT;
12107                 return;
12108         }
12109         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12110                                                     "block interate buffer");
12111         for (group = 0; group < fs->group_desc_count; group++) {
12112                 retval = io_channel_read_blk(fs->io,
12113                       fs->group_desc[group].bg_inode_table,
12114                       fs->inode_blocks_per_group, buf);
12115                 if (retval) {
12116                         bb_error_msg(_("while reading inode table (group %d)"),
12117                                 group);
12118                         ctx->flags |= E2F_FLAG_ABORT;
12119                         return;
12120                 }
12121                 inode = (struct ext2_inode *) buf;
12122                 for (i=0; i < fs->super->s_inodes_per_group;
12123                      i++, ino++, inode++) {
12124                         ctx->stashed_ino = ino;
12125                         ctx->stashed_inode = inode;
12126
12127                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12128                                 ext2fs_swap_inode(fs, inode, inode, 0);
12129
12130                         /*
12131                          * Skip deleted files.
12132                          */
12133                         if (inode->i_links_count == 0)
12134                                 continue;
12135
12136                         if (LINUX_S_ISDIR(inode->i_mode) ||
12137                             ((inode->i_block[EXT2_IND_BLOCK] ||
12138                               inode->i_block[EXT2_DIND_BLOCK] ||
12139                               inode->i_block[EXT2_TIND_BLOCK]) &&
12140                              ext2fs_inode_has_valid_blocks(inode)))
12141                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12142
12143                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12144                                 return;
12145
12146                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12147                                 ext2fs_swap_inode(fs, inode, inode, 1);
12148                 }
12149                 retval = io_channel_write_blk(fs->io,
12150                       fs->group_desc[group].bg_inode_table,
12151                       fs->inode_blocks_per_group, buf);
12152                 if (retval) {
12153                         bb_error_msg(_("while writing inode table (group %d)"),
12154                                 group);
12155                         ctx->flags |= E2F_FLAG_ABORT;
12156                         return;
12157                 }
12158         }
12159         ext2fs_free_mem(&buf);
12160         ext2fs_free_mem(&block_buf);
12161         e2fsck_use_inode_shortcuts(ctx, 0);
12162         ext2fs_flush_icache(fs);
12163 }
12164
12165 #if defined(__powerpc__) && BB_BIG_ENDIAN
12166 /*
12167  * On the PowerPC, the big-endian variant of the ext2 filesystem
12168  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12169  * of each word.  Thus a bitmap with only bit 0 set would be, as
12170  * a string of bytes, 00 00 00 01 00 ...
12171  * To cope with this, we byte-reverse each word of a bitmap if
12172  * we have a big-endian filesystem, that is, if we are *not*
12173  * byte-swapping other word-sized numbers.
12174  */
12175 #define EXT2_BIG_ENDIAN_BITMAPS
12176 #endif
12177
12178 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12179 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12180 {
12181         __u32 *p = (__u32 *) bmap->bitmap;
12182         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12183
12184         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12185                 *p = ext2fs_swab32(*p);
12186 }
12187 #endif
12188
12189
12190 #ifdef ENABLE_SWAPFS
12191 static void swap_filesys(e2fsck_t ctx)
12192 {
12193         ext2_filsys fs = ctx->fs;
12194         if (!(ctx->options & E2F_OPT_PREEN))
12195                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12196
12197         /* Byte swap */
12198
12199         if (fs->super->s_mnt_count) {
12200                 fprintf(stderr, _("%s: the filesystem must be freshly "
12201                         "checked using fsck\n"
12202                         "and not mounted before trying to "
12203                         "byte-swap it.\n"), ctx->device_name);
12204                 ctx->flags |= E2F_FLAG_ABORT;
12205                 return;
12206         }
12207         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12208                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12209                                EXT2_FLAG_SWAP_BYTES_WRITE);
12210                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12211         } else {
12212                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12213                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12214         }
12215         swap_inodes(ctx);
12216         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12217                 return;
12218         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12219                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12220         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12221                        EXT2_FLAG_SWAP_BYTES_WRITE);
12222
12223 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12224         e2fsck_read_bitmaps(ctx);
12225         ext2fs_swap_bitmap(fs->inode_map);
12226         ext2fs_swap_bitmap(fs->block_map);
12227         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12228 #endif
12229         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12230         ext2fs_flush(fs);
12231         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12232 }
12233 #endif  /* ENABLE_SWAPFS */
12234
12235 #endif
12236
12237 /*
12238  * util.c --- miscellaneous utilities
12239  */
12240
12241
12242 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12243                              const char *description)
12244 {
12245         void *ret;
12246         char buf[256];
12247
12248         ret = malloc(size);
12249         if (!ret) {
12250                 sprintf(buf, "Can't allocate %s\n", description);
12251                 bb_error_msg_and_die(buf);
12252         }
12253         memset(ret, 0, size);
12254         return ret;
12255 }
12256
12257 static char *string_copy(const char *str, int len)
12258 {
12259         char    *ret;
12260
12261         if (!str)
12262                 return NULL;
12263         if (!len)
12264                 len = strlen(str);
12265         ret = malloc(len+1);
12266         if (ret) {
12267                 strncpy(ret, str, len);
12268                 ret[len] = 0;
12269         }
12270         return ret;
12271 }
12272
12273 #ifndef HAVE_CONIO_H
12274 static int read_a_char(void)
12275 {
12276         char    c;
12277         int     r;
12278         int     fail = 0;
12279
12280         while(1) {
12281                 if (e2fsck_global_ctx &&
12282                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12283                         return 3;
12284                 }
12285                 r = read(0, &c, 1);
12286                 if (r == 1)
12287                         return c;
12288                 if (fail++ > 100)
12289                         break;
12290         }
12291         return EOF;
12292 }
12293 #endif
12294
12295 static int ask_yn(const char * string, int def)
12296 {
12297         int             c;
12298         const char      *defstr;
12299         static const char short_yes[] = "yY";
12300         static const char short_no[] = "nN";
12301
12302 #ifdef HAVE_TERMIOS_H
12303         struct termios  termios, tmp;
12304
12305         tcgetattr (0, &termios);
12306         tmp = termios;
12307         tmp.c_lflag &= ~(ICANON | ECHO);
12308         tmp.c_cc[VMIN] = 1;
12309         tmp.c_cc[VTIME] = 0;
12310         tcsetattr (0, TCSANOW, &tmp);
12311 #endif
12312
12313         if (def == 1)
12314                 defstr = "<y>";
12315         else if (def == 0)
12316                 defstr = "<n>";
12317         else
12318                 defstr = " (y/n)";
12319         printf("%s%s? ", string, defstr);
12320         while (1) {
12321                 fflush (stdout);
12322                 if ((c = read_a_char()) == EOF)
12323                         break;
12324                 if (c == 3) {
12325 #ifdef HAVE_TERMIOS_H
12326                         tcsetattr (0, TCSANOW, &termios);
12327 #endif
12328                         if (e2fsck_global_ctx &&
12329                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12330                                 puts("\n");
12331                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12332                         }
12333                         puts(_("cancelled!\n"));
12334                         return 0;
12335                 }
12336                 if (strchr(short_yes, (char) c)) {
12337                         def = 1;
12338                         break;
12339                 }
12340                 else if (strchr(short_no, (char) c)) {
12341                         def = 0;
12342                         break;
12343                 }
12344                 else if ((c == ' ' || c == '\n') && (def != -1))
12345                         break;
12346         }
12347         if (def)
12348                 puts("yes\n");
12349         else
12350                 puts ("no\n");
12351 #ifdef HAVE_TERMIOS_H
12352         tcsetattr (0, TCSANOW, &termios);
12353 #endif
12354         return def;
12355 }
12356
12357 int ask (e2fsck_t ctx, const char * string, int def)
12358 {
12359         if (ctx->options & E2F_OPT_NO) {
12360                 printf (_("%s? no\n\n"), string);
12361                 return 0;
12362         }
12363         if (ctx->options & E2F_OPT_YES) {
12364                 printf (_("%s? yes\n\n"), string);
12365                 return 1;
12366         }
12367         if (ctx->options & E2F_OPT_PREEN) {
12368                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
12369                 return def;
12370         }
12371         return ask_yn(string, def);
12372 }
12373
12374 void e2fsck_read_bitmaps(e2fsck_t ctx)
12375 {
12376         ext2_filsys fs = ctx->fs;
12377         errcode_t       retval;
12378
12379         if (ctx->invalid_bitmaps) {
12380                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12381                         ctx->device_name);
12382                 bb_error_msg_and_die(0);
12383         }
12384
12385         ehandler_operation(_("reading inode and block bitmaps"));
12386         retval = ext2fs_read_bitmaps(fs);
12387         ehandler_operation(0);
12388         if (retval) {
12389                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12390                         ctx->device_name);
12391                 bb_error_msg_and_die(0);
12392         }
12393 }
12394
12395 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12396 {
12397         ext2_filsys fs = ctx->fs;
12398         errcode_t       retval;
12399
12400         if (ext2fs_test_bb_dirty(fs)) {
12401                 ehandler_operation(_("writing block bitmaps"));
12402                 retval = ext2fs_write_block_bitmap(fs);
12403                 ehandler_operation(0);
12404                 if (retval) {
12405                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12406                                 ctx->device_name);
12407                         bb_error_msg_and_die(0);
12408                 }
12409         }
12410
12411         if (ext2fs_test_ib_dirty(fs)) {
12412                 ehandler_operation(_("writing inode bitmaps"));
12413                 retval = ext2fs_write_inode_bitmap(fs);
12414                 ehandler_operation(0);
12415                 if (retval) {
12416                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12417                                 ctx->device_name);
12418                         bb_error_msg_and_die(0);
12419                 }
12420         }
12421 }
12422
12423 void preenhalt(e2fsck_t ctx)
12424 {
12425         ext2_filsys fs = ctx->fs;
12426
12427         if (!(ctx->options & E2F_OPT_PREEN))
12428                 return;
12429         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12430                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12431                ctx->device_name);
12432         if (fs != NULL) {
12433                 fs->super->s_state |= EXT2_ERROR_FS;
12434                 ext2fs_mark_super_dirty(fs);
12435                 ext2fs_close(fs);
12436         }
12437         exit(EXIT_UNCORRECTED);
12438 }
12439
12440 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12441                               struct ext2_inode * inode, const char *proc)
12442 {
12443         int retval;
12444
12445         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12446         if (retval) {
12447                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12448                 bb_error_msg_and_die(0);
12449         }
12450 }
12451
12452 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12453                                struct ext2_inode * inode, int bufsize,
12454                                const char *proc)
12455 {
12456         int retval;
12457
12458         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12459         if (retval) {
12460                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12461                 bb_error_msg_and_die(0);
12462         }
12463 }
12464
12465 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12466                                struct ext2_inode * inode, const char *proc)
12467 {
12468         int retval;
12469
12470         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12471         if (retval) {
12472                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12473                 bb_error_msg_and_die(0);
12474         }
12475 }
12476
12477 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12478                    io_manager manager)
12479 {
12480         struct ext2_super_block *sb;
12481         io_channel              io = NULL;
12482         void                    *buf = NULL;
12483         int                     blocksize;
12484         blk_t                   superblock, ret_sb = 8193;
12485
12486         if (fs && fs->super) {
12487                 ret_sb = (fs->super->s_blocks_per_group +
12488                           fs->super->s_first_data_block);
12489                 if (ctx) {
12490                         ctx->superblock = ret_sb;
12491                         ctx->blocksize = fs->blocksize;
12492                 }
12493                 return ret_sb;
12494         }
12495
12496         if (ctx) {
12497                 if (ctx->blocksize) {
12498                         ret_sb = ctx->blocksize * 8;
12499                         if (ctx->blocksize == 1024)
12500                                 ret_sb++;
12501                         ctx->superblock = ret_sb;
12502                         return ret_sb;
12503                 }
12504                 ctx->superblock = ret_sb;
12505                 ctx->blocksize = 1024;
12506         }
12507
12508         if (!name || !manager)
12509                 goto cleanup;
12510
12511         if (manager->open(name, 0, &io) != 0)
12512                 goto cleanup;
12513
12514         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12515                 goto cleanup;
12516         sb = (struct ext2_super_block *) buf;
12517
12518         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12519              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
12520                 superblock = blocksize*8;
12521                 if (blocksize == 1024)
12522                         superblock++;
12523                 io_channel_set_blksize(io, blocksize);
12524                 if (io_channel_read_blk(io, superblock,
12525                                         -SUPERBLOCK_SIZE, buf))
12526                         continue;
12527 #if BB_BIG_ENDIAN
12528                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12529                         ext2fs_swap_super(sb);
12530 #endif
12531                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12532                         ret_sb = superblock;
12533                         if (ctx) {
12534                                 ctx->superblock = superblock;
12535                                 ctx->blocksize = blocksize;
12536                         }
12537                         break;
12538                 }
12539         }
12540
12541 cleanup:
12542         if (io)
12543                 io_channel_close(io);
12544         ext2fs_free_mem(&buf);
12545         return (ret_sb);
12546 }
12547
12548
12549 /*
12550  * This function runs through the e2fsck passes and calls them all,
12551  * returning restart, abort, or cancel as necessary...
12552  */
12553 typedef void (*pass_t)(e2fsck_t ctx);
12554
12555 static const pass_t e2fsck_passes[] = {
12556         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12557         e2fsck_pass5, 0 };
12558
12559 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12560
12561 static int e2fsck_run(e2fsck_t ctx)
12562 {
12563         int     i;
12564         pass_t  e2fsck_pass;
12565
12566         if (setjmp(ctx->abort_loc)) {
12567                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12568                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12569         }
12570         ctx->flags |= E2F_FLAG_SETJMP_OK;
12571
12572         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12573                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12574                         break;
12575                 e2fsck_pass(ctx);
12576                 if (ctx->progress)
12577                         (void) (ctx->progress)(ctx, 0, 0, 0);
12578         }
12579         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12580
12581         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12582                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12583         return 0;
12584 }
12585
12586
12587 /*
12588  * unix.c - The unix-specific code for e2fsck
12589  */
12590
12591
12592 /* Command line options */
12593 static int swapfs;
12594 #ifdef ENABLE_SWAPFS
12595 static int normalize_swapfs;
12596 #endif
12597 static int cflag;               /* check disk */
12598 static int show_version_only;
12599 static int verbose;
12600
12601 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12602
12603 static void show_stats(e2fsck_t ctx)
12604 {
12605         ext2_filsys fs = ctx->fs;
12606         int inodes, inodes_used, blocks, blocks_used;
12607         int dir_links;
12608         int num_files, num_links;
12609         int frag_percent;
12610
12611         dir_links = 2 * ctx->fs_directory_count - 1;
12612         num_files = ctx->fs_total_count - dir_links;
12613         num_links = ctx->fs_links_count - dir_links;
12614         inodes = fs->super->s_inodes_count;
12615         inodes_used = (fs->super->s_inodes_count -
12616                        fs->super->s_free_inodes_count);
12617         blocks = fs->super->s_blocks_count;
12618         blocks_used = (fs->super->s_blocks_count -
12619                        fs->super->s_free_blocks_count);
12620
12621         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12622         frag_percent = (frag_percent + 5) / 10;
12623
12624         if (!verbose) {
12625                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12626                        ctx->device_name, inodes_used, inodes,
12627                        frag_percent / 10, frag_percent % 10,
12628                        blocks_used, blocks);
12629                 return;
12630         }
12631         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12632                 100 * inodes_used / inodes);
12633         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
12634                 P_E2("", "s", ctx->fs_fragmented),
12635                 frag_percent / 10, frag_percent % 10);
12636         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12637                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12638         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12639                 (int) ((long long) 100 * blocks_used / blocks));
12640         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12641         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12642         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12643         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12644         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12645         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12646         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12647         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12648         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12649         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12650         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12651 }
12652
12653 static void check_mount(e2fsck_t ctx)
12654 {
12655         errcode_t       retval;
12656         int             cont;
12657
12658         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12659                                          &ctx->mount_flags);
12660         if (retval) {
12661                 bb_error_msg(_("while determining whether %s is mounted."),
12662                         ctx->filesystem_name);
12663                 return;
12664         }
12665
12666         /*
12667          * If the filesystem isn't mounted, or it's the root filesystem
12668          * and it's mounted read-only, then everything's fine.
12669          */
12670         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12671             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12672              (ctx->mount_flags & EXT2_MF_READONLY)))
12673                 return;
12674
12675         if (ctx->options & E2F_OPT_READONLY) {
12676                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12677                 return;
12678         }
12679
12680         printf(_("%s is mounted.  "), ctx->filesystem_name);
12681         if (!ctx->interactive)
12682                 bb_error_msg_and_die(_("Cannot continue, aborting.\n\n"));
12683         printf(_("\n\n\007\007\007\007WARNING!!!  "
12684                "Running e2fsck on a mounted filesystem may cause\n"
12685                "SEVERE filesystem damage.\007\007\007\n\n"));
12686         cont = ask_yn(_("Do you really want to continue"), -1);
12687         if (!cont) {
12688                 printf (_("check aborted.\n"));
12689                 exit (0);
12690         }
12691         return;
12692 }
12693
12694 static int is_on_batt(void)
12695 {
12696         FILE    *f;
12697         DIR     *d;
12698         char    tmp[80], tmp2[80], fname[80];
12699         unsigned int    acflag;
12700         struct dirent*  de;
12701
12702         f = fopen("/proc/apm", "r");
12703         if (f) {
12704                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12705                         acflag = 1;
12706                 fclose(f);
12707                 return (acflag != 1);
12708         }
12709         d = opendir("/proc/acpi/ac_adapter");
12710         if (d) {
12711                 while ((de=readdir(d)) != NULL) {
12712                         if (!strncmp(".", de->d_name, 1))
12713                                 continue;
12714                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12715                                  de->d_name);
12716                         f = fopen(fname, "r");
12717                         if (!f)
12718                                 continue;
12719                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12720                                 tmp[0] = 0;
12721                         fclose(f);
12722                         if (strncmp(tmp, "off-line", 8) == 0) {
12723                                 closedir(d);
12724                                 return 1;
12725                         }
12726                 }
12727                 closedir(d);
12728         }
12729         return 0;
12730 }
12731
12732 /*
12733  * This routine checks to see if a filesystem can be skipped; if so,
12734  * it will exit with EXIT_OK.  Under some conditions it will print a
12735  * message explaining why a check is being forced.
12736  */
12737 static void check_if_skip(e2fsck_t ctx)
12738 {
12739         ext2_filsys fs = ctx->fs;
12740         const char *reason = NULL;
12741         unsigned int reason_arg = 0;
12742         long next_check;
12743         int batt = is_on_batt();
12744         time_t now = time(0);
12745
12746         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12747                 return;
12748
12749         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12750             !ext2fs_test_valid(fs))
12751                 reason = _(" contains a file system with errors");
12752         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12753                 reason = _(" was not cleanly unmounted");
12754         else if ((fs->super->s_max_mnt_count > 0) &&
12755                  (fs->super->s_mnt_count >=
12756                   (unsigned) fs->super->s_max_mnt_count)) {
12757                 reason = _(" has been mounted %u times without being checked");
12758                 reason_arg = fs->super->s_mnt_count;
12759                 if (batt && (fs->super->s_mnt_count <
12760                              (unsigned) fs->super->s_max_mnt_count*2))
12761                         reason = 0;
12762         } else if (fs->super->s_checkinterval &&
12763                    ((now - fs->super->s_lastcheck) >=
12764                     fs->super->s_checkinterval)) {
12765                 reason = _(" has gone %u days without being checked");
12766                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12767                 if (batt && ((now - fs->super->s_lastcheck) <
12768                              fs->super->s_checkinterval*2))
12769                         reason = 0;
12770         }
12771         if (reason) {
12772                 fputs(ctx->device_name, stdout);
12773                 printf(reason, reason_arg);
12774                 fputs(_(", check forced.\n"), stdout);
12775                 return;
12776         }
12777         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12778                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12779                fs->super->s_inodes_count,
12780                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12781                fs->super->s_blocks_count);
12782         next_check = 100000;
12783         if (fs->super->s_max_mnt_count > 0) {
12784                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12785                 if (next_check <= 0)
12786                         next_check = 1;
12787         }
12788         if (fs->super->s_checkinterval &&
12789             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12790                 next_check = 1;
12791         if (next_check <= 5) {
12792                 if (next_check == 1)
12793                         fputs(_(" (check after next mount)"), stdout);
12794                 else
12795                         printf(_(" (check in %ld mounts)"), next_check);
12796         }
12797         fputc('\n', stdout);
12798         ext2fs_close(fs);
12799         ctx->fs = NULL;
12800         e2fsck_free_context(ctx);
12801         exit(EXIT_OK);
12802 }
12803
12804 /*
12805  * For completion notice
12806  */
12807 struct percent_tbl {
12808         int     max_pass;
12809         int     table[32];
12810 };
12811 static const struct percent_tbl e2fsck_tbl = {
12812         5, { 0, 70, 90, 92,  95, 100 }
12813 };
12814
12815 static char bar[128], spaces[128];
12816
12817 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12818                           int max)
12819 {
12820         float   percent;
12821
12822         if (pass <= 0)
12823                 return 0.0;
12824         if (pass > tbl->max_pass || max == 0)
12825                 return 100.0;
12826         percent = ((float) curr) / ((float) max);
12827         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12828                 + tbl->table[pass-1]);
12829 }
12830
12831 void e2fsck_clear_progbar(e2fsck_t ctx)
12832 {
12833         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12834                 return;
12835
12836         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12837                ctx->stop_meta);
12838         fflush(stdout);
12839         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12840 }
12841
12842 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12843                            unsigned int dpynum)
12844 {
12845         static const char spinner[] = "\\|/-";
12846         int     i;
12847         unsigned int    tick;
12848         struct timeval  tv;
12849         int dpywidth;
12850         int fixed_percent;
12851
12852         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12853                 return 0;
12854
12855         /*
12856          * Calculate the new progress position.  If the
12857          * percentage hasn't changed, then we skip out right
12858          * away.
12859          */
12860         fixed_percent = (int) ((10 * percent) + 0.5);
12861         if (ctx->progress_last_percent == fixed_percent)
12862                 return 0;
12863         ctx->progress_last_percent = fixed_percent;
12864
12865         /*
12866          * If we've already updated the spinner once within
12867          * the last 1/8th of a second, no point doing it
12868          * again.
12869          */
12870         gettimeofday(&tv, NULL);
12871         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12872         if ((tick == ctx->progress_last_time) &&
12873             (fixed_percent != 0) && (fixed_percent != 1000))
12874                 return 0;
12875         ctx->progress_last_time = tick;
12876
12877         /*
12878          * Advance the spinner, and note that the progress bar
12879          * will be on the screen
12880          */
12881         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12882         ctx->flags |= E2F_FLAG_PROG_BAR;
12883
12884         dpywidth = 66 - strlen(label);
12885         dpywidth = 8 * (dpywidth / 8);
12886         if (dpynum)
12887                 dpywidth -= 8;
12888
12889         i = ((percent * dpywidth) + 50) / 100;
12890         printf("%s%s: |%s%s", ctx->start_meta, label,
12891                bar + (sizeof(bar) - (i+1)),
12892                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12893         if (fixed_percent == 1000)
12894                 fputc('|', stdout);
12895         else
12896                 fputc(spinner[ctx->progress_pos & 3], stdout);
12897         printf(" %4.1f%%  ", percent);
12898         if (dpynum)
12899                 printf("%u\r", dpynum);
12900         else
12901                 fputs(" \r", stdout);
12902         fputs(ctx->stop_meta, stdout);
12903
12904         if (fixed_percent == 1000)
12905                 e2fsck_clear_progbar(ctx);
12906         fflush(stdout);
12907
12908         return 0;
12909 }
12910
12911 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12912                                   unsigned long cur, unsigned long max)
12913 {
12914         char buf[80];
12915         float percent;
12916
12917         if (pass == 0)
12918                 return 0;
12919
12920         if (ctx->progress_fd) {
12921                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12922                 write(ctx->progress_fd, buf, strlen(buf));
12923         } else {
12924                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12925                 e2fsck_simple_progress(ctx, ctx->device_name,
12926                                        percent, 0);
12927         }
12928         return 0;
12929 }
12930
12931 static void reserve_stdio_fds(void)
12932 {
12933         int     fd;
12934
12935         while (1) {
12936                 fd = open(bb_dev_null, O_RDWR);
12937                 if (fd > 2)
12938                         break;
12939                 if (fd < 0) {
12940                         fprintf(stderr, _("ERROR: Couldn't open "
12941                                 "/dev/null (%s)\n"),
12942                                 strerror(errno));
12943                         break;
12944                 }
12945         }
12946         close(fd);
12947 }
12948
12949 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12950 {
12951         e2fsck_t ctx = e2fsck_global_ctx;
12952
12953         if (!ctx)
12954                 return;
12955
12956         ctx->progress = e2fsck_update_progress;
12957         ctx->progress_fd = 0;
12958 }
12959
12960 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12961 {
12962         e2fsck_t ctx = e2fsck_global_ctx;
12963
12964         if (!ctx)
12965                 return;
12966
12967         e2fsck_clear_progbar(ctx);
12968         ctx->progress = 0;
12969 }
12970
12971 static void signal_cancel(int sig FSCK_ATTR((unused)))
12972 {
12973         e2fsck_t ctx = e2fsck_global_ctx;
12974
12975         if (!ctx)
12976                 exit(FSCK_CANCELED);
12977
12978         ctx->flags |= E2F_FLAG_CANCEL;
12979 }
12980
12981 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12982 {
12983         char    *buf, *token, *next, *p, *arg;
12984         int     ea_ver;
12985         int     extended_usage = 0;
12986
12987         buf = string_copy(opts, 0);
12988         for (token = buf; token && *token; token = next) {
12989                 p = strchr(token, ',');
12990                 next = 0;
12991                 if (p) {
12992                         *p = 0;
12993                         next = p+1;
12994                 }
12995                 arg = strchr(token, '=');
12996                 if (arg) {
12997                         *arg = 0;
12998                         arg++;
12999                 }
13000                 if (strcmp(token, "ea_ver") == 0) {
13001                         if (!arg) {
13002                                 extended_usage++;
13003                                 continue;
13004                         }
13005                         ea_ver = strtoul(arg, &p, 0);
13006                         if (*p ||
13007                             ((ea_ver != 1) && (ea_ver != 2))) {
13008                                 fprintf(stderr,
13009                                         _("Invalid EA version.\n"));
13010                                 extended_usage++;
13011                                 continue;
13012                         }
13013                         ctx->ext_attr_ver = ea_ver;
13014                 } else {
13015                         fprintf(stderr, _("Unknown extended option: %s\n"),
13016                                 token);
13017                         extended_usage++;
13018                 }
13019         }
13020         if (extended_usage) {
13021                 bb_error_msg_and_die(
13022                         "Extended options are separated by commas, "
13023                         "and may take an argument which\n"
13024                         "is set off by an equals ('=') sign.  "
13025                         "Valid extended options are:\n"
13026                         "\tea_ver=<ea_version (1 or 2)>\n\n");
13027         }
13028 }
13029
13030
13031 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
13032 {
13033         int             flush = 0;
13034         int             c, fd;
13035         e2fsck_t        ctx;
13036         errcode_t       retval;
13037         struct sigaction        sa;
13038         char            *extended_opts = 0;
13039
13040         retval = e2fsck_allocate_context(&ctx);
13041         if (retval)
13042                 return retval;
13043
13044         *ret_ctx = ctx;
13045
13046         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
13047         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
13048         if (isatty(0) && isatty(1)) {
13049                 ctx->interactive = 1;
13050         } else {
13051                 ctx->start_meta[0] = '\001';
13052                 ctx->stop_meta[0] = '\002';
13053         }
13054         memset(bar, '=', sizeof(bar)-1);
13055         memset(spaces, ' ', sizeof(spaces)-1);
13056         blkid_get_cache(&ctx->blkid, NULL);
13057
13058         if (argc && *argv)
13059                 ctx->program_name = *argv;
13060         else
13061                 ctx->program_name = "e2fsck";
13062         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13063                 switch (c) {
13064                 case 'C':
13065                         ctx->progress = e2fsck_update_progress;
13066                         ctx->progress_fd = atoi(optarg);
13067                         if (!ctx->progress_fd)
13068                                 break;
13069                         /* Validate the file descriptor to avoid disasters */
13070                         fd = dup(ctx->progress_fd);
13071                         if (fd < 0) {
13072                                 fprintf(stderr,
13073                                 _("Error validating file descriptor %d: %s\n"),
13074                                         ctx->progress_fd,
13075                                         error_message(errno));
13076                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13077                         } else
13078                                 close(fd);
13079                         break;
13080                 case 'D':
13081                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13082                         break;
13083                 case 'E':
13084                         extended_opts = optarg;
13085                         break;
13086                 case 'p':
13087                 case 'a':
13088                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13089                         conflict_opt:
13090                                 bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
13091                         }
13092                         ctx->options |= E2F_OPT_PREEN;
13093                         break;
13094                 case 'n':
13095                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13096                                 goto conflict_opt;
13097                         ctx->options |= E2F_OPT_NO;
13098                         break;
13099                 case 'y':
13100                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13101                                 goto conflict_opt;
13102                         ctx->options |= E2F_OPT_YES;
13103                         break;
13104                 case 't':
13105                         /* FIXME - This needs to go away in a future path - will change binary */
13106                         fprintf(stderr, _("The -t option is not "
13107                                 "supported on this version of e2fsck.\n"));
13108                         break;
13109                 case 'c':
13110                         if (cflag++)
13111                                 ctx->options |= E2F_OPT_WRITECHECK;
13112                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13113                         break;
13114                 case 'r':
13115                         /* What we do by default, anyway! */
13116                         break;
13117                 case 'b':
13118                         ctx->use_superblock = atoi(optarg);
13119                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13120                         break;
13121                 case 'B':
13122                         ctx->blocksize = atoi(optarg);
13123                         break;
13124                 case 'I':
13125                         ctx->inode_buffer_blocks = atoi(optarg);
13126                         break;
13127                 case 'j':
13128                         ctx->journal_name = string_copy(optarg, 0);
13129                         break;
13130                 case 'P':
13131                         ctx->process_inode_size = atoi(optarg);
13132                         break;
13133                 case 'd':
13134                         ctx->options |= E2F_OPT_DEBUG;
13135                         break;
13136                 case 'f':
13137                         ctx->options |= E2F_OPT_FORCE;
13138                         break;
13139                 case 'F':
13140                         flush = 1;
13141                         break;
13142                 case 'v':
13143                         verbose = 1;
13144                         break;
13145                 case 'V':
13146                         show_version_only = 1;
13147                         break;
13148                 case 'N':
13149                         ctx->device_name = optarg;
13150                         break;
13151 #ifdef ENABLE_SWAPFS
13152                 case 's':
13153                         normalize_swapfs = 1;
13154                 case 'S':
13155                         swapfs = 1;
13156                         break;
13157 #else
13158                 case 's':
13159                 case 'S':
13160                         fprintf(stderr, _("Byte-swapping filesystems "
13161                                           "not compiled in this version "
13162                                           "of e2fsck\n"));
13163                         exit(1);
13164 #endif
13165                 default:
13166                         bb_show_usage();
13167                 }
13168         if (show_version_only)
13169                 return 0;
13170         if (optind != argc - 1)
13171                 bb_show_usage();
13172         if ((ctx->options & E2F_OPT_NO) &&
13173             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13174                 ctx->options |= E2F_OPT_READONLY;
13175         ctx->io_options = strchr(argv[optind], '?');
13176         if (ctx->io_options)
13177                 *ctx->io_options++ = 0;
13178         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13179         if (!ctx->filesystem_name) {
13180                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13181                 bb_error_msg_and_die(0);
13182         }
13183         if (extended_opts)
13184                 parse_extended_opts(ctx, extended_opts);
13185
13186         if (flush) {
13187                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13188                 if (fd < 0) {
13189                         bb_error_msg(_("while opening %s for flushing"),
13190                                 ctx->filesystem_name);
13191                         bb_error_msg_and_die(0);
13192                 }
13193                 if ((retval = ext2fs_sync_device(fd, 1))) {
13194                         bb_error_msg(_("while trying to flush %s"),
13195                                 ctx->filesystem_name);
13196                         bb_error_msg_and_die(0);
13197                 }
13198                 close(fd);
13199         }
13200 #ifdef ENABLE_SWAPFS
13201         if (swapfs && cflag) {
13202                         fprintf(stderr, _("Incompatible options not "
13203                                           "allowed when byte-swapping.\n"));
13204                         exit(EXIT_USAGE);
13205         }
13206 #endif
13207         /*
13208          * Set up signal action
13209          */
13210         memset(&sa, 0, sizeof(struct sigaction));
13211         sa.sa_handler = signal_cancel;
13212         sigaction(SIGINT, &sa, 0);
13213         sigaction(SIGTERM, &sa, 0);
13214 #ifdef SA_RESTART
13215         sa.sa_flags = SA_RESTART;
13216 #endif
13217         e2fsck_global_ctx = ctx;
13218         sa.sa_handler = signal_progress_on;
13219         sigaction(SIGUSR1, &sa, 0);
13220         sa.sa_handler = signal_progress_off;
13221         sigaction(SIGUSR2, &sa, 0);
13222
13223         /* Update our PATH to include /sbin if we need to run badblocks  */
13224         if (cflag)
13225                 e2fs_set_sbin_path();
13226         return 0;
13227 }
13228
13229 static const char my_ver_string[] = E2FSPROGS_VERSION;
13230 static const char my_ver_date[] = E2FSPROGS_DATE;
13231
13232 int e2fsck_main (int argc, char *argv[])
13233 {
13234         errcode_t       retval;
13235         int             exit_value = EXIT_OK;
13236         ext2_filsys     fs = 0;
13237         io_manager      io_ptr;
13238         struct ext2_super_block *sb;
13239         const char      *lib_ver_date;
13240         int             my_ver, lib_ver;
13241         e2fsck_t        ctx;
13242         struct problem_context pctx;
13243         int flags, run_result;
13244
13245         clear_problem_context(&pctx);
13246
13247         my_ver = ext2fs_parse_version_string(my_ver_string);
13248         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13249         if (my_ver > lib_ver) {
13250                 fprintf( stderr, _("Error: ext2fs library version "
13251                         "out of date!\n"));
13252                 show_version_only++;
13253         }
13254
13255         retval = PRS(argc, argv, &ctx);
13256         if (retval) {
13257                 bb_error_msg(_("while trying to initialize program"));
13258                 exit(EXIT_ERROR);
13259         }
13260         reserve_stdio_fds();
13261
13262         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13263                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13264                          my_ver_date);
13265
13266         if (show_version_only) {
13267                 fprintf(stderr, _("\tUsing %s, %s\n"),
13268                         error_message(EXT2_ET_BASE), lib_ver_date);
13269                 exit(EXIT_OK);
13270         }
13271
13272         check_mount(ctx);
13273
13274         if (!(ctx->options & E2F_OPT_PREEN) &&
13275             !(ctx->options & E2F_OPT_NO) &&
13276             !(ctx->options & E2F_OPT_YES)) {
13277                 if (!ctx->interactive)
13278                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13279         }
13280         ctx->superblock = ctx->use_superblock;
13281 restart:
13282 #ifdef CONFIG_TESTIO_DEBUG
13283         io_ptr = test_io_manager;
13284         test_io_backing_manager = unix_io_manager;
13285 #else
13286         io_ptr = unix_io_manager;
13287 #endif
13288         flags = 0;
13289         if ((ctx->options & E2F_OPT_READONLY) == 0)
13290                 flags |= EXT2_FLAG_RW;
13291
13292         if (ctx->superblock && ctx->blocksize) {
13293                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13294                                       flags, ctx->superblock, ctx->blocksize,
13295                                       io_ptr, &fs);
13296         } else if (ctx->superblock) {
13297                 int blocksize;
13298                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13299                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13300                         retval = ext2fs_open2(ctx->filesystem_name,
13301                                               ctx->io_options, flags,
13302                                               ctx->superblock, blocksize,
13303                                               io_ptr, &fs);
13304                         if (!retval)
13305                                 break;
13306                 }
13307         } else
13308                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13309                                       flags, 0, 0, io_ptr, &fs);
13310         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13311             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13312             ((retval == EXT2_ET_BAD_MAGIC) ||
13313              ((retval == 0) && ext2fs_check_desc(fs)))) {
13314                 if (!fs || (fs->group_desc_count > 1)) {
13315                         printf(_("%s trying backup blocks...\n"),
13316                                retval ? _("Couldn't find ext2 superblock,") :
13317                                _("Group descriptors look bad..."));
13318                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13319                         if (fs)
13320                                 ext2fs_close(fs);
13321                         goto restart;
13322                 }
13323         }
13324         if (retval) {
13325                 bb_error_msg(_("while trying to open %s"),
13326                         ctx->filesystem_name);
13327                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13328                         printf(_("The filesystem revision is apparently "
13329                                "too high for this version of e2fsck.\n"
13330                                "(Or the filesystem superblock "
13331                                "is corrupt)\n\n"));
13332                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13333                 } else if (retval == EXT2_ET_SHORT_READ)
13334                         printf(_("Could this be a zero-length partition?\n"));
13335                 else if ((retval == EPERM) || (retval == EACCES))
13336                         printf(_("You must have %s access to the "
13337                                "filesystem or be root\n"),
13338                                (ctx->options & E2F_OPT_READONLY) ?
13339                                "r/o" : "r/w");
13340                 else if (retval == ENXIO)
13341                         printf(_("Possibly non-existent or swap device?\n"));
13342 #ifdef EROFS
13343                 else if (retval == EROFS)
13344                         printf(_("Disk write-protected; use the -n option "
13345                                "to do a read-only\n"
13346                                "check of the device.\n"));
13347 #endif
13348                 else
13349                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13350                 bb_error_msg_and_die(0);
13351         }
13352         ctx->fs = fs;
13353         fs->priv_data = ctx;
13354         sb = fs->super;
13355         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13356                 bb_error_msg(_("while trying to open %s"),
13357                         ctx->filesystem_name);
13358         get_newer:
13359                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13360         }
13361
13362         /*
13363          * Set the device name, which is used whenever we print error
13364          * or informational messages to the user.
13365          */
13366         if (ctx->device_name == 0 &&
13367             (sb->s_volume_name[0] != 0)) {
13368                 ctx->device_name = string_copy(sb->s_volume_name,
13369                                                sizeof(sb->s_volume_name));
13370         }
13371         if (ctx->device_name == 0)
13372                 ctx->device_name = ctx->filesystem_name;
13373
13374         /*
13375          * Make sure the ext3 superblock fields are consistent.
13376          */
13377         retval = e2fsck_check_ext3_journal(ctx);
13378         if (retval) {
13379                 bb_error_msg(_("while checking ext3 journal for %s"),
13380                         ctx->device_name);
13381                 bb_error_msg_and_die(0);
13382         }
13383
13384         /*
13385          * Check to see if we need to do ext3-style recovery.  If so,
13386          * do it, and then restart the fsck.
13387          */
13388         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13389                 if (ctx->options & E2F_OPT_READONLY) {
13390                         printf(_("Warning: skipping journal recovery "
13391                                  "because doing a read-only filesystem "
13392                                  "check.\n"));
13393                         io_channel_flush(ctx->fs->io);
13394                 } else {
13395                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13396                                 /*
13397                                  * Whoops, we attempted to run the
13398                                  * journal twice.  This should never
13399                                  * happen, unless the hardware or
13400                                  * device driver is being bogus.
13401                                  */
13402                                 bb_error_msg(_("unable to set superblock flags on %s\n"), ctx->device_name);
13403                                 bb_error_msg_and_die(0);
13404                         }
13405                         retval = e2fsck_run_ext3_journal(ctx);
13406                         if (retval) {
13407                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13408                                         ctx->device_name);
13409                                 bb_error_msg_and_die(0);
13410                         }
13411                         ext2fs_close(ctx->fs);
13412                         ctx->fs = 0;
13413                         ctx->flags |= E2F_FLAG_RESTARTED;
13414                         goto restart;
13415                 }
13416         }
13417
13418         /*
13419          * Check for compatibility with the feature sets.  We need to
13420          * be more stringent than ext2fs_open().
13421          */
13422         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13423             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13424                 bb_error_msg("(%s)", ctx->device_name);
13425                 goto get_newer;
13426         }
13427         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13428                 bb_error_msg("(%s)", ctx->device_name);
13429                 goto get_newer;
13430         }
13431 #ifdef ENABLE_COMPRESSION
13432         /* FIXME - do we support this at all? */
13433         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13434                 bb_error_msg(_("Warning: compression support is experimental.\n"));
13435 #endif
13436 #ifndef ENABLE_HTREE
13437         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13438                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13439                           "but filesystem %s has HTREE directories.\n"),
13440                         ctx->device_name);
13441                 goto get_newer;
13442         }
13443 #endif
13444
13445         /*
13446          * If the user specified a specific superblock, presumably the
13447          * master superblock has been trashed.  So we mark the
13448          * superblock as dirty, so it can be written out.
13449          */
13450         if (ctx->superblock &&
13451             !(ctx->options & E2F_OPT_READONLY))
13452                 ext2fs_mark_super_dirty(fs);
13453
13454         /*
13455          * We only update the master superblock because (a) paranoia;
13456          * we don't want to corrupt the backup superblocks, and (b) we
13457          * don't need to update the mount count and last checked
13458          * fields in the backup superblock (the kernel doesn't
13459          * update the backup superblocks anyway).
13460          */
13461         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13462
13463         ehandler_init(fs->io);
13464
13465         if (ctx->superblock)
13466                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13467         ext2fs_mark_valid(fs);
13468         check_super_block(ctx);
13469         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13470                 bb_error_msg_and_die(0);
13471         check_if_skip(ctx);
13472         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13473                 bb_error_msg_and_die(0);
13474 #ifdef ENABLE_SWAPFS
13475
13476 #ifdef WORDS_BIGENDIAN
13477 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13478 #else
13479 #define NATIVE_FLAG 0
13480 #endif
13481
13482
13483         if (normalize_swapfs) {
13484                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13485                         fprintf(stderr, _("%s: Filesystem byte order "
13486                                 "already normalized.\n"), ctx->device_name);
13487                         bb_error_msg_and_die(0);
13488                 }
13489         }
13490         if (swapfs) {
13491                 swap_filesys(ctx);
13492                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13493                         bb_error_msg_and_die(0);
13494         }
13495 #endif
13496
13497         /*
13498          * Mark the system as valid, 'til proven otherwise
13499          */
13500         ext2fs_mark_valid(fs);
13501
13502         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13503         if (retval) {
13504                 bb_error_msg(_("while reading bad blocks inode"));
13505                 preenhalt(ctx);
13506                 printf(_("This doesn't bode well,"
13507                          " but we'll try to go on...\n"));
13508         }
13509
13510         run_result = e2fsck_run(ctx);
13511         e2fsck_clear_progbar(ctx);
13512         if (run_result == E2F_FLAG_RESTART) {
13513                 printf(_("Restarting e2fsck from the beginning...\n"));
13514                 retval = e2fsck_reset_context(ctx);
13515                 if (retval) {
13516                         bb_error_msg(_("while resetting context"));
13517                         bb_error_msg_and_die(0);
13518                 }
13519                 ext2fs_close(fs);
13520                 goto restart;
13521         }
13522         if (run_result & E2F_FLAG_CANCEL) {
13523                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13524                        ctx->device_name : ctx->filesystem_name);
13525                 exit_value |= FSCK_CANCELED;
13526         }
13527         if (run_result & E2F_FLAG_ABORT)
13528                 bb_error_msg_and_die(_("aborted"));
13529
13530         /* Cleanup */
13531         if (ext2fs_test_changed(fs)) {
13532                 exit_value |= EXIT_NONDESTRUCT;
13533                 if (!(ctx->options & E2F_OPT_PREEN))
13534                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13535                                ctx->device_name);
13536                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13537                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13538                                ctx->device_name);
13539                         exit_value |= EXIT_DESTRUCT;
13540                 }
13541         }
13542         if (!ext2fs_test_valid(fs)) {
13543                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13544                          "errors **********\n\n"), ctx->device_name);
13545                 exit_value |= EXIT_UNCORRECTED;
13546                 exit_value &= ~EXIT_NONDESTRUCT;
13547         }
13548         if (exit_value & FSCK_CANCELED)
13549                 exit_value &= ~EXIT_NONDESTRUCT;
13550         else {
13551                 show_stats(ctx);
13552                 if (!(ctx->options & E2F_OPT_READONLY)) {
13553                         if (ext2fs_test_valid(fs)) {
13554                                 if (!(sb->s_state & EXT2_VALID_FS))
13555                                         exit_value |= EXIT_NONDESTRUCT;
13556                                 sb->s_state = EXT2_VALID_FS;
13557                         } else
13558                                 sb->s_state &= ~EXT2_VALID_FS;
13559                         sb->s_mnt_count = 0;
13560                         sb->s_lastcheck = time(NULL);
13561                         ext2fs_mark_super_dirty(fs);
13562                 }
13563         }
13564
13565         e2fsck_write_bitmaps(ctx);
13566
13567         ext2fs_close(fs);
13568         ctx->fs = NULL;
13569         free(ctx->filesystem_name);
13570         free(ctx->journal_name);
13571         e2fsck_free_context(ctx);
13572
13573         return exit_value;
13574 }