- fix the build if we have ftpput without ftpget (speeling reeoe)
[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 #define _(x) x
43 #define N_(x) x
44
45 /*
46  * Procedure declarations
47  */
48
49 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
50
51 /* pass1.c */
52 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
53
54 /* pass2.c */
55 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
56                                     ext2_ino_t ino, char *buf);
57
58 /* pass3.c */
59 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
60 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
61                                          int num, int gauranteed_size);
62 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
63 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
64                                            int adj);
65
66 /* rehash.c */
67 static void e2fsck_rehash_directories(e2fsck_t ctx);
68
69 /* util.c */
70 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
71                                     const char *description);
72 static int ask(e2fsck_t ctx, const char * string, int def);
73 static void e2fsck_read_bitmaps(e2fsck_t ctx);
74 static void preenhalt(e2fsck_t ctx);
75 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
76                               struct ext2_inode * inode, const char * proc);
77 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
78                                struct ext2_inode * inode, const char * proc);
79 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
80                            const char *name, io_manager manager);
81
82 /* unix.c */
83 static void e2fsck_clear_progbar(e2fsck_t ctx);
84 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
85                                   float percent, unsigned int dpynum);
86
87
88 /*
89  * problem.h --- e2fsck problem error codes
90  */
91
92 typedef __u32 problem_t;
93
94 struct problem_context {
95         errcode_t       errcode;
96         ext2_ino_t ino, ino2, dir;
97         struct ext2_inode *inode;
98         struct ext2_dir_entry *dirent;
99         blk_t   blk, blk2;
100         e2_blkcnt_t     blkcount;
101         int             group;
102         __u64   num;
103         const char *str;
104 };
105
106
107 /*
108  * Function declarations
109  */
110 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
111 static int end_problem_latch(e2fsck_t ctx, int mask);
112 static int set_latch_flags(int mask, int setflags, int clearflags);
113 static void clear_problem_context(struct problem_context *ctx);
114
115 /*
116  * Dictionary Abstract Data Type
117  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
118  *
119  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
120  * kazlib_1_20
121  */
122
123 #ifndef DICT_H
124 #define DICT_H
125
126 /*
127  * Blurb for inclusion into C++ translation units
128  */
129
130 typedef unsigned long dictcount_t;
131 #define DICTCOUNT_T_MAX ULONG_MAX
132
133 /*
134  * The dictionary is implemented as a red-black tree
135  */
136
137 typedef enum { dnode_red, dnode_black } dnode_color_t;
138
139 typedef struct dnode_t {
140     struct dnode_t *dict_left;
141     struct dnode_t *dict_right;
142     struct dnode_t *dict_parent;
143     dnode_color_t dict_color;
144     const void *dict_key;
145     void *dict_data;
146 } dnode_t;
147
148 typedef int (*dict_comp_t)(const void *, const void *);
149 typedef void (*dnode_free_t)(dnode_t *);
150
151 typedef struct dict_t {
152     dnode_t dict_nilnode;
153     dictcount_t dict_nodecount;
154     dictcount_t dict_maxcount;
155     dict_comp_t dict_compare;
156     dnode_free_t dict_freenode;
157     int dict_dupes;
158 } dict_t;
159
160 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
161
162 typedef struct dict_load_t {
163     dict_t *dict_dictptr;
164     dnode_t dict_nilnode;
165 } dict_load_t;
166
167 #define dict_count(D) ((D)->dict_nodecount)
168 #define dnode_get(N) ((N)->dict_data)
169 #define dnode_getkey(N) ((N)->dict_key)
170
171 #endif
172
173 /*
174  * Compatibility header file for e2fsck which should be included
175  * instead of linux/jfs.h
176  *
177  * Copyright (C) 2000 Stephen C. Tweedie
178  */
179
180 /*
181  * Pull in the definition of the e2fsck context structure
182  */
183
184 struct buffer_head {
185         char            b_data[8192];
186         e2fsck_t        b_ctx;
187         io_channel      b_io;
188         int             b_size;
189         blk_t           b_blocknr;
190         int             b_dirty;
191         int             b_uptodate;
192         int             b_err;
193 };
194
195
196 #define K_DEV_FS        1
197 #define K_DEV_JOURNAL   2
198
199 #define lock_buffer(bh) do {} while(0)
200 #define unlock_buffer(bh) do {} while(0)
201 #define buffer_req(bh) 1
202 #define do_readahead(journal, start) do {} while(0)
203
204 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
205
206 typedef struct {
207         int     object_length;
208 } kmem_cache_t;
209
210 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
211
212 /*
213  * We use the standard libext2fs portability tricks for inline
214  * functions.
215  */
216
217 static kmem_cache_t * do_cache_create(int len)
218 {
219         kmem_cache_t *new_cache;
220
221         new_cache = malloc(sizeof(*new_cache));
222         if (new_cache)
223                 new_cache->object_length = len;
224         return new_cache;
225 }
226
227 static void do_cache_destroy(kmem_cache_t *cache)
228 {
229         free(cache);
230 }
231
232
233 /*
234  * Dictionary Abstract Data Type
235  */
236
237
238 /*
239  * These macros provide short convenient names for structure members,
240  * which are embellished with dict_ prefixes so that they are
241  * properly confined to the documented namespace. It's legal for a
242  * program which uses dict to define, for instance, a macro called ``parent''.
243  * Such a macro would interfere with the dnode_t struct definition.
244  * In general, highly portable and reusable C modules which expose their
245  * structures need to confine structure member names to well-defined spaces.
246  * The resulting identifiers aren't necessarily convenient to use, nor
247  * readable, in the implementation, however!
248  */
249
250 #define left dict_left
251 #define right dict_right
252 #define parent dict_parent
253 #define color dict_color
254 #define key dict_key
255 #define data dict_data
256
257 #define nilnode dict_nilnode
258 #define maxcount dict_maxcount
259 #define compare dict_compare
260 #define dupes dict_dupes
261
262 #define dict_root(D) ((D)->nilnode.left)
263 #define dict_nil(D) (&(D)->nilnode)
264
265 static void dnode_free(dnode_t *node);
266
267 /*
268  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
269  * its right child C are rearranged so that the P instead becomes the left
270  * child of C.   The left subtree of C is inherited as the new right subtree
271  * for P.  The ordering of the keys within the tree is thus preserved.
272  */
273
274 static void rotate_left(dnode_t *upper)
275 {
276     dnode_t *lower, *lowleft, *upparent;
277
278     lower = upper->right;
279     upper->right = lowleft = lower->left;
280     lowleft->parent = upper;
281
282     lower->parent = upparent = upper->parent;
283
284     /* don't need to check for root node here because root->parent is
285        the sentinel nil node, and root->parent->left points back to root */
286
287     if (upper == upparent->left) {
288         upparent->left = lower;
289     } else {
290         assert (upper == upparent->right);
291         upparent->right = lower;
292     }
293
294     lower->left = upper;
295     upper->parent = lower;
296 }
297
298 /*
299  * This operation is the ``mirror'' image of rotate_left. It is
300  * the same procedure, but with left and right interchanged.
301  */
302
303 static void rotate_right(dnode_t *upper)
304 {
305     dnode_t *lower, *lowright, *upparent;
306
307     lower = upper->left;
308     upper->left = lowright = lower->right;
309     lowright->parent = upper;
310
311     lower->parent = upparent = upper->parent;
312
313     if (upper == upparent->right) {
314         upparent->right = lower;
315     } else {
316         assert (upper == upparent->left);
317         upparent->left = lower;
318     }
319
320     lower->right = upper;
321     upper->parent = lower;
322 }
323
324 /*
325  * Do a postorder traversal of the tree rooted at the specified
326  * node and free everything under it.  Used by dict_free().
327  */
328
329 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
330 {
331     if (node == nil)
332         return;
333     free_nodes(dict, node->left, nil);
334     free_nodes(dict, node->right, nil);
335     dict->dict_freenode(node);
336 }
337
338 /*
339  * Verify that the tree contains the given node. This is done by
340  * traversing all of the nodes and comparing their pointers to the
341  * given pointer. Returns 1 if the node is found, otherwise
342  * returns zero. It is intended for debugging purposes.
343  */
344
345 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
346 {
347     if (root != nil) {
348         return root == node
349                 || verify_dict_has_node(nil, root->left, node)
350                 || verify_dict_has_node(nil, root->right, node);
351     }
352     return 0;
353 }
354
355
356 /*
357  * Select a different set of node allocator routines.
358  */
359
360 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
361 {
362     assert (dict_count(dict) == 0);
363     dict->dict_freenode = fr;
364 }
365
366 /*
367  * Free all the nodes in the dictionary by using the dictionary's
368  * installed free routine. The dictionary is emptied.
369  */
370
371 static void dict_free_nodes(dict_t *dict)
372 {
373     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
374     free_nodes(dict, root, nil);
375     dict->dict_nodecount = 0;
376     dict->nilnode.left = &dict->nilnode;
377     dict->nilnode.right = &dict->nilnode;
378 }
379
380 /*
381  * Initialize a user-supplied dictionary object.
382  */
383
384 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
385 {
386     dict->compare = comp;
387     dict->dict_freenode = dnode_free;
388     dict->dict_nodecount = 0;
389     dict->maxcount = maxcount;
390     dict->nilnode.left = &dict->nilnode;
391     dict->nilnode.right = &dict->nilnode;
392     dict->nilnode.parent = &dict->nilnode;
393     dict->nilnode.color = dnode_black;
394     dict->dupes = 0;
395     return dict;
396 }
397
398 /*
399  * Locate a node in the dictionary having the given key.
400  * If the node is not found, a null a pointer is returned (rather than
401  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
402  * located node is returned.
403  */
404
405 static dnode_t *dict_lookup(dict_t *dict, const void *key)
406 {
407     dnode_t *root = dict_root(dict);
408     dnode_t *nil = dict_nil(dict);
409     dnode_t *saved;
410     int result;
411
412     /* simple binary search adapted for trees that contain duplicate keys */
413
414     while (root != nil) {
415         result = dict->compare(key, root->key);
416         if (result < 0)
417             root = root->left;
418         else if (result > 0)
419             root = root->right;
420         else {
421             if (!dict->dupes) { /* no duplicates, return match          */
422                 return root;
423             } else {            /* could be dupes, find leftmost one    */
424                 do {
425                     saved = root;
426                     root = root->left;
427                     while (root != nil && dict->compare(key, root->key))
428                         root = root->right;
429                 } while (root != nil);
430                 return saved;
431             }
432         }
433     }
434
435     return NULL;
436 }
437
438 /*
439  * Insert a node into the dictionary. The node should have been
440  * initialized with a data field. All other fields are ignored.
441  * The behavior is undefined if the user attempts to insert into
442  * a dictionary that is already full (for which the dict_isfull()
443  * function returns true).
444  */
445
446 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
447 {
448     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
449     dnode_t *parent = nil, *uncle, *grandpa;
450     int result = -1;
451
452     node->key = key;
453
454     /* basic binary tree insert */
455
456     while (where != nil) {
457         parent = where;
458         result = dict->compare(key, where->key);
459         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
460         assert (dict->dupes || result != 0);
461         if (result < 0)
462             where = where->left;
463         else
464             where = where->right;
465     }
466
467     assert (where == nil);
468
469     if (result < 0)
470         parent->left = node;
471     else
472         parent->right = node;
473
474     node->parent = parent;
475     node->left = nil;
476     node->right = nil;
477
478     dict->dict_nodecount++;
479
480     /* red black adjustments */
481
482     node->color = dnode_red;
483
484     while (parent->color == dnode_red) {
485         grandpa = parent->parent;
486         if (parent == grandpa->left) {
487             uncle = grandpa->right;
488             if (uncle->color == dnode_red) {    /* red parent, red uncle */
489                 parent->color = dnode_black;
490                 uncle->color = dnode_black;
491                 grandpa->color = dnode_red;
492                 node = grandpa;
493                 parent = grandpa->parent;
494             } else {                            /* red parent, black uncle */
495                 if (node == parent->right) {
496                     rotate_left(parent);
497                     parent = node;
498                     assert (grandpa == parent->parent);
499                     /* rotation between parent and child preserves grandpa */
500                 }
501                 parent->color = dnode_black;
502                 grandpa->color = dnode_red;
503                 rotate_right(grandpa);
504                 break;
505             }
506         } else {        /* symmetric cases: parent == parent->parent->right */
507             uncle = grandpa->left;
508             if (uncle->color == dnode_red) {
509                 parent->color = dnode_black;
510                 uncle->color = dnode_black;
511                 grandpa->color = dnode_red;
512                 node = grandpa;
513                 parent = grandpa->parent;
514             } else {
515                 if (node == parent->left) {
516                     rotate_right(parent);
517                     parent = node;
518                     assert (grandpa == parent->parent);
519                 }
520                 parent->color = dnode_black;
521                 grandpa->color = dnode_red;
522                 rotate_left(grandpa);
523                 break;
524             }
525         }
526     }
527
528     dict_root(dict)->color = dnode_black;
529
530 }
531
532 /*
533  * Allocate a node using the dictionary's allocator routine, give it
534  * the data item.
535  */
536
537 static dnode_t *dnode_init(dnode_t *dnode, void *data)
538 {
539     dnode->data = data;
540     dnode->parent = NULL;
541     dnode->left = NULL;
542     dnode->right = NULL;
543     return dnode;
544 }
545
546 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
547 {
548     dnode_t *node = malloc(sizeof(dnode_t));
549
550     if (node) {
551         dnode_init(node, data);
552         dict_insert(dict, node, key);
553         return 1;
554     }
555     return 0;
556 }
557
558 /*
559  * Return the node with the lowest (leftmost) key. If the dictionary is empty
560  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
561  */
562
563 static dnode_t *dict_first(dict_t *dict)
564 {
565     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
566
567     if (root != nil)
568         while ((left = root->left) != nil)
569             root = left;
570
571     return (root == nil) ? NULL : root;
572 }
573
574 /*
575  * Return the given node's successor node---the node which has the
576  * next key in the the left to right ordering. If the node has
577  * no successor, a null pointer is returned rather than a pointer to
578  * the nil node.
579  */
580
581 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
582 {
583     dnode_t *nil = dict_nil(dict), *parent, *left;
584
585     if (curr->right != nil) {
586         curr = curr->right;
587         while ((left = curr->left) != nil)
588             curr = left;
589         return curr;
590     }
591
592     parent = curr->parent;
593
594     while (parent != nil && curr == parent->right) {
595         curr = parent;
596         parent = curr->parent;
597     }
598
599     return (parent == nil) ? NULL : parent;
600 }
601
602
603 static void dnode_free(dnode_t *node)
604 {
605     free(node);
606 }
607
608
609 #undef left
610 #undef right
611 #undef parent
612 #undef color
613 #undef key
614 #undef data
615
616 #undef nilnode
617 #undef maxcount
618 #undef compare
619 #undef dupes
620
621
622 /*
623  * dirinfo.c --- maintains the directory information table for e2fsck.
624  */
625
626 /*
627  * This subroutine is called during pass1 to create a directory info
628  * entry.  During pass1, the passed-in parent is 0; it will get filled
629  * in during pass2.
630  */
631 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
632 {
633         struct dir_info *dir;
634         int             i, j;
635         ext2_ino_t      num_dirs;
636         errcode_t       retval;
637         unsigned long   old_size;
638
639         if (!ctx->dir_info) {
640                 ctx->dir_info_count = 0;
641                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
642                 if (retval)
643                         num_dirs = 1024;        /* Guess */
644                 ctx->dir_info_size = num_dirs + 10;
645                 ctx->dir_info  = (struct dir_info *)
646                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
647                                                * sizeof (struct dir_info),
648                                                "directory map");
649         }
650
651         if (ctx->dir_info_count >= ctx->dir_info_size) {
652                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
653                 ctx->dir_info_size += 10;
654                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
655                                            sizeof(struct dir_info),
656                                            &ctx->dir_info);
657                 if (retval) {
658                         ctx->dir_info_size -= 10;
659                         return;
660                 }
661         }
662
663         /*
664          * Normally, add_dir_info is called with each inode in
665          * sequential order; but once in a while (like when pass 3
666          * needs to recreate the root directory or lost+found
667          * directory) it is called out of order.  In those cases, we
668          * need to move the dir_info entries down to make room, since
669          * the dir_info array needs to be sorted by inode number for
670          * get_dir_info()'s sake.
671          */
672         if (ctx->dir_info_count &&
673             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
674                 for (i = ctx->dir_info_count-1; i > 0; i--)
675                         if (ctx->dir_info[i-1].ino < ino)
676                                 break;
677                 dir = &ctx->dir_info[i];
678                 if (dir->ino != ino)
679                         for (j = ctx->dir_info_count++; j > i; j--)
680                                 ctx->dir_info[j] = ctx->dir_info[j-1];
681         } else
682                 dir = &ctx->dir_info[ctx->dir_info_count++];
683
684         dir->ino = ino;
685         dir->dotdot = parent;
686         dir->parent = parent;
687 }
688
689 /*
690  * get_dir_info() --- given an inode number, try to find the directory
691  * information entry for it.
692  */
693 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
694 {
695         int     low, high, mid;
696
697         low = 0;
698         high = ctx->dir_info_count-1;
699         if (!ctx->dir_info)
700                 return 0;
701         if (ino == ctx->dir_info[low].ino)
702                 return &ctx->dir_info[low];
703         if  (ino == ctx->dir_info[high].ino)
704                 return &ctx->dir_info[high];
705
706         while (low < high) {
707                 mid = (low+high)/2;
708                 if (mid == low || mid == high)
709                         break;
710                 if (ino == ctx->dir_info[mid].ino)
711                         return &ctx->dir_info[mid];
712                 if (ino < ctx->dir_info[mid].ino)
713                         high = mid;
714                 else
715                         low = mid;
716         }
717         return 0;
718 }
719
720 /*
721  * Free the dir_info structure when it isn't needed any more.
722  */
723 static void e2fsck_free_dir_info(e2fsck_t ctx)
724 {
725         ext2fs_free_mem(&ctx->dir_info);
726         ctx->dir_info_size = 0;
727         ctx->dir_info_count = 0;
728 }
729
730 /*
731  * Return the count of number of directories in the dir_info structure
732  */
733 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
734 {
735         return ctx->dir_info_count;
736 }
737
738 /*
739  * A simple interator function
740  */
741 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
742 {
743         if (*control >= ctx->dir_info_count)
744                 return 0;
745
746         return(ctx->dir_info + (*control)++);
747 }
748
749 /*
750  * dirinfo.c --- maintains the directory information table for e2fsck.
751  *
752  */
753
754 #ifdef ENABLE_HTREE
755
756 /*
757  * This subroutine is called during pass1 to create a directory info
758  * entry.  During pass1, the passed-in parent is 0; it will get filled
759  * in during pass2.
760  */
761 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
762 {
763         struct dx_dir_info *dir;
764         int             i, j;
765         errcode_t       retval;
766         unsigned long   old_size;
767
768         if (!ctx->dx_dir_info) {
769                 ctx->dx_dir_info_count = 0;
770                 ctx->dx_dir_info_size = 100; /* Guess */
771                 ctx->dx_dir_info  = (struct dx_dir_info *)
772                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
773                                                * sizeof (struct dx_dir_info),
774                                                "directory map");
775         }
776
777         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
778                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
779                 ctx->dx_dir_info_size += 10;
780                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
781                                            sizeof(struct dx_dir_info),
782                                            &ctx->dx_dir_info);
783                 if (retval) {
784                         ctx->dx_dir_info_size -= 10;
785                         return;
786                 }
787         }
788
789         /*
790          * Normally, add_dx_dir_info is called with each inode in
791          * sequential order; but once in a while (like when pass 3
792          * needs to recreate the root directory or lost+found
793          * directory) it is called out of order.  In those cases, we
794          * need to move the dx_dir_info entries down to make room, since
795          * the dx_dir_info array needs to be sorted by inode number for
796          * get_dx_dir_info()'s sake.
797          */
798         if (ctx->dx_dir_info_count &&
799             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
800                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
801                         if (ctx->dx_dir_info[i-1].ino < ino)
802                                 break;
803                 dir = &ctx->dx_dir_info[i];
804                 if (dir->ino != ino)
805                         for (j = ctx->dx_dir_info_count++; j > i; j--)
806                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
807         } else
808                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
809
810         dir->ino = ino;
811         dir->numblocks = num_blocks;
812         dir->hashversion = 0;
813         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
814                                        * sizeof (struct dx_dirblock_info),
815                                        "dx_block info array");
816
817 }
818
819 /*
820  * get_dx_dir_info() --- given an inode number, try to find the directory
821  * information entry for it.
822  */
823 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
824 {
825         int     low, high, mid;
826
827         low = 0;
828         high = ctx->dx_dir_info_count-1;
829         if (!ctx->dx_dir_info)
830                 return 0;
831         if (ino == ctx->dx_dir_info[low].ino)
832                 return &ctx->dx_dir_info[low];
833         if  (ino == ctx->dx_dir_info[high].ino)
834                 return &ctx->dx_dir_info[high];
835
836         while (low < high) {
837                 mid = (low+high)/2;
838                 if (mid == low || mid == high)
839                         break;
840                 if (ino == ctx->dx_dir_info[mid].ino)
841                         return &ctx->dx_dir_info[mid];
842                 if (ino < ctx->dx_dir_info[mid].ino)
843                         high = mid;
844                 else
845                         low = mid;
846         }
847         return 0;
848 }
849
850 /*
851  * Free the dx_dir_info structure when it isn't needed any more.
852  */
853 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
854 {
855         int     i;
856         struct dx_dir_info *dir;
857
858         if (ctx->dx_dir_info) {
859                 dir = ctx->dx_dir_info;
860                 for (i=0; i < ctx->dx_dir_info_count; i++) {
861                         ext2fs_free_mem(&dir->dx_block);
862                 }
863                 ext2fs_free_mem(&ctx->dx_dir_info);
864         }
865         ctx->dx_dir_info_size = 0;
866         ctx->dx_dir_info_count = 0;
867 }
868
869 /*
870  * A simple interator function
871  */
872 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
873 {
874         if (*control >= ctx->dx_dir_info_count)
875                 return 0;
876
877         return(ctx->dx_dir_info + (*control)++);
878 }
879
880 #endif /* ENABLE_HTREE */
881 /*
882  * e2fsck.c - a consistency checker for the new extended file system.
883  *
884  */
885
886 /*
887  * This function allocates an e2fsck context
888  */
889 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
890 {
891         e2fsck_t        context;
892         errcode_t       retval;
893
894         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
895         if (retval)
896                 return retval;
897
898         memset(context, 0, sizeof(struct e2fsck_struct));
899
900         context->process_inode_size = 256;
901         context->ext_attr_ver = 2;
902
903         *ret = context;
904         return 0;
905 }
906
907 struct ea_refcount_el {
908         blk_t   ea_blk;
909         int     ea_count;
910 };
911
912 struct ea_refcount {
913         blk_t           count;
914         blk_t           size;
915         blk_t           cursor;
916         struct ea_refcount_el   *list;
917 };
918
919 static void ea_refcount_free(ext2_refcount_t refcount)
920 {
921         if (!refcount)
922                 return;
923
924         ext2fs_free_mem(&refcount->list);
925         ext2fs_free_mem(&refcount);
926 }
927
928 /*
929  * This function resets an e2fsck context; it is called when e2fsck
930  * needs to be restarted.
931  */
932 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
933 {
934         ctx->flags = 0;
935         ctx->lost_and_found = 0;
936         ctx->bad_lost_and_found = 0;
937         ext2fs_free_inode_bitmap(ctx->inode_used_map);
938         ctx->inode_used_map = 0;
939         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
940         ctx->inode_dir_map = 0;
941         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
942         ctx->inode_reg_map = 0;
943         ext2fs_free_block_bitmap(ctx->block_found_map);
944         ctx->block_found_map = 0;
945         ext2fs_free_icount(ctx->inode_link_info);
946         ctx->inode_link_info = 0;
947         if (ctx->journal_io) {
948                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
949                         io_channel_close(ctx->journal_io);
950                 ctx->journal_io = 0;
951         }
952         if (ctx->fs) {
953                 ext2fs_free_dblist(ctx->fs->dblist);
954                 ctx->fs->dblist = 0;
955         }
956         e2fsck_free_dir_info(ctx);
957 #ifdef ENABLE_HTREE
958         e2fsck_free_dx_dir_info(ctx);
959 #endif
960         ea_refcount_free(ctx->refcount);
961         ctx->refcount = 0;
962         ea_refcount_free(ctx->refcount_extra);
963         ctx->refcount_extra = 0;
964         ext2fs_free_block_bitmap(ctx->block_dup_map);
965         ctx->block_dup_map = 0;
966         ext2fs_free_block_bitmap(ctx->block_ea_map);
967         ctx->block_ea_map = 0;
968         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
969         ctx->inode_bad_map = 0;
970         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
971         ctx->inode_imagic_map = 0;
972         ext2fs_u32_list_free(ctx->dirs_to_hash);
973         ctx->dirs_to_hash = 0;
974
975         /*
976          * Clear the array of invalid meta-data flags
977          */
978         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
979         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
980         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
981
982         /* Clear statistic counters */
983         ctx->fs_directory_count = 0;
984         ctx->fs_regular_count = 0;
985         ctx->fs_blockdev_count = 0;
986         ctx->fs_chardev_count = 0;
987         ctx->fs_links_count = 0;
988         ctx->fs_symlinks_count = 0;
989         ctx->fs_fast_symlinks_count = 0;
990         ctx->fs_fifo_count = 0;
991         ctx->fs_total_count = 0;
992         ctx->fs_sockets_count = 0;
993         ctx->fs_ind_count = 0;
994         ctx->fs_dind_count = 0;
995         ctx->fs_tind_count = 0;
996         ctx->fs_fragmented = 0;
997         ctx->large_files = 0;
998
999         /* Reset the superblock to the user's requested value */
1000         ctx->superblock = ctx->use_superblock;
1001
1002         return 0;
1003 }
1004
1005 static void e2fsck_free_context(e2fsck_t ctx)
1006 {
1007         if (!ctx)
1008                 return;
1009
1010         e2fsck_reset_context(ctx);
1011         if (ctx->blkid)
1012                 blkid_put_cache(ctx->blkid);
1013
1014         ext2fs_free_mem(&ctx);
1015 }
1016
1017 /*
1018  * ea_refcount.c
1019  */
1020
1021 /*
1022  * The strategy we use for keeping track of EA refcounts is as
1023  * follows.  We keep a sorted array of first EA blocks and its
1024  * reference counts.  Once the refcount has dropped to zero, it is
1025  * removed from the array to save memory space.  Once the EA block is
1026  * checked, its bit is set in the block_ea_map bitmap.
1027  */
1028
1029
1030 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1031 {
1032         ext2_refcount_t refcount;
1033         errcode_t       retval;
1034         size_t          bytes;
1035
1036         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1037         if (retval)
1038                 return retval;
1039         memset(refcount, 0, sizeof(struct ea_refcount));
1040
1041         if (!size)
1042                 size = 500;
1043         refcount->size = size;
1044         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1045 #ifdef DEBUG
1046         printf("Refcount allocated %d entries, %d bytes.\n",
1047                refcount->size, bytes);
1048 #endif
1049         retval = ext2fs_get_mem(bytes, &refcount->list);
1050         if (retval)
1051                 goto errout;
1052         memset(refcount->list, 0, bytes);
1053
1054         refcount->count = 0;
1055         refcount->cursor = 0;
1056
1057         *ret = refcount;
1058         return 0;
1059
1060 errout:
1061         ea_refcount_free(refcount);
1062         return(retval);
1063 }
1064
1065 /*
1066  * collapse_refcount() --- go through the refcount array, and get rid
1067  * of any count == zero entries
1068  */
1069 static void refcount_collapse(ext2_refcount_t refcount)
1070 {
1071         unsigned int    i, j;
1072         struct ea_refcount_el   *list;
1073
1074         list = refcount->list;
1075         for (i = 0, j = 0; i < refcount->count; i++) {
1076                 if (list[i].ea_count) {
1077                         if (i != j)
1078                                 list[j] = list[i];
1079                         j++;
1080                 }
1081         }
1082 #if defined(DEBUG) || defined(TEST_PROGRAM)
1083         printf("Refcount_collapse: size was %d, now %d\n",
1084                refcount->count, j);
1085 #endif
1086         refcount->count = j;
1087 }
1088
1089
1090 /*
1091  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1092  *      specified position.
1093  */
1094 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1095                                                  blk_t blk, int pos)
1096 {
1097         struct ea_refcount_el   *el;
1098         errcode_t               retval;
1099         blk_t                   new_size = 0;
1100         int                     num;
1101
1102         if (refcount->count >= refcount->size) {
1103                 new_size = refcount->size + 100;
1104 #ifdef DEBUG
1105                 printf("Reallocating refcount %d entries...\n", new_size);
1106 #endif
1107                 retval = ext2fs_resize_mem((size_t) refcount->size *
1108                                            sizeof(struct ea_refcount_el),
1109                                            (size_t) new_size *
1110                                            sizeof(struct ea_refcount_el),
1111                                            &refcount->list);
1112                 if (retval)
1113                         return 0;
1114                 refcount->size = new_size;
1115         }
1116         num = (int) refcount->count - pos;
1117         if (num < 0)
1118                 return 0;       /* should never happen */
1119         if (num) {
1120                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1121                         sizeof(struct ea_refcount_el) * num);
1122         }
1123         refcount->count++;
1124         el = &refcount->list[pos];
1125         el->ea_count = 0;
1126         el->ea_blk = blk;
1127         return el;
1128 }
1129
1130
1131 /*
1132  * get_refcount_el() --- given an block number, try to find refcount
1133  *      information in the sorted list.  If the create flag is set,
1134  *      and we can't find an entry, create one in the sorted list.
1135  */
1136 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1137                                               blk_t blk, int create)
1138 {
1139         float   range;
1140         int     low, high, mid;
1141         blk_t   lowval, highval;
1142
1143         if (!refcount || !refcount->list)
1144                 return 0;
1145 retry:
1146         low = 0;
1147         high = (int) refcount->count-1;
1148         if (create && ((refcount->count == 0) ||
1149                        (blk > refcount->list[high].ea_blk))) {
1150                 if (refcount->count >= refcount->size)
1151                         refcount_collapse(refcount);
1152
1153                 return insert_refcount_el(refcount, blk,
1154                                           (unsigned) refcount->count);
1155         }
1156         if (refcount->count == 0)
1157                 return 0;
1158
1159         if (refcount->cursor >= refcount->count)
1160                 refcount->cursor = 0;
1161         if (blk == refcount->list[refcount->cursor].ea_blk)
1162                 return &refcount->list[refcount->cursor++];
1163 #ifdef DEBUG
1164         printf("Non-cursor get_refcount_el: %u\n", blk);
1165 #endif
1166         while (low <= high) {
1167                 if (low == high)
1168                         mid = low;
1169                 else {
1170                         /* Interpolate for efficiency */
1171                         lowval = refcount->list[low].ea_blk;
1172                         highval = refcount->list[high].ea_blk;
1173
1174                         if (blk < lowval)
1175                                 range = 0;
1176                         else if (blk > highval)
1177                                 range = 1;
1178                         else
1179                                 range = ((float) (blk - lowval)) /
1180                                         (highval - lowval);
1181                         mid = low + ((int) (range * (high-low)));
1182                 }
1183
1184                 if (blk == refcount->list[mid].ea_blk) {
1185                         refcount->cursor = mid+1;
1186                         return &refcount->list[mid];
1187                 }
1188                 if (blk < refcount->list[mid].ea_blk)
1189                         high = mid-1;
1190                 else
1191                         low = mid+1;
1192         }
1193         /*
1194          * If we need to create a new entry, it should be right at
1195          * low (where high will be left at low-1).
1196          */
1197         if (create) {
1198                 if (refcount->count >= refcount->size) {
1199                         refcount_collapse(refcount);
1200                         if (refcount->count < refcount->size)
1201                                 goto retry;
1202                 }
1203                 return insert_refcount_el(refcount, blk, low);
1204         }
1205         return 0;
1206 }
1207
1208 static errcode_t
1209 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1210 {
1211         struct ea_refcount_el   *el;
1212
1213         el = get_refcount_el(refcount, blk, 1);
1214         if (!el)
1215                 return EXT2_ET_NO_MEMORY;
1216         el->ea_count++;
1217
1218         if (ret)
1219                 *ret = el->ea_count;
1220         return 0;
1221 }
1222
1223 static errcode_t
1224 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1225 {
1226         struct ea_refcount_el   *el;
1227
1228         el = get_refcount_el(refcount, blk, 0);
1229         if (!el || el->ea_count == 0)
1230                 return EXT2_ET_INVALID_ARGUMENT;
1231
1232         el->ea_count--;
1233
1234         if (ret)
1235                 *ret = el->ea_count;
1236         return 0;
1237 }
1238
1239 static errcode_t
1240 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1241 {
1242         struct ea_refcount_el   *el;
1243
1244         /*
1245          * Get the refcount element
1246          */
1247         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1248         if (!el)
1249                 return count ? EXT2_ET_NO_MEMORY : 0;
1250         el->ea_count = count;
1251         return 0;
1252 }
1253
1254 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1255 {
1256         refcount->cursor = 0;
1257 }
1258
1259
1260 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1261 {
1262         struct ea_refcount_el   *list;
1263
1264         while (1) {
1265                 if (refcount->cursor >= refcount->count)
1266                         return 0;
1267                 list = refcount->list;
1268                 if (list[refcount->cursor].ea_count) {
1269                         if (ret)
1270                                 *ret = list[refcount->cursor].ea_count;
1271                         return list[refcount->cursor++].ea_blk;
1272                 }
1273                 refcount->cursor++;
1274         }
1275 }
1276
1277
1278 /*
1279  * ehandler.c --- handle bad block errors which come up during the
1280  *      course of an e2fsck session.
1281  */
1282
1283
1284 static const char *operation;
1285
1286 static errcode_t
1287 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1288                          void *data, size_t size FSCK_ATTR((unused)),
1289                          int actual FSCK_ATTR((unused)), errcode_t error)
1290 {
1291         int     i;
1292         char    *p;
1293         ext2_filsys fs = (ext2_filsys) channel->app_data;
1294         e2fsck_t ctx;
1295
1296         ctx = (e2fsck_t) fs->priv_data;
1297
1298         /*
1299          * If more than one block was read, try reading each block
1300          * separately.  We could use the actual bytes read to figure
1301          * out where to start, but we don't bother.
1302          */
1303         if (count > 1) {
1304                 p = (char *) data;
1305                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1306                         error = io_channel_read_blk(channel, block,
1307                                                     1, p);
1308                         if (error)
1309                                 return error;
1310                 }
1311                 return 0;
1312         }
1313         if (operation)
1314                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1315                        error_message(error), operation);
1316         else
1317                 printf(_("Error reading block %lu (%s).  "), block,
1318                        error_message(error));
1319         preenhalt(ctx);
1320         if (ask(ctx, _("Ignore error"), 1)) {
1321                 if (ask(ctx, _("Force rewrite"), 1))
1322                         io_channel_write_blk(channel, block, 1, data);
1323                 return 0;
1324         }
1325
1326         return error;
1327 }
1328
1329 static errcode_t
1330 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1331                         const void *data, size_t size FSCK_ATTR((unused)),
1332                         int actual FSCK_ATTR((unused)), errcode_t error)
1333 {
1334         int             i;
1335         const char      *p;
1336         ext2_filsys fs = (ext2_filsys) channel->app_data;
1337         e2fsck_t ctx;
1338
1339         ctx = (e2fsck_t) fs->priv_data;
1340
1341         /*
1342          * If more than one block was written, try writing each block
1343          * separately.  We could use the actual bytes read to figure
1344          * out where to start, but we don't bother.
1345          */
1346         if (count > 1) {
1347                 p = (const char *) data;
1348                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1349                         error = io_channel_write_blk(channel, block,
1350                                                      1, p);
1351                         if (error)
1352                                 return error;
1353                 }
1354                 return 0;
1355         }
1356
1357         if (operation)
1358                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1359                        error_message(error), operation);
1360         else
1361                 printf(_("Error writing block %lu (%s).  "), block,
1362                        error_message(error));
1363         preenhalt(ctx);
1364         if (ask(ctx, _("Ignore error"), 1))
1365                 return 0;
1366
1367         return error;
1368 }
1369
1370 static inline const char *ehandler_operation(const char *op)
1371 {
1372         const char *ret = operation;
1373
1374         operation = op;
1375         return ret;
1376 }
1377
1378 static void ehandler_init(io_channel channel)
1379 {
1380         channel->read_error = e2fsck_handle_read_error;
1381         channel->write_error = e2fsck_handle_write_error;
1382 }
1383
1384 /*
1385  * journal.c --- code for handling the "ext3" journal
1386  *
1387  * Copyright (C) 2000 Andreas Dilger
1388  * Copyright (C) 2000 Theodore Ts'o
1389  *
1390  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1391  * Copyright (C) 1999 Red Hat Software
1392  *
1393  * This file may be redistributed under the terms of the
1394  * GNU General Public License version 2 or at your discretion
1395  * any later version.
1396  */
1397
1398 /*
1399  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1400  * This creates a larger static binary, and a smaller binary using
1401  * shared libraries.  It's also probably slightly less CPU-efficient,
1402  * which is why it's not on by default.  But, it's a good way of
1403  * testing the functions in inode_io.c and fileio.c.
1404  */
1405 #undef USE_INODE_IO
1406
1407 /* Kernel compatibility functions for handling the journal.  These allow us
1408  * to use the recovery.c file virtually unchanged from the kernel, so we
1409  * don't have to do much to keep kernel and user recovery in sync.
1410  */
1411 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1412 {
1413 #ifdef USE_INODE_IO
1414         *phys = block;
1415         return 0;
1416 #else
1417         struct inode    *inode = journal->j_inode;
1418         errcode_t       retval;
1419         blk_t           pblk;
1420
1421         if (!inode) {
1422                 *phys = block;
1423                 return 0;
1424         }
1425
1426         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1427                             &inode->i_ext2, NULL, 0, block, &pblk);
1428         *phys = pblk;
1429         return (retval);
1430 #endif
1431 }
1432
1433 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1434 {
1435         struct buffer_head *bh;
1436
1437         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1438         if (!bh)
1439                 return NULL;
1440
1441         bh->b_ctx = kdev->k_ctx;
1442         if (kdev->k_dev == K_DEV_FS)
1443                 bh->b_io = kdev->k_ctx->fs->io;
1444         else
1445                 bh->b_io = kdev->k_ctx->journal_io;
1446         bh->b_size = blocksize;
1447         bh->b_blocknr = blocknr;
1448
1449         return bh;
1450 }
1451
1452 static void sync_blockdev(kdev_t kdev)
1453 {
1454         io_channel      io;
1455
1456         if (kdev->k_dev == K_DEV_FS)
1457                 io = kdev->k_ctx->fs->io;
1458         else
1459                 io = kdev->k_ctx->journal_io;
1460
1461         io_channel_flush(io);
1462 }
1463
1464 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1465 {
1466         int retval;
1467         struct buffer_head *bh;
1468
1469         for (; nr > 0; --nr) {
1470                 bh = *bhp++;
1471                 if (rw == READ && !bh->b_uptodate) {
1472                         retval = io_channel_read_blk(bh->b_io,
1473                                                      bh->b_blocknr,
1474                                                      1, bh->b_data);
1475                         if (retval) {
1476                                 bb_error_msg("while reading block %lu\n",
1477                                         (unsigned long) bh->b_blocknr);
1478                                 bh->b_err = retval;
1479                                 continue;
1480                         }
1481                         bh->b_uptodate = 1;
1482                 } else if (rw == WRITE && bh->b_dirty) {
1483                         retval = io_channel_write_blk(bh->b_io,
1484                                                       bh->b_blocknr,
1485                                                       1, bh->b_data);
1486                         if (retval) {
1487                                 bb_error_msg("while writing block %lu\n",
1488                                         (unsigned long) bh->b_blocknr);
1489                                 bh->b_err = retval;
1490                                 continue;
1491                         }
1492                         bh->b_dirty = 0;
1493                         bh->b_uptodate = 1;
1494                 }
1495         }
1496 }
1497
1498 static inline void mark_buffer_dirty(struct buffer_head *bh)
1499 {
1500         bh->b_dirty = 1;
1501 }
1502
1503 static inline void mark_buffer_clean(struct buffer_head * bh)
1504 {
1505         bh->b_dirty = 0;
1506 }
1507
1508 static void brelse(struct buffer_head *bh)
1509 {
1510         if (bh->b_dirty)
1511                 ll_rw_block(WRITE, 1, &bh);
1512         ext2fs_free_mem(&bh);
1513 }
1514
1515 static inline int buffer_uptodate(struct buffer_head *bh)
1516 {
1517         return bh->b_uptodate;
1518 }
1519
1520 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1521 {
1522         bh->b_uptodate = val;
1523 }
1524
1525 static void wait_on_buffer(struct buffer_head *bh)
1526 {
1527         if (!bh->b_uptodate)
1528                 ll_rw_block(READ, 1, &bh);
1529 }
1530
1531
1532 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1533 {
1534         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1535
1536         /* if we had an error doing journal recovery, we need a full fsck */
1537         if (error)
1538                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1539         ext2fs_mark_super_dirty(ctx->fs);
1540 }
1541
1542 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1543 {
1544         struct ext2_super_block *sb = ctx->fs->super;
1545         struct ext2_super_block jsuper;
1546         struct problem_context  pctx;
1547         struct buffer_head      *bh;
1548         struct inode            *j_inode = NULL;
1549         struct kdev_s           *dev_fs = NULL, *dev_journal;
1550         const char              *journal_name = 0;
1551         journal_t               *journal = NULL;
1552         errcode_t               retval = 0;
1553         io_manager              io_ptr = 0;
1554         unsigned long           start = 0;
1555         blk_t                   blk;
1556         int                     ext_journal = 0;
1557         int                     tried_backup_jnl = 0;
1558         int                     i;
1559
1560         clear_problem_context(&pctx);
1561
1562         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1563         if (!journal) {
1564                 return EXT2_ET_NO_MEMORY;
1565         }
1566
1567         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1568         if (!dev_fs) {
1569                 retval = EXT2_ET_NO_MEMORY;
1570                 goto errout;
1571         }
1572         dev_journal = dev_fs+1;
1573
1574         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1575         dev_fs->k_dev = K_DEV_FS;
1576         dev_journal->k_dev = K_DEV_JOURNAL;
1577
1578         journal->j_dev = dev_journal;
1579         journal->j_fs_dev = dev_fs;
1580         journal->j_inode = NULL;
1581         journal->j_blocksize = ctx->fs->blocksize;
1582
1583         if (uuid_is_null(sb->s_journal_uuid)) {
1584                 if (!sb->s_journal_inum)
1585                         return EXT2_ET_BAD_INODE_NUM;
1586                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1587                                                  "journal inode");
1588                 if (!j_inode) {
1589                         retval = EXT2_ET_NO_MEMORY;
1590                         goto errout;
1591                 }
1592
1593                 j_inode->i_ctx = ctx;
1594                 j_inode->i_ino = sb->s_journal_inum;
1595
1596                 if ((retval = ext2fs_read_inode(ctx->fs,
1597                                                 sb->s_journal_inum,
1598                                                 &j_inode->i_ext2))) {
1599                 try_backup_journal:
1600                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1601                             tried_backup_jnl)
1602                                 goto errout;
1603                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1604                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1605                                EXT2_N_BLOCKS*4);
1606                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1607                         j_inode->i_ext2.i_links_count = 1;
1608                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1609                         tried_backup_jnl++;
1610                 }
1611                 if (!j_inode->i_ext2.i_links_count ||
1612                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1613                         retval = EXT2_ET_NO_JOURNAL;
1614                         goto try_backup_journal;
1615                 }
1616                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1617                     JFS_MIN_JOURNAL_BLOCKS) {
1618                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1619                         goto try_backup_journal;
1620                 }
1621                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1622                         blk = j_inode->i_ext2.i_block[i];
1623                         if (!blk) {
1624                                 if (i < EXT2_NDIR_BLOCKS) {
1625                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1626                                         goto try_backup_journal;
1627                                 }
1628                                 continue;
1629                         }
1630                         if (blk < sb->s_first_data_block ||
1631                             blk >= sb->s_blocks_count) {
1632                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1633                                 goto try_backup_journal;
1634                         }
1635                 }
1636                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1637
1638 #ifdef USE_INODE_IO
1639                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1640                                                  &j_inode->i_ext2,
1641                                                  &journal_name);
1642                 if (retval)
1643                         goto errout;
1644
1645                 io_ptr = inode_io_manager;
1646 #else
1647                 journal->j_inode = j_inode;
1648                 ctx->journal_io = ctx->fs->io;
1649                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1650                         goto errout;
1651 #endif
1652         } else {
1653                 ext_journal = 1;
1654                 if (!ctx->journal_name) {
1655                         char uuid[37];
1656
1657                         uuid_unparse(sb->s_journal_uuid, uuid);
1658                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1659                                                               "UUID", uuid);
1660                         if (!ctx->journal_name)
1661                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1662                 }
1663                 journal_name = ctx->journal_name;
1664
1665                 if (!journal_name) {
1666                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1667                         return EXT2_ET_LOAD_EXT_JOURNAL;
1668                 }
1669
1670                 io_ptr = unix_io_manager;
1671         }
1672
1673 #ifndef USE_INODE_IO
1674         if (ext_journal)
1675 #endif
1676                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1677                                       &ctx->journal_io);
1678         if (retval)
1679                 goto errout;
1680
1681         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1682
1683         if (ext_journal) {
1684                 if (ctx->fs->blocksize == 1024)
1685                         start = 1;
1686                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1687                 if (!bh) {
1688                         retval = EXT2_ET_NO_MEMORY;
1689                         goto errout;
1690                 }
1691                 ll_rw_block(READ, 1, &bh);
1692                 if ((retval = bh->b_err) != 0)
1693                         goto errout;
1694                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1695                        sizeof(jsuper));
1696                 brelse(bh);
1697 #if BB_BIG_ENDIAN
1698                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1699                         ext2fs_swap_super(&jsuper);
1700 #endif
1701                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1702                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1703                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1704                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1705                         goto errout;
1706                 }
1707                 /* Make sure the journal UUID is correct */
1708                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1709                            sizeof(jsuper.s_uuid))) {
1710                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1711                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1712                         goto errout;
1713                 }
1714
1715                 journal->j_maxlen = jsuper.s_blocks_count;
1716                 start++;
1717         }
1718
1719         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1720                 retval = EXT2_ET_NO_MEMORY;
1721                 goto errout;
1722         }
1723
1724         journal->j_sb_buffer = bh;
1725         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1726
1727 #ifdef USE_INODE_IO
1728         ext2fs_free_mem(&j_inode);
1729 #endif
1730
1731         *ret_journal = journal;
1732         return 0;
1733
1734 errout:
1735         ext2fs_free_mem(&dev_fs);
1736         ext2fs_free_mem(&j_inode);
1737         ext2fs_free_mem(&journal);
1738         return retval;
1739
1740 }
1741
1742 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1743                                               struct problem_context *pctx)
1744 {
1745         struct ext2_super_block *sb = ctx->fs->super;
1746         int recover = ctx->fs->super->s_feature_incompat &
1747                 EXT3_FEATURE_INCOMPAT_RECOVER;
1748         int has_journal = ctx->fs->super->s_feature_compat &
1749                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1750
1751         if (has_journal || sb->s_journal_inum) {
1752                 /* The journal inode is bogus, remove and force full fsck */
1753                 pctx->ino = sb->s_journal_inum;
1754                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1755                         if (has_journal && sb->s_journal_inum)
1756                                 printf("*** ext3 journal has been deleted - "
1757                                        "filesystem is now ext2 only ***\n\n");
1758                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1759                         sb->s_journal_inum = 0;
1760                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1761                         e2fsck_clear_recover(ctx, 1);
1762                         return 0;
1763                 }
1764                 return EXT2_ET_BAD_INODE_NUM;
1765         } else if (recover) {
1766                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1767                         e2fsck_clear_recover(ctx, 1);
1768                         return 0;
1769                 }
1770                 return EXT2_ET_UNSUPP_FEATURE;
1771         }
1772         return 0;
1773 }
1774
1775 #define V1_SB_SIZE      0x0024
1776 static void clear_v2_journal_fields(journal_t *journal)
1777 {
1778         e2fsck_t ctx = journal->j_dev->k_ctx;
1779         struct problem_context pctx;
1780
1781         clear_problem_context(&pctx);
1782
1783         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1784                 return;
1785
1786         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1787                ctx->fs->blocksize-V1_SB_SIZE);
1788         mark_buffer_dirty(journal->j_sb_buffer);
1789 }
1790
1791
1792 static errcode_t e2fsck_journal_load(journal_t *journal)
1793 {
1794         e2fsck_t ctx = journal->j_dev->k_ctx;
1795         journal_superblock_t *jsb;
1796         struct buffer_head *jbh = journal->j_sb_buffer;
1797         struct problem_context pctx;
1798
1799         clear_problem_context(&pctx);
1800
1801         ll_rw_block(READ, 1, &jbh);
1802         if (jbh->b_err) {
1803                 bb_error_msg(_("reading journal superblock\n"));
1804                 return jbh->b_err;
1805         }
1806
1807         jsb = journal->j_superblock;
1808         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1809         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1810                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1811
1812         switch (ntohl(jsb->s_header.h_blocktype)) {
1813         case JFS_SUPERBLOCK_V1:
1814                 journal->j_format_version = 1;
1815                 if (jsb->s_feature_compat ||
1816                     jsb->s_feature_incompat ||
1817                     jsb->s_feature_ro_compat ||
1818                     jsb->s_nr_users)
1819                         clear_v2_journal_fields(journal);
1820                 break;
1821
1822         case JFS_SUPERBLOCK_V2:
1823                 journal->j_format_version = 2;
1824                 if (ntohl(jsb->s_nr_users) > 1 &&
1825                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1826                         clear_v2_journal_fields(journal);
1827                 if (ntohl(jsb->s_nr_users) > 1) {
1828                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1829                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1830                 }
1831                 break;
1832
1833         /*
1834          * These should never appear in a journal super block, so if
1835          * they do, the journal is badly corrupted.
1836          */
1837         case JFS_DESCRIPTOR_BLOCK:
1838         case JFS_COMMIT_BLOCK:
1839         case JFS_REVOKE_BLOCK:
1840                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1841
1842         /* If we don't understand the superblock major type, but there
1843          * is a magic number, then it is likely to be a new format we
1844          * just don't understand, so leave it alone. */
1845         default:
1846                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1847         }
1848
1849         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1850                 return EXT2_ET_UNSUPP_FEATURE;
1851
1852         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1853                 return EXT2_ET_RO_UNSUPP_FEATURE;
1854
1855         /* We have now checked whether we know enough about the journal
1856          * format to be able to proceed safely, so any other checks that
1857          * fail we should attempt to recover from. */
1858         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1859                 bb_error_msg(_("%s: no valid journal superblock found\n"),
1860                         ctx->device_name);
1861                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1862         }
1863
1864         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1865                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1866         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1867                 bb_error_msg(_("%s: journal too short\n"),
1868                         ctx->device_name);
1869                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1870         }
1871
1872         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1873         journal->j_transaction_sequence = journal->j_tail_sequence;
1874         journal->j_tail = ntohl(jsb->s_start);
1875         journal->j_first = ntohl(jsb->s_first);
1876         journal->j_last = ntohl(jsb->s_maxlen);
1877
1878         return 0;
1879 }
1880
1881 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1882                                        journal_t *journal)
1883 {
1884         char *p;
1885         union {
1886                 uuid_t uuid;
1887                 __u32 val[4];
1888         } u;
1889         __u32 new_seq = 0;
1890         int i;
1891
1892         /* Leave a valid existing V1 superblock signature alone.
1893          * Anything unrecognisable we overwrite with a new V2
1894          * signature. */
1895
1896         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1897             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1898                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1899                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1900         }
1901
1902         /* Zero out everything else beyond the superblock header */
1903
1904         p = ((char *) jsb) + sizeof(journal_header_t);
1905         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1906
1907         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1908         jsb->s_maxlen = htonl(journal->j_maxlen);
1909         jsb->s_first = htonl(1);
1910
1911         /* Initialize the journal sequence number so that there is "no"
1912          * chance we will find old "valid" transactions in the journal.
1913          * This avoids the need to zero the whole journal (slow to do,
1914          * and risky when we are just recovering the filesystem).
1915          */
1916         uuid_generate(u.uuid);
1917         for (i = 0; i < 4; i ++)
1918                 new_seq ^= u.val[i];
1919         jsb->s_sequence = htonl(new_seq);
1920
1921         mark_buffer_dirty(journal->j_sb_buffer);
1922         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1923 }
1924
1925 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1926                                                   journal_t *journal,
1927                                                   struct problem_context *pctx)
1928 {
1929         struct ext2_super_block *sb = ctx->fs->super;
1930         int recover = ctx->fs->super->s_feature_incompat &
1931                 EXT3_FEATURE_INCOMPAT_RECOVER;
1932
1933         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1934                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1935                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1936                                                    journal);
1937                         journal->j_transaction_sequence = 1;
1938                         e2fsck_clear_recover(ctx, recover);
1939                         return 0;
1940                 }
1941                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1942         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1943                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1944
1945         return 0;
1946 }
1947
1948 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1949                                    int reset, int drop)
1950 {
1951         journal_superblock_t *jsb;
1952
1953         if (drop)
1954                 mark_buffer_clean(journal->j_sb_buffer);
1955         else if (!(ctx->options & E2F_OPT_READONLY)) {
1956                 jsb = journal->j_superblock;
1957                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1958                 if (reset)
1959                         jsb->s_start = 0; /* this marks the journal as empty */
1960                 mark_buffer_dirty(journal->j_sb_buffer);
1961         }
1962         brelse(journal->j_sb_buffer);
1963
1964         if (ctx->journal_io) {
1965                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1966                         io_channel_close(ctx->journal_io);
1967                 ctx->journal_io = 0;
1968         }
1969
1970 #ifndef USE_INODE_IO
1971         ext2fs_free_mem(&journal->j_inode);
1972 #endif
1973         ext2fs_free_mem(&journal->j_fs_dev);
1974         ext2fs_free_mem(&journal);
1975 }
1976
1977 /*
1978  * This function makes sure that the superblock fields regarding the
1979  * journal are consistent.
1980  */
1981 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1982 {
1983         struct ext2_super_block *sb = ctx->fs->super;
1984         journal_t *journal;
1985         int recover = ctx->fs->super->s_feature_incompat &
1986                 EXT3_FEATURE_INCOMPAT_RECOVER;
1987         struct problem_context pctx;
1988         problem_t problem;
1989         int reset = 0, force_fsck = 0;
1990         int retval;
1991
1992         /* If we don't have any journal features, don't do anything more */
1993         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1994             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1995             uuid_is_null(sb->s_journal_uuid))
1996                 return 0;
1997
1998         clear_problem_context(&pctx);
1999         pctx.num = sb->s_journal_inum;
2000
2001         retval = e2fsck_get_journal(ctx, &journal);
2002         if (retval) {
2003                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2004                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2005                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2006                     (retval == EXT2_ET_NO_JOURNAL))
2007                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2008                 return retval;
2009         }
2010
2011         retval = e2fsck_journal_load(journal);
2012         if (retval) {
2013                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2014                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2015                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2016                                   &pctx))) ||
2017                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2018                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2019                                   &pctx))) ||
2020                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2021                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2022                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2023                                                                   &pctx);
2024                 e2fsck_journal_release(ctx, journal, 0, 1);
2025                 return retval;
2026         }
2027
2028         /*
2029          * We want to make the flags consistent here.  We will not leave with
2030          * needs_recovery set but has_journal clear.  We can't get in a loop
2031          * with -y, -n, or -p, only if a user isn't making up their mind.
2032          */
2033 no_has_journal:
2034         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2035                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2036                 pctx.str = "inode";
2037                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2038                         if (recover &&
2039                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2040                                 goto no_has_journal;
2041                         /*
2042                          * Need a full fsck if we are releasing a
2043                          * journal stored on a reserved inode.
2044                          */
2045                         force_fsck = recover ||
2046                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2047                         /* Clear all of the journal fields */
2048                         sb->s_journal_inum = 0;
2049                         sb->s_journal_dev = 0;
2050                         memset(sb->s_journal_uuid, 0,
2051                                sizeof(sb->s_journal_uuid));
2052                         e2fsck_clear_recover(ctx, force_fsck);
2053                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2054                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2055                         ext2fs_mark_super_dirty(ctx->fs);
2056                 }
2057         }
2058
2059         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2060             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2061             journal->j_superblock->s_start != 0) {
2062                 /* Print status information */
2063                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2064                 if (ctx->superblock)
2065                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2066                 else
2067                         problem = PR_0_JOURNAL_RUN;
2068                 if (fix_problem(ctx, problem, &pctx)) {
2069                         ctx->options |= E2F_OPT_FORCE;
2070                         sb->s_feature_incompat |=
2071                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2072                         ext2fs_mark_super_dirty(ctx->fs);
2073                 } else if (fix_problem(ctx,
2074                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2075                         reset = 1;
2076                         sb->s_state &= ~EXT2_VALID_FS;
2077                         ext2fs_mark_super_dirty(ctx->fs);
2078                 }
2079                 /*
2080                  * If the user answers no to the above question, we
2081                  * ignore the fact that journal apparently has data;
2082                  * accidentally replaying over valid data would be far
2083                  * worse than skipping a questionable recovery.
2084                  *
2085                  * XXX should we abort with a fatal error here?  What
2086                  * will the ext3 kernel code do if a filesystem with
2087                  * !NEEDS_RECOVERY but with a non-zero
2088                  * journal->j_superblock->s_start is mounted?
2089                  */
2090         }
2091
2092         e2fsck_journal_release(ctx, journal, reset, 0);
2093         return retval;
2094 }
2095
2096 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2097 {
2098         journal_t *journal;
2099         int retval;
2100
2101         journal_init_revoke_caches();
2102         retval = e2fsck_get_journal(ctx, &journal);
2103         if (retval)
2104                 return retval;
2105
2106         retval = e2fsck_journal_load(journal);
2107         if (retval)
2108                 goto errout;
2109
2110         retval = journal_init_revoke(journal, 1024);
2111         if (retval)
2112                 goto errout;
2113
2114         retval = -journal_recover(journal);
2115         if (retval)
2116                 goto errout;
2117
2118         if (journal->j_superblock->s_errno) {
2119                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2120                 ext2fs_mark_super_dirty(ctx->fs);
2121                 journal->j_superblock->s_errno = 0;
2122                 mark_buffer_dirty(journal->j_sb_buffer);
2123         }
2124
2125 errout:
2126         journal_destroy_revoke(journal);
2127         journal_destroy_revoke_caches();
2128         e2fsck_journal_release(ctx, journal, 1, 0);
2129         return retval;
2130 }
2131
2132 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2133 {
2134         io_manager io_ptr = ctx->fs->io->manager;
2135         int blocksize = ctx->fs->blocksize;
2136         errcode_t       retval, recover_retval;
2137
2138         printf(_("%s: recovering journal\n"), ctx->device_name);
2139         if (ctx->options & E2F_OPT_READONLY) {
2140                 printf(_("%s: won't do journal recovery while read-only\n"),
2141                        ctx->device_name);
2142                 return EXT2_ET_FILE_RO;
2143         }
2144
2145         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2146                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2147
2148         recover_retval = recover_ext3_journal(ctx);
2149
2150         /*
2151          * Reload the filesystem context to get up-to-date data from disk
2152          * because journal recovery will change the filesystem under us.
2153          */
2154         ext2fs_close(ctx->fs);
2155         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2156                              ctx->superblock, blocksize, io_ptr,
2157                              &ctx->fs);
2158
2159         if (retval) {
2160                 bb_error_msg(_("while trying to re-open %s"),
2161                         ctx->device_name);
2162                 bb_error_msg_and_die(0);
2163         }
2164         ctx->fs->priv_data = ctx;
2165
2166         /* Set the superblock flags */
2167         e2fsck_clear_recover(ctx, recover_retval);
2168         return recover_retval;
2169 }
2170
2171 /*
2172  * This function will move the journal inode from a visible file in
2173  * the filesystem directory hierarchy to the reserved inode if necessary.
2174  */
2175 static const char * const journal_names[] = {
2176         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2177
2178 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2179 {
2180         struct ext2_super_block *sb = ctx->fs->super;
2181         struct problem_context  pctx;
2182         struct ext2_inode       inode;
2183         ext2_filsys             fs = ctx->fs;
2184         ext2_ino_t              ino;
2185         errcode_t               retval;
2186         const char * const *    cpp;
2187         int                     group, mount_flags;
2188
2189         clear_problem_context(&pctx);
2190
2191         /*
2192          * If the filesystem is opened read-only, or there is no
2193          * journal, then do nothing.
2194          */
2195         if ((ctx->options & E2F_OPT_READONLY) ||
2196             (sb->s_journal_inum == 0) ||
2197             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2198                 return;
2199
2200         /*
2201          * Read in the journal inode
2202          */
2203         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2204                 return;
2205
2206         /*
2207          * If it's necessary to backup the journal inode, do so.
2208          */
2209         if ((sb->s_jnl_backup_type == 0) ||
2210             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2211              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2212                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2213                         memcpy(sb->s_jnl_blocks, inode.i_block,
2214                                EXT2_N_BLOCKS*4);
2215                         sb->s_jnl_blocks[16] = inode.i_size;
2216                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2217                         ext2fs_mark_super_dirty(fs);
2218                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2219                 }
2220         }
2221
2222         /*
2223          * If the journal is already the hidden inode, then do nothing
2224          */
2225         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2226                 return;
2227
2228         /*
2229          * The journal inode had better have only one link and not be readable.
2230          */
2231         if (inode.i_links_count != 1)
2232                 return;
2233
2234         /*
2235          * If the filesystem is mounted, or we can't tell whether
2236          * or not it's mounted, do nothing.
2237          */
2238         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2239         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2240                 return;
2241
2242         /*
2243          * If we can't find the name of the journal inode, then do
2244          * nothing.
2245          */
2246         for (cpp = journal_names; *cpp; cpp++) {
2247                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2248                                        strlen(*cpp), 0, &ino);
2249                 if ((retval == 0) && (ino == sb->s_journal_inum))
2250                         break;
2251         }
2252         if (*cpp == 0)
2253                 return;
2254
2255         /* We need the inode bitmap to be loaded */
2256         retval = ext2fs_read_bitmaps(fs);
2257         if (retval)
2258                 return;
2259
2260         pctx.str = *cpp;
2261         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2262                 return;
2263
2264         /*
2265          * OK, we've done all the checks, let's actually move the
2266          * journal inode.  Errors at this point mean we need to force
2267          * an ext2 filesystem check.
2268          */
2269         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2270                 goto err_out;
2271         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2272                 goto err_out;
2273         sb->s_journal_inum = EXT2_JOURNAL_INO;
2274         ext2fs_mark_super_dirty(fs);
2275         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2276         inode.i_links_count = 0;
2277         inode.i_dtime = time(0);
2278         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2279                 goto err_out;
2280
2281         group = ext2fs_group_of_ino(fs, ino);
2282         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2283         ext2fs_mark_ib_dirty(fs);
2284         fs->group_desc[group].bg_free_inodes_count++;
2285         fs->super->s_free_inodes_count++;
2286         return;
2287
2288 err_out:
2289         pctx.errcode = retval;
2290         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2291         fs->super->s_state &= ~EXT2_VALID_FS;
2292         ext2fs_mark_super_dirty(fs);
2293         return;
2294 }
2295
2296 /*
2297  * message.c --- print e2fsck messages (with compression)
2298  *
2299  * print_e2fsck_message() prints a message to the user, using
2300  * compression techniques and expansions of abbreviations.
2301  *
2302  * The following % expansions are supported:
2303  *
2304  *      %b      <blk>                   block number
2305  *      %B      <blkcount>              integer
2306  *      %c      <blk2>                  block number
2307  *      %Di     <dirent>->ino           inode number
2308  *      %Dn     <dirent>->name          string
2309  *      %Dr     <dirent>->rec_len
2310  *      %Dl     <dirent>->name_len
2311  *      %Dt     <dirent>->filetype
2312  *      %d      <dir>                   inode number
2313  *      %g      <group>                 integer
2314  *      %i      <ino>                   inode number
2315  *      %Is     <inode> -> i_size
2316  *      %IS     <inode> -> i_extra_isize
2317  *      %Ib     <inode> -> i_blocks
2318  *      %Il     <inode> -> i_links_count
2319  *      %Im     <inode> -> i_mode
2320  *      %IM     <inode> -> i_mtime
2321  *      %IF     <inode> -> i_faddr
2322  *      %If     <inode> -> i_file_acl
2323  *      %Id     <inode> -> i_dir_acl
2324  *      %Iu     <inode> -> i_uid
2325  *      %Ig     <inode> -> i_gid
2326  *      %j      <ino2>                  inode number
2327  *      %m      <com_err error message>
2328  *      %N      <num>
2329  *      %p      ext2fs_get_pathname of directory <ino>
2330  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2331  *                      the containing directory.  (If dirent is NULL
2332  *                      then return the pathname of directory <ino2>)
2333  *      %q      ext2fs_get_pathname of directory <dir>
2334  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2335  *                      the containing directory.
2336  *      %s      <str>                   miscellaneous string
2337  *      %S      backup superblock
2338  *      %X      <num> hexadecimal format
2339  *
2340  * The following '@' expansions are supported:
2341  *
2342  *      @a      extended attribute
2343  *      @A      error allocating
2344  *      @b      block
2345  *      @B      bitmap
2346  *      @c      compress
2347  *      @C      conflicts with some other fs block
2348  *      @D      deleted
2349  *      @d      directory
2350  *      @e      entry
2351  *      @E      Entry '%Dn' in %p (%i)
2352  *      @f      filesystem
2353  *      @F      for @i %i (%Q) is
2354  *      @g      group
2355  *      @h      HTREE directory inode
2356  *      @i      inode
2357  *      @I      illegal
2358  *      @j      journal
2359  *      @l      lost+found
2360  *      @L      is a link
2361  *      @m      multiply-claimed
2362  *      @n      invalid
2363  *      @o      orphaned
2364  *      @p      problem in
2365  *      @r      root inode
2366  *      @s      should be
2367  *      @S      superblock
2368  *      @u      unattached
2369  *      @v      device
2370  *      @z      zero-length
2371  */
2372
2373
2374 /*
2375  * This structure defines the abbreviations used by the text strings
2376  * below.  The first character in the string is the index letter.  An
2377  * abbreviation of the form '@<i>' is expanded by looking up the index
2378  * letter <i> in the table below.
2379  */
2380 static const char * const abbrevs[] = {
2381         N_("aextended attribute"),
2382         N_("Aerror allocating"),
2383         N_("bblock"),
2384         N_("Bbitmap"),
2385         N_("ccompress"),
2386         N_("Cconflicts with some other fs @b"),
2387         N_("iinode"),
2388         N_("Iillegal"),
2389         N_("jjournal"),
2390         N_("Ddeleted"),
2391         N_("ddirectory"),
2392         N_("eentry"),
2393         N_("E@e '%Dn' in %p (%i)"),
2394         N_("ffilesystem"),
2395         N_("Ffor @i %i (%Q) is"),
2396         N_("ggroup"),
2397         N_("hHTREE @d @i"),
2398         N_("llost+found"),
2399         N_("Lis a link"),
2400     N_("mmultiply-claimed"),
2401     N_("ninvalid"),
2402         N_("oorphaned"),
2403         N_("pproblem in"),
2404         N_("rroot @i"),
2405         N_("sshould be"),
2406         N_("Ssuper@b"),
2407         N_("uunattached"),
2408         N_("vdevice"),
2409         N_("zzero-length"),
2410         "@@",
2411         0
2412         };
2413
2414 /*
2415  * Give more user friendly names to the "special" inodes.
2416  */
2417 #define num_special_inodes      11
2418 static const char * const special_inode_name[] =
2419 {
2420         N_("<The NULL inode>"),                 /* 0 */
2421         N_("<The bad blocks inode>"),           /* 1 */
2422         "/",                                    /* 2 */
2423         N_("<The ACL index inode>"),            /* 3 */
2424         N_("<The ACL data inode>"),             /* 4 */
2425         N_("<The boot loader inode>"),          /* 5 */
2426         N_("<The undelete directory inode>"),   /* 6 */
2427         N_("<The group descriptor inode>"),     /* 7 */
2428         N_("<The journal inode>"),              /* 8 */
2429         N_("<Reserved inode 9>"),               /* 9 */
2430         N_("<Reserved inode 10>"),              /* 10 */
2431 };
2432
2433 /*
2434  * This function does "safe" printing.  It will convert non-printable
2435  * ASCII characters using '^' and M- notation.
2436  */
2437 static void safe_print(const char *cp, int len)
2438 {
2439         unsigned char   ch;
2440
2441         if (len < 0)
2442                 len = strlen(cp);
2443
2444         while (len--) {
2445                 ch = *cp++;
2446                 if (ch > 128) {
2447                         fputs("M-", stdout);
2448                         ch -= 128;
2449                 }
2450                 if ((ch < 32) || (ch == 0x7f)) {
2451                         fputc('^', stdout);
2452                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2453                 }
2454                 fputc(ch, stdout);
2455         }
2456 }
2457
2458
2459 /*
2460  * This function prints a pathname, using the ext2fs_get_pathname
2461  * function
2462  */
2463 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2464 {
2465         errcode_t       retval;
2466         char            *path;
2467
2468         if (!dir && (ino < num_special_inodes)) {
2469                 fputs(_(special_inode_name[ino]), stdout);
2470                 return;
2471         }
2472
2473         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2474         if (retval)
2475                 fputs("???", stdout);
2476         else {
2477                 safe_print(path, -1);
2478                 ext2fs_free_mem(&path);
2479         }
2480 }
2481
2482 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2483                           struct problem_context *pctx, int first);
2484 /*
2485  * This function handles the '@' expansion.  We allow recursive
2486  * expansion; an @ expression can contain further '@' and '%'
2487  * expressions.
2488  */
2489 static void expand_at_expression(e2fsck_t ctx, char ch,
2490                                           struct problem_context *pctx,
2491                                           int *first)
2492 {
2493         const char * const *cpp;
2494         const char *str;
2495
2496         /* Search for the abbreviation */
2497         for (cpp = abbrevs; *cpp; cpp++) {
2498                 if (ch == *cpp[0])
2499                         break;
2500         }
2501         if (*cpp) {
2502                 str = _(*cpp) + 1;
2503                 if (*first && islower(*str)) {
2504                         *first = 0;
2505                         fputc(toupper(*str++), stdout);
2506                 }
2507                 print_e2fsck_message(ctx, str, pctx, *first);
2508         } else
2509                 printf("@%c", ch);
2510 }
2511
2512 /*
2513  * This function expands '%IX' expressions
2514  */
2515 static void expand_inode_expression(char ch,
2516                                              struct problem_context *ctx)
2517 {
2518         struct ext2_inode       *inode;
2519         struct ext2_inode_large *large_inode;
2520         char *                  time_str;
2521         time_t                  t;
2522         int                     do_gmt = -1;
2523
2524         if (!ctx || !ctx->inode)
2525                 goto no_inode;
2526
2527         inode = ctx->inode;
2528         large_inode = (struct ext2_inode_large *) inode;
2529
2530         switch (ch) {
2531         case 's':
2532                 if (LINUX_S_ISDIR(inode->i_mode))
2533                         printf("%u", inode->i_size);
2534                 else {
2535 #ifdef EXT2_NO_64_TYPE
2536                         if (inode->i_size_high)
2537                                 printf("0x%x%08x", inode->i_size_high,
2538                                        inode->i_size);
2539                         else
2540                                 printf("%u", inode->i_size);
2541 #else
2542                         printf("%llu", (inode->i_size |
2543                                         ((__u64) inode->i_size_high << 32)));
2544 #endif
2545                 }
2546                 break;
2547         case 'S':
2548                 printf("%u", large_inode->i_extra_isize);
2549                 break;
2550         case 'b':
2551                 printf("%u", inode->i_blocks);
2552                 break;
2553         case 'l':
2554                 printf("%d", inode->i_links_count);
2555                 break;
2556         case 'm':
2557                 printf("0%o", inode->i_mode);
2558                 break;
2559         case 'M':
2560                 /* The diet libc doesn't respect the TZ environemnt variable */
2561                 if (do_gmt == -1) {
2562                         time_str = getenv("TZ");
2563                         if (!time_str)
2564                                 time_str = "";
2565                         do_gmt = !strcmp(time_str, "GMT");
2566                 }
2567                 t = inode->i_mtime;
2568                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2569                 printf("%.24s", time_str);
2570                 break;
2571         case 'F':
2572                 printf("%u", inode->i_faddr);
2573                 break;
2574         case 'f':
2575                 printf("%u", inode->i_file_acl);
2576                 break;
2577         case 'd':
2578                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2579                               inode->i_dir_acl : 0));
2580                 break;
2581         case 'u':
2582                 printf("%d", (inode->i_uid |
2583                               (inode->osd2.linux2.l_i_uid_high << 16)));
2584                 break;
2585         case 'g':
2586                 printf("%d", (inode->i_gid |
2587                               (inode->osd2.linux2.l_i_gid_high << 16)));
2588                 break;
2589         default:
2590         no_inode:
2591                 printf("%%I%c", ch);
2592                 break;
2593         }
2594 }
2595
2596 /*
2597  * This function expands '%dX' expressions
2598  */
2599 static void expand_dirent_expression(char ch,
2600                                               struct problem_context *ctx)
2601 {
2602         struct ext2_dir_entry   *dirent;
2603         int     len;
2604
2605         if (!ctx || !ctx->dirent)
2606                 goto no_dirent;
2607
2608         dirent = ctx->dirent;
2609
2610         switch (ch) {
2611         case 'i':
2612                 printf("%u", dirent->inode);
2613                 break;
2614         case 'n':
2615                 len = dirent->name_len & 0xFF;
2616                 if (len > EXT2_NAME_LEN)
2617                         len = EXT2_NAME_LEN;
2618                 if (len > dirent->rec_len)
2619                         len = dirent->rec_len;
2620                 safe_print(dirent->name, len);
2621                 break;
2622         case 'r':
2623                 printf("%u", dirent->rec_len);
2624                 break;
2625         case 'l':
2626                 printf("%u", dirent->name_len & 0xFF);
2627                 break;
2628         case 't':
2629                 printf("%u", dirent->name_len >> 8);
2630                 break;
2631         default:
2632         no_dirent:
2633                 printf("%%D%c", ch);
2634                 break;
2635         }
2636 }
2637
2638 static void expand_percent_expression(ext2_filsys fs, char ch,
2639                                                struct problem_context *ctx)
2640 {
2641         if (!ctx)
2642                 goto no_context;
2643
2644         switch (ch) {
2645         case '%':
2646                 fputc('%', stdout);
2647                 break;
2648         case 'b':
2649                 printf("%u", ctx->blk);
2650                 break;
2651         case 'B':
2652 #ifdef EXT2_NO_64_TYPE
2653                 printf("%d", ctx->blkcount);
2654 #else
2655                 printf("%lld", ctx->blkcount);
2656 #endif
2657                 break;
2658         case 'c':
2659                 printf("%u", ctx->blk2);
2660                 break;
2661         case 'd':
2662                 printf("%u", ctx->dir);
2663                 break;
2664         case 'g':
2665                 printf("%d", ctx->group);
2666                 break;
2667         case 'i':
2668                 printf("%u", ctx->ino);
2669                 break;
2670         case 'j':
2671                 printf("%u", ctx->ino2);
2672                 break;
2673         case 'm':
2674                 printf("%s", error_message(ctx->errcode));
2675                 break;
2676         case 'N':
2677 #ifdef EXT2_NO_64_TYPE
2678                 printf("%u", ctx->num);
2679 #else
2680                 printf("%llu", ctx->num);
2681 #endif
2682                 break;
2683         case 'p':
2684                 print_pathname(fs, ctx->ino, 0);
2685                 break;
2686         case 'P':
2687                 print_pathname(fs, ctx->ino2,
2688                                ctx->dirent ? ctx->dirent->inode : 0);
2689                 break;
2690         case 'q':
2691                 print_pathname(fs, ctx->dir, 0);
2692                 break;
2693         case 'Q':
2694                 print_pathname(fs, ctx->dir, ctx->ino);
2695                 break;
2696         case 'S':
2697                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2698                 break;
2699         case 's':
2700                 printf("%s", ctx->str ? ctx->str : "NULL");
2701                 break;
2702         case 'X':
2703 #ifdef EXT2_NO_64_TYPE
2704                 printf("0x%x", ctx->num);
2705 #else
2706                 printf("0x%llx", ctx->num);
2707 #endif
2708                 break;
2709         default:
2710         no_context:
2711                 printf("%%%c", ch);
2712                 break;
2713         }
2714 }
2715
2716
2717 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2718                           struct problem_context *pctx, int first)
2719 {
2720         ext2_filsys fs = ctx->fs;
2721         const char *    cp;
2722         int             i;
2723
2724         e2fsck_clear_progbar(ctx);
2725         for (cp = msg; *cp; cp++) {
2726                 if (cp[0] == '@') {
2727                         cp++;
2728                         expand_at_expression(ctx, *cp, pctx, &first);
2729                 } else if (cp[0] == '%' && cp[1] == 'I') {
2730                         cp += 2;
2731                         expand_inode_expression(*cp, pctx);
2732                 } else if (cp[0] == '%' && cp[1] == 'D') {
2733                         cp += 2;
2734                         expand_dirent_expression(*cp, pctx);
2735                 } else if ((cp[0] == '%')) {
2736                         cp++;
2737                         expand_percent_expression(fs, *cp, pctx);
2738                 } else {
2739                         for (i=0; cp[i]; i++)
2740                                 if ((cp[i] == '@') || cp[i] == '%')
2741                                         break;
2742                         printf("%.*s", i, cp);
2743                         cp += i-1;
2744                 }
2745                 first = 0;
2746         }
2747 }
2748
2749
2750 /*
2751  * region.c --- code which manages allocations within a region.
2752  */
2753
2754 struct region_el {
2755         region_addr_t   start;
2756         region_addr_t   end;
2757         struct region_el *next;
2758 };
2759
2760 struct region_struct {
2761         region_addr_t   min;
2762         region_addr_t   max;
2763         struct region_el *allocated;
2764 };
2765
2766 static region_t region_create(region_addr_t min, region_addr_t max)
2767 {
2768         region_t        region;
2769
2770         region = malloc(sizeof(struct region_struct));
2771         if (!region)
2772                 return NULL;
2773         memset(region, 0, sizeof(struct region_struct));
2774         region->min = min;
2775         region->max = max;
2776         return region;
2777 }
2778
2779 static void region_free(region_t region)
2780 {
2781         struct region_el        *r, *next;
2782
2783         for (r = region->allocated; r; r = next) {
2784                 next = r->next;
2785                 free(r);
2786         }
2787         memset(region, 0, sizeof(struct region_struct));
2788         free(region);
2789 }
2790
2791 static int region_allocate(region_t region, region_addr_t start, int n)
2792 {
2793         struct region_el        *r, *new_region, *prev, *next;
2794         region_addr_t end;
2795
2796         end = start+n;
2797         if ((start < region->min) || (end > region->max))
2798                 return -1;
2799         if (n == 0)
2800                 return 1;
2801
2802         /*
2803          * Search through the linked list.  If we find that it
2804          * conflicts witih something that's already allocated, return
2805          * 1; if we can find an existing region which we can grow, do
2806          * so.  Otherwise, stop when we find the appropriate place
2807          * insert a new region element into the linked list.
2808          */
2809         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2810                 if (((start >= r->start) && (start < r->end)) ||
2811                     ((end > r->start) && (end <= r->end)) ||
2812                     ((start <= r->start) && (end >= r->end)))
2813                         return 1;
2814                 if (end == r->start) {
2815                         r->start = start;
2816                         return 0;
2817                 }
2818                 if (start == r->end) {
2819                         if ((next = r->next)) {
2820                                 if (end > next->start)
2821                                         return 1;
2822                                 if (end == next->start) {
2823                                         r->end = next->end;
2824                                         r->next = next->next;
2825                                         free(next);
2826                                         return 0;
2827                                 }
2828                         }
2829                         r->end = end;
2830                         return 0;
2831                 }
2832                 if (start < r->start)
2833                         break;
2834         }
2835         /*
2836          * Insert a new region element structure into the linked list
2837          */
2838         new_region = malloc(sizeof(struct region_el));
2839         if (!new_region)
2840                 return -1;
2841         new_region->start = start;
2842         new_region->end = start + n;
2843         new_region->next = r;
2844         if (prev)
2845                 prev->next = new_region;
2846         else
2847                 region->allocated = new_region;
2848         return 0;
2849 }
2850
2851 /*
2852  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2853  *
2854  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2855  * and applies the following tests to each inode:
2856  *
2857  *      - The mode field of the inode must be legal.
2858  *      - The size and block count fields of the inode are correct.
2859  *      - A data block must not be used by another inode
2860  *
2861  * Pass 1 also gathers the collects the following information:
2862  *
2863  *      - A bitmap of which inodes are in use.          (inode_used_map)
2864  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2865  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2866  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2867  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2868  *      - A bitmap of which blocks are in use.          (block_found_map)
2869  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2870  *      - The data blocks of the directory inodes.      (dir_map)
2871  *
2872  * Pass 1 is designed to stash away enough information so that the
2873  * other passes should not need to read in the inode information
2874  * during the normal course of a filesystem check.  (Althogh if an
2875  * inconsistency is detected, other passes may need to read in an
2876  * inode to fix it.)
2877  *
2878  * Note that pass 1B will be invoked if there are any duplicate blocks
2879  * found.
2880  */
2881
2882
2883 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2884                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2885                          int ref_offset, void *priv_data);
2886 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2887                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2888                              int ref_offset, void *priv_data);
2889 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2890                          char *block_buf);
2891 static void mark_table_blocks(e2fsck_t ctx);
2892 static void alloc_imagic_map(e2fsck_t ctx);
2893 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2894 static void handle_fs_bad_blocks(e2fsck_t ctx);
2895 static void process_inodes(e2fsck_t ctx, char *block_buf);
2896 static int process_inode_cmp(const void *a, const void *b);
2897 static errcode_t scan_callback(ext2_filsys fs,
2898                                   dgrp_t group, void * priv_data);
2899 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2900                                     char *block_buf, int adjust_sign);
2901 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2902
2903 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2904                                struct ext2_inode * inode, int bufsize,
2905                                const char *proc);
2906
2907 struct process_block_struct_1 {
2908         ext2_ino_t      ino;
2909         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2910                                 fragmented:1, compressed:1, bbcheck:1;
2911         blk_t           num_blocks;
2912         blk_t           max_blocks;
2913         e2_blkcnt_t     last_block;
2914         int             num_illegal_blocks;
2915         blk_t           previous_block;
2916         struct ext2_inode *inode;
2917         struct problem_context *pctx;
2918         ext2fs_block_bitmap fs_meta_blocks;
2919         e2fsck_t        ctx;
2920 };
2921
2922 struct process_inode_block {
2923         ext2_ino_t ino;
2924         struct ext2_inode inode;
2925 };
2926
2927 struct scan_callback_struct {
2928         e2fsck_t        ctx;
2929         char            *block_buf;
2930 };
2931
2932 /*
2933  * For the inodes to process list.
2934  */
2935 static struct process_inode_block *inodes_to_process;
2936 static int process_inode_count;
2937
2938 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2939                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2940
2941 /*
2942  * Free all memory allocated by pass1 in preparation for restarting
2943  * things.
2944  */
2945 static void unwind_pass1(void)
2946 {
2947         ext2fs_free_mem(&inodes_to_process);
2948 }
2949
2950 /*
2951  * Check to make sure a device inode is real.  Returns 1 if the device
2952  * checks out, 0 if not.
2953  *
2954  * Note: this routine is now also used to check FIFO's and Sockets,
2955  * since they have the same requirement; the i_block fields should be
2956  * zero.
2957  */
2958 static int
2959 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2960 {
2961         int     i;
2962
2963         /*
2964          * If i_blocks is non-zero, or the index flag is set, then
2965          * this is a bogus device/fifo/socket
2966          */
2967         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2968             (inode->i_flags & EXT2_INDEX_FL))
2969                 return 0;
2970
2971         /*
2972          * We should be able to do the test below all the time, but
2973          * because the kernel doesn't forcibly clear the device
2974          * inode's additional i_block fields, there are some rare
2975          * occasions when a legitimate device inode will have non-zero
2976          * additional i_block fields.  So for now, we only complain
2977          * when the immutable flag is set, which should never happen
2978          * for devices.  (And that's when the problem is caused, since
2979          * you can't set or clear immutable flags for devices.)  Once
2980          * the kernel has been fixed we can change this...
2981          */
2982         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2983                 for (i=4; i < EXT2_N_BLOCKS; i++)
2984                         if (inode->i_block[i])
2985                                 return 0;
2986         }
2987         return 1;
2988 }
2989
2990 /*
2991  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2992  * checks out, 0 if not.
2993  */
2994 static int
2995 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2996 {
2997         unsigned int len;
2998         int i;
2999         blk_t   blocks;
3000
3001         if ((inode->i_size_high || inode->i_size == 0) ||
3002             (inode->i_flags & EXT2_INDEX_FL))
3003                 return 0;
3004
3005         blocks = ext2fs_inode_data_blocks(fs, inode);
3006         if (blocks) {
3007                 if ((inode->i_size >= fs->blocksize) ||
3008                     (blocks != fs->blocksize >> 9) ||
3009                     (inode->i_block[0] < fs->super->s_first_data_block) ||
3010                     (inode->i_block[0] >= fs->super->s_blocks_count))
3011                         return 0;
3012
3013                 for (i = 1; i < EXT2_N_BLOCKS; i++)
3014                         if (inode->i_block[i])
3015                                 return 0;
3016
3017                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
3018                         return 0;
3019
3020                 len = strnlen(buf, fs->blocksize);
3021                 if (len == fs->blocksize)
3022                         return 0;
3023         } else {
3024                 if (inode->i_size >= sizeof(inode->i_block))
3025                         return 0;
3026
3027                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3028                 if (len == sizeof(inode->i_block))
3029                         return 0;
3030         }
3031         if (len != inode->i_size)
3032                 return 0;
3033         return 1;
3034 }
3035
3036 /*
3037  * If the immutable (or append-only) flag is set on the inode, offer
3038  * to clear it.
3039  */
3040 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3041 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3042 {
3043         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3044                 return;
3045
3046         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3047                 return;
3048
3049         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3050         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3051 }
3052
3053 /*
3054  * If device, fifo or socket, check size is zero -- if not offer to
3055  * clear it
3056  */
3057 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3058 {
3059         struct ext2_inode *inode = pctx->inode;
3060
3061         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3062                 return;
3063
3064         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3065                 return;
3066
3067         inode->i_size = 0;
3068         inode->i_size_high = 0;
3069         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3070 }
3071
3072 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3073 {
3074         struct ext2_super_block *sb = ctx->fs->super;
3075         struct ext2_inode_large *inode;
3076         struct ext2_ext_attr_entry *entry;
3077         char *start, *end;
3078         int storage_size, remain, offs;
3079         int problem = 0;
3080
3081         inode = (struct ext2_inode_large *) pctx->inode;
3082         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3083                 inode->i_extra_isize;
3084         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3085                 inode->i_extra_isize + sizeof(__u32);
3086         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3087         entry = (struct ext2_ext_attr_entry *) start;
3088
3089         /* scan all entry's headers first */
3090
3091         /* take finish entry 0UL into account */
3092         remain = storage_size - sizeof(__u32);
3093         offs = end - start;
3094
3095         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3096
3097                 /* header eats this space */
3098                 remain -= sizeof(struct ext2_ext_attr_entry);
3099
3100                 /* is attribute name valid? */
3101                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3102                         pctx->num = entry->e_name_len;
3103                         problem = PR_1_ATTR_NAME_LEN;
3104                         goto fix;
3105                 }
3106
3107                 /* attribute len eats this space */
3108                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3109
3110                 /* check value size */
3111                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3112                         pctx->num = entry->e_value_size;
3113                         problem = PR_1_ATTR_VALUE_SIZE;
3114                         goto fix;
3115                 }
3116
3117                 /* check value placement */
3118                 if (entry->e_value_offs +
3119                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3120                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3121                         pctx->num = entry->e_value_offs;
3122                         problem = PR_1_ATTR_VALUE_OFFSET;
3123                         goto fix;
3124                 }
3125
3126                 /* e_value_block must be 0 in inode's ea */
3127                 if (entry->e_value_block != 0) {
3128                         pctx->num = entry->e_value_block;
3129                         problem = PR_1_ATTR_VALUE_BLOCK;
3130                         goto fix;
3131                 }
3132
3133                 /* e_hash must be 0 in inode's ea */
3134                 if (entry->e_hash != 0) {
3135                         pctx->num = entry->e_hash;
3136                         problem = PR_1_ATTR_HASH;
3137                         goto fix;
3138                 }
3139
3140                 remain -= entry->e_value_size;
3141                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3142
3143                 entry = EXT2_EXT_ATTR_NEXT(entry);
3144         }
3145 fix:
3146         /*
3147          * it seems like a corruption. it's very unlikely we could repair
3148          * EA(s) in automatic fashion -bzzz
3149          */
3150         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3151                 return;
3152
3153         /* simple remove all possible EA(s) */
3154         *((__u32 *)start) = 0UL;
3155         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3156                                 EXT2_INODE_SIZE(sb), "pass1");
3157 }
3158
3159 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3160 {
3161         struct ext2_super_block *sb = ctx->fs->super;
3162         struct ext2_inode_large *inode;
3163         __u32 *eamagic;
3164         int min, max;
3165
3166         inode = (struct ext2_inode_large *) pctx->inode;
3167         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3168                 /* this isn't large inode. so, nothing to check */
3169                 return;
3170         }
3171
3172         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3173         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3174         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3175         /*
3176          * For now we will allow i_extra_isize to be 0, but really
3177          * implementations should never allow i_extra_isize to be 0
3178          */
3179         if (inode->i_extra_isize &&
3180             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3181                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3182                         return;
3183                 inode->i_extra_isize = min;
3184                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3185                                         EXT2_INODE_SIZE(sb), "pass1");
3186                 return;
3187         }
3188
3189         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3190                         inode->i_extra_isize);
3191         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3192                 /* it seems inode has an extended attribute(s) in body */
3193                 check_ea_in_inode(ctx, pctx);
3194         }
3195 }
3196
3197 static void e2fsck_pass1(e2fsck_t ctx)
3198 {
3199         int     i;
3200         __u64   max_sizes;
3201         ext2_filsys fs = ctx->fs;
3202         ext2_ino_t      ino;
3203         struct ext2_inode *inode;
3204         ext2_inode_scan scan;
3205         char            *block_buf;
3206         unsigned char   frag, fsize;
3207         struct          problem_context pctx;
3208         struct          scan_callback_struct scan_struct;
3209         struct ext2_super_block *sb = ctx->fs->super;
3210         int             imagic_fs;
3211         int             busted_fs_time = 0;
3212         int             inode_size;
3213
3214         clear_problem_context(&pctx);
3215
3216         if (!(ctx->options & E2F_OPT_PREEN))
3217                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3218
3219         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3220             !(ctx->options & E2F_OPT_NO)) {
3221                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3222                         ctx->dirs_to_hash = 0;
3223         }
3224
3225         /* Pass 1 */
3226
3227 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3228
3229         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3230                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3231                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3232                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3233                 max_sizes = (max_sizes * (1UL << i)) - 1;
3234                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3235         }
3236 #undef EXT2_BPP
3237
3238         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3239
3240         /*
3241          * Allocate bitmaps structures
3242          */
3243         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3244                                               &ctx->inode_used_map);
3245         if (pctx.errcode) {
3246                 pctx.num = 1;
3247                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3248                 ctx->flags |= E2F_FLAG_ABORT;
3249                 return;
3250         }
3251         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3252                                 _("directory inode map"), &ctx->inode_dir_map);
3253         if (pctx.errcode) {
3254                 pctx.num = 2;
3255                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3256                 ctx->flags |= E2F_FLAG_ABORT;
3257                 return;
3258         }
3259         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3260                         _("regular file inode map"), &ctx->inode_reg_map);
3261         if (pctx.errcode) {
3262                 pctx.num = 6;
3263                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3264                 ctx->flags |= E2F_FLAG_ABORT;
3265                 return;
3266         }
3267         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3268                                               &ctx->block_found_map);
3269         if (pctx.errcode) {
3270                 pctx.num = 1;
3271                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3272                 ctx->flags |= E2F_FLAG_ABORT;
3273                 return;
3274         }
3275         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3276                                              &ctx->inode_link_info);
3277         if (pctx.errcode) {
3278                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3279                 ctx->flags |= E2F_FLAG_ABORT;
3280                 return;
3281         }
3282         inode_size = EXT2_INODE_SIZE(fs->super);
3283         inode = (struct ext2_inode *)
3284                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3285
3286         inodes_to_process = (struct process_inode_block *)
3287                 e2fsck_allocate_memory(ctx,
3288                                        (ctx->process_inode_size *
3289                                         sizeof(struct process_inode_block)),
3290                                        "array of inodes to process");
3291         process_inode_count = 0;
3292
3293         pctx.errcode = ext2fs_init_dblist(fs, 0);
3294         if (pctx.errcode) {
3295                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3296                 ctx->flags |= E2F_FLAG_ABORT;
3297                 return;
3298         }
3299
3300         /*
3301          * If the last orphan field is set, clear it, since the pass1
3302          * processing will automatically find and clear the orphans.
3303          * In the future, we may want to try using the last_orphan
3304          * linked list ourselves, but for now, we clear it so that the
3305          * ext3 mount code won't get confused.
3306          */
3307         if (!(ctx->options & E2F_OPT_READONLY)) {
3308                 if (fs->super->s_last_orphan) {
3309                         fs->super->s_last_orphan = 0;
3310                         ext2fs_mark_super_dirty(fs);
3311                 }
3312         }
3313
3314         mark_table_blocks(ctx);
3315         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3316                                                     "block interate buffer");
3317         e2fsck_use_inode_shortcuts(ctx, 1);
3318         ehandler_operation(_("doing inode scan"));
3319         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3320                                               &scan);
3321         if (pctx.errcode) {
3322                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3323                 ctx->flags |= E2F_FLAG_ABORT;
3324                 return;
3325         }
3326         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3327         ctx->stashed_inode = inode;
3328         scan_struct.ctx = ctx;
3329         scan_struct.block_buf = block_buf;
3330         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3331         if (ctx->progress)
3332                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3333                         return;
3334         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3335             (fs->super->s_mtime < fs->super->s_inodes_count))
3336                 busted_fs_time = 1;
3337
3338         while (1) {
3339                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3340                                                           inode, inode_size);
3341                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3342                         return;
3343                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3344                         continue;
3345                 }
3346                 if (pctx.errcode) {
3347                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3348                         ctx->flags |= E2F_FLAG_ABORT;
3349                         return;
3350                 }
3351                 if (!ino)
3352                         break;
3353                 pctx.ino = ino;
3354                 pctx.inode = inode;
3355                 ctx->stashed_ino = ino;
3356                 if (inode->i_links_count) {
3357                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3358                                            ino, inode->i_links_count);
3359                         if (pctx.errcode) {
3360                                 pctx.num = inode->i_links_count;
3361                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3362                                 ctx->flags |= E2F_FLAG_ABORT;
3363                                 return;
3364                         }
3365                 }
3366                 if (ino == EXT2_BAD_INO) {
3367                         struct process_block_struct_1 pb;
3368
3369                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3370                                                           &pb.fs_meta_blocks);
3371                         if (pctx.errcode) {
3372                                 pctx.num = 4;
3373                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3374                                 ctx->flags |= E2F_FLAG_ABORT;
3375                                 return;
3376                         }
3377                         pb.ino = EXT2_BAD_INO;
3378                         pb.num_blocks = pb.last_block = 0;
3379                         pb.num_illegal_blocks = 0;
3380                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3381                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3382                         pb.inode = inode;
3383                         pb.pctx = &pctx;
3384                         pb.ctx = ctx;
3385                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3386                                      block_buf, process_bad_block, &pb);
3387                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3388                         if (pctx.errcode) {
3389                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3390                                 ctx->flags |= E2F_FLAG_ABORT;
3391                                 return;
3392                         }
3393                         if (pb.bbcheck)
3394                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3395                                 ctx->flags |= E2F_FLAG_ABORT;
3396                                 return;
3397                         }
3398                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3399                         clear_problem_context(&pctx);
3400                         continue;
3401                 } else if (ino == EXT2_ROOT_INO) {
3402                         /*
3403                          * Make sure the root inode is a directory; if
3404                          * not, offer to clear it.  It will be
3405                          * regnerated in pass #3.
3406                          */
3407                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3408                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3409                                         inode->i_dtime = time(0);
3410                                         inode->i_links_count = 0;
3411                                         ext2fs_icount_store(ctx->inode_link_info,
3412                                                             ino, 0);
3413                                         e2fsck_write_inode(ctx, ino, inode,
3414                                                            "pass1");
3415                                 }
3416
3417                         }
3418                         /*
3419                          * If dtime is set, offer to clear it.  mke2fs
3420                          * version 0.2b created filesystems with the
3421                          * dtime field set for the root and lost+found
3422                          * directories.  We won't worry about
3423                          * /lost+found, since that can be regenerated
3424                          * easily.  But we will fix the root directory
3425                          * as a special case.
3426                          */
3427                         if (inode->i_dtime && inode->i_links_count) {
3428                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3429                                         inode->i_dtime = 0;
3430                                         e2fsck_write_inode(ctx, ino, inode,
3431                                                            "pass1");
3432                                 }
3433                         }
3434                 } else if (ino == EXT2_JOURNAL_INO) {
3435                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3436                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3437                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3438                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3439                                                 &pctx)) {
3440                                         inode->i_mode = LINUX_S_IFREG;
3441                                         e2fsck_write_inode(ctx, ino, inode,
3442                                                            "pass1");
3443                                 }
3444                                 check_blocks(ctx, &pctx, block_buf);
3445                                 continue;
3446                         }
3447                         if ((inode->i_links_count || inode->i_blocks ||
3448                              inode->i_blocks || inode->i_block[0]) &&
3449                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3450                                         &pctx)) {
3451                                 memset(inode, 0, inode_size);
3452                                 ext2fs_icount_store(ctx->inode_link_info,
3453                                                     ino, 0);
3454                                 e2fsck_write_inode_full(ctx, ino, inode,
3455                                                         inode_size, "pass1");
3456                         }
3457                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3458                         int     problem = 0;
3459
3460                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3461                         if (ino == EXT2_BOOT_LOADER_INO) {
3462                                 if (LINUX_S_ISDIR(inode->i_mode))
3463                                         problem = PR_1_RESERVED_BAD_MODE;
3464                         } else if (ino == EXT2_RESIZE_INO) {
3465                                 if (inode->i_mode &&
3466                                     !LINUX_S_ISREG(inode->i_mode))
3467                                         problem = PR_1_RESERVED_BAD_MODE;
3468                         } else {
3469                                 if (inode->i_mode != 0)
3470                                         problem = PR_1_RESERVED_BAD_MODE;
3471                         }
3472                         if (problem) {
3473                                 if (fix_problem(ctx, problem, &pctx)) {
3474                                         inode->i_mode = 0;
3475                                         e2fsck_write_inode(ctx, ino, inode,
3476                                                            "pass1");
3477                                 }
3478                         }
3479                         check_blocks(ctx, &pctx, block_buf);
3480                         continue;
3481                 }
3482                 /*
3483                  * Check for inodes who might have been part of the
3484                  * orphaned list linked list.  They should have gotten
3485                  * dealt with by now, unless the list had somehow been
3486                  * corrupted.
3487                  *
3488                  * FIXME: In the future, inodes which are still in use
3489                  * (and which are therefore) pending truncation should
3490                  * be handled specially.  Right now we just clear the
3491                  * dtime field, and the normal e2fsck handling of
3492                  * inodes where i_size and the inode blocks are
3493                  * inconsistent is to fix i_size, instead of releasing
3494                  * the extra blocks.  This won't catch the inodes that
3495                  * was at the end of the orphan list, but it's better
3496                  * than nothing.  The right answer is that there
3497                  * shouldn't be any bugs in the orphan list handling.  :-)
3498                  */
3499                 if (inode->i_dtime && !busted_fs_time &&
3500                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3501                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3502                                 inode->i_dtime = inode->i_links_count ?
3503                                         0 : time(0);
3504                                 e2fsck_write_inode(ctx, ino, inode,
3505                                                    "pass1");
3506                         }
3507                 }
3508
3509                 /*
3510                  * This code assumes that deleted inodes have
3511                  * i_links_count set to 0.
3512                  */
3513                 if (!inode->i_links_count) {
3514                         if (!inode->i_dtime && inode->i_mode) {
3515                                 if (fix_problem(ctx,
3516                                             PR_1_ZERO_DTIME, &pctx)) {
3517                                         inode->i_dtime = time(0);
3518                                         e2fsck_write_inode(ctx, ino, inode,
3519                                                            "pass1");
3520                                 }
3521                         }
3522                         continue;
3523                 }
3524                 /*
3525                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3526                  * deleted files.  Oops.
3527                  *
3528                  * Since all new ext2 implementations get this right,
3529                  * we now assume that the case of non-zero
3530                  * i_links_count and non-zero dtime means that we
3531                  * should keep the file, not delete it.
3532                  *
3533                  */
3534                 if (inode->i_dtime) {
3535                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3536                                 inode->i_dtime = 0;
3537                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3538                         }
3539                 }
3540
3541                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3542                 switch (fs->super->s_creator_os) {
3543                     case EXT2_OS_LINUX:
3544                         frag = inode->osd2.linux2.l_i_frag;
3545                         fsize = inode->osd2.linux2.l_i_fsize;
3546                         break;
3547                     case EXT2_OS_HURD:
3548                         frag = inode->osd2.hurd2.h_i_frag;
3549                         fsize = inode->osd2.hurd2.h_i_fsize;
3550                         break;
3551                     case EXT2_OS_MASIX:
3552                         frag = inode->osd2.masix2.m_i_frag;
3553                         fsize = inode->osd2.masix2.m_i_fsize;
3554                         break;
3555                     default:
3556                         frag = fsize = 0;
3557                 }
3558
3559                 if (inode->i_faddr || frag || fsize ||
3560                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3561                         mark_inode_bad(ctx, ino);
3562                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3563                         if (imagic_fs) {
3564                                 if (!ctx->inode_imagic_map)
3565                                         alloc_imagic_map(ctx);
3566                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3567                                                          ino);
3568                         } else {
3569                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3570                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3571                                         e2fsck_write_inode(ctx, ino,
3572                                                            inode, "pass1");
3573                                 }
3574                         }
3575                 }
3576
3577                 check_inode_extra_space(ctx, &pctx);
3578
3579                 if (LINUX_S_ISDIR(inode->i_mode)) {
3580                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3581                         e2fsck_add_dir_info(ctx, ino, 0);
3582                         ctx->fs_directory_count++;
3583                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3584                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3585                         ctx->fs_regular_count++;
3586                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3587                            e2fsck_pass1_check_device_inode(fs, inode)) {
3588                         check_immutable(ctx, &pctx);
3589                         check_size(ctx, &pctx);
3590                         ctx->fs_chardev_count++;
3591                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3592                            e2fsck_pass1_check_device_inode(fs, inode)) {
3593                         check_immutable(ctx, &pctx);
3594                         check_size(ctx, &pctx);
3595                         ctx->fs_blockdev_count++;
3596                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3597                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3598                         check_immutable(ctx, &pctx);
3599                         ctx->fs_symlinks_count++;
3600                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3601                                 ctx->fs_fast_symlinks_count++;
3602                                 check_blocks(ctx, &pctx, block_buf);
3603                                 continue;
3604                         }
3605                 }
3606                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3607                          e2fsck_pass1_check_device_inode(fs, inode)) {
3608                         check_immutable(ctx, &pctx);
3609                         check_size(ctx, &pctx);
3610                         ctx->fs_fifo_count++;
3611                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3612                            e2fsck_pass1_check_device_inode(fs, inode)) {
3613                         check_immutable(ctx, &pctx);
3614                         check_size(ctx, &pctx);
3615                         ctx->fs_sockets_count++;
3616                 } else
3617                         mark_inode_bad(ctx, ino);
3618                 if (inode->i_block[EXT2_IND_BLOCK])
3619                         ctx->fs_ind_count++;
3620                 if (inode->i_block[EXT2_DIND_BLOCK])
3621                         ctx->fs_dind_count++;
3622                 if (inode->i_block[EXT2_TIND_BLOCK])
3623                         ctx->fs_tind_count++;
3624                 if (inode->i_block[EXT2_IND_BLOCK] ||
3625                     inode->i_block[EXT2_DIND_BLOCK] ||
3626                     inode->i_block[EXT2_TIND_BLOCK] ||
3627                     inode->i_file_acl) {
3628                         inodes_to_process[process_inode_count].ino = ino;
3629                         inodes_to_process[process_inode_count].inode = *inode;
3630                         process_inode_count++;
3631                 } else
3632                         check_blocks(ctx, &pctx, block_buf);
3633
3634                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3635                         return;
3636
3637                 if (process_inode_count >= ctx->process_inode_size) {
3638                         process_inodes(ctx, block_buf);
3639
3640                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3641                                 return;
3642                 }
3643         }
3644         process_inodes(ctx, block_buf);
3645         ext2fs_close_inode_scan(scan);
3646         ehandler_operation(0);
3647
3648         /*
3649          * If any extended attribute blocks' reference counts need to
3650          * be adjusted, either up (ctx->refcount_extra), or down
3651          * (ctx->refcount), then fix them.
3652          */
3653         if (ctx->refcount) {
3654                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3655                 ea_refcount_free(ctx->refcount);
3656                 ctx->refcount = 0;
3657         }
3658         if (ctx->refcount_extra) {
3659                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3660                                         block_buf, +1);
3661                 ea_refcount_free(ctx->refcount_extra);
3662                 ctx->refcount_extra = 0;
3663         }
3664
3665         if (ctx->invalid_bitmaps)
3666                 handle_fs_bad_blocks(ctx);
3667
3668         /* We don't need the block_ea_map any more */
3669         ext2fs_free_block_bitmap(ctx->block_ea_map);
3670         ctx->block_ea_map = 0;
3671
3672         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3673                 ext2fs_block_bitmap save_bmap;
3674
3675                 save_bmap = fs->block_map;
3676                 fs->block_map = ctx->block_found_map;
3677                 clear_problem_context(&pctx);
3678                 pctx.errcode = ext2fs_create_resize_inode(fs);
3679                 if (pctx.errcode) {
3680                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3681                         /* Should never get here */
3682                         ctx->flags |= E2F_FLAG_ABORT;
3683                         return;
3684                 }
3685                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3686                                   "recreate inode");
3687                 inode->i_mtime = time(0);
3688                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, 
3689                                   "recreate inode");
3690                 fs->block_map = save_bmap;
3691                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3692         }
3693
3694         if (ctx->flags & E2F_FLAG_RESTART) {
3695                 /*
3696                  * Only the master copy of the superblock and block
3697                  * group descriptors are going to be written during a
3698                  * restart, so set the superblock to be used to be the
3699                  * master superblock.
3700                  */
3701                 ctx->use_superblock = 0;
3702                 unwind_pass1();
3703                 goto endit;
3704         }
3705
3706         if (ctx->block_dup_map) {
3707                 if (ctx->options & E2F_OPT_PREEN) {
3708                         clear_problem_context(&pctx);
3709                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3710                 }
3711                 e2fsck_pass1_dupblocks(ctx, block_buf);
3712         }
3713         ext2fs_free_mem(&inodes_to_process);
3714 endit:
3715         e2fsck_use_inode_shortcuts(ctx, 0);
3716
3717         ext2fs_free_mem(&block_buf);
3718         ext2fs_free_mem(&inode);
3719
3720 }
3721
3722 /*
3723  * When the inode_scan routines call this callback at the end of the
3724  * glock group, call process_inodes.
3725  */
3726 static errcode_t scan_callback(ext2_filsys fs,
3727                                dgrp_t group, void * priv_data)
3728 {
3729         struct scan_callback_struct *scan_struct;
3730         e2fsck_t ctx;
3731
3732         scan_struct = (struct scan_callback_struct *) priv_data;
3733         ctx = scan_struct->ctx;
3734
3735         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3736
3737         if (ctx->progress)
3738                 if ((ctx->progress)(ctx, 1, group+1,
3739                                     ctx->fs->group_desc_count))
3740                         return EXT2_ET_CANCEL_REQUESTED;
3741
3742         return 0;
3743 }
3744
3745 /*
3746  * Process the inodes in the "inodes to process" list.
3747  */
3748 static void process_inodes(e2fsck_t ctx, char *block_buf)
3749 {
3750         int                     i;
3751         struct ext2_inode       *old_stashed_inode;
3752         ext2_ino_t              old_stashed_ino;
3753         const char              *old_operation;
3754         char                    buf[80];
3755         struct problem_context  pctx;
3756
3757         /* begin process_inodes */
3758         if (process_inode_count == 0)
3759                 return;
3760         old_operation = ehandler_operation(0);
3761         old_stashed_inode = ctx->stashed_inode;
3762         old_stashed_ino = ctx->stashed_ino;
3763         qsort(inodes_to_process, process_inode_count,
3764                       sizeof(struct process_inode_block), process_inode_cmp);
3765         clear_problem_context(&pctx);
3766         for (i=0; i < process_inode_count; i++) {
3767                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3768                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3769                 sprintf(buf, _("reading indirect blocks of inode %u"),
3770                         pctx.ino);
3771                 ehandler_operation(buf);
3772                 check_blocks(ctx, &pctx, block_buf);
3773                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3774                         break;
3775         }
3776         ctx->stashed_inode = old_stashed_inode;
3777         ctx->stashed_ino = old_stashed_ino;
3778         process_inode_count = 0;
3779         /* end process inodes */
3780
3781         ehandler_operation(old_operation);
3782 }
3783
3784 static int process_inode_cmp(const void *a, const void *b)
3785 {
3786         const struct process_inode_block *ib_a =
3787                 (const struct process_inode_block *) a;
3788         const struct process_inode_block *ib_b =
3789                 (const struct process_inode_block *) b;
3790         int     ret;
3791
3792         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3793                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3794         if (ret == 0)
3795                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3796         return ret;
3797 }
3798
3799 /*
3800  * Mark an inode as being bad in some what
3801  */
3802 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3803 {
3804         struct          problem_context pctx;
3805
3806         if (!ctx->inode_bad_map) {
3807                 clear_problem_context(&pctx);
3808
3809                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3810                             _("bad inode map"), &ctx->inode_bad_map);
3811                 if (pctx.errcode) {
3812                         pctx.num = 3;
3813                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3814                         /* Should never get here */
3815                         ctx->flags |= E2F_FLAG_ABORT;
3816                         return;
3817                 }
3818         }
3819         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3820 }
3821
3822
3823 /*
3824  * This procedure will allocate the inode imagic table
3825  */
3826 static void alloc_imagic_map(e2fsck_t ctx)
3827 {
3828         struct          problem_context pctx;
3829
3830         clear_problem_context(&pctx);
3831         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3832                                               _("imagic inode map"),
3833                                               &ctx->inode_imagic_map);
3834         if (pctx.errcode) {
3835                 pctx.num = 5;
3836                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3837                 /* Should never get here */
3838                 ctx->flags |= E2F_FLAG_ABORT;
3839                 return;
3840         }
3841 }
3842
3843 /*
3844  * Marks a block as in use, setting the dup_map if it's been set
3845  * already.  Called by process_block and process_bad_block.
3846  *
3847  * WARNING: Assumes checks have already been done to make sure block
3848  * is valid.  This is true in both process_block and process_bad_block.
3849  */
3850 static void mark_block_used(e2fsck_t ctx, blk_t block)
3851 {
3852         struct          problem_context pctx;
3853
3854         clear_problem_context(&pctx);
3855
3856         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3857                 if (!ctx->block_dup_map) {
3858                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3859                               _("multiply claimed block map"),
3860                               &ctx->block_dup_map);
3861                         if (pctx.errcode) {
3862                                 pctx.num = 3;
3863                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3864                                             &pctx);
3865                                 /* Should never get here */
3866                                 ctx->flags |= E2F_FLAG_ABORT;
3867                                 return;
3868                         }
3869                 }
3870                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3871         } else {
3872                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3873         }
3874 }
3875
3876 /*
3877  * Adjust the extended attribute block's reference counts at the end
3878  * of pass 1, either by subtracting out references for EA blocks that
3879  * are still referenced in ctx->refcount, or by adding references for
3880  * EA blocks that had extra references as accounted for in
3881  * ctx->refcount_extra.
3882  */
3883 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3884                                     char *block_buf, int adjust_sign)
3885 {
3886         struct ext2_ext_attr_header     *header;
3887         struct problem_context          pctx;
3888         ext2_filsys                     fs = ctx->fs;
3889         blk_t                           blk;
3890         __u32                           should_be;
3891         int                             count;
3892
3893         clear_problem_context(&pctx);
3894
3895         ea_refcount_intr_begin(refcount);
3896         while (1) {
3897                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3898                         break;
3899                 pctx.blk = blk;
3900                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3901                 if (pctx.errcode) {
3902                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3903                         return;
3904                 }
3905                 header = (struct ext2_ext_attr_header *) block_buf;
3906                 pctx.blkcount = header->h_refcount;
3907                 should_be = header->h_refcount + adjust_sign * count;
3908                 pctx.num = should_be;
3909                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3910                         header->h_refcount = should_be;
3911                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3912                                                              block_buf);
3913                         if (pctx.errcode) {
3914                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3915                                 continue;
3916                         }
3917                 }
3918         }
3919 }
3920
3921 /*
3922  * Handle processing the extended attribute blocks
3923  */
3924 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3925                            char *block_buf)
3926 {
3927         ext2_filsys fs = ctx->fs;
3928         ext2_ino_t      ino = pctx->ino;
3929         struct ext2_inode *inode = pctx->inode;
3930         blk_t           blk;
3931         char *          end;
3932         struct ext2_ext_attr_header *header;
3933         struct ext2_ext_attr_entry *entry;
3934         int             count;
3935         region_t        region;
3936
3937         blk = inode->i_file_acl;
3938         if (blk == 0)
3939                 return 0;
3940
3941         /*
3942          * If the Extended attribute flag isn't set, then a non-zero
3943          * file acl means that the inode is corrupted.
3944          *
3945          * Or if the extended attribute block is an invalid block,
3946          * then the inode is also corrupted.
3947          */
3948         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3949             (blk < fs->super->s_first_data_block) ||
3950             (blk >= fs->super->s_blocks_count)) {
3951                 mark_inode_bad(ctx, ino);
3952                 return 0;
3953         }
3954
3955         /* If ea bitmap hasn't been allocated, create it */
3956         if (!ctx->block_ea_map) {
3957                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3958                                                       _("ext attr block map"),
3959                                                       &ctx->block_ea_map);
3960                 if (pctx->errcode) {
3961                         pctx->num = 2;
3962                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3963                         ctx->flags |= E2F_FLAG_ABORT;
3964                         return 0;
3965                 }
3966         }
3967
3968         /* Create the EA refcount structure if necessary */
3969         if (!ctx->refcount) {
3970                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3971                 if (pctx->errcode) {
3972                         pctx->num = 1;
3973                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3974                         ctx->flags |= E2F_FLAG_ABORT;
3975                         return 0;
3976                 }
3977         }
3978
3979         /* Have we seen this EA block before? */
3980         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3981                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3982                         return 1;
3983                 /* Ooops, this EA was referenced more than it stated */
3984                 if (!ctx->refcount_extra) {
3985                         pctx->errcode = ea_refcount_create(0,
3986                                            &ctx->refcount_extra);
3987                         if (pctx->errcode) {
3988                                 pctx->num = 2;
3989                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3990                                 ctx->flags |= E2F_FLAG_ABORT;
3991                                 return 0;
3992                         }
3993                 }
3994                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3995                 return 1;
3996         }
3997
3998         /*
3999          * OK, we haven't seen this EA block yet.  So we need to
4000          * validate it
4001          */
4002         pctx->blk = blk;
4003         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
4004         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
4005                 goto clear_extattr;
4006         header = (struct ext2_ext_attr_header *) block_buf;
4007         pctx->blk = inode->i_file_acl;
4008         if (((ctx->ext_attr_ver == 1) &&
4009              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
4010             ((ctx->ext_attr_ver == 2) &&
4011              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
4012                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
4013                         goto clear_extattr;
4014         }
4015
4016         if (header->h_blocks != 1) {
4017                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
4018                         goto clear_extattr;
4019         }
4020
4021         region = region_create(0, fs->blocksize);
4022         if (!region) {
4023                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4024                 ctx->flags |= E2F_FLAG_ABORT;
4025                 return 0;
4026         }
4027         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4028                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4029                         goto clear_extattr;
4030         }
4031
4032         entry = (struct ext2_ext_attr_entry *)(header+1);
4033         end = block_buf + fs->blocksize;
4034         while ((char *)entry < end && *(__u32 *)entry) {
4035                 if (region_allocate(region, (char *)entry - (char *)header,
4036                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4037                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4038                                 goto clear_extattr;
4039                 }
4040                 if ((ctx->ext_attr_ver == 1 &&
4041                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4042                     (ctx->ext_attr_ver == 2 &&
4043                      entry->e_name_index == 0)) {
4044                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4045                                 goto clear_extattr;
4046                 }
4047                 if (entry->e_value_block != 0) {
4048                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4049                                 goto clear_extattr;
4050                 }
4051                 if (entry->e_value_size &&
4052                     region_allocate(region, entry->e_value_offs,
4053                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4054                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4055                                 goto clear_extattr;
4056                 }
4057                 entry = EXT2_EXT_ATTR_NEXT(entry);
4058         }
4059         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4060                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4061                         goto clear_extattr;
4062         }
4063         region_free(region);
4064
4065         count = header->h_refcount - 1;
4066         if (count)
4067                 ea_refcount_store(ctx->refcount, blk, count);
4068         mark_block_used(ctx, blk);
4069         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4070
4071         return 1;
4072
4073 clear_extattr:
4074         inode->i_file_acl = 0;
4075         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4076         return 0;
4077 }
4078
4079 /* Returns 1 if bad htree, 0 if OK */
4080 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4081                         ext2_ino_t ino FSCK_ATTR((unused)),
4082                         struct ext2_inode *inode,
4083                         char *block_buf)
4084 {
4085         struct ext2_dx_root_info        *root;
4086         ext2_filsys                     fs = ctx->fs;
4087         errcode_t                       retval;
4088         blk_t                           blk;
4089
4090         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4091              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4092             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4093              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4094                 return 1;
4095
4096         blk = inode->i_block[0];
4097         if (((blk == 0) ||
4098              (blk < fs->super->s_first_data_block) ||
4099              (blk >= fs->super->s_blocks_count)) &&
4100             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4101                 return 1;
4102
4103         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4104         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4105                 return 1;
4106
4107         /* XXX should check that beginning matches a directory */
4108         root = (struct ext2_dx_root_info *) (block_buf + 24);
4109
4110         if ((root->reserved_zero || root->info_length < 8) &&
4111             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4112                 return 1;
4113
4114         pctx->num = root->hash_version;
4115         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4116             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4117             (root->hash_version != EXT2_HASH_TEA) &&
4118             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4119                 return 1;
4120
4121         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4122             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4123                 return 1;
4124
4125         pctx->num = root->indirect_levels;
4126         if ((root->indirect_levels > 1) &&
4127             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4128                 return 1;
4129
4130         return 0;
4131 }
4132
4133 /*
4134  * This subroutine is called on each inode to account for all of the
4135  * blocks used by that inode.
4136  */
4137 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4138                          char *block_buf)
4139 {
4140         ext2_filsys fs = ctx->fs;
4141         struct process_block_struct_1 pb;
4142         ext2_ino_t      ino = pctx->ino;
4143         struct ext2_inode *inode = pctx->inode;
4144         int             bad_size = 0;
4145         int             dirty_inode = 0;
4146         __u64           size;
4147
4148         pb.ino = ino;
4149         pb.num_blocks = 0;
4150         pb.last_block = -1;
4151         pb.num_illegal_blocks = 0;
4152         pb.suppress = 0; pb.clear = 0;
4153         pb.fragmented = 0;
4154         pb.compressed = 0;
4155         pb.previous_block = 0;
4156         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4157         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4158         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4159         pb.inode = inode;
4160         pb.pctx = pctx;
4161         pb.ctx = ctx;
4162         pctx->ino = ino;
4163         pctx->errcode = 0;
4164
4165         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4166                 if (fs->super->s_feature_incompat &
4167                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4168                         pb.compressed = 1;
4169                 else {
4170                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4171                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4172                                 dirty_inode++;
4173                         }
4174                 }
4175         }
4176
4177         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4178                 pb.num_blocks++;
4179
4180         if (ext2fs_inode_has_valid_blocks(inode))
4181                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4182                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4183                                        block_buf, process_block, &pb);
4184         end_problem_latch(ctx, PR_LATCH_BLOCK);
4185         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4186         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4187                 goto out;
4188         if (pctx->errcode)
4189                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4190
4191         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4192                 ctx->fs_fragmented++;
4193
4194         if (pb.clear) {
4195                 inode->i_links_count = 0;
4196                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4197                 inode->i_dtime = time(0);
4198                 dirty_inode++;
4199                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4200                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4201                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4202                 /*
4203                  * The inode was probably partially accounted for
4204                  * before processing was aborted, so we need to
4205                  * restart the pass 1 scan.
4206                  */
4207                 ctx->flags |= E2F_FLAG_RESTART;
4208                 goto out;
4209         }
4210
4211         if (inode->i_flags & EXT2_INDEX_FL) {
4212                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4213                         inode->i_flags &= ~EXT2_INDEX_FL;
4214                         dirty_inode++;
4215                 } else {
4216 #ifdef ENABLE_HTREE
4217                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4218 #endif
4219                 }
4220         }
4221         if (ctx->dirs_to_hash && pb.is_dir &&
4222             !(inode->i_flags & EXT2_INDEX_FL) &&
4223             ((inode->i_size / fs->blocksize) >= 3))
4224                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4225
4226         if (!pb.num_blocks && pb.is_dir) {
4227                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4228                         inode->i_links_count = 0;
4229                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4230                         inode->i_dtime = time(0);
4231                         dirty_inode++;
4232                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4233                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4234                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4235                         ctx->fs_directory_count--;
4236                         goto out;
4237                 }
4238         }
4239
4240         pb.num_blocks *= (fs->blocksize / 512);
4241
4242         if (pb.is_dir) {
4243                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4244                 if (nblock > (pb.last_block + 1))
4245                         bad_size = 1;
4246                 else if (nblock < (pb.last_block + 1)) {
4247                         if (((pb.last_block + 1) - nblock) >
4248                             fs->super->s_prealloc_dir_blocks)
4249                                 bad_size = 2;
4250                 }
4251         } else {
4252                 size = EXT2_I_SIZE(inode);
4253                 if ((pb.last_block >= 0) &&
4254                     (size < (__u64) pb.last_block * fs->blocksize))
4255                         bad_size = 3;
4256                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4257                         bad_size = 4;
4258         }
4259         /* i_size for symlinks is checked elsewhere */
4260         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4261                 pctx->num = (pb.last_block+1) * fs->blocksize;
4262                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4263                         inode->i_size = pctx->num;
4264                         if (!LINUX_S_ISDIR(inode->i_mode))
4265                                 inode->i_size_high = pctx->num >> 32;
4266                         dirty_inode++;
4267                 }
4268                 pctx->num = 0;
4269         }
4270         if (LINUX_S_ISREG(inode->i_mode) &&
4271             (inode->i_size_high || inode->i_size & 0x80000000UL))
4272                 ctx->large_files++;
4273         if (pb.num_blocks != inode->i_blocks) {
4274                 pctx->num = pb.num_blocks;
4275                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4276                         inode->i_blocks = pb.num_blocks;
4277                         dirty_inode++;
4278                 }
4279                 pctx->num = 0;
4280         }
4281 out:
4282         if (dirty_inode)
4283                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4284 }
4285
4286
4287 /*
4288  * This is a helper function for check_blocks().
4289  */
4290 static int process_block(ext2_filsys fs,
4291                   blk_t *block_nr,
4292                   e2_blkcnt_t blockcnt,
4293                   blk_t ref_block FSCK_ATTR((unused)),
4294                   int ref_offset FSCK_ATTR((unused)),
4295                   void *priv_data)
4296 {
4297         struct process_block_struct_1 *p;
4298         struct problem_context *pctx;
4299         blk_t   blk = *block_nr;
4300         int     ret_code = 0;
4301         int     problem = 0;
4302         e2fsck_t        ctx;
4303
4304         p = (struct process_block_struct_1 *) priv_data;
4305         pctx = p->pctx;
4306         ctx = p->ctx;
4307
4308         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4309                 /* todo: Check that the comprblk_fl is high, that the
4310                    blkaddr pattern looks right (all non-holes up to
4311                    first EXT2FS_COMPRESSED_BLKADDR, then all
4312                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4313                    that the feature_incompat bit is high, and that the
4314                    inode is a regular file.  If we're doing a "full
4315                    check" (a concept introduced to e2fsck by e2compr,
4316                    meaning that we look at data blocks as well as
4317                    metadata) then call some library routine that
4318                    checks the compressed data.  I'll have to think
4319                    about this, because one particularly important
4320                    problem to be able to fix is to recalculate the
4321                    cluster size if necessary.  I think that perhaps
4322                    we'd better do most/all e2compr-specific checks
4323                    separately, after the non-e2compr checks.  If not
4324                    doing a full check, it may be useful to test that
4325                    the personality is linux; e.g. if it isn't then
4326                    perhaps this really is just an illegal block. */
4327                 return 0;
4328         }
4329
4330         if (blk == 0) {
4331                 if (p->is_dir == 0) {
4332                         /*
4333                          * Should never happen, since only directories
4334                          * get called with BLOCK_FLAG_HOLE
4335                          */
4336 #if DEBUG_E2FSCK
4337                         printf("process_block() called with blk == 0, "
4338                                "blockcnt=%d, inode %lu???\n",
4339                                blockcnt, p->ino);
4340 #endif
4341                         return 0;
4342                 }
4343                 if (blockcnt < 0)
4344                         return 0;
4345                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4346                         goto mark_dir;
4347                 }
4348                 return 0;
4349         }
4350
4351         /*
4352          * Simplistic fragmentation check.  We merely require that the
4353          * file be contiguous.  (Which can never be true for really
4354          * big files that are greater than a block group.)
4355          */
4356         if (!HOLE_BLKADDR(p->previous_block)) {
4357                 if (p->previous_block+1 != blk)
4358                         p->fragmented = 1;
4359         }
4360         p->previous_block = blk;
4361
4362         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4363                 problem = PR_1_TOOBIG_DIR;
4364         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4365                 problem = PR_1_TOOBIG_REG;
4366         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4367                 problem = PR_1_TOOBIG_SYMLINK;
4368
4369         if (blk < fs->super->s_first_data_block ||
4370             blk >= fs->super->s_blocks_count)
4371                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4372
4373         if (problem) {
4374                 p->num_illegal_blocks++;
4375                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4376                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4377                                 p->clear = 1;
4378                                 return BLOCK_ABORT;
4379                         }
4380                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4381                                 p->suppress = 1;
4382                                 set_latch_flags(PR_LATCH_BLOCK,
4383                                                 PRL_SUPPRESS, 0);
4384                         }
4385                 }
4386                 pctx->blk = blk;
4387                 pctx->blkcount = blockcnt;
4388                 if (fix_problem(ctx, problem, pctx)) {
4389                         blk = *block_nr = 0;
4390                         ret_code = BLOCK_CHANGED;
4391                         goto mark_dir;
4392                 } else
4393                         return 0;
4394         }
4395
4396         if (p->ino == EXT2_RESIZE_INO) {
4397                 /*
4398                  * The resize inode has already be sanity checked
4399                  * during pass #0 (the superblock checks).  All we
4400                  * have to do is mark the double indirect block as
4401                  * being in use; all of the other blocks are handled
4402                  * by mark_table_blocks()).
4403                  */
4404                 if (blockcnt == BLOCK_COUNT_DIND)
4405                         mark_block_used(ctx, blk);
4406         } else
4407                 mark_block_used(ctx, blk);
4408         p->num_blocks++;
4409         if (blockcnt >= 0)
4410                 p->last_block = blockcnt;
4411 mark_dir:
4412         if (p->is_dir && (blockcnt >= 0)) {
4413                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4414                                                     blk, blockcnt);
4415                 if (pctx->errcode) {
4416                         pctx->blk = blk;
4417                         pctx->num = blockcnt;
4418                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4419                         /* Should never get here */
4420                         ctx->flags |= E2F_FLAG_ABORT;
4421                         return BLOCK_ABORT;
4422                 }
4423         }
4424         return ret_code;
4425 }
4426
4427 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4428                       blk_t *block_nr,
4429                       e2_blkcnt_t blockcnt,
4430                       blk_t ref_block FSCK_ATTR((unused)),
4431                       int ref_offset FSCK_ATTR((unused)),
4432                       void *priv_data EXT2FS_ATTR((unused)))
4433 {
4434         /*
4435          * Note: This function processes blocks for the bad blocks
4436          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4437          */
4438
4439         printf("Unrecoverable Error: Found %lli bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4440         return BLOCK_ERROR;
4441 }
4442
4443 /*
4444  * This routine gets called at the end of pass 1 if bad blocks are
4445  * detected in the superblock, group descriptors, inode_bitmaps, or
4446  * block bitmaps.  At this point, all of the blocks have been mapped
4447  * out, so we can try to allocate new block(s) to replace the bad
4448  * blocks.
4449  */
4450 static void handle_fs_bad_blocks(e2fsck_t ctx)
4451 {
4452         printf("Bad blocks detected on your filesystem\n"
4453                 "You should get your data off as the device will soon die\n");
4454 }
4455
4456 /*
4457  * This routine marks all blocks which are used by the superblock,
4458  * group descriptors, inode bitmaps, and block bitmaps.
4459  */
4460 static void mark_table_blocks(e2fsck_t ctx)
4461 {
4462         ext2_filsys fs = ctx->fs;
4463         blk_t   block, b;
4464         dgrp_t  i;
4465         int     j;
4466         struct problem_context pctx;
4467
4468         clear_problem_context(&pctx);
4469
4470         block = fs->super->s_first_data_block;
4471         for (i = 0; i < fs->group_desc_count; i++) {
4472                 pctx.group = i;
4473
4474                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4475
4476                 /*
4477                  * Mark the blocks used for the inode table
4478                  */
4479                 if (fs->group_desc[i].bg_inode_table) {
4480                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4481                              j < fs->inode_blocks_per_group;
4482                              j++, b++) {
4483                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4484                                                              b)) {
4485                                         pctx.blk = b;
4486                                         if (fix_problem(ctx,
4487                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4488                                                 ctx->invalid_inode_table_flag[i]++;
4489                                                 ctx->invalid_bitmaps++;
4490                                         }
4491                                 } else {
4492                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
4493                                                              b);
4494                                 }
4495                         }
4496                 }
4497
4498                 /*
4499                  * Mark block used for the block bitmap
4500                  */
4501                 if (fs->group_desc[i].bg_block_bitmap) {
4502                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4503                                      fs->group_desc[i].bg_block_bitmap)) {
4504                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4505                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4506                                         ctx->invalid_block_bitmap_flag[i]++;
4507                                         ctx->invalid_bitmaps++;
4508                                 }
4509                         } else {
4510                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4511                                      fs->group_desc[i].bg_block_bitmap);
4512                     }
4513
4514                 }
4515                 /*
4516                  * Mark block used for the inode bitmap
4517                  */
4518                 if (fs->group_desc[i].bg_inode_bitmap) {
4519                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4520                                      fs->group_desc[i].bg_inode_bitmap)) {
4521                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4522                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4523                                         ctx->invalid_inode_bitmap_flag[i]++;
4524                                         ctx->invalid_bitmaps++;
4525                                 }
4526                         } else {
4527                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4528                                      fs->group_desc[i].bg_inode_bitmap);
4529                         }
4530                 }
4531                 block += fs->super->s_blocks_per_group;
4532         }
4533 }
4534
4535 /*
4536  * Thes subroutines short circuits ext2fs_get_blocks and
4537  * ext2fs_check_directory; we use them since we already have the inode
4538  * structure, so there's no point in letting the ext2fs library read
4539  * the inode again.
4540  */
4541 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4542                                   blk_t *blocks)
4543 {
4544         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545         int     i;
4546
4547         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4548                 return EXT2_ET_CALLBACK_NOTHANDLED;
4549
4550         for (i=0; i < EXT2_N_BLOCKS; i++)
4551                 blocks[i] = ctx->stashed_inode->i_block[i];
4552         return 0;
4553 }
4554
4555 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4556                                   struct ext2_inode *inode)
4557 {
4558         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4559
4560         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4561                 return EXT2_ET_CALLBACK_NOTHANDLED;
4562         *inode = *ctx->stashed_inode;
4563         return 0;
4564 }
4565
4566 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4567                             struct ext2_inode *inode)
4568 {
4569         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4570
4571         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4572                 *ctx->stashed_inode = *inode;
4573         return EXT2_ET_CALLBACK_NOTHANDLED;
4574 }
4575
4576 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4577 {
4578         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4579
4580         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4581                 return EXT2_ET_CALLBACK_NOTHANDLED;
4582
4583         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4584                 return EXT2_ET_NO_DIRECTORY;
4585         return 0;
4586 }
4587
4588 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4589 {
4590         ext2_filsys fs = ctx->fs;
4591
4592         if (bool) {
4593                 fs->get_blocks = pass1_get_blocks;
4594                 fs->check_directory = pass1_check_directory;
4595                 fs->read_inode = pass1_read_inode;
4596                 fs->write_inode = pass1_write_inode;
4597                 ctx->stashed_ino = 0;
4598         } else {
4599                 fs->get_blocks = 0;
4600                 fs->check_directory = 0;
4601                 fs->read_inode = 0;
4602                 fs->write_inode = 0;
4603         }
4604 }
4605
4606 /*
4607  * pass1b.c --- Pass #1b of e2fsck
4608  *
4609  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4610  * only invoked if pass 1 discovered blocks which are in use by more
4611  * than one inode.
4612  *
4613  * Pass1B scans the data blocks of all the inodes again, generating a
4614  * complete list of duplicate blocks and which inodes have claimed
4615  * them.
4616  *
4617  * Pass1C does a tree-traversal of the filesystem, to determine the
4618  * parent directories of these inodes.  This step is necessary so that
4619  * e2fsck can print out the pathnames of affected inodes.
4620  *
4621  * Pass1D is a reconciliation pass.  For each inode with duplicate
4622  * blocks, the user is prompted if s/he would like to clone the file
4623  * (so that the file gets a fresh copy of the duplicated blocks) or
4624  * simply to delete the file.
4625  *
4626  */
4627
4628
4629 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4630 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4631 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4632
4633 /* Define an extension to the ext2 library's block count information */
4634 #define BLOCK_COUNT_EXTATTR     (-5)
4635
4636 struct block_el {
4637         blk_t   block;
4638         struct block_el *next;
4639 };
4640
4641 struct inode_el {
4642         ext2_ino_t      inode;
4643         struct inode_el *next;
4644 };
4645
4646 struct dup_block {
4647         int             num_bad;
4648         struct inode_el *inode_list;
4649 };
4650
4651 /*
4652  * This structure stores information about a particular inode which
4653  * is sharing blocks with other inodes.  This information is collected
4654  * to display to the user, so that the user knows what files he or she
4655  * is dealing with, when trying to decide how to resolve the conflict
4656  * of multiply-claimed blocks.
4657  */
4658 struct dup_inode {
4659         ext2_ino_t              dir;
4660         int                     num_dupblocks;
4661         struct ext2_inode       inode;
4662         struct block_el         *block_list;
4663 };
4664
4665 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4666                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4667                                 int ref_offset, void *priv_data);
4668 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4669                         struct dup_inode *dp, char *block_buf);
4670 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4671                       struct dup_inode *dp, char* block_buf);
4672 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4673
4674 static void pass1b(e2fsck_t ctx, char *block_buf);
4675 static void pass1c(e2fsck_t ctx, char *block_buf);
4676 static void pass1d(e2fsck_t ctx, char *block_buf);
4677
4678 static int dup_inode_count = 0;
4679
4680 static dict_t blk_dict, ino_dict;
4681
4682 static ext2fs_inode_bitmap inode_dup_map;
4683
4684 static int dict_int_cmp(const void *a, const void *b)
4685 {
4686         intptr_t        ia, ib;
4687
4688         ia = (intptr_t)a;
4689         ib = (intptr_t)b;
4690
4691         return (ia-ib);
4692 }
4693
4694 /*
4695  * Add a duplicate block record
4696  */
4697 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4698                      struct ext2_inode *inode)
4699 {
4700         dnode_t *n;
4701         struct dup_block        *db;
4702         struct dup_inode        *di;
4703         struct block_el         *blk_el;
4704         struct inode_el         *ino_el;
4705
4706         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4707         if (n)
4708                 db = (struct dup_block *) dnode_get(n);
4709         else {
4710                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4711                          sizeof(struct dup_block), "duplicate block header");
4712                 db->num_bad = 0;
4713                 db->inode_list = 0;
4714                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4715         }
4716         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4717                          sizeof(struct inode_el), "inode element");
4718         ino_el->inode = ino;
4719         ino_el->next = db->inode_list;
4720         db->inode_list = ino_el;
4721         db->num_bad++;
4722
4723         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4724         if (n)
4725                 di = (struct dup_inode *) dnode_get(n);
4726         else {
4727                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4728                          sizeof(struct dup_inode), "duplicate inode header");
4729                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
4730                 di->num_dupblocks = 0;
4731                 di->block_list = 0;
4732                 di->inode = *inode;
4733                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4734         }
4735         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4736                          sizeof(struct block_el), "block element");
4737         blk_el->block = blk;
4738         blk_el->next = di->block_list;
4739         di->block_list = blk_el;
4740         di->num_dupblocks++;
4741 }
4742
4743 /*
4744  * Free a duplicate inode record
4745  */
4746 static void inode_dnode_free(dnode_t *node)
4747 {
4748         struct dup_inode        *di;
4749         struct block_el         *p, *next;
4750
4751         di = (struct dup_inode *) dnode_get(node);
4752         for (p = di->block_list; p; p = next) {
4753                 next = p->next;
4754                 free(p);
4755         }
4756         free(node);
4757 }
4758
4759 /*
4760  * Free a duplicate block record
4761  */
4762 static void block_dnode_free(dnode_t *node)
4763 {
4764         struct dup_block        *db;
4765         struct inode_el         *p, *next;
4766
4767         db = (struct dup_block *) dnode_get(node);
4768         for (p = db->inode_list; p; p = next) {
4769                 next = p->next;
4770                 free(p);
4771         }
4772         free(node);
4773 }
4774
4775
4776 /*
4777  * Main procedure for handling duplicate blocks
4778  */
4779 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4780 {
4781         ext2_filsys             fs = ctx->fs;
4782         struct problem_context  pctx;
4783
4784         clear_problem_context(&pctx);
4785
4786         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4787                       _("multiply claimed inode map"), &inode_dup_map);
4788         if (pctx.errcode) {
4789                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4790                 ctx->flags |= E2F_FLAG_ABORT;
4791                 return;
4792         }
4793
4794         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4795         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4796         dict_set_allocator(&ino_dict, inode_dnode_free);
4797         dict_set_allocator(&blk_dict, block_dnode_free);
4798
4799         pass1b(ctx, block_buf);
4800         pass1c(ctx, block_buf);
4801         pass1d(ctx, block_buf);
4802
4803         /*
4804          * Time to free all of the accumulated data structures that we
4805          * don't need anymore.
4806          */
4807         dict_free_nodes(&ino_dict);
4808         dict_free_nodes(&blk_dict);
4809 }
4810
4811 /*
4812  * Scan the inodes looking for inodes that contain duplicate blocks.
4813  */
4814 struct process_block_struct_1b {
4815         e2fsck_t        ctx;
4816         ext2_ino_t      ino;
4817         int             dup_blocks;
4818         struct ext2_inode *inode;
4819         struct problem_context *pctx;
4820 };
4821
4822 static void pass1b(e2fsck_t ctx, char *block_buf)
4823 {
4824         ext2_filsys fs = ctx->fs;
4825         ext2_ino_t ino;
4826         struct ext2_inode inode;
4827         ext2_inode_scan scan;
4828         struct process_block_struct_1b pb;
4829         struct problem_context pctx;
4830
4831         clear_problem_context(&pctx);
4832
4833         if (!(ctx->options & E2F_OPT_PREEN))
4834                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4835         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4836                                               &scan);
4837         if (pctx.errcode) {
4838                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4839                 ctx->flags |= E2F_FLAG_ABORT;
4840                 return;
4841         }
4842         ctx->stashed_inode = &inode;
4843         pb.ctx = ctx;
4844         pb.pctx = &pctx;
4845         pctx.str = "pass1b";
4846         while (1) {
4847                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4848                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4849                         continue;
4850                 if (pctx.errcode) {
4851                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4852                         ctx->flags |= E2F_FLAG_ABORT;
4853                         return;
4854                 }
4855                 if (!ino)
4856                         break;
4857                 pctx.ino = ctx->stashed_ino = ino;
4858                 if ((ino != EXT2_BAD_INO) &&
4859                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4860                         continue;
4861
4862                 pb.ino = ino;
4863                 pb.dup_blocks = 0;
4864                 pb.inode = &inode;
4865
4866                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4867                     (ino == EXT2_BAD_INO))
4868                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4869                                      0, block_buf, process_pass1b_block, &pb);
4870                 if (inode.i_file_acl)
4871                         process_pass1b_block(fs, &inode.i_file_acl,
4872                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4873                 if (pb.dup_blocks) {
4874                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4875                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4876                             ino == EXT2_ROOT_INO)
4877                                 dup_inode_count++;
4878                 }
4879                 if (pctx.errcode)
4880                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4881         }
4882         ext2fs_close_inode_scan(scan);
4883         e2fsck_use_inode_shortcuts(ctx, 0);
4884 }
4885
4886 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4887                                 blk_t   *block_nr,
4888                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4889                                 blk_t ref_blk FSCK_ATTR((unused)),
4890                                 int ref_offset FSCK_ATTR((unused)),
4891                                 void *priv_data)
4892 {
4893         struct process_block_struct_1b *p;
4894         e2fsck_t ctx;
4895
4896         if (HOLE_BLKADDR(*block_nr))
4897                 return 0;
4898         p = (struct process_block_struct_1b *) priv_data;
4899         ctx = p->ctx;
4900
4901         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4902                 return 0;
4903
4904         /* OK, this is a duplicate block */
4905         if (p->ino != EXT2_BAD_INO) {
4906                 p->pctx->blk = *block_nr;
4907                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4908         }
4909         p->dup_blocks++;
4910         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4911
4912         add_dupe(ctx, p->ino, *block_nr, p->inode);
4913
4914         return 0;
4915 }
4916
4917 /*
4918  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4919  * is used so that we can print pathnames when prompting the user for
4920  * what to do.
4921  */
4922 struct search_dir_struct {
4923         int             count;
4924         ext2_ino_t      first_inode;
4925         ext2_ino_t      max_inode;
4926 };
4927
4928 static int search_dirent_proc(ext2_ino_t dir, int entry,
4929                               struct ext2_dir_entry *dirent,
4930                               int offset FSCK_ATTR((unused)),
4931                               int blocksize FSCK_ATTR((unused)),
4932                               char *buf FSCK_ATTR((unused)),
4933                               void *priv_data)
4934 {
4935         struct search_dir_struct *sd;
4936         struct dup_inode        *p;
4937         dnode_t                 *n;
4938
4939         sd = (struct search_dir_struct *) priv_data;
4940
4941         if (dirent->inode > sd->max_inode)
4942                 /* Should abort this inode, but not everything */
4943                 return 0;
4944
4945         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4946             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4947                 return 0;
4948
4949         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4950         if (!n)
4951                 return 0;
4952         p = (struct dup_inode *) dnode_get(n);
4953         p->dir = dir;
4954         sd->count--;
4955
4956         return(sd->count ? 0 : DIRENT_ABORT);
4957 }
4958
4959
4960 static void pass1c(e2fsck_t ctx, char *block_buf)
4961 {
4962         ext2_filsys fs = ctx->fs;
4963         struct search_dir_struct sd;
4964         struct problem_context pctx;
4965
4966         clear_problem_context(&pctx);
4967
4968         if (!(ctx->options & E2F_OPT_PREEN))
4969                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4970
4971         /*
4972          * Search through all directories to translate inodes to names
4973          * (by searching for the containing directory for that inode.)
4974          */
4975         sd.count = dup_inode_count;
4976         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4977         sd.max_inode = fs->super->s_inodes_count;
4978         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4979                                   search_dirent_proc, &sd);
4980 }
4981
4982 static void pass1d(e2fsck_t ctx, char *block_buf)
4983 {
4984         ext2_filsys fs = ctx->fs;
4985         struct dup_inode        *p, *t;
4986         struct dup_block        *q;
4987         ext2_ino_t              *shared, ino;
4988         int     shared_len;
4989         int     i;
4990         int     file_ok;
4991         int     meta_data = 0;
4992         struct problem_context pctx;
4993         dnode_t *n, *m;
4994         struct block_el *s;
4995         struct inode_el *r;
4996
4997         clear_problem_context(&pctx);
4998
4999         if (!(ctx->options & E2F_OPT_PREEN))
5000                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
5001         e2fsck_read_bitmaps(ctx);
5002
5003         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
5004         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
5005         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
5006                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
5007                                 "Shared inode list");
5008         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
5009                 p = (struct dup_inode *) dnode_get(n);
5010                 shared_len = 0;
5011                 file_ok = 1;
5012                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
5013                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
5014                         continue;
5015
5016                 /*
5017                  * Find all of the inodes which share blocks with this
5018                  * one.  First we find all of the duplicate blocks
5019                  * belonging to this inode, and then search each block
5020                  * get the list of inodes, and merge them together.
5021                  */
5022                 for (s = p->block_list; s; s = s->next) {
5023                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5024                         if (!m)
5025                                 continue; /* Should never happen... */
5026                         q = (struct dup_block *) dnode_get(m);
5027                         if (q->num_bad > 1)
5028                                 file_ok = 0;
5029                         if (check_if_fs_block(ctx, s->block)) {
5030                                 file_ok = 0;
5031                                 meta_data = 1;
5032                         }
5033
5034                         /*
5035                          * Add all inodes used by this block to the
5036                          * shared[] --- which is a unique list, so
5037                          * if an inode is already in shared[], don't
5038                          * add it again.
5039                          */
5040                         for (r = q->inode_list; r; r = r->next) {
5041                                 if (r->inode == ino)
5042                                         continue;
5043                                 for (i = 0; i < shared_len; i++)
5044                                         if (shared[i] == r->inode)
5045                                                 break;
5046                                 if (i == shared_len) {
5047                                         shared[shared_len++] = r->inode;
5048                                 }
5049                         }
5050                 }
5051
5052                 /*
5053                  * Report the inode that we are working on
5054                  */
5055                 pctx.inode = &p->inode;
5056                 pctx.ino = ino;
5057                 pctx.dir = p->dir;
5058                 pctx.blkcount = p->num_dupblocks;
5059                 pctx.num = meta_data ? shared_len+1 : shared_len;
5060                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5061                 pctx.blkcount = 0;
5062                 pctx.num = 0;
5063
5064                 if (meta_data)
5065                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5066
5067                 for (i = 0; i < shared_len; i++) {
5068                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5069                         if (!m)
5070                                 continue; /* should never happen */
5071                         t = (struct dup_inode *) dnode_get(m);
5072                         /*
5073                          * Report the inode that we are sharing with
5074                          */
5075                         pctx.inode = &t->inode;
5076                         pctx.ino = shared[i];
5077                         pctx.dir = t->dir;
5078                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5079                 }
5080                 if (file_ok) {
5081                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5082                         continue;
5083                 }
5084                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5085                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5086                         if (pctx.errcode)
5087                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5088                         else
5089                                 continue;
5090                 }
5091                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5092                         delete_file(ctx, ino, p, block_buf);
5093                 else
5094                         ext2fs_unmark_valid(fs);
5095         }
5096         ext2fs_free_mem(&shared);
5097 }
5098
5099 /*
5100  * Drop the refcount on the dup_block structure, and clear the entry
5101  * in the block_dup_map if appropriate.
5102  */
5103 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5104 {
5105         p->num_bad--;
5106         if (p->num_bad <= 0 ||
5107             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5108                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5109 }
5110
5111 static int delete_file_block(ext2_filsys fs,
5112                              blk_t      *block_nr,
5113                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5114                              blk_t ref_block FSCK_ATTR((unused)),
5115                              int ref_offset FSCK_ATTR((unused)),
5116                              void *priv_data)
5117 {
5118         struct process_block_struct_1b *pb;
5119         struct dup_block *p;
5120         dnode_t *n;
5121         e2fsck_t ctx;
5122
5123         pb = (struct process_block_struct_1b *) priv_data;
5124         ctx = pb->ctx;
5125
5126         if (HOLE_BLKADDR(*block_nr))
5127                 return 0;
5128
5129         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5130                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5131                 if (n) {
5132                         p = (struct dup_block *) dnode_get(n);
5133                         decrement_badcount(ctx, *block_nr, p);
5134                 } else
5135                         bb_error_msg(_("internal error; can't find dup_blk for %d\n"),
5136                                 *block_nr);
5137         } else {
5138                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5139                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5140         }
5141
5142         return 0;
5143 }
5144
5145 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5146                         struct dup_inode *dp, char* block_buf)
5147 {
5148         ext2_filsys fs = ctx->fs;
5149         struct process_block_struct_1b pb;
5150         struct ext2_inode       inode;
5151         struct problem_context  pctx;
5152         unsigned int            count;
5153
5154         clear_problem_context(&pctx);
5155         pctx.ino = pb.ino = ino;
5156         pb.dup_blocks = dp->num_dupblocks;
5157         pb.ctx = ctx;
5158         pctx.str = "delete_file";
5159
5160         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5161         if (ext2fs_inode_has_valid_blocks(&inode))
5162                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5163                                                      delete_file_block, &pb);
5164         if (pctx.errcode)
5165                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5166         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5167         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5168         if (ctx->inode_bad_map)
5169                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5170         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5171
5172         /* Inode may have changed by block_iterate, so reread it */
5173         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5174         inode.i_links_count = 0;
5175         inode.i_dtime = time(0);
5176         if (inode.i_file_acl &&
5177             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5178                 count = 1;
5179                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5180                                                    block_buf, -1, &count);
5181                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5182                         pctx.errcode = 0;
5183                         count = 1;
5184                 }
5185                 if (pctx.errcode) {
5186                         pctx.blk = inode.i_file_acl;
5187                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5188                 }
5189                 /*
5190                  * If the count is zero, then arrange to have the
5191                  * block deleted.  If the block is in the block_dup_map,
5192                  * also call delete_file_block since it will take care
5193                  * of keeping the accounting straight.
5194                  */
5195                 if ((count == 0) ||
5196                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5197                                              inode.i_file_acl))
5198                         delete_file_block(fs, &inode.i_file_acl,
5199                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5200         }
5201         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5202 }
5203
5204 struct clone_struct {
5205         errcode_t       errcode;
5206         ext2_ino_t      dir;
5207         char    *buf;
5208         e2fsck_t ctx;
5209 };
5210
5211 static int clone_file_block(ext2_filsys fs,
5212                             blk_t       *block_nr,
5213                             e2_blkcnt_t blockcnt,
5214                             blk_t ref_block FSCK_ATTR((unused)),
5215                             int ref_offset FSCK_ATTR((unused)),
5216                             void *priv_data)
5217 {
5218         struct dup_block *p;
5219         blk_t   new_block;
5220         errcode_t       retval;
5221         struct clone_struct *cs = (struct clone_struct *) priv_data;
5222         dnode_t *n;
5223         e2fsck_t ctx;
5224
5225         ctx = cs->ctx;
5226
5227         if (HOLE_BLKADDR(*block_nr))
5228                 return 0;
5229
5230         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5231                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5232                 if (n) {
5233                         p = (struct dup_block *) dnode_get(n);
5234                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5235                                                   &new_block);
5236                         if (retval) {
5237                                 cs->errcode = retval;
5238                                 return BLOCK_ABORT;
5239                         }
5240                         if (cs->dir && (blockcnt >= 0)) {
5241                                 retval = ext2fs_set_dir_block(fs->dblist,
5242                                       cs->dir, new_block, blockcnt);
5243                                 if (retval) {
5244                                         cs->errcode = retval;
5245                                         return BLOCK_ABORT;
5246                                 }
5247                         }
5248
5249                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5250                                                      cs->buf);
5251                         if (retval) {
5252                                 cs->errcode = retval;
5253                                 return BLOCK_ABORT;
5254                         }
5255                         retval = io_channel_write_blk(fs->io, new_block, 1,
5256                                                       cs->buf);
5257                         if (retval) {
5258                                 cs->errcode = retval;
5259                                 return BLOCK_ABORT;
5260                         }
5261                         decrement_badcount(ctx, *block_nr, p);
5262                         *block_nr = new_block;
5263                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5264                                                  new_block);
5265                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5266                         return BLOCK_CHANGED;
5267                 } else
5268                         bb_error_msg(_("internal error; can't find dup_blk for %d\n"),
5269                                 *block_nr);
5270         }
5271         return 0;
5272 }
5273
5274 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5275                       struct dup_inode *dp, char* block_buf)
5276 {
5277         ext2_filsys fs = ctx->fs;
5278         errcode_t       retval;
5279         struct clone_struct cs;
5280         struct problem_context  pctx;
5281         blk_t           blk;
5282         dnode_t         *n;
5283         struct inode_el *ino_el;
5284         struct dup_block        *db;
5285         struct dup_inode        *di;
5286
5287         clear_problem_context(&pctx);
5288         cs.errcode = 0;
5289         cs.dir = 0;
5290         cs.ctx = ctx;
5291         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5292         if (retval)
5293                 return retval;
5294
5295         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5296                 cs.dir = ino;
5297
5298         pctx.ino = ino;
5299         pctx.str = "clone_file";
5300         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5301                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5302                                                      clone_file_block, &cs);
5303         ext2fs_mark_bb_dirty(fs);
5304         if (pctx.errcode) {
5305                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5306                 retval = pctx.errcode;
5307                 goto errout;
5308         }
5309         if (cs.errcode) {
5310                 bb_error_msg(_("returned from clone_file_block"));
5311                 retval = cs.errcode;
5312                 goto errout;
5313         }
5314         /* The inode may have changed on disk, so we have to re-read it */
5315         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5316         blk = dp->inode.i_file_acl;
5317         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5318                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5319                     BLOCK_CHANGED)) {
5320                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5321                 /*
5322                  * If we cloned the EA block, find all other inodes
5323                  * which refered to that EA block, and modify
5324                  * them to point to the new EA block.
5325                  */
5326                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5327                 db = (struct dup_block *) dnode_get(n);
5328                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5329                         if (ino_el->inode == ino)
5330                                 continue;
5331                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5332                         di = (struct dup_inode *) dnode_get(n);
5333                         if (di->inode.i_file_acl == blk) {
5334                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5335                                 e2fsck_write_inode(ctx, ino_el->inode,
5336                                            &di->inode, "clone file EA");
5337                                 decrement_badcount(ctx, blk, db);
5338                         }
5339                 }
5340         }
5341         retval = 0;
5342 errout:
5343         ext2fs_free_mem(&cs.buf);
5344         return retval;
5345 }
5346
5347 /*
5348  * This routine returns 1 if a block overlaps with one of the superblocks,
5349  * group descriptors, inode bitmaps, or block bitmaps.
5350  */
5351 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5352 {
5353         ext2_filsys fs = ctx->fs;
5354         blk_t   block;
5355         dgrp_t  i;
5356
5357         block = fs->super->s_first_data_block;
5358         for (i = 0; i < fs->group_desc_count; i++) {
5359
5360                 /* Check superblocks/block group descriptros */
5361                 if (ext2fs_bg_has_super(fs, i)) {
5362                         if (test_block >= block &&
5363                             (test_block <= block + fs->desc_blocks))
5364                                 return 1;
5365                 }
5366
5367                 /* Check the inode table */
5368                 if ((fs->group_desc[i].bg_inode_table) &&
5369                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5370                     (test_block < (fs->group_desc[i].bg_inode_table +
5371                                    fs->inode_blocks_per_group)))
5372                         return 1;
5373
5374                 /* Check the bitmap blocks */
5375                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5376                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5377                         return 1;
5378
5379                 block += fs->super->s_blocks_per_group;
5380         }
5381         return 0;
5382 }
5383 /*
5384  * pass2.c --- check directory structure
5385  *
5386  * Pass 2 of e2fsck iterates through all active directory inodes, and
5387  * applies to following tests to each directory entry in the directory
5388  * blocks in the inodes:
5389  *
5390  *      - The length of the directory entry (rec_len) should be at
5391  *              least 8 bytes, and no more than the remaining space
5392  *              left in the directory block.
5393  *      - The length of the name in the directory entry (name_len)
5394  *              should be less than (rec_len - 8).
5395  *      - The inode number in the directory entry should be within
5396  *              legal bounds.
5397  *      - The inode number should refer to a in-use inode.
5398  *      - The first entry should be '.', and its inode should be
5399  *              the inode of the directory.
5400  *      - The second entry should be '..'.
5401  *
5402  * To minimize disk seek time, the directory blocks are processed in
5403  * sorted order of block numbers.
5404  *
5405  * Pass 2 also collects the following information:
5406  *      - The inode numbers of the subdirectories for each directory.
5407  *
5408  * Pass 2 relies on the following information from previous passes:
5409  *      - The directory information collected in pass 1.
5410  *      - The inode_used_map bitmap
5411  *      - The inode_bad_map bitmap
5412  *      - The inode_dir_map bitmap
5413  *
5414  * Pass 2 frees the following data structures
5415  *      - The inode_bad_map bitmap
5416  *      - The inode_reg_map bitmap
5417  */
5418
5419 /*
5420  * Keeps track of how many times an inode is referenced.
5421  */
5422 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5423 static int check_dir_block(ext2_filsys fs,
5424                            struct ext2_db_entry *dir_blocks_info,
5425                            void *priv_data);
5426 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5427                               struct problem_context *pctx);
5428 static int update_dir_block(ext2_filsys fs,
5429                             blk_t       *block_nr,
5430                             e2_blkcnt_t blockcnt,
5431                             blk_t       ref_block,
5432                             int         ref_offset,
5433                             void        *priv_data);
5434 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5435 static int htree_depth(struct dx_dir_info *dx_dir,
5436                        struct dx_dirblock_info *dx_db);
5437 static int special_dir_block_cmp(const void *a, const void *b);
5438
5439 struct check_dir_struct {
5440         char *buf;
5441         struct problem_context  pctx;
5442         int     count, max;
5443         e2fsck_t ctx;
5444 };
5445
5446 static void e2fsck_pass2(e2fsck_t ctx)
5447 {
5448         struct ext2_super_block *sb = ctx->fs->super;
5449         struct problem_context  pctx;
5450         ext2_filsys             fs = ctx->fs;
5451         char                    *buf;
5452         struct dir_info         *dir;
5453         struct check_dir_struct cd;
5454         struct dx_dir_info      *dx_dir;
5455         struct dx_dirblock_info *dx_db, *dx_parent;
5456         int                     b;
5457         int                     i, depth;
5458         problem_t               code;
5459         int                     bad_dir;
5460
5461         clear_problem_context(&cd.pctx);
5462
5463         /* Pass 2 */
5464
5465         if (!(ctx->options & E2F_OPT_PREEN))
5466                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5467
5468         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5469                                                 0, ctx->inode_link_info,
5470                                                 &ctx->inode_count);
5471         if (cd.pctx.errcode) {
5472                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5473                 ctx->flags |= E2F_FLAG_ABORT;
5474                 return;
5475         }
5476         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5477                                               "directory scan buffer");
5478
5479         /*
5480          * Set up the parent pointer for the root directory, if
5481          * present.  (If the root directory is not present, we will
5482          * create it in pass 3.)
5483          */
5484         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5485         if (dir)
5486                 dir->parent = EXT2_ROOT_INO;
5487
5488         cd.buf = buf;
5489         cd.ctx = ctx;
5490         cd.count = 1;
5491         cd.max = ext2fs_dblist_count(fs->dblist);
5492
5493         if (ctx->progress)
5494                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5495
5496         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5497                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5498
5499         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5500                                                 &cd);
5501         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5502                 return;
5503         if (cd.pctx.errcode) {
5504                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5505                 ctx->flags |= E2F_FLAG_ABORT;
5506                 return;
5507         }
5508
5509 #ifdef ENABLE_HTREE
5510         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5511                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5512                         return;
5513                 if (dx_dir->numblocks == 0)
5514                         continue;
5515                 clear_problem_context(&pctx);
5516                 bad_dir = 0;
5517                 pctx.dir = dx_dir->ino;
5518                 dx_db = dx_dir->dx_block;
5519                 if (dx_db->flags & DX_FLAG_REFERENCED)
5520                         dx_db->flags |= DX_FLAG_DUP_REF;
5521                 else
5522                         dx_db->flags |= DX_FLAG_REFERENCED;
5523                 /*
5524                  * Find all of the first and last leaf blocks, and
5525                  * update their parent's min and max hash values
5526                  */
5527                 for (b=0, dx_db = dx_dir->dx_block;
5528                      b < dx_dir->numblocks;
5529                      b++, dx_db++) {
5530                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5531                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5532                                 continue;
5533                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5534                         /*
5535                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5536                          */
5537                         if (dx_db->flags & DX_FLAG_FIRST)
5538                                 dx_parent->min_hash = dx_db->min_hash;
5539                         /*
5540                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5541                          */
5542                         if (dx_db->flags & DX_FLAG_LAST)
5543                                 dx_parent->max_hash = dx_db->max_hash;
5544                 }
5545
5546                 for (b=0, dx_db = dx_dir->dx_block;
5547                      b < dx_dir->numblocks;
5548                      b++, dx_db++) {
5549                         pctx.blkcount = b;
5550                         pctx.group = dx_db->parent;
5551                         code = 0;
5552                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5553                             (dx_db->min_hash < dx_db->node_min_hash)) {
5554                                 pctx.blk = dx_db->min_hash;
5555                                 pctx.blk2 = dx_db->node_min_hash;
5556                                 code = PR_2_HTREE_MIN_HASH;
5557                                 fix_problem(ctx, code, &pctx);
5558                                 bad_dir++;
5559                         }
5560                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5561                                 depth = htree_depth(dx_dir, dx_db);
5562                                 if (depth != dx_dir->depth) {
5563                                         code = PR_2_HTREE_BAD_DEPTH;
5564                                         fix_problem(ctx, code, &pctx);
5565                                         bad_dir++;
5566                                 }
5567                         }
5568                         /*
5569                          * This test doesn't apply for the root block
5570                          * at block #0
5571                          */
5572                         if (b &&
5573                             (dx_db->max_hash > dx_db->node_max_hash)) {
5574                                 pctx.blk = dx_db->max_hash;
5575                                 pctx.blk2 = dx_db->node_max_hash;
5576                                 code = PR_2_HTREE_MAX_HASH;
5577                                 fix_problem(ctx, code, &pctx);
5578                                 bad_dir++;
5579                         }
5580                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5581                                 code = PR_2_HTREE_NOTREF;
5582                                 fix_problem(ctx, code, &pctx);
5583                                 bad_dir++;
5584                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5585                                 code = PR_2_HTREE_DUPREF;
5586                                 fix_problem(ctx, code, &pctx);
5587                                 bad_dir++;
5588                         }
5589                         if (code == 0)
5590                                 continue;
5591                 }
5592                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5593                         clear_htree(ctx, dx_dir->ino);
5594                         dx_dir->numblocks = 0;
5595                 }
5596         }
5597 #endif
5598         ext2fs_free_mem(&buf);
5599         ext2fs_free_dblist(fs->dblist);
5600
5601         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5602         ctx->inode_bad_map = 0;
5603         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5604         ctx->inode_reg_map = 0;
5605
5606         clear_problem_context(&pctx);
5607         if (ctx->large_files) {
5608                 if (!(sb->s_feature_ro_compat &
5609                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5610                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5611                         sb->s_feature_ro_compat |=
5612                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5613                         ext2fs_mark_super_dirty(fs);
5614                 }
5615                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5616                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5617                         ext2fs_update_dynamic_rev(fs);
5618                         ext2fs_mark_super_dirty(fs);
5619                 }
5620         } else if (!ctx->large_files &&
5621             (sb->s_feature_ro_compat &
5622               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5623                 if (fs->flags & EXT2_FLAG_RW) {
5624                         sb->s_feature_ro_compat &=
5625                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5626                         ext2fs_mark_super_dirty(fs);
5627                 }
5628         }
5629
5630 }
5631
5632 #define MAX_DEPTH 32000
5633 static int htree_depth(struct dx_dir_info *dx_dir,
5634                        struct dx_dirblock_info *dx_db)
5635 {
5636         int     depth = 0;
5637
5638         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5639                 dx_db = &dx_dir->dx_block[dx_db->parent];
5640                 depth++;
5641         }
5642         return depth;
5643 }
5644
5645 static int dict_de_cmp(const void *a, const void *b)
5646 {
5647         const struct ext2_dir_entry *de_a, *de_b;
5648         int     a_len, b_len;
5649
5650         de_a = (const struct ext2_dir_entry *) a;
5651         a_len = de_a->name_len & 0xFF;
5652         de_b = (const struct ext2_dir_entry *) b;
5653         b_len = de_b->name_len & 0xFF;
5654
5655         if (a_len != b_len)
5656                 return (a_len - b_len);
5657
5658         return strncmp(de_a->name, de_b->name, a_len);
5659 }
5660
5661 /*
5662  * This is special sort function that makes sure that directory blocks
5663  * with a dirblock of zero are sorted to the beginning of the list.
5664  * This guarantees that the root node of the htree directories are
5665  * processed first, so we know what hash version to use.
5666  */
5667 static int special_dir_block_cmp(const void *a, const void *b)
5668 {
5669         const struct ext2_db_entry *db_a =
5670                 (const struct ext2_db_entry *) a;
5671         const struct ext2_db_entry *db_b =
5672                 (const struct ext2_db_entry *) b;
5673
5674         if (db_a->blockcnt && !db_b->blockcnt)
5675                 return 1;
5676
5677         if (!db_a->blockcnt && db_b->blockcnt)
5678                 return -1;
5679
5680         if (db_a->blk != db_b->blk)
5681                 return (int) (db_a->blk - db_b->blk);
5682
5683         if (db_a->ino != db_b->ino)
5684                 return (int) (db_a->ino - db_b->ino);
5685
5686         return (int) (db_a->blockcnt - db_b->blockcnt);
5687 }
5688
5689
5690 /*
5691  * Make sure the first entry in the directory is '.', and that the
5692  * directory entry is sane.
5693  */
5694 static int check_dot(e2fsck_t ctx,
5695                      struct ext2_dir_entry *dirent,
5696                      ext2_ino_t ino, struct problem_context *pctx)
5697 {
5698         struct ext2_dir_entry *nextdir;
5699         int     status = 0;
5700         int     created = 0;
5701         int     new_len;
5702         int     problem = 0;
5703
5704         if (!dirent->inode)
5705                 problem = PR_2_MISSING_DOT;
5706         else if (((dirent->name_len & 0xFF) != 1) ||
5707                  (dirent->name[0] != '.'))
5708                 problem = PR_2_1ST_NOT_DOT;
5709         else if (dirent->name[1] != '\0')
5710                 problem = PR_2_DOT_NULL_TERM;
5711
5712         if (problem) {
5713                 if (fix_problem(ctx, problem, pctx)) {
5714                         if (dirent->rec_len < 12)
5715                                 dirent->rec_len = 12;
5716                         dirent->inode = ino;
5717                         dirent->name_len = 1;
5718                         dirent->name[0] = '.';
5719                         dirent->name[1] = '\0';
5720                         status = 1;
5721                         created = 1;
5722                 }
5723         }
5724         if (dirent->inode != ino) {
5725                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5726                         dirent->inode = ino;
5727                         status = 1;
5728                 }
5729         }
5730         if (dirent->rec_len > 12) {
5731                 new_len = dirent->rec_len - 12;
5732                 if (new_len > 12) {
5733                         if (created ||
5734                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5735                                 nextdir = (struct ext2_dir_entry *)
5736                                         ((char *) dirent + 12);
5737                                 dirent->rec_len = 12;
5738                                 nextdir->rec_len = new_len;
5739                                 nextdir->inode = 0;
5740                                 nextdir->name_len = 0;
5741                                 status = 1;
5742                         }
5743                 }
5744         }
5745         return status;
5746 }
5747
5748 /*
5749  * Make sure the second entry in the directory is '..', and that the
5750  * directory entry is sane.  We do not check the inode number of '..'
5751  * here; this gets done in pass 3.
5752  */
5753 static int check_dotdot(e2fsck_t ctx,
5754                         struct ext2_dir_entry *dirent,
5755                         struct dir_info *dir, struct problem_context *pctx)
5756 {
5757         int             problem = 0;
5758
5759         if (!dirent->inode)
5760                 problem = PR_2_MISSING_DOT_DOT;
5761         else if (((dirent->name_len & 0xFF) != 2) ||
5762                  (dirent->name[0] != '.') ||
5763                  (dirent->name[1] != '.'))
5764                 problem = PR_2_2ND_NOT_DOT_DOT;
5765         else if (dirent->name[2] != '\0')
5766                 problem = PR_2_DOT_DOT_NULL_TERM;
5767
5768         if (problem) {
5769                 if (fix_problem(ctx, problem, pctx)) {
5770                         if (dirent->rec_len < 12)
5771                                 dirent->rec_len = 12;
5772                         /*
5773                          * Note: we don't have the parent inode just
5774                          * yet, so we will fill it in with the root
5775                          * inode.  This will get fixed in pass 3.
5776                          */
5777                         dirent->inode = EXT2_ROOT_INO;
5778                         dirent->name_len = 2;
5779                         dirent->name[0] = '.';
5780                         dirent->name[1] = '.';
5781                         dirent->name[2] = '\0';
5782                         return 1;
5783                 }
5784                 return 0;
5785         }
5786         dir->dotdot = dirent->inode;
5787         return 0;
5788 }
5789
5790 /*
5791  * Check to make sure a directory entry doesn't contain any illegal
5792  * characters.
5793  */
5794 static int check_name(e2fsck_t ctx,
5795                       struct ext2_dir_entry *dirent,
5796                       struct problem_context *pctx)
5797 {
5798         int     i;
5799         int     fixup = -1;
5800         int     ret = 0;
5801
5802         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5803                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5804                         if (fixup < 0) {
5805                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5806                         }
5807                         if (fixup) {
5808                                 dirent->name[i] = '.';
5809                                 ret = 1;
5810                         }
5811                 }
5812         }
5813         return ret;
5814 }
5815
5816 /*
5817  * Check the directory filetype (if present)
5818  */
5819
5820 /*
5821  * Given a mode, return the ext2 file type
5822  */
5823 static int ext2_file_type(unsigned int mode)
5824 {
5825         if (LINUX_S_ISREG(mode))
5826                 return EXT2_FT_REG_FILE;
5827
5828         if (LINUX_S_ISDIR(mode))
5829                 return EXT2_FT_DIR;
5830
5831         if (LINUX_S_ISCHR(mode))
5832                 return EXT2_FT_CHRDEV;
5833
5834         if (LINUX_S_ISBLK(mode))
5835                 return EXT2_FT_BLKDEV;
5836
5837         if (LINUX_S_ISLNK(mode))
5838                 return EXT2_FT_SYMLINK;
5839
5840         if (LINUX_S_ISFIFO(mode))
5841                 return EXT2_FT_FIFO;
5842
5843         if (LINUX_S_ISSOCK(mode))
5844                 return EXT2_FT_SOCK;
5845
5846         return 0;
5847 }
5848
5849 static int check_filetype(e2fsck_t ctx,
5850                                    struct ext2_dir_entry *dirent,
5851                                    struct problem_context *pctx)
5852 {
5853         int     filetype = dirent->name_len >> 8;
5854         int     should_be = EXT2_FT_UNKNOWN;
5855         struct ext2_inode       inode;
5856
5857         if (!(ctx->fs->super->s_feature_incompat &
5858               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5859                 if (filetype == 0 ||
5860                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5861                         return 0;
5862                 dirent->name_len = dirent->name_len & 0xFF;
5863                 return 1;
5864         }
5865
5866         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5867                 should_be = EXT2_FT_DIR;
5868         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5869                                             dirent->inode)) {
5870                 should_be = EXT2_FT_REG_FILE;
5871         } else if (ctx->inode_bad_map &&
5872                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5873                                             dirent->inode))
5874                 should_be = 0;
5875         else {
5876                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5877                                   "check_filetype");
5878                 should_be = ext2_file_type(inode.i_mode);
5879         }
5880         if (filetype == should_be)
5881                 return 0;
5882         pctx->num = should_be;
5883
5884         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5885                         pctx) == 0)
5886                 return 0;
5887
5888         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5889         return 1;
5890 }
5891
5892 #ifdef ENABLE_HTREE
5893 static void parse_int_node(ext2_filsys fs,
5894                            struct ext2_db_entry *db,
5895                            struct check_dir_struct *cd,
5896                            struct dx_dir_info   *dx_dir,
5897                            char *block_buf)
5898 {
5899         struct          ext2_dx_root_info  *root;
5900         struct          ext2_dx_entry *ent;
5901         struct          ext2_dx_countlimit *limit;
5902         struct dx_dirblock_info *dx_db;
5903         int             i, expect_limit, count;
5904         blk_t           blk;
5905         ext2_dirhash_t  min_hash = 0xffffffff;
5906         ext2_dirhash_t  max_hash = 0;
5907         ext2_dirhash_t  hash = 0, prev_hash;
5908
5909         if (db->blockcnt == 0) {
5910                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5911                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5912         } else {
5913                 ent = (struct ext2_dx_entry *) (block_buf+8);
5914         }
5915         limit = (struct ext2_dx_countlimit *) ent;
5916
5917         count = ext2fs_le16_to_cpu(limit->count);
5918         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5919                 sizeof(struct ext2_dx_entry);
5920         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5921                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5922                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5923                         goto clear_and_exit;
5924         }
5925         if (count > expect_limit) {
5926                 cd->pctx.num = count;
5927                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5928                         goto clear_and_exit;
5929                 count = expect_limit;
5930         }
5931
5932         for (i=0; i < count; i++) {
5933                 prev_hash = hash;
5934                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5935                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5936                 /* Check to make sure the block is valid */
5937                 if (blk > (blk_t) dx_dir->numblocks) {
5938                         cd->pctx.blk = blk;
5939                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5940                                         &cd->pctx))
5941                                 goto clear_and_exit;
5942                 }
5943                 if (hash < prev_hash &&
5944                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5945                         goto clear_and_exit;
5946                 dx_db = &dx_dir->dx_block[blk];
5947                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5948                         dx_db->flags |= DX_FLAG_DUP_REF;
5949                 } else {
5950                         dx_db->flags |= DX_FLAG_REFERENCED;
5951                         dx_db->parent = db->blockcnt;
5952                 }
5953                 if (hash < min_hash)
5954                         min_hash = hash;
5955                 if (hash > max_hash)
5956                         max_hash = hash;
5957                 dx_db->node_min_hash = hash;
5958                 if ((i+1) < count)
5959                         dx_db->node_max_hash =
5960                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5961                 else {
5962                         dx_db->node_max_hash = 0xfffffffe;
5963                         dx_db->flags |= DX_FLAG_LAST;
5964                 }
5965                 if (i == 0)
5966                         dx_db->flags |= DX_FLAG_FIRST;
5967         }
5968         dx_db = &dx_dir->dx_block[db->blockcnt];
5969         dx_db->min_hash = min_hash;
5970         dx_db->max_hash = max_hash;
5971         return;
5972
5973 clear_and_exit:
5974         clear_htree(cd->ctx, cd->pctx.ino);
5975         dx_dir->numblocks = 0;
5976 }
5977 #endif /* ENABLE_HTREE */
5978
5979 /*
5980  * Given a busted directory, try to salvage it somehow.
5981  *
5982  */
5983 static void salvage_directory(ext2_filsys fs,
5984                               struct ext2_dir_entry *dirent,
5985                               struct ext2_dir_entry *prev,
5986                               unsigned int *offset)
5987 {
5988         char    *cp = (char *) dirent;
5989         int left = fs->blocksize - *offset - dirent->rec_len;
5990         int name_len = dirent->name_len & 0xFF;
5991
5992         /*
5993          * Special case of directory entry of size 8: copy what's left
5994          * of the directory block up to cover up the invalid hole.
5995          */
5996         if ((left >= 12) && (dirent->rec_len == 8)) {
5997                 memmove(cp, cp+8, left);
5998                 memset(cp + left, 0, 8);
5999                 return;
6000         }
6001         /*
6002          * If the directory entry overruns the end of the directory
6003          * block, and the name is small enough to fit, then adjust the
6004          * record length.
6005          */
6006         if ((left < 0) &&
6007             (name_len + 8 <= dirent->rec_len + left) &&
6008             dirent->inode <= fs->super->s_inodes_count &&
6009             strnlen(dirent->name, name_len) == name_len) {
6010                 dirent->rec_len += left;
6011                 return;
6012         }
6013         /*
6014          * If the directory entry is a multiple of four, so it is
6015          * valid, let the previous directory entry absorb the invalid
6016          * one.
6017          */
6018         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
6019                 prev->rec_len += dirent->rec_len;
6020                 *offset += dirent->rec_len;
6021                 return;
6022         }
6023         /*
6024          * Default salvage method --- kill all of the directory
6025          * entries for the rest of the block.  We will either try to
6026          * absorb it into the previous directory entry, or create a
6027          * new empty directory entry the rest of the directory block.
6028          */
6029         if (prev) {
6030                 prev->rec_len += fs->blocksize - *offset;
6031                 *offset = fs->blocksize;
6032         } else {
6033                 dirent->rec_len = fs->blocksize - *offset;
6034                 dirent->name_len = 0;
6035                 dirent->inode = 0;
6036         }
6037 }
6038
6039 static int check_dir_block(ext2_filsys fs,
6040                            struct ext2_db_entry *db,
6041                            void *priv_data)
6042 {
6043         struct dir_info         *subdir, *dir;
6044         struct dx_dir_info      *dx_dir;
6045 #ifdef ENABLE_HTREE
6046         struct dx_dirblock_info *dx_db = 0;
6047 #endif /* ENABLE_HTREE */
6048         struct ext2_dir_entry   *dirent, *prev;
6049         ext2_dirhash_t          hash;
6050         unsigned int            offset = 0;
6051         int                     dir_modified = 0;
6052         int                     dot_state;
6053         blk_t                   block_nr = db->blk;
6054         ext2_ino_t              ino = db->ino;
6055         __u16                   links;
6056         struct check_dir_struct *cd;
6057         char                    *buf;
6058         e2fsck_t                ctx;
6059         int                     problem;
6060         struct ext2_dx_root_info *root;
6061         struct ext2_dx_countlimit *limit;
6062         static dict_t de_dict;
6063         struct problem_context  pctx;
6064         int     dups_found = 0;
6065
6066         cd = (struct check_dir_struct *) priv_data;
6067         buf = cd->buf;
6068         ctx = cd->ctx;
6069
6070         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6071                 return DIRENT_ABORT;
6072
6073         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6074                 return DIRENT_ABORT;
6075
6076         /*
6077          * Make sure the inode is still in use (could have been
6078          * deleted in the duplicate/bad blocks pass.
6079          */
6080         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6081                 return 0;
6082
6083         cd->pctx.ino = ino;
6084         cd->pctx.blk = block_nr;
6085         cd->pctx.blkcount = db->blockcnt;
6086         cd->pctx.ino2 = 0;
6087         cd->pctx.dirent = 0;
6088         cd->pctx.num = 0;
6089
6090         if (db->blk == 0) {
6091                 if (allocate_dir_block(ctx, db, &cd->pctx))
6092                         return 0;
6093                 block_nr = db->blk;
6094         }
6095
6096         if (db->blockcnt)
6097                 dot_state = 2;
6098         else
6099                 dot_state = 0;
6100
6101         if (ctx->dirs_to_hash &&
6102             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6103                 dups_found++;
6104
6105         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6106         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6107                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6108         if (cd->pctx.errcode) {
6109                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6110                         ctx->flags |= E2F_FLAG_ABORT;
6111                         return DIRENT_ABORT;
6112                 }
6113                 memset(buf, 0, fs->blocksize);
6114         }
6115 #ifdef ENABLE_HTREE
6116         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6117         if (dx_dir && dx_dir->numblocks) {
6118                 if (db->blockcnt >= dx_dir->numblocks) {
6119                         printf("XXX should never happen!!!\n");
6120                         abort();
6121                 }
6122                 dx_db = &dx_dir->dx_block[db->blockcnt];
6123                 dx_db->type = DX_DIRBLOCK_LEAF;
6124                 dx_db->phys = block_nr;
6125                 dx_db->min_hash = ~0;
6126                 dx_db->max_hash = 0;
6127
6128                 dirent = (struct ext2_dir_entry *) buf;
6129                 limit = (struct ext2_dx_countlimit *) (buf+8);
6130                 if (db->blockcnt == 0) {
6131                         root = (struct ext2_dx_root_info *) (buf + 24);
6132                         dx_db->type = DX_DIRBLOCK_ROOT;
6133                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6134                         if ((root->reserved_zero ||
6135                              root->info_length < 8 ||
6136                              root->indirect_levels > 1) &&
6137                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6138                                 clear_htree(ctx, ino);
6139                                 dx_dir->numblocks = 0;
6140                                 dx_db = 0;
6141                         }
6142                         dx_dir->hashversion = root->hash_version;
6143                         dx_dir->depth = root->indirect_levels + 1;
6144                 } else if ((dirent->inode == 0) &&
6145                            (dirent->rec_len == fs->blocksize) &&
6146                            (dirent->name_len == 0) &&
6147                            (ext2fs_le16_to_cpu(limit->limit) ==
6148                             ((fs->blocksize-8) /
6149                              sizeof(struct ext2_dx_entry))))
6150                         dx_db->type = DX_DIRBLOCK_NODE;
6151         }
6152 #endif /* ENABLE_HTREE */
6153
6154         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6155         prev = 0;
6156         do {
6157                 problem = 0;
6158                 dirent = (struct ext2_dir_entry *) (buf + offset);
6159                 cd->pctx.dirent = dirent;
6160                 cd->pctx.num = offset;
6161                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6162                     (dirent->rec_len < 12) ||
6163                     ((dirent->rec_len % 4) != 0) ||
6164                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6165                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6166                                 salvage_directory(fs, dirent, prev, &offset);
6167                                 dir_modified++;
6168                                 continue;
6169                         } else
6170                                 goto abort_free_dict;
6171                 }
6172                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6173                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6174                                 dirent->name_len = EXT2_NAME_LEN;
6175                                 dir_modified++;
6176                         }
6177                 }
6178
6179                 if (dot_state == 0) {
6180                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6181                                 dir_modified++;
6182                 } else if (dot_state == 1) {
6183                         dir = e2fsck_get_dir_info(ctx, ino);
6184                         if (!dir) {
6185                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6186                                 goto abort_free_dict;
6187                         }
6188                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6189                                 dir_modified++;
6190                 } else if (dirent->inode == ino) {
6191                         problem = PR_2_LINK_DOT;
6192                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6193                                 dirent->inode = 0;
6194                                 dir_modified++;
6195                                 goto next;
6196                         }
6197                 }
6198                 if (!dirent->inode)
6199                         goto next;
6200
6201                 /*
6202                  * Make sure the inode listed is a legal one.
6203                  */
6204                 if (((dirent->inode != EXT2_ROOT_INO) &&
6205                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6206                     (dirent->inode > fs->super->s_inodes_count)) {
6207                         problem = PR_2_BAD_INO;
6208                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6209                                                dirent->inode))) {
6210                         /*
6211                          * If the inode is unused, offer to clear it.
6212                          */
6213                         problem = PR_2_UNUSED_INODE;
6214                 } else if ((dot_state > 1) &&
6215                            ((dirent->name_len & 0xFF) == 1) &&
6216                            (dirent->name[0] == '.')) {
6217                         /*
6218                          * If there's a '.' entry in anything other
6219                          * than the first directory entry, it's a
6220                          * duplicate entry that should be removed.
6221                          */
6222                         problem = PR_2_DUP_DOT;
6223                 } else if ((dot_state > 1) &&
6224                            ((dirent->name_len & 0xFF) == 2) &&
6225                            (dirent->name[0] == '.') &&
6226                            (dirent->name[1] == '.')) {
6227                         /*
6228                          * If there's a '..' entry in anything other
6229                          * than the second directory entry, it's a
6230                          * duplicate entry that should be removed.
6231                          */
6232                         problem = PR_2_DUP_DOT_DOT;
6233                 } else if ((dot_state > 1) &&
6234                            (dirent->inode == EXT2_ROOT_INO)) {
6235                         /*
6236                          * Don't allow links to the root directory.
6237                          * We check this specially to make sure we
6238                          * catch this error case even if the root
6239                          * directory hasn't been created yet.
6240                          */
6241                         problem = PR_2_LINK_ROOT;
6242                 } else if ((dot_state > 1) &&
6243                            (dirent->name_len & 0xFF) == 0) {
6244                         /*
6245                          * Don't allow zero-length directory names.
6246                          */
6247                         problem = PR_2_NULL_NAME;
6248                 }
6249
6250                 if (problem) {
6251                         if (fix_problem(ctx, problem, &cd->pctx)) {
6252                                 dirent->inode = 0;
6253                                 dir_modified++;
6254                                 goto next;
6255                         } else {
6256                                 ext2fs_unmark_valid(fs);
6257                                 if (problem == PR_2_BAD_INO)
6258                                         goto next;
6259                         }
6260                 }
6261
6262                 /*
6263                  * If the inode was marked as having bad fields in
6264                  * pass1, process it and offer to fix/clear it.
6265                  * (We wait until now so that we can display the
6266                  * pathname to the user.)
6267                  */
6268                 if (ctx->inode_bad_map &&
6269                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6270                                              dirent->inode)) {
6271                         if (e2fsck_process_bad_inode(ctx, ino,
6272                                                      dirent->inode,
6273                                                      buf + fs->blocksize)) {
6274                                 dirent->inode = 0;
6275                                 dir_modified++;
6276                                 goto next;
6277                         }
6278                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6279                                 return DIRENT_ABORT;
6280                 }
6281
6282                 if (check_name(ctx, dirent, &cd->pctx))
6283                         dir_modified++;
6284
6285                 if (check_filetype(ctx, dirent, &cd->pctx))
6286                         dir_modified++;
6287
6288 #ifdef ENABLE_HTREE
6289                 if (dx_db) {
6290                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6291                                        (dirent->name_len & 0xFF),
6292                                        fs->super->s_hash_seed, &hash, 0);
6293                         if (hash < dx_db->min_hash)
6294                                 dx_db->min_hash = hash;
6295                         if (hash > dx_db->max_hash)
6296                                 dx_db->max_hash = hash;
6297                 }
6298 #endif
6299
6300                 /*
6301                  * If this is a directory, then mark its parent in its
6302                  * dir_info structure.  If the parent field is already
6303                  * filled in, then this directory has more than one
6304                  * hard link.  We assume the first link is correct,
6305                  * and ask the user if he/she wants to clear this one.
6306                  */
6307                 if ((dot_state > 1) &&
6308                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6309                                               dirent->inode))) {
6310                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6311                         if (!subdir) {
6312                                 cd->pctx.ino = dirent->inode;
6313                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6314                                 goto abort_free_dict;
6315                         }
6316                         if (subdir->parent) {
6317                                 cd->pctx.ino2 = subdir->parent;
6318                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6319                                                 &cd->pctx)) {
6320                                         dirent->inode = 0;
6321                                         dir_modified++;
6322                                         goto next;
6323                                 }
6324                                 cd->pctx.ino2 = 0;
6325                         } else
6326                                 subdir->parent = ino;
6327                 }
6328
6329                 if (dups_found) {
6330                         ;
6331                 } else if (dict_lookup(&de_dict, dirent)) {
6332                         clear_problem_context(&pctx);
6333                         pctx.ino = ino;
6334                         pctx.dirent = dirent;
6335                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6336                         if (!ctx->dirs_to_hash)
6337                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6338                         if (ctx->dirs_to_hash)
6339                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6340                         dups_found++;
6341                 } else
6342                         dict_alloc_insert(&de_dict, dirent, dirent);
6343
6344                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6345                                         &links);
6346                 if (links > 1)
6347                         ctx->fs_links_count++;
6348                 ctx->fs_total_count++;
6349         next:
6350                 prev = dirent;
6351                 offset += dirent->rec_len;
6352                 dot_state++;
6353         } while (offset < fs->blocksize);
6354 #ifdef ENABLE_HTREE
6355         if (dx_db) {
6356                 cd->pctx.dir = cd->pctx.ino;
6357                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6358                     (dx_db->type == DX_DIRBLOCK_NODE))
6359                         parse_int_node(fs, db, cd, dx_dir, buf);
6360         }
6361 #endif /* ENABLE_HTREE */
6362         if (offset != fs->blocksize) {
6363                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6364                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6365                         dirent->rec_len = cd->pctx.num;
6366                         dir_modified++;
6367                 }
6368         }
6369         if (dir_modified) {
6370                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6371                 if (cd->pctx.errcode) {
6372                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6373                                          &cd->pctx))
6374                                 goto abort_free_dict;
6375                 }
6376                 ext2fs_mark_changed(fs);
6377         }
6378         dict_free_nodes(&de_dict);
6379         return 0;
6380 abort_free_dict:
6381         dict_free_nodes(&de_dict);
6382         ctx->flags |= E2F_FLAG_ABORT;
6383         return DIRENT_ABORT;
6384 }
6385
6386 /*
6387  * This function is called to deallocate a block, and is an interator
6388  * functioned called by deallocate inode via ext2fs_iterate_block().
6389  */
6390 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6391                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6392                                   blk_t ref_block FSCK_ATTR((unused)),
6393                                   int ref_offset FSCK_ATTR((unused)),
6394                                   void *priv_data)
6395 {
6396         e2fsck_t        ctx = (e2fsck_t) priv_data;
6397
6398         if (HOLE_BLKADDR(*block_nr))
6399                 return 0;
6400         if ((*block_nr < fs->super->s_first_data_block) ||
6401             (*block_nr >= fs->super->s_blocks_count))
6402                 return 0;
6403         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6404         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6405         return 0;
6406 }
6407
6408 /*
6409  * This fuction deallocates an inode
6410  */
6411 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6412 {
6413         ext2_filsys fs = ctx->fs;
6414         struct ext2_inode       inode;
6415         struct problem_context  pctx;
6416         __u32                   count;
6417
6418         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6419         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6420         inode.i_links_count = 0;
6421         inode.i_dtime = time(0);
6422         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6423         clear_problem_context(&pctx);
6424         pctx.ino = ino;
6425
6426         /*
6427          * Fix up the bitmaps...
6428          */
6429         e2fsck_read_bitmaps(ctx);
6430         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6431         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6432         if (ctx->inode_bad_map)
6433                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6434         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6435
6436         if (inode.i_file_acl &&
6437             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6438                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6439                                                    block_buf, -1, &count);
6440                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6441                         pctx.errcode = 0;
6442                         count = 1;
6443                 }
6444                 if (pctx.errcode) {
6445                         pctx.blk = inode.i_file_acl;
6446                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6447                         ctx->flags |= E2F_FLAG_ABORT;
6448                         return;
6449                 }
6450                 if (count == 0) {
6451                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6452                                                    inode.i_file_acl);
6453                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6454                 }
6455                 inode.i_file_acl = 0;
6456         }
6457
6458         if (!ext2fs_inode_has_valid_blocks(&inode))
6459                 return;
6460
6461         if (LINUX_S_ISREG(inode.i_mode) &&
6462             (inode.i_size_high || inode.i_size & 0x80000000UL))
6463                 ctx->large_files--;
6464
6465         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6466                                             deallocate_inode_block, ctx);
6467         if (pctx.errcode) {
6468                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6469                 ctx->flags |= E2F_FLAG_ABORT;
6470                 return;
6471         }
6472 }
6473
6474 /*
6475  * This fuction clears the htree flag on an inode
6476  */
6477 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6478 {
6479         struct ext2_inode       inode;
6480
6481         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6482         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6483         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6484         if (ctx->dirs_to_hash)
6485                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6486 }
6487
6488
6489 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6490                                     ext2_ino_t ino, char *buf)
6491 {
6492         ext2_filsys fs = ctx->fs;
6493         struct ext2_inode       inode;
6494         int                     inode_modified = 0;
6495         int                     not_fixed = 0;
6496         unsigned char           *frag, *fsize;
6497         struct problem_context  pctx;
6498         int     problem = 0;
6499
6500         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6501
6502         clear_problem_context(&pctx);
6503         pctx.ino = ino;
6504         pctx.dir = dir;
6505         pctx.inode = &inode;
6506
6507         if (inode.i_file_acl &&
6508             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6509             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6510                 inode.i_file_acl = 0;
6511 #if BB_BIG_ENDIAN
6512                 /*
6513                  * This is a special kludge to deal with long symlinks
6514                  * on big endian systems.  i_blocks had already been
6515                  * decremented earlier in pass 1, but since i_file_acl
6516                  * hadn't yet been cleared, ext2fs_read_inode()
6517                  * assumed that the file was short symlink and would
6518                  * not have byte swapped i_block[0].  Hence, we have
6519                  * to byte-swap it here.
6520                  */
6521                 if (LINUX_S_ISLNK(inode.i_mode) &&
6522                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6523                     (inode.i_blocks == fs->blocksize >> 9))
6524                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6525 #endif
6526                 inode_modified++;
6527         } else
6528                 not_fixed++;
6529
6530         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6531             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6532             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6533             !(LINUX_S_ISSOCK(inode.i_mode)))
6534                 problem = PR_2_BAD_MODE;
6535         else if (LINUX_S_ISCHR(inode.i_mode)
6536                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6537                 problem = PR_2_BAD_CHAR_DEV;
6538         else if (LINUX_S_ISBLK(inode.i_mode)
6539                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6540                 problem = PR_2_BAD_BLOCK_DEV;
6541         else if (LINUX_S_ISFIFO(inode.i_mode)
6542                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6543                 problem = PR_2_BAD_FIFO;
6544         else if (LINUX_S_ISSOCK(inode.i_mode)
6545                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6546                 problem = PR_2_BAD_SOCKET;
6547         else if (LINUX_S_ISLNK(inode.i_mode)
6548                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6549                 problem = PR_2_INVALID_SYMLINK;
6550         }
6551
6552         if (problem) {
6553                 if (fix_problem(ctx, problem, &pctx)) {
6554                         deallocate_inode(ctx, ino, 0);
6555                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6556                                 return 0;
6557                         return 1;
6558                 } else
6559                         not_fixed++;
6560                 problem = 0;
6561         }
6562
6563         if (inode.i_faddr) {
6564                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6565                         inode.i_faddr = 0;
6566                         inode_modified++;
6567                 } else
6568                         not_fixed++;
6569         }
6570
6571         switch (fs->super->s_creator_os) {
6572             case EXT2_OS_LINUX:
6573                 frag = &inode.osd2.linux2.l_i_frag;
6574                 fsize = &inode.osd2.linux2.l_i_fsize;
6575                 break;
6576             case EXT2_OS_HURD:
6577                 frag = &inode.osd2.hurd2.h_i_frag;
6578                 fsize = &inode.osd2.hurd2.h_i_fsize;
6579                 break;
6580             case EXT2_OS_MASIX:
6581                 frag = &inode.osd2.masix2.m_i_frag;
6582                 fsize = &inode.osd2.masix2.m_i_fsize;
6583                 break;
6584             default:
6585                 frag = fsize = 0;
6586         }
6587         if (frag && *frag) {
6588                 pctx.num = *frag;
6589                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6590                         *frag = 0;
6591                         inode_modified++;
6592                 } else
6593                         not_fixed++;
6594                 pctx.num = 0;
6595         }
6596         if (fsize && *fsize) {
6597                 pctx.num = *fsize;
6598                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6599                         *fsize = 0;
6600                         inode_modified++;
6601                 } else
6602                         not_fixed++;
6603                 pctx.num = 0;
6604         }
6605
6606         if (inode.i_file_acl &&
6607             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6608              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6609                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6610                         inode.i_file_acl = 0;
6611                         inode_modified++;
6612                 } else
6613                         not_fixed++;
6614         }
6615         if (inode.i_dir_acl &&
6616             LINUX_S_ISDIR(inode.i_mode)) {
6617                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6618                         inode.i_dir_acl = 0;
6619                         inode_modified++;
6620                 } else
6621                         not_fixed++;
6622         }
6623
6624         if (inode_modified)
6625                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6626         if (!not_fixed)
6627                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6628         return 0;
6629 }
6630
6631
6632 /*
6633  * allocate_dir_block --- this function allocates a new directory
6634  *      block for a particular inode; this is done if a directory has
6635  *      a "hole" in it, or if a directory has a illegal block number
6636  *      that was zeroed out and now needs to be replaced.
6637  */
6638 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6639                               struct problem_context *pctx)
6640 {
6641         ext2_filsys fs = ctx->fs;
6642         blk_t                   blk;
6643         char                    *block;
6644         struct ext2_inode       inode;
6645
6646         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6647                 return 1;
6648
6649         /*
6650          * Read the inode and block bitmaps in; we'll be messing with
6651          * them.
6652          */
6653         e2fsck_read_bitmaps(ctx);
6654
6655         /*
6656          * First, find a free block
6657          */
6658         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6659         if (pctx->errcode) {
6660                 pctx->str = "ext2fs_new_block";
6661                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6662                 return 1;
6663         }
6664         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6665         ext2fs_mark_block_bitmap(fs->block_map, blk);
6666         ext2fs_mark_bb_dirty(fs);
6667
6668         /*
6669          * Now let's create the actual data block for the inode
6670          */
6671         if (db->blockcnt)
6672                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6673         else
6674                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6675                                                      EXT2_ROOT_INO, &block);
6676
6677         if (pctx->errcode) {
6678                 pctx->str = "ext2fs_new_dir_block";
6679                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6680                 return 1;
6681         }
6682
6683         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6684         ext2fs_free_mem(&block);
6685         if (pctx->errcode) {
6686                 pctx->str = "ext2fs_write_dir_block";
6687                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6688                 return 1;
6689         }
6690
6691         /*
6692          * Update the inode block count
6693          */
6694         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6695         inode.i_blocks += fs->blocksize / 512;
6696         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6697                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6698         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6699
6700         /*
6701          * Finally, update the block pointers for the inode
6702          */
6703         db->blk = blk;
6704         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6705                                       0, update_dir_block, db);
6706         if (pctx->errcode) {
6707                 pctx->str = "ext2fs_block_iterate";
6708                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6709                 return 1;
6710         }
6711
6712         return 0;
6713 }
6714
6715 /*
6716  * This is a helper function for allocate_dir_block().
6717  */
6718 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6719                             blk_t       *block_nr,
6720                             e2_blkcnt_t blockcnt,
6721                             blk_t ref_block FSCK_ATTR((unused)),
6722                             int ref_offset FSCK_ATTR((unused)),
6723                             void *priv_data)
6724 {
6725         struct ext2_db_entry *db;
6726
6727         db = (struct ext2_db_entry *) priv_data;
6728         if (db->blockcnt == (int) blockcnt) {
6729                 *block_nr = db->blk;
6730                 return BLOCK_CHANGED;
6731         }
6732         return 0;
6733 }
6734
6735 /*
6736  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6737  *
6738  * Pass #3 assures that all directories are connected to the
6739  * filesystem tree, using the following algorithm:
6740  *
6741  * First, the root directory is checked to make sure it exists; if
6742  * not, e2fsck will offer to create a new one.  It is then marked as
6743  * "done".
6744  *
6745  * Then, pass3 interates over all directory inodes; for each directory
6746  * it attempts to trace up the filesystem tree, using dirinfo.parent
6747  * until it reaches a directory which has been marked "done".  If it
6748  * can not do so, then the directory must be disconnected, and e2fsck
6749  * will offer to reconnect it to /lost+found.  While it is chasing
6750  * parent pointers up the filesystem tree, if pass3 sees a directory
6751  * twice, then it has detected a filesystem loop, and it will again
6752  * offer to reconnect the directory to /lost+found in to break the
6753  * filesystem loop.
6754  *
6755  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6756  * reconnect inodes to /lost+found; this subroutine is also used by
6757  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6758  * is responsible for creating /lost+found if it does not exist.
6759  *
6760  * Pass 3 frees the following data structures:
6761  *      - The dirinfo directory information cache.
6762  */
6763
6764 static void check_root(e2fsck_t ctx);
6765 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6766                            struct problem_context *pctx);
6767 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6768
6769 static ext2fs_inode_bitmap inode_loop_detect;
6770 static ext2fs_inode_bitmap inode_done_map;
6771
6772 static void e2fsck_pass3(e2fsck_t ctx)
6773 {
6774         ext2_filsys fs = ctx->fs;
6775         int             i;
6776         struct problem_context  pctx;
6777         struct dir_info *dir;
6778         unsigned long maxdirs, count;
6779
6780         clear_problem_context(&pctx);
6781
6782         /* Pass 3 */
6783
6784         if (!(ctx->options & E2F_OPT_PREEN))
6785                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6786
6787         /*
6788          * Allocate some bitmaps to do loop detection.
6789          */
6790         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6791                                                     &inode_done_map);
6792         if (pctx.errcode) {
6793                 pctx.num = 2;
6794                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6795                 ctx->flags |= E2F_FLAG_ABORT;
6796                 goto abort_exit;
6797         }
6798         check_root(ctx);
6799         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6800                 goto abort_exit;
6801
6802         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6803
6804         maxdirs = e2fsck_get_num_dirinfo(ctx);
6805         count = 1;
6806
6807         if (ctx->progress)
6808                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6809                         goto abort_exit;
6810
6811         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6812                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6813                         goto abort_exit;
6814                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6815                         goto abort_exit;
6816                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6817                         if (check_directory(ctx, dir, &pctx))
6818                                 goto abort_exit;
6819         }
6820
6821         /*
6822          * Force the creation of /lost+found if not present
6823          */
6824         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6825                 e2fsck_get_lost_and_found(ctx, 1);
6826
6827         /*
6828          * If there are any directories that need to be indexed or
6829          * optimized, do it here.
6830          */
6831         e2fsck_rehash_directories(ctx);
6832
6833 abort_exit:
6834         e2fsck_free_dir_info(ctx);
6835         ext2fs_free_inode_bitmap(inode_loop_detect);
6836         inode_loop_detect = 0;
6837         ext2fs_free_inode_bitmap(inode_done_map);
6838         inode_done_map = 0;
6839 }
6840
6841 /*
6842  * This makes sure the root inode is present; if not, we ask if the
6843  * user wants us to create it.  Not creating it is a fatal error.
6844  */
6845 static void check_root(e2fsck_t ctx)
6846 {
6847         ext2_filsys fs = ctx->fs;
6848         blk_t                   blk;
6849         struct ext2_inode       inode;
6850         char *                  block;
6851         struct problem_context  pctx;
6852
6853         clear_problem_context(&pctx);
6854
6855         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6856                 /*
6857                  * If the root inode is not a directory, die here.  The
6858                  * user must have answered 'no' in pass1 when we
6859                  * offered to clear it.
6860                  */
6861                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6862                                                EXT2_ROOT_INO))) {
6863                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6864                         ctx->flags |= E2F_FLAG_ABORT;
6865                 }
6866                 return;
6867         }
6868
6869         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6870                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6871                 ctx->flags |= E2F_FLAG_ABORT;
6872                 return;
6873         }
6874
6875         e2fsck_read_bitmaps(ctx);
6876
6877         /*
6878          * First, find a free block
6879          */
6880         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6881         if (pctx.errcode) {
6882                 pctx.str = "ext2fs_new_block";
6883                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6884                 ctx->flags |= E2F_FLAG_ABORT;
6885                 return;
6886         }
6887         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6888         ext2fs_mark_block_bitmap(fs->block_map, blk);
6889         ext2fs_mark_bb_dirty(fs);
6890
6891         /*
6892          * Now let's create the actual data block for the inode
6893          */
6894         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6895                                             &block);
6896         if (pctx.errcode) {
6897                 pctx.str = "ext2fs_new_dir_block";
6898                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6899                 ctx->flags |= E2F_FLAG_ABORT;
6900                 return;
6901         }
6902
6903         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6904         if (pctx.errcode) {
6905                 pctx.str = "ext2fs_write_dir_block";
6906                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6907                 ctx->flags |= E2F_FLAG_ABORT;
6908                 return;
6909         }
6910         ext2fs_free_mem(&block);
6911
6912         /*
6913          * Set up the inode structure
6914          */
6915         memset(&inode, 0, sizeof(inode));
6916         inode.i_mode = 040755;
6917         inode.i_size = fs->blocksize;
6918         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
6919         inode.i_links_count = 2;
6920         inode.i_blocks = fs->blocksize / 512;
6921         inode.i_block[0] = blk;
6922
6923         /*
6924          * Write out the inode.
6925          */
6926         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6927         if (pctx.errcode) {
6928                 pctx.str = "ext2fs_write_inode";
6929                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6930                 ctx->flags |= E2F_FLAG_ABORT;
6931                 return;
6932         }
6933
6934         /*
6935          * Miscellaneous bookkeeping...
6936          */
6937         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6938         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6939         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6940
6941         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6942         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6943         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6944         ext2fs_mark_ib_dirty(fs);
6945 }
6946
6947 /*
6948  * This subroutine is responsible for making sure that a particular
6949  * directory is connected to the root; if it isn't we trace it up as
6950  * far as we can go, and then offer to connect the resulting parent to
6951  * the lost+found.  We have to do loop detection; if we ever discover
6952  * a loop, we treat that as a disconnected directory and offer to
6953  * reparent it to lost+found.
6954  *
6955  * However, loop detection is expensive, because for very large
6956  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6957  * is non-trivial.  Loops in filesystems are also a rare error case,
6958  * and we shouldn't optimize for error cases.  So we try two passes of
6959  * the algorithm.  The first time, we ignore loop detection and merely
6960  * increment a counter; if the counter exceeds some extreme threshold,
6961  * then we try again with the loop detection bitmap enabled.
6962  */
6963 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6964                            struct problem_context *pctx)
6965 {
6966         ext2_filsys     fs = ctx->fs;
6967         struct dir_info *p = dir;
6968         int             loop_pass = 0, parent_count = 0;
6969
6970         if (!p)
6971                 return 0;
6972
6973         while (1) {
6974                 /*
6975                  * Mark this inode as being "done"; by the time we
6976                  * return from this function, the inode we either be
6977                  * verified as being connected to the directory tree,
6978                  * or we will have offered to reconnect this to
6979                  * lost+found.
6980                  *
6981                  * If it was marked done already, then we've reached a
6982                  * parent we've already checked.
6983                  */
6984                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6985                         break;
6986
6987                 /*
6988                  * If this directory doesn't have a parent, or we've
6989                  * seen the parent once already, then offer to
6990                  * reparent it to lost+found
6991                  */
6992                 if (!p->parent ||
6993                     (loop_pass &&
6994                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6995                                               p->parent)))) {
6996                         pctx->ino = p->ino;
6997                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6998                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6999                                         ext2fs_unmark_valid(fs);
7000                                 else {
7001                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
7002                                         p->parent = ctx->lost_and_found;
7003                                         fix_dotdot(ctx, p, ctx->lost_and_found);
7004                                 }
7005                         }
7006                         break;
7007                 }
7008                 p = e2fsck_get_dir_info(ctx, p->parent);
7009                 if (!p) {
7010                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
7011                         return 0;
7012                 }
7013                 if (loop_pass) {
7014                         ext2fs_mark_inode_bitmap(inode_loop_detect,
7015                                                  p->ino);
7016                 } else if (parent_count++ > 2048) {
7017                         /*
7018                          * If we've run into a path depth that's
7019                          * greater than 2048, try again with the inode
7020                          * loop bitmap turned on and start from the
7021                          * top.
7022                          */
7023                         loop_pass = 1;
7024                         if (inode_loop_detect)
7025                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
7026                         else {
7027                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7028                                 if (pctx->errcode) {
7029                                         pctx->num = 1;
7030                                         fix_problem(ctx,
7031                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7032                                         ctx->flags |= E2F_FLAG_ABORT;
7033                                         return -1;
7034                                 }
7035                         }
7036                         p = dir;
7037                 }
7038         }
7039
7040         /*
7041          * Make sure that .. and the parent directory are the same;
7042          * offer to fix it if not.
7043          */
7044         if (dir->parent != dir->dotdot) {
7045                 pctx->ino = dir->ino;
7046                 pctx->ino2 = dir->dotdot;
7047                 pctx->dir = dir->parent;
7048                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7049                         fix_dotdot(ctx, dir, dir->parent);
7050         }
7051         return 0;
7052 }
7053
7054 /*
7055  * This routine gets the lost_and_found inode, making it a directory
7056  * if necessary
7057  */
7058 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7059 {
7060         ext2_filsys fs = ctx->fs;
7061         ext2_ino_t                      ino;
7062         blk_t                   blk;
7063         errcode_t               retval;
7064         struct ext2_inode       inode;
7065         char *                  block;
7066         static const char       name[] = "lost+found";
7067         struct  problem_context pctx;
7068         struct dir_info         *dirinfo;
7069
7070         if (ctx->lost_and_found)
7071                 return ctx->lost_and_found;
7072
7073         clear_problem_context(&pctx);
7074
7075         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7076                                sizeof(name)-1, 0, &ino);
7077         if (retval && !fix)
7078                 return 0;
7079         if (!retval) {
7080                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7081                         ctx->lost_and_found = ino;
7082                         return ino;
7083                 }
7084
7085                 /* Lost+found isn't a directory! */
7086                 if (!fix)
7087                         return 0;
7088                 pctx.ino = ino;
7089                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7090                         return 0;
7091
7092                 /* OK, unlink the old /lost+found file. */
7093                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7094                 if (pctx.errcode) {
7095                         pctx.str = "ext2fs_unlink";
7096                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7097                         return 0;
7098                 }
7099                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7100                 if (dirinfo)
7101                         dirinfo->parent = 0;
7102                 e2fsck_adjust_inode_count(ctx, ino, -1);
7103         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7104                 pctx.errcode = retval;
7105                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7106         }
7107         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7108                 return 0;
7109
7110         /*
7111          * Read the inode and block bitmaps in; we'll be messing with
7112          * them.
7113          */
7114         e2fsck_read_bitmaps(ctx);
7115
7116         /*
7117          * First, find a free block
7118          */
7119         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7120         if (retval) {
7121                 pctx.errcode = retval;
7122                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7123                 return 0;
7124         }
7125         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7126         ext2fs_block_alloc_stats(fs, blk, +1);
7127
7128         /*
7129          * Next find a free inode.
7130          */
7131         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7132                                   ctx->inode_used_map, &ino);
7133         if (retval) {
7134                 pctx.errcode = retval;
7135                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7136                 return 0;
7137         }
7138         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7139         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7140         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7141
7142         /*
7143          * Now let's create the actual data block for the inode
7144          */
7145         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7146         if (retval) {
7147                 pctx.errcode = retval;
7148                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7149                 return 0;
7150         }
7151
7152         retval = ext2fs_write_dir_block(fs, blk, block);
7153         ext2fs_free_mem(&block);
7154         if (retval) {
7155                 pctx.errcode = retval;
7156                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7157                 return 0;
7158         }
7159
7160         /*
7161          * Set up the inode structure
7162          */
7163         memset(&inode, 0, sizeof(inode));
7164         inode.i_mode = 040700;
7165         inode.i_size = fs->blocksize;
7166         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
7167         inode.i_links_count = 2;
7168         inode.i_blocks = fs->blocksize / 512;
7169         inode.i_block[0] = blk;
7170
7171         /*
7172          * Next, write out the inode.
7173          */
7174         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7175         if (pctx.errcode) {
7176                 pctx.str = "ext2fs_write_inode";
7177                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7178                 return 0;
7179         }
7180         /*
7181          * Finally, create the directory link
7182          */
7183         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7184         if (pctx.errcode) {
7185                 pctx.str = "ext2fs_link";
7186                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7187                 return 0;
7188         }
7189
7190         /*
7191          * Miscellaneous bookkeeping that needs to be kept straight.
7192          */
7193         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7194         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7195         ext2fs_icount_store(ctx->inode_count, ino, 2);
7196         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7197         ctx->lost_and_found = ino;
7198         return ino;
7199 }
7200
7201 /*
7202  * This routine will connect a file to lost+found
7203  */
7204 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7205 {
7206         ext2_filsys fs = ctx->fs;
7207         errcode_t       retval;
7208         char            name[80];
7209         struct problem_context  pctx;
7210         struct ext2_inode       inode;
7211         int             file_type = 0;
7212
7213         clear_problem_context(&pctx);
7214         pctx.ino = ino;
7215
7216         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7217                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7218                         ctx->bad_lost_and_found++;
7219         }
7220         if (ctx->bad_lost_and_found) {
7221                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7222                 return 1;
7223         }
7224
7225         sprintf(name, "#%u", ino);
7226         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7227                 file_type = ext2_file_type(inode.i_mode);
7228         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7229         if (retval == EXT2_ET_DIR_NO_SPACE) {
7230                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7231                         return 1;
7232                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7233                                                  1, 0);
7234                 if (retval) {
7235                         pctx.errcode = retval;
7236                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7237                         return 1;
7238                 }
7239                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7240                                      ino, file_type);
7241         }
7242         if (retval) {
7243                 pctx.errcode = retval;
7244                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7245                 return 1;
7246         }
7247         e2fsck_adjust_inode_count(ctx, ino, 1);
7248
7249         return 0;
7250 }
7251
7252 /*
7253  * Utility routine to adjust the inode counts on an inode.
7254  */
7255 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7256 {
7257         ext2_filsys fs = ctx->fs;
7258         errcode_t               retval;
7259         struct ext2_inode       inode;
7260
7261         if (!ino)
7262                 return 0;
7263
7264         retval = ext2fs_read_inode(fs, ino, &inode);
7265         if (retval)
7266                 return retval;
7267
7268         if (adj == 1) {
7269                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7270                 if (inode.i_links_count == (__u16) ~0)
7271                         return 0;
7272                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7273                 inode.i_links_count++;
7274         } else if (adj == -1) {
7275                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7276                 if (inode.i_links_count == 0)
7277                         return 0;
7278                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7279                 inode.i_links_count--;
7280         }
7281
7282         retval = ext2fs_write_inode(fs, ino, &inode);
7283         if (retval)
7284                 return retval;
7285
7286         return 0;
7287 }
7288
7289 /*
7290  * Fix parent --- this routine fixes up the parent of a directory.
7291  */
7292 struct fix_dotdot_struct {
7293         ext2_filsys     fs;
7294         ext2_ino_t      parent;
7295         int             done;
7296         e2fsck_t        ctx;
7297 };
7298
7299 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7300                            int  offset FSCK_ATTR((unused)),
7301                            int  blocksize FSCK_ATTR((unused)),
7302                            char *buf FSCK_ATTR((unused)),
7303                            void *priv_data)
7304 {
7305         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7306         errcode_t       retval;
7307         struct problem_context pctx;
7308
7309         if ((dirent->name_len & 0xFF) != 2)
7310                 return 0;
7311         if (strncmp(dirent->name, "..", 2))
7312                 return 0;
7313
7314         clear_problem_context(&pctx);
7315
7316         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7317         if (retval) {
7318                 pctx.errcode = retval;
7319                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7320         }
7321         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7322         if (retval) {
7323                 pctx.errcode = retval;
7324                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7325         }
7326         dirent->inode = fp->parent;
7327
7328         fp->done++;
7329         return DIRENT_ABORT | DIRENT_CHANGED;
7330 }
7331
7332 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7333 {
7334         ext2_filsys fs = ctx->fs;
7335         errcode_t       retval;
7336         struct fix_dotdot_struct fp;
7337         struct problem_context pctx;
7338
7339         fp.fs = fs;
7340         fp.parent = parent;
7341         fp.done = 0;
7342         fp.ctx = ctx;
7343
7344         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7345                                     0, fix_dotdot_proc, &fp);
7346         if (retval || !fp.done) {
7347                 clear_problem_context(&pctx);
7348                 pctx.ino = dir->ino;
7349                 pctx.errcode = retval;
7350                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7351                             PR_3_FIX_PARENT_NOFIND, &pctx);
7352                 ext2fs_unmark_valid(fs);
7353         }
7354         dir->dotdot = parent;
7355
7356         return;
7357 }
7358
7359 /*
7360  * These routines are responsible for expanding a /lost+found if it is
7361  * too small.
7362  */
7363
7364 struct expand_dir_struct {
7365         int                     num;
7366         int                     guaranteed_size;
7367         int                     newblocks;
7368         int                     last_block;
7369         errcode_t               err;
7370         e2fsck_t                ctx;
7371 };
7372
7373 static int expand_dir_proc(ext2_filsys fs,
7374                            blk_t        *blocknr,
7375                            e2_blkcnt_t  blockcnt,
7376                            blk_t ref_block FSCK_ATTR((unused)),
7377                            int ref_offset FSCK_ATTR((unused)),
7378                            void *priv_data)
7379 {
7380         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7381         blk_t   new_blk;
7382         static blk_t    last_blk = 0;
7383         char            *block;
7384         errcode_t       retval;
7385         e2fsck_t        ctx;
7386
7387         ctx = es->ctx;
7388
7389         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7390                 return BLOCK_ABORT;
7391
7392         if (blockcnt > 0)
7393                 es->last_block = blockcnt;
7394         if (*blocknr) {
7395                 last_blk = *blocknr;
7396                 return 0;
7397         }
7398         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7399                                   &new_blk);
7400         if (retval) {
7401                 es->err = retval;
7402                 return BLOCK_ABORT;
7403         }
7404         if (blockcnt > 0) {
7405                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7406                 if (retval) {
7407                         es->err = retval;
7408                         return BLOCK_ABORT;
7409                 }
7410                 es->num--;
7411                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7412         } else {
7413                 retval = ext2fs_get_mem(fs->blocksize, &block);
7414                 if (retval) {
7415                         es->err = retval;
7416                         return BLOCK_ABORT;
7417                 }
7418                 memset(block, 0, fs->blocksize);
7419                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7420         }
7421         if (retval) {
7422                 es->err = retval;
7423                 return BLOCK_ABORT;
7424         }
7425         ext2fs_free_mem(&block);
7426         *blocknr = new_blk;
7427         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7428         ext2fs_block_alloc_stats(fs, new_blk, +1);
7429         es->newblocks++;
7430
7431         if (es->num == 0)
7432                 return (BLOCK_CHANGED | BLOCK_ABORT);
7433         else
7434                 return BLOCK_CHANGED;
7435 }
7436
7437 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7438                                   int num, int guaranteed_size)
7439 {
7440         ext2_filsys fs = ctx->fs;
7441         errcode_t       retval;
7442         struct expand_dir_struct es;
7443         struct ext2_inode       inode;
7444
7445         if (!(fs->flags & EXT2_FLAG_RW))
7446                 return EXT2_ET_RO_FILSYS;
7447
7448         /*
7449          * Read the inode and block bitmaps in; we'll be messing with
7450          * them.
7451          */
7452         e2fsck_read_bitmaps(ctx);
7453
7454         retval = ext2fs_check_directory(fs, dir);
7455         if (retval)
7456                 return retval;
7457
7458         es.num = num;
7459         es.guaranteed_size = guaranteed_size;
7460         es.last_block = 0;
7461         es.err = 0;
7462         es.newblocks = 0;
7463         es.ctx = ctx;
7464
7465         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7466                                        0, expand_dir_proc, &es);
7467
7468         if (es.err)
7469                 return es.err;
7470
7471         /*
7472          * Update the size and block count fields in the inode.
7473          */
7474         retval = ext2fs_read_inode(fs, dir, &inode);
7475         if (retval)
7476                 return retval;
7477
7478         inode.i_size = (es.last_block + 1) * fs->blocksize;
7479         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7480
7481         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7482
7483         return 0;
7484 }
7485
7486 /*
7487  * pass4.c -- pass #4 of e2fsck: Check reference counts
7488  *
7489  * Pass 4 frees the following data structures:
7490  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7491  */
7492
7493 /*
7494  * This routine is called when an inode is not connected to the
7495  * directory tree.
7496  *
7497  * This subroutine returns 1 then the caller shouldn't bother with the
7498  * rest of the pass 4 tests.
7499  */
7500 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7501 {
7502         ext2_filsys fs = ctx->fs;
7503         struct ext2_inode       inode;
7504         struct problem_context  pctx;
7505
7506         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7507         clear_problem_context(&pctx);
7508         pctx.ino = i;
7509         pctx.inode = &inode;
7510
7511         /*
7512          * Offer to delete any zero-length files that does not have
7513          * blocks.  If there is an EA block, it might have useful
7514          * information, so we won't prompt to delete it, but let it be
7515          * reconnected to lost+found.
7516          */
7517         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7518                                 LINUX_S_ISDIR(inode.i_mode))) {
7519                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7520                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7521                         inode.i_links_count = 0;
7522                         inode.i_dtime = time(0);
7523                         e2fsck_write_inode(ctx, i, &inode,
7524                                            "disconnect_inode");
7525                         /*
7526                          * Fix up the bitmaps...
7527                          */
7528                         e2fsck_read_bitmaps(ctx);
7529                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7530                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7531                         ext2fs_inode_alloc_stats2(fs, i, -1,
7532                                                   LINUX_S_ISDIR(inode.i_mode));
7533                         return 0;
7534                 }
7535         }
7536
7537         /*
7538          * Prompt to reconnect.
7539          */
7540         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7541                 if (e2fsck_reconnect_file(ctx, i))
7542                         ext2fs_unmark_valid(fs);
7543         } else {
7544                 /*
7545                  * If we don't attach the inode, then skip the
7546                  * i_links_test since there's no point in trying to
7547                  * force i_links_count to zero.
7548                  */
7549                 ext2fs_unmark_valid(fs);
7550                 return 1;
7551         }
7552         return 0;
7553 }
7554
7555
7556 static void e2fsck_pass4(e2fsck_t ctx)
7557 {
7558         ext2_filsys fs = ctx->fs;
7559         ext2_ino_t      i;
7560         struct ext2_inode       inode;
7561         struct problem_context  pctx;
7562         __u16   link_count, link_counted;
7563         char    *buf = 0;
7564         int     group, maxgroup;
7565
7566         /* Pass 4 */
7567
7568         clear_problem_context(&pctx);
7569
7570         if (!(ctx->options & E2F_OPT_PREEN))
7571                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7572
7573         group = 0;
7574         maxgroup = fs->group_desc_count;
7575         if (ctx->progress)
7576                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7577                         return;
7578
7579         for (i=1; i <= fs->super->s_inodes_count; i++) {
7580                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7581                         return;
7582                 if ((i % fs->super->s_inodes_per_group) == 0) {
7583                         group++;
7584                         if (ctx->progress)
7585                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7586                                         return;
7587                 }
7588                 if (i == EXT2_BAD_INO ||
7589                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7590                         continue;
7591                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7592                     (ctx->inode_imagic_map &&
7593                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7594                         continue;
7595                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7596                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7597                 if (link_counted == 0) {
7598                         if (!buf)
7599                                 buf = e2fsck_allocate_memory(ctx,
7600                                      fs->blocksize, "bad_inode buffer");
7601                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7602                                 continue;
7603                         if (disconnect_inode(ctx, i))
7604                                 continue;
7605                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7606                                             &link_count);
7607                         ext2fs_icount_fetch(ctx->inode_count, i,
7608                                             &link_counted);
7609                 }
7610                 if (link_counted != link_count) {
7611                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7612                         pctx.ino = i;
7613                         pctx.inode = &inode;
7614                         if (link_count != inode.i_links_count) {
7615                                 pctx.num = link_count;
7616                                 fix_problem(ctx,
7617                                             PR_4_INCONSISTENT_COUNT, &pctx);
7618                         }
7619                         pctx.num = link_counted;
7620                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7621                                 inode.i_links_count = link_counted;
7622                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7623                         }
7624                 }
7625         }
7626         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7627         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7628         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7629         ctx->inode_imagic_map = 0;
7630         ext2fs_free_mem(&buf);
7631 }
7632
7633 /*
7634  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7635  */
7636
7637 #define NO_BLK ((blk_t) -1)
7638
7639 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7640                             struct problem_context *pctx)
7641 {
7642         switch (problem) {
7643         case PR_5_BLOCK_UNUSED:
7644                 if (pctx->blk == pctx->blk2)
7645                         pctx->blk2 = 0;
7646                 else
7647                         problem = PR_5_BLOCK_RANGE_UNUSED;
7648                 break;
7649         case PR_5_BLOCK_USED:
7650                 if (pctx->blk == pctx->blk2)
7651                         pctx->blk2 = 0;
7652                 else
7653                         problem = PR_5_BLOCK_RANGE_USED;
7654                 break;
7655         case PR_5_INODE_UNUSED:
7656                 if (pctx->ino == pctx->ino2)
7657                         pctx->ino2 = 0;
7658                 else
7659                         problem = PR_5_INODE_RANGE_UNUSED;
7660                 break;
7661         case PR_5_INODE_USED:
7662                 if (pctx->ino == pctx->ino2)
7663                         pctx->ino2 = 0;
7664                 else
7665                         problem = PR_5_INODE_RANGE_USED;
7666                 break;
7667         }
7668         fix_problem(ctx, problem, pctx);
7669         pctx->blk = pctx->blk2 = NO_BLK;
7670         pctx->ino = pctx->ino2 = 0;
7671 }
7672
7673 static void check_block_bitmaps(e2fsck_t ctx)
7674 {
7675         ext2_filsys fs = ctx->fs;
7676         blk_t   i;
7677         int     *free_array;
7678         int     group = 0;
7679         unsigned int    blocks = 0;
7680         unsigned int    free_blocks = 0;
7681         int     group_free = 0;
7682         int     actual, bitmap;
7683         struct problem_context  pctx;
7684         int     problem, save_problem, fixit, had_problem;
7685         errcode_t       retval;
7686
7687         clear_problem_context(&pctx);
7688         free_array = (int *) e2fsck_allocate_memory(ctx,
7689             fs->group_desc_count * sizeof(int), "free block count array");
7690
7691         if ((fs->super->s_first_data_block <
7692              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7693             (fs->super->s_blocks_count-1 >
7694              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7695                 pctx.num = 1;
7696                 pctx.blk = fs->super->s_first_data_block;
7697                 pctx.blk2 = fs->super->s_blocks_count -1;
7698                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7699                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7700                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7701
7702                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7703                 return;
7704         }
7705
7706         if ((fs->super->s_first_data_block <
7707              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7708             (fs->super->s_blocks_count-1 >
7709              ext2fs_get_block_bitmap_end(fs->block_map))) {
7710                 pctx.num = 2;
7711                 pctx.blk = fs->super->s_first_data_block;
7712                 pctx.blk2 = fs->super->s_blocks_count -1;
7713                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7714                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7715                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7716
7717                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7718                 return;
7719         }
7720
7721 redo_counts:
7722         had_problem = 0;
7723         save_problem = 0;
7724         pctx.blk = pctx.blk2 = NO_BLK;
7725         for (i = fs->super->s_first_data_block;
7726              i < fs->super->s_blocks_count;
7727              i++) {
7728                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7729                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7730
7731                 if (actual == bitmap)
7732                         goto do_counts;
7733
7734                 if (!actual && bitmap) {
7735                         /*
7736                          * Block not used, but marked in use in the bitmap.
7737                          */
7738                         problem = PR_5_BLOCK_UNUSED;
7739                 } else {
7740                         /*
7741                          * Block used, but not marked in use in the bitmap.
7742                          */
7743                         problem = PR_5_BLOCK_USED;
7744                 }
7745                 if (pctx.blk == NO_BLK) {
7746                         pctx.blk = pctx.blk2 = i;
7747                         save_problem = problem;
7748                 } else {
7749                         if ((problem == save_problem) &&
7750                             (pctx.blk2 == i-1))
7751                                 pctx.blk2++;
7752                         else {
7753                                 print_bitmap_problem(ctx, save_problem, &pctx);
7754                                 pctx.blk = pctx.blk2 = i;
7755                                 save_problem = problem;
7756                         }
7757                 }
7758                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7759                 had_problem++;
7760
7761         do_counts:
7762                 if (!bitmap) {
7763                         group_free++;
7764                         free_blocks++;
7765                 }
7766                 blocks ++;
7767                 if ((blocks == fs->super->s_blocks_per_group) ||
7768                     (i == fs->super->s_blocks_count-1)) {
7769                         free_array[group] = group_free;
7770                         group ++;
7771                         blocks = 0;
7772                         group_free = 0;
7773                         if (ctx->progress)
7774                                 if ((ctx->progress)(ctx, 5, group,
7775                                                     fs->group_desc_count*2))
7776                                         return;
7777                 }
7778         }
7779         if (pctx.blk != NO_BLK)
7780                 print_bitmap_problem(ctx, save_problem, &pctx);
7781         if (had_problem)
7782                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7783         else
7784                 fixit = -1;
7785         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7786
7787         if (fixit == 1) {
7788                 ext2fs_free_block_bitmap(fs->block_map);
7789                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7790                                                   &fs->block_map);
7791                 if (retval) {
7792                         clear_problem_context(&pctx);
7793                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7794                         ctx->flags |= E2F_FLAG_ABORT;
7795                         return;
7796                 }
7797                 ext2fs_set_bitmap_padding(fs->block_map);
7798                 ext2fs_mark_bb_dirty(fs);
7799
7800                 /* Redo the counts */
7801                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7802                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7803                 goto redo_counts;
7804         } else if (fixit == 0)
7805                 ext2fs_unmark_valid(fs);
7806
7807         for (i = 0; i < fs->group_desc_count; i++) {
7808                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7809                         pctx.group = i;
7810                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7811                         pctx.blk2 = free_array[i];
7812
7813                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7814                                         &pctx)) {
7815                                 fs->group_desc[i].bg_free_blocks_count =
7816                                         free_array[i];
7817                                 ext2fs_mark_super_dirty(fs);
7818                         } else
7819                                 ext2fs_unmark_valid(fs);
7820                 }
7821         }
7822         if (free_blocks != fs->super->s_free_blocks_count) {
7823                 pctx.group = 0;
7824                 pctx.blk = fs->super->s_free_blocks_count;
7825                 pctx.blk2 = free_blocks;
7826
7827                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7828                         fs->super->s_free_blocks_count = free_blocks;
7829                         ext2fs_mark_super_dirty(fs);
7830                 } else
7831                         ext2fs_unmark_valid(fs);
7832         }
7833         ext2fs_free_mem(&free_array);
7834 }
7835
7836 static void check_inode_bitmaps(e2fsck_t ctx)
7837 {
7838         ext2_filsys fs = ctx->fs;
7839         ext2_ino_t      i;
7840         unsigned int    free_inodes = 0;
7841         int             group_free = 0;
7842         int             dirs_count = 0;
7843         int             group = 0;
7844         unsigned int    inodes = 0;
7845         int             *free_array;
7846         int             *dir_array;
7847         int             actual, bitmap;
7848         errcode_t       retval;
7849         struct problem_context  pctx;
7850         int             problem, save_problem, fixit, had_problem;
7851
7852         clear_problem_context(&pctx);
7853         free_array = (int *) e2fsck_allocate_memory(ctx,
7854             fs->group_desc_count * sizeof(int), "free inode count array");
7855
7856         dir_array = (int *) e2fsck_allocate_memory(ctx,
7857            fs->group_desc_count * sizeof(int), "directory count array");
7858
7859         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7860             (fs->super->s_inodes_count >
7861              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7862                 pctx.num = 3;
7863                 pctx.blk = 1;
7864                 pctx.blk2 = fs->super->s_inodes_count;
7865                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7866                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7867                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7868
7869                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7870                 return;
7871         }
7872         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7873             (fs->super->s_inodes_count >
7874              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7875                 pctx.num = 4;
7876                 pctx.blk = 1;
7877                 pctx.blk2 = fs->super->s_inodes_count;
7878                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7879                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7880                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7881
7882                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7883                 return;
7884         }
7885
7886 redo_counts:
7887         had_problem = 0;
7888         save_problem = 0;
7889         pctx.ino = pctx.ino2 = 0;
7890         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7891                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7892                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7893
7894                 if (actual == bitmap)
7895                         goto do_counts;
7896
7897                 if (!actual && bitmap) {
7898                         /*
7899                          * Inode wasn't used, but marked in bitmap
7900                          */
7901                         problem = PR_5_INODE_UNUSED;
7902                 } else /* if (actual && !bitmap) */ {
7903                         /*
7904                          * Inode used, but not in bitmap
7905                          */
7906                         problem = PR_5_INODE_USED;
7907                 }
7908                 if (pctx.ino == 0) {
7909                         pctx.ino = pctx.ino2 = i;
7910                         save_problem = problem;
7911                 } else {
7912                         if ((problem == save_problem) &&
7913                             (pctx.ino2 == i-1))
7914                                 pctx.ino2++;
7915                         else {
7916                                 print_bitmap_problem(ctx, save_problem, &pctx);
7917                                 pctx.ino = pctx.ino2 = i;
7918                                 save_problem = problem;
7919                         }
7920                 }
7921                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7922                 had_problem++;
7923
7924 do_counts:
7925                 if (!bitmap) {
7926                         group_free++;
7927                         free_inodes++;
7928                 } else {
7929                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7930                                 dirs_count++;
7931                 }
7932                 inodes++;
7933                 if ((inodes == fs->super->s_inodes_per_group) ||
7934                     (i == fs->super->s_inodes_count)) {
7935                         free_array[group] = group_free;
7936                         dir_array[group] = dirs_count;
7937                         group ++;
7938                         inodes = 0;
7939                         group_free = 0;
7940                         dirs_count = 0;
7941                         if (ctx->progress)
7942                                 if ((ctx->progress)(ctx, 5,
7943                                             group + fs->group_desc_count,
7944                                             fs->group_desc_count*2))
7945                                         return;
7946                 }
7947         }
7948         if (pctx.ino)
7949                 print_bitmap_problem(ctx, save_problem, &pctx);
7950
7951         if (had_problem)
7952                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7953         else
7954                 fixit = -1;
7955         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7956
7957         if (fixit == 1) {
7958                 ext2fs_free_inode_bitmap(fs->inode_map);
7959                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7960                                                   &fs->inode_map);
7961                 if (retval) {
7962                         clear_problem_context(&pctx);
7963                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7964                         ctx->flags |= E2F_FLAG_ABORT;
7965                         return;
7966                 }
7967                 ext2fs_set_bitmap_padding(fs->inode_map);
7968                 ext2fs_mark_ib_dirty(fs);
7969
7970                 /* redo counts */
7971                 inodes = 0; free_inodes = 0; group_free = 0;
7972                 dirs_count = 0; group = 0;
7973                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7974                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7975                 goto redo_counts;
7976         } else if (fixit == 0)
7977                 ext2fs_unmark_valid(fs);
7978
7979         for (i = 0; i < fs->group_desc_count; i++) {
7980                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7981                         pctx.group = i;
7982                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7983                         pctx.ino2 = free_array[i];
7984                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7985                                         &pctx)) {
7986                                 fs->group_desc[i].bg_free_inodes_count =
7987                                         free_array[i];
7988                                 ext2fs_mark_super_dirty(fs);
7989                         } else
7990                                 ext2fs_unmark_valid(fs);
7991                 }
7992                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7993                         pctx.group = i;
7994                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7995                         pctx.ino2 = dir_array[i];
7996
7997                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7998                                         &pctx)) {
7999                                 fs->group_desc[i].bg_used_dirs_count =
8000                                         dir_array[i];
8001                                 ext2fs_mark_super_dirty(fs);
8002                         } else
8003                                 ext2fs_unmark_valid(fs);
8004                 }
8005         }
8006         if (free_inodes != fs->super->s_free_inodes_count) {
8007                 pctx.group = -1;
8008                 pctx.ino = fs->super->s_free_inodes_count;
8009                 pctx.ino2 = free_inodes;
8010
8011                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
8012                         fs->super->s_free_inodes_count = free_inodes;
8013                         ext2fs_mark_super_dirty(fs);
8014                 } else
8015                         ext2fs_unmark_valid(fs);
8016         }
8017         ext2fs_free_mem(&free_array);
8018         ext2fs_free_mem(&dir_array);
8019 }
8020
8021 static void check_inode_end(e2fsck_t ctx)
8022 {
8023         ext2_filsys fs = ctx->fs;
8024         ext2_ino_t      end, save_inodes_count, i;
8025         struct problem_context  pctx;
8026
8027         clear_problem_context(&pctx);
8028
8029         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8030         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8031                                                      &save_inodes_count);
8032         if (pctx.errcode) {
8033                 pctx.num = 1;
8034                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8035                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8036                 return;
8037         }
8038         if (save_inodes_count == end)
8039                 return;
8040
8041         for (i = save_inodes_count + 1; i <= end; i++) {
8042                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8043                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8044                                 for (i = save_inodes_count + 1; i <= end; i++)
8045                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8046                                                                  i);
8047                                 ext2fs_mark_ib_dirty(fs);
8048                         } else
8049                                 ext2fs_unmark_valid(fs);
8050                         break;
8051                 }
8052         }
8053
8054         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8055                                                      save_inodes_count, 0);
8056         if (pctx.errcode) {
8057                 pctx.num = 2;
8058                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8059                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8060                 return;
8061         }
8062 }
8063
8064 static void check_block_end(e2fsck_t ctx)
8065 {
8066         ext2_filsys fs = ctx->fs;
8067         blk_t   end, save_blocks_count, i;
8068         struct problem_context  pctx;
8069
8070         clear_problem_context(&pctx);
8071
8072         end = fs->block_map->start +
8073                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8074         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8075                                                      &save_blocks_count);
8076         if (pctx.errcode) {
8077                 pctx.num = 3;
8078                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8079                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8080                 return;
8081         }
8082         if (save_blocks_count == end)
8083                 return;
8084
8085         for (i = save_blocks_count + 1; i <= end; i++) {
8086                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8087                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8088                                 for (i = save_blocks_count + 1; i <= end; i++)
8089                                         ext2fs_mark_block_bitmap(fs->block_map,
8090                                                                  i);
8091                                 ext2fs_mark_bb_dirty(fs);
8092                         } else
8093                                 ext2fs_unmark_valid(fs);
8094                         break;
8095                 }
8096         }
8097
8098         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8099                                                      save_blocks_count, 0);
8100         if (pctx.errcode) {
8101                 pctx.num = 4;
8102                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8103                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8104                 return;
8105         }
8106 }
8107
8108 static void e2fsck_pass5(e2fsck_t ctx)
8109 {
8110         struct problem_context  pctx;
8111
8112         /* Pass 5 */
8113
8114         clear_problem_context(&pctx);
8115
8116         if (!(ctx->options & E2F_OPT_PREEN))
8117                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8118
8119         if (ctx->progress)
8120                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8121                         return;
8122
8123         e2fsck_read_bitmaps(ctx);
8124
8125         check_block_bitmaps(ctx);
8126         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8127                 return;
8128         check_inode_bitmaps(ctx);
8129         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8130                 return;
8131         check_inode_end(ctx);
8132         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8133                 return;
8134         check_block_end(ctx);
8135         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8136                 return;
8137
8138         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8139         ctx->inode_used_map = 0;
8140         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8141         ctx->inode_dir_map = 0;
8142         ext2fs_free_block_bitmap(ctx->block_found_map);
8143         ctx->block_found_map = 0;
8144 }
8145
8146 /*
8147  * problem.c --- report filesystem problems to the user
8148  */
8149
8150 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8151 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8152 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8153 #define PR_MSG_ONLY     0x000008 /* Print message only */
8154
8155 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8156
8157 #define PR_FATAL        0x001000 /* Fatal error */
8158 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8159                                  /* ask another */
8160 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8161 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8162 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8163 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8164 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8165
8166
8167 #define PROMPT_NONE     0
8168 #define PROMPT_FIX      1
8169 #define PROMPT_CLEAR    2
8170 #define PROMPT_RELOCATE 3
8171 #define PROMPT_ALLOCATE 4
8172 #define PROMPT_EXPAND   5
8173 #define PROMPT_CONNECT  6
8174 #define PROMPT_CREATE   7
8175 #define PROMPT_SALVAGE  8
8176 #define PROMPT_TRUNCATE 9
8177 #define PROMPT_CLEAR_INODE 10
8178 #define PROMPT_ABORT    11
8179 #define PROMPT_SPLIT    12
8180 #define PROMPT_CONTINUE 13
8181 #define PROMPT_CLONE    14
8182 #define PROMPT_DELETE   15
8183 #define PROMPT_SUPPRESS 16
8184 #define PROMPT_UNLINK   17
8185 #define PROMPT_CLEAR_HTREE 18
8186 #define PROMPT_RECREATE 19
8187 #define PROMPT_NULL     20
8188
8189 struct e2fsck_problem {
8190         problem_t       e2p_code;
8191         const char *    e2p_description;
8192         char            prompt;
8193         int             flags;
8194         problem_t       second_code;
8195 };
8196
8197 struct latch_descr {
8198         int             latch_code;
8199         problem_t       question;
8200         problem_t       end_message;
8201         int             flags;
8202 };
8203
8204 /*
8205  * These are the prompts which are used to ask the user if they want
8206  * to fix a problem.
8207  */
8208 static const char * const prompt[] = {
8209         N_("(no prompt)"),      /* 0 */
8210         N_("Fix"),              /* 1 */
8211         N_("Clear"),            /* 2 */
8212         N_("Relocate"),         /* 3 */
8213         N_("Allocate"),         /* 4 */
8214         N_("Expand"),           /* 5 */
8215         N_("Connect to /lost+found"), /* 6 */
8216         N_("Create"),           /* 7 */
8217         N_("Salvage"),          /* 8 */
8218         N_("Truncate"),         /* 9 */
8219         N_("Clear inode"),      /* 10 */
8220         N_("Abort"),            /* 11 */
8221         N_("Split"),            /* 12 */
8222         N_("Continue"),         /* 13 */
8223         N_("Clone multiply-claimed blocks"), /* 14 */
8224         N_("Delete file"),      /* 15 */
8225         N_("Suppress messages"),/* 16 */
8226         N_("Unlink"),           /* 17 */
8227         N_("Clear HTree index"),/* 18 */
8228         N_("Recreate"),         /* 19 */
8229         "",                     /* 20 */
8230 };
8231
8232 /*
8233  * These messages are printed when we are preen mode and we will be
8234  * automatically fixing the problem.
8235  */
8236 static const char * const preen_msg[] = {
8237         N_("(NONE)"),           /* 0 */
8238         N_("FIXED"),            /* 1 */
8239         N_("CLEARED"),          /* 2 */
8240         N_("RELOCATED"),        /* 3 */
8241         N_("ALLOCATED"),        /* 4 */
8242         N_("EXPANDED"),         /* 5 */
8243         N_("RECONNECTED"),      /* 6 */
8244         N_("CREATED"),          /* 7 */
8245         N_("SALVAGED"),         /* 8 */
8246         N_("TRUNCATED"),        /* 9 */
8247         N_("INODE CLEARED"),    /* 10 */
8248         N_("ABORTED"),          /* 11 */
8249         N_("SPLIT"),            /* 12 */
8250         N_("CONTINUING"),       /* 13 */
8251         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8252         N_("FILE DELETED"),     /* 15 */
8253         N_("SUPPRESSED"),       /* 16 */
8254         N_("UNLINKED"),         /* 17 */
8255         N_("HTREE INDEX CLEARED"),/* 18 */
8256         N_("WILL RECREATE"),    /* 19 */
8257         "",                     /* 20 */
8258 };
8259
8260 static const struct e2fsck_problem problem_table[] = {
8261
8262         /* Pre-Pass 1 errors */
8263
8264         /* Block bitmap not in group */
8265         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8266           PROMPT_RELOCATE, PR_LATCH_RELOC },
8267
8268         /* Inode bitmap not in group */
8269         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8270           PROMPT_RELOCATE, PR_LATCH_RELOC },
8271
8272         /* Inode table not in group */
8273         { PR_0_ITABLE_NOT_GROUP,
8274           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8275           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8276           PROMPT_RELOCATE, PR_LATCH_RELOC },
8277
8278         /* Superblock corrupt */
8279         { PR_0_SB_CORRUPT,
8280           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8281           "@f.  If the @v is valid and it really contains an ext2\n"
8282           "@f (and not swap or ufs or something else), then the @S\n"
8283           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8284           "    e2fsck -b %S <@v>\n\n"),
8285           PROMPT_NONE, PR_FATAL },
8286
8287         /* Filesystem size is wrong */
8288         { PR_0_FS_SIZE_WRONG,
8289           N_("The @f size (according to the @S) is %b @bs\n"
8290           "The physical size of the @v is %c @bs\n"
8291           "Either the @S or the partition table is likely to be corrupt!\n"),
8292           PROMPT_ABORT, 0 },
8293
8294         /* Fragments not supported */
8295         { PR_0_NO_FRAGMENTS,
8296           N_("@S @b_size = %b, fragsize = %c.\n"
8297           "This version of e2fsck does not support fragment sizes different\n"
8298           "from the @b size.\n"),
8299           PROMPT_NONE, PR_FATAL },
8300
8301           /* Bad blocks_per_group */
8302         { PR_0_BLOCKS_PER_GROUP,
8303           N_("@S @bs_per_group = %b, should have been %c\n"),
8304           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8305
8306         /* Bad first_data_block */
8307         { PR_0_FIRST_DATA_BLOCK,
8308           N_("@S first_data_@b = %b, should have been %c\n"),
8309           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8310
8311         /* Adding UUID to filesystem */
8312         { PR_0_ADD_UUID,
8313           N_("@f did not have a UUID; generating one.\n\n"),
8314           PROMPT_NONE, 0 },
8315
8316         /* Relocate hint */
8317         { PR_0_RELOCATE_HINT,
8318           N_("Note: if several inode or block bitmap blocks or part\n"
8319           "of the inode table require relocation, you may wish to try\n"
8320           "running e2fsck with the '-b %S' option first.  The problem\n"
8321           "may lie only with the primary block group descriptors, and\n"
8322           "the backup block group descriptors may be OK.\n\n"),
8323           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8324
8325         /* Miscellaneous superblock corruption */
8326         { PR_0_MISC_CORRUPT_SUPER,
8327           N_("Corruption found in @S.  (%s = %N).\n"),
8328           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8329
8330         /* Error determing physical device size of filesystem */
8331         { PR_0_GETSIZE_ERROR,
8332           N_("Error determining size of the physical @v: %m\n"),
8333           PROMPT_NONE, PR_FATAL },
8334
8335         /* Inode count in superblock is incorrect */
8336         { PR_0_INODE_COUNT_WRONG,
8337           N_("@i count in @S is %i, @s %j.\n"),
8338           PROMPT_FIX, 0 },
8339
8340         { PR_0_HURD_CLEAR_FILETYPE,
8341           N_("The Hurd does not support the filetype feature.\n"),
8342           PROMPT_CLEAR, 0 },
8343
8344         /* Journal inode is invalid */
8345         { PR_0_JOURNAL_BAD_INODE,
8346           N_("@S has an @n ext3 @j (@i %i).\n"),
8347           PROMPT_CLEAR, PR_PREEN_OK },
8348
8349         /* The external journal has (unsupported) multiple filesystems */
8350         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8351           N_("External @j has multiple @f users (unsupported).\n"),
8352           PROMPT_NONE, PR_FATAL },
8353
8354         /* Can't find external journal */
8355         { PR_0_CANT_FIND_JOURNAL,
8356           N_("Can't find external @j\n"),
8357           PROMPT_NONE, PR_FATAL },
8358
8359         /* External journal has bad superblock */
8360         { PR_0_EXT_JOURNAL_BAD_SUPER,
8361           N_("External @j has bad @S\n"),
8362           PROMPT_NONE, PR_FATAL },
8363
8364         /* Superblock has a bad journal UUID */
8365         { PR_0_JOURNAL_BAD_UUID,
8366           N_("External @j does not support this @f\n"),
8367           PROMPT_NONE, PR_FATAL },
8368
8369         /* Journal has an unknown superblock type */
8370         { PR_0_JOURNAL_UNSUPP_SUPER,
8371           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8372              "It is likely that your copy of e2fsck is old and/or doesn't "
8373              "support this @j format.\n"
8374              "It is also possible the @j @S is corrupt.\n"),
8375           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8376
8377         /* Journal superblock is corrupt */
8378         { PR_0_JOURNAL_BAD_SUPER,
8379           N_("Ext3 @j @S is corrupt.\n"),
8380           PROMPT_FIX, PR_PREEN_OK },
8381
8382         /* Superblock flag should be cleared */
8383         { PR_0_JOURNAL_HAS_JOURNAL,
8384           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8385           PROMPT_CLEAR, PR_PREEN_OK },
8386
8387         /* Superblock flag is incorrect */
8388         { PR_0_JOURNAL_RECOVER_SET,
8389           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8390           PROMPT_CLEAR, PR_PREEN_OK },
8391
8392         /* Journal has data, but recovery flag is clear */
8393         { PR_0_JOURNAL_RECOVERY_CLEAR,
8394           N_("ext3 recovery flag is clear, but @j has data.\n"),
8395           PROMPT_NONE, 0 },
8396
8397         /* Ask if we should clear the journal */
8398         { PR_0_JOURNAL_RESET_JOURNAL,
8399           N_("Clear @j"),
8400           PROMPT_NULL, PR_PREEN_NOMSG },
8401
8402         /* Ask if we should run the journal anyway */
8403         { PR_0_JOURNAL_RUN,
8404           N_("Run @j anyway"),
8405           PROMPT_NULL, 0 },
8406
8407         /* Run the journal by default */
8408         { PR_0_JOURNAL_RUN_DEFAULT,
8409           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8410           PROMPT_NONE, 0 },
8411
8412         /* Clearing orphan inode */
8413         { PR_0_ORPHAN_CLEAR_INODE,
8414           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8415           PROMPT_NONE, 0 },
8416
8417         /* Illegal block found in orphaned inode */
8418         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8419            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8420           PROMPT_NONE, 0 },
8421
8422         /* Already cleared block found in orphaned inode */
8423         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8424            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8425           PROMPT_NONE, 0 },
8426
8427         /* Illegal orphan inode in superblock */
8428         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8429           N_("@I @o @i %i in @S.\n"),
8430           PROMPT_NONE, 0 },
8431
8432         /* Illegal inode in orphaned inode list */
8433         { PR_0_ORPHAN_ILLEGAL_INODE,
8434           N_("@I @i %i in @o @i list.\n"),
8435           PROMPT_NONE, 0 },
8436
8437         /* Filesystem revision is 0, but feature flags are set */
8438         { PR_0_FS_REV_LEVEL,
8439           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8440           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8441
8442         /* Journal superblock has an unknown read-only feature flag set */
8443         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8444           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8445           PROMPT_ABORT, 0 },
8446
8447         /* Journal superblock has an unknown incompatible feature flag set */
8448         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8449           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8450           PROMPT_ABORT, 0 },
8451
8452         /* Journal has unsupported version number */
8453         { PR_0_JOURNAL_UNSUPP_VERSION,
8454           N_("@j version not supported by this e2fsck.\n"),
8455           PROMPT_ABORT, 0 },
8456
8457         /* Moving journal to hidden file */
8458         { PR_0_MOVE_JOURNAL,
8459           N_("Moving @j from /%s to hidden @i.\n\n"),
8460           PROMPT_NONE, 0 },
8461
8462         /* Error moving journal to hidden file */
8463         { PR_0_ERR_MOVE_JOURNAL,
8464           N_("Error moving @j: %m\n\n"),
8465           PROMPT_NONE, 0 },
8466
8467         /* Clearing V2 journal superblock */
8468         { PR_0_CLEAR_V2_JOURNAL,
8469           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8470              "Clearing fields beyond the V1 @j @S...\n\n"),
8471           PROMPT_NONE, 0 },
8472
8473         /* Backup journal inode blocks */
8474         { PR_0_BACKUP_JNL,
8475           N_("Backing up @j @i @b information.\n\n"),
8476           PROMPT_NONE, 0 },
8477
8478         /* Reserved blocks w/o resize_inode */
8479         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8480           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8481              "is %N; @s zero.  "),
8482           PROMPT_FIX, 0 },
8483
8484         /* Resize_inode not enabled, but resize inode is non-zero */
8485         { PR_0_CLEAR_RESIZE_INODE,
8486           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8487           PROMPT_CLEAR, 0 },
8488
8489         /* Resize inode invalid */
8490         { PR_0_RESIZE_INODE_INVALID,
8491           N_("Resize @i not valid.  "),
8492           PROMPT_RECREATE, 0 },
8493
8494         /* Pass 1 errors */
8495
8496         /* Pass 1: Checking inodes, blocks, and sizes */
8497         { PR_1_PASS_HEADER,
8498           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8499           PROMPT_NONE, 0 },
8500
8501         /* Root directory is not an inode */
8502         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8503           PROMPT_CLEAR, 0 },
8504
8505         /* Root directory has dtime set */
8506         { PR_1_ROOT_DTIME,
8507           N_("@r has dtime set (probably due to old mke2fs).  "),
8508           PROMPT_FIX, PR_PREEN_OK },
8509
8510         /* Reserved inode has bad mode */
8511         { PR_1_RESERVED_BAD_MODE,
8512           N_("Reserved @i %i (%Q) has @n mode.  "),
8513           PROMPT_CLEAR, PR_PREEN_OK },
8514
8515         /* Deleted inode has zero dtime */
8516         { PR_1_ZERO_DTIME,
8517           N_("@D @i %i has zero dtime.  "),
8518           PROMPT_FIX, PR_PREEN_OK },
8519
8520         /* Inode in use, but dtime set */
8521         { PR_1_SET_DTIME,
8522           N_("@i %i is in use, but has dtime set.  "),
8523           PROMPT_FIX, PR_PREEN_OK },
8524
8525         /* Zero-length directory */
8526         { PR_1_ZERO_LENGTH_DIR,
8527           N_("@i %i is a @z @d.  "),
8528           PROMPT_CLEAR, PR_PREEN_OK },
8529
8530         /* Block bitmap conflicts with some other fs block */
8531         { PR_1_BB_CONFLICT,
8532           N_("@g %g's @b @B at %b @C.\n"),
8533           PROMPT_RELOCATE, 0 },
8534
8535         /* Inode bitmap conflicts with some other fs block */
8536         { PR_1_IB_CONFLICT,
8537           N_("@g %g's @i @B at %b @C.\n"),
8538           PROMPT_RELOCATE, 0 },
8539
8540         /* Inode table conflicts with some other fs block */
8541         { PR_1_ITABLE_CONFLICT,
8542           N_("@g %g's @i table at %b @C.\n"),
8543           PROMPT_RELOCATE, 0 },
8544
8545         /* Block bitmap is on a bad block */
8546         { PR_1_BB_BAD_BLOCK,
8547           N_("@g %g's @b @B (%b) is bad.  "),
8548           PROMPT_RELOCATE, 0 },
8549
8550         /* Inode bitmap is on a bad block */
8551         { PR_1_IB_BAD_BLOCK,
8552           N_("@g %g's @i @B (%b) is bad.  "),
8553           PROMPT_RELOCATE, 0 },
8554
8555         /* Inode has incorrect i_size */
8556         { PR_1_BAD_I_SIZE,
8557           N_("@i %i, i_size is %Is, @s %N.  "),
8558           PROMPT_FIX, PR_PREEN_OK },
8559
8560         /* Inode has incorrect i_blocks */
8561         { PR_1_BAD_I_BLOCKS,
8562           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8563           PROMPT_FIX, PR_PREEN_OK },
8564
8565         /* Illegal blocknumber in inode */
8566         { PR_1_ILLEGAL_BLOCK_NUM,
8567           N_("@I @b #%B (%b) in @i %i.  "),
8568           PROMPT_CLEAR, PR_LATCH_BLOCK },
8569
8570         /* Block number overlaps fs metadata */
8571         { PR_1_BLOCK_OVERLAPS_METADATA,
8572           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8573           PROMPT_CLEAR, PR_LATCH_BLOCK },
8574
8575         /* Inode has illegal blocks (latch question) */
8576         { PR_1_INODE_BLOCK_LATCH,
8577           N_("@i %i has illegal @b(s).  "),
8578           PROMPT_CLEAR, 0 },
8579
8580         /* Too many bad blocks in inode */
8581         { PR_1_TOO_MANY_BAD_BLOCKS,
8582           N_("Too many illegal @bs in @i %i.\n"),
8583           PROMPT_CLEAR_INODE, PR_NO_OK },
8584
8585         /* Illegal block number in bad block inode */
8586         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8587           N_("@I @b #%B (%b) in bad @b @i.  "),
8588           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8589
8590         /* Bad block inode has illegal blocks (latch question) */
8591         { PR_1_INODE_BBLOCK_LATCH,
8592           N_("Bad @b @i has illegal @b(s).  "),
8593           PROMPT_CLEAR, 0 },
8594
8595         /* Duplicate or bad blocks in use! */
8596         { PR_1_DUP_BLOCKS_PREENSTOP,
8597           N_("Duplicate or bad @b in use!\n"),
8598           PROMPT_NONE, 0 },
8599
8600         /* Bad block used as bad block indirect block */
8601         { PR_1_BBINODE_BAD_METABLOCK,
8602           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8603           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8604
8605         /* Inconsistency can't be fixed prompt */
8606         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8607           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8608              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8609              "in the @f.\n"),
8610           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8611
8612         /* Bad primary block */
8613         { PR_1_BAD_PRIMARY_BLOCK,
8614           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
8615           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8616
8617         /* Bad primary block prompt */
8618         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8619           N_("You can remove this @b from the bad @b list and hope\n"
8620              "that the @b is really OK.  But there are no guarantees.\n\n"),
8621           PROMPT_CLEAR, PR_PREEN_NOMSG },
8622
8623         /* Bad primary superblock */
8624         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8625           N_("The primary @S (%b) is on the bad @b list.\n"),
8626           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8627
8628         /* Bad primary block group descriptors */
8629         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8630           N_("Block %b in the primary @g descriptors "
8631           "is on the bad @b list\n"),
8632           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8633
8634         /* Bad superblock in group */
8635         { PR_1_BAD_SUPERBLOCK,
8636           N_("Warning: Group %g's @S (%b) is bad.\n"),
8637           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8638
8639         /* Bad block group descriptors in group */
8640         { PR_1_BAD_GROUP_DESCRIPTORS,
8641           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8642           "@b (%b).\n"),
8643           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8644
8645         /* Block claimed for no reason */
8646         { PR_1_PROGERR_CLAIMED_BLOCK,
8647           N_("Programming error?  @b #%b claimed for no reason in "
8648           "process_bad_@b.\n"),
8649           PROMPT_NONE, PR_PREEN_OK },
8650
8651         /* Error allocating blocks for relocating metadata */
8652         { PR_1_RELOC_BLOCK_ALLOCATE,
8653           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8654           PROMPT_NONE, PR_PREEN_OK },
8655
8656         /* Error allocating block buffer during relocation process */
8657         { PR_1_RELOC_MEMORY_ALLOCATE,
8658           N_("@A @b buffer for relocating %s\n"),
8659           PROMPT_NONE, PR_PREEN_OK },
8660
8661         /* Relocating metadata group information from X to Y */
8662         { PR_1_RELOC_FROM_TO,
8663           N_("Relocating @g %g's %s from %b to %c...\n"),
8664           PROMPT_NONE, PR_PREEN_OK },
8665
8666         /* Relocating metatdata group information to X */
8667         { PR_1_RELOC_TO,
8668           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8669           PROMPT_NONE, PR_PREEN_OK },
8670
8671         /* Block read error during relocation process */
8672         { PR_1_RELOC_READ_ERR,
8673           N_("Warning: could not read @b %b of %s: %m\n"),
8674           PROMPT_NONE, PR_PREEN_OK },
8675
8676         /* Block write error during relocation process */
8677         { PR_1_RELOC_WRITE_ERR,
8678           N_("Warning: could not write @b %b for %s: %m\n"),
8679           PROMPT_NONE, PR_PREEN_OK },
8680
8681         /* Error allocating inode bitmap */
8682         { PR_1_ALLOCATE_IBITMAP_ERROR,
8683           N_("@A @i @B (%N): %m\n"),
8684           PROMPT_NONE, PR_FATAL },
8685
8686         /* Error allocating block bitmap */
8687         { PR_1_ALLOCATE_BBITMAP_ERROR,
8688           N_("@A @b @B (%N): %m\n"),
8689           PROMPT_NONE, PR_FATAL },
8690
8691         /* Error allocating icount structure */
8692         { PR_1_ALLOCATE_ICOUNT,
8693           N_("@A icount link information: %m\n"),
8694           PROMPT_NONE, PR_FATAL },
8695
8696         /* Error allocating dbcount */
8697         { PR_1_ALLOCATE_DBCOUNT,
8698           N_("@A @d @b array: %m\n"),
8699           PROMPT_NONE, PR_FATAL },
8700
8701         /* Error while scanning inodes */
8702         { PR_1_ISCAN_ERROR,
8703           N_("Error while scanning @is (%i): %m\n"),
8704           PROMPT_NONE, PR_FATAL },
8705
8706         /* Error while iterating over blocks */
8707         { PR_1_BLOCK_ITERATE,
8708           N_("Error while iterating over @bs in @i %i: %m\n"),
8709           PROMPT_NONE, PR_FATAL },
8710
8711         /* Error while storing inode count information */
8712         { PR_1_ICOUNT_STORE,
8713           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8714           PROMPT_NONE, PR_FATAL },
8715
8716         /* Error while storing directory block information */
8717         { PR_1_ADD_DBLOCK,
8718           N_("Error storing @d @b information "
8719           "(@i=%i, @b=%b, num=%N): %m\n"),
8720           PROMPT_NONE, PR_FATAL },
8721
8722         /* Error while reading inode (for clearing) */
8723         { PR_1_READ_INODE,
8724           N_("Error reading @i %i: %m\n"),
8725           PROMPT_NONE, PR_FATAL },
8726
8727         /* Suppress messages prompt */
8728         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8729
8730         /* Imagic flag set on an inode when filesystem doesn't support it */
8731         { PR_1_SET_IMAGIC,
8732           N_("@i %i has imagic flag set.  "),
8733           PROMPT_CLEAR, 0 },
8734
8735         /* Immutable flag set on a device or socket inode */
8736         { PR_1_SET_IMMUTABLE,
8737           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8738              "or append-only flag set.  "),
8739           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8740
8741         /* Compression flag set on an inode when filesystem doesn't support it */
8742         { PR_1_COMPR_SET,
8743           N_("@i %i has @cion flag set on @f without @cion support.  "),
8744           PROMPT_CLEAR, 0 },
8745
8746         /* Non-zero size for device, fifo or socket inode */
8747         { PR_1_SET_NONZSIZE,
8748           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8749           PROMPT_FIX, PR_PREEN_OK },
8750
8751         /* Filesystem revision is 0, but feature flags are set */
8752         { PR_1_FS_REV_LEVEL,
8753           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8754           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8755
8756         /* Journal inode is not in use, but contains data */
8757         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8758           N_("@j @i is not in use, but contains data.  "),
8759           PROMPT_CLEAR, PR_PREEN_OK },
8760
8761         /* Journal has bad mode */
8762         { PR_1_JOURNAL_BAD_MODE,
8763           N_("@j is not regular file.  "),
8764           PROMPT_FIX, PR_PREEN_OK },
8765
8766         /* Deal with inodes that were part of orphan linked list */
8767         { PR_1_LOW_DTIME,
8768           N_("@i %i was part of the @o @i list.  "),
8769           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8770
8771         /* Deal with inodes that were part of corrupted orphan linked
8772            list (latch question) */
8773         { PR_1_ORPHAN_LIST_REFUGEES,
8774           N_("@is that were part of a corrupted orphan linked list found.  "),
8775           PROMPT_FIX, 0 },
8776
8777         /* Error allocating refcount structure */
8778         { PR_1_ALLOCATE_REFCOUNT,
8779           N_("@A refcount structure (%N): %m\n"),
8780           PROMPT_NONE, PR_FATAL },
8781
8782         /* Error reading extended attribute block */
8783         { PR_1_READ_EA_BLOCK,
8784           N_("Error reading @a @b %b for @i %i.  "),
8785           PROMPT_CLEAR, 0 },
8786
8787         /* Invalid extended attribute block */
8788         { PR_1_BAD_EA_BLOCK,
8789           N_("@i %i has a bad @a @b %b.  "),
8790           PROMPT_CLEAR, 0 },
8791
8792         /* Error reading Extended Attribute block while fixing refcount */
8793         { PR_1_EXTATTR_READ_ABORT,
8794           N_("Error reading @a @b %b (%m).  "),
8795           PROMPT_ABORT, 0 },
8796
8797         /* Extended attribute reference count incorrect */
8798         { PR_1_EXTATTR_REFCOUNT,
8799           N_("@a @b %b has reference count %B, @s %N.  "),
8800           PROMPT_FIX, 0 },
8801
8802         /* Error writing Extended Attribute block while fixing refcount */
8803         { PR_1_EXTATTR_WRITE,
8804           N_("Error writing @a @b %b (%m).  "),
8805           PROMPT_ABORT, 0 },
8806
8807         /* Multiple EA blocks not supported */
8808         { PR_1_EA_MULTI_BLOCK,
8809           N_("@a @b %b has h_@bs > 1.  "),
8810           PROMPT_CLEAR, 0},
8811
8812         /* Error allocating EA region allocation structure */
8813         { PR_1_EA_ALLOC_REGION,
8814           N_("@A @a @b %b.  "),
8815           PROMPT_ABORT, 0},
8816
8817         /* Error EA allocation collision */
8818         { PR_1_EA_ALLOC_COLLISION,
8819           N_("@a @b %b is corrupt (allocation collision).  "),
8820           PROMPT_CLEAR, 0},
8821
8822         /* Bad extended attribute name */
8823         { PR_1_EA_BAD_NAME,
8824           N_("@a @b %b is corrupt (@n name).  "),
8825           PROMPT_CLEAR, 0},
8826
8827         /* Bad extended attribute value */
8828         { PR_1_EA_BAD_VALUE,
8829           N_("@a @b %b is corrupt (@n value).  "),
8830           PROMPT_CLEAR, 0},
8831
8832         /* Inode too big (latch question) */
8833         { PR_1_INODE_TOOBIG,
8834           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8835
8836         /* Directory too big */
8837         { PR_1_TOOBIG_DIR,
8838           N_("@b #%B (%b) causes @d to be too big.  "),
8839           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8840
8841         /* Regular file too big */
8842         { PR_1_TOOBIG_REG,
8843           N_("@b #%B (%b) causes file to be too big.  "),
8844           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8845
8846         /* Symlink too big */
8847         { PR_1_TOOBIG_SYMLINK,
8848           N_("@b #%B (%b) causes symlink to be too big.  "),
8849           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8850
8851         /* INDEX_FL flag set on a non-HTREE filesystem */
8852         { PR_1_HTREE_SET,
8853           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8854           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8855
8856         /* INDEX_FL flag set on a non-directory */
8857         { PR_1_HTREE_NODIR,
8858           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8859           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8860
8861         /* Invalid root node in HTREE directory */
8862         { PR_1_HTREE_BADROOT,
8863           N_("@h %i has an @n root node.\n"),
8864           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8865
8866         /* Unsupported hash version in HTREE directory */
8867         { PR_1_HTREE_HASHV,
8868           N_("@h %i has an unsupported hash version (%N)\n"),
8869           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8870
8871         /* Incompatible flag in HTREE root node */
8872         { PR_1_HTREE_INCOMPAT,
8873           N_("@h %i uses an incompatible htree root node flag.\n"),
8874           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8875
8876         /* HTREE too deep */
8877         { PR_1_HTREE_DEPTH,
8878           N_("@h %i has a tree depth (%N) which is too big\n"),
8879           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8880
8881         /* Bad block has indirect block that conflicts with filesystem block */
8882         { PR_1_BB_FS_BLOCK,
8883           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8884              "@f metadata.  "),
8885           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8886
8887         /* Resize inode failed */
8888         { PR_1_RESIZE_INODE_CREATE,
8889           N_("Resize @i (re)creation failed: %m."),
8890           PROMPT_ABORT, 0 },
8891
8892         /* invalid inode->i_extra_isize */
8893         { PR_1_EXTRA_ISIZE,
8894           N_("@i %i has a extra size (%IS) which is @n\n"),
8895           PROMPT_FIX, PR_PREEN_OK },
8896
8897         /* invalid ea entry->e_name_len */
8898         { PR_1_ATTR_NAME_LEN,
8899           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8900           PROMPT_CLEAR, PR_PREEN_OK },
8901
8902         /* invalid ea entry->e_value_size */
8903         { PR_1_ATTR_VALUE_SIZE,
8904           N_("@a in @i %i has a value size (%N) which is @n\n"),
8905           PROMPT_CLEAR, PR_PREEN_OK },
8906
8907         /* invalid ea entry->e_value_offs */
8908         { PR_1_ATTR_VALUE_OFFSET,
8909           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8910           PROMPT_CLEAR, PR_PREEN_OK },
8911
8912         /* invalid ea entry->e_value_block */
8913         { PR_1_ATTR_VALUE_BLOCK,
8914           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8915           PROMPT_CLEAR, PR_PREEN_OK },
8916
8917         /* invalid ea entry->e_hash */
8918         { PR_1_ATTR_HASH,
8919           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8920           PROMPT_CLEAR, PR_PREEN_OK },
8921
8922         /* Pass 1b errors */
8923
8924         /* Pass 1B: Rescan for duplicate/bad blocks */
8925         { PR_1B_PASS_HEADER,
8926           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8927           "Pass 1B: Rescanning for @m @bs\n"),
8928           PROMPT_NONE, 0 },
8929
8930         /* Duplicate/bad block(s) header */
8931         { PR_1B_DUP_BLOCK_HEADER,
8932           N_("@m @b(s) in @i %i:"),
8933           PROMPT_NONE, 0 },
8934
8935         /* Duplicate/bad block(s) in inode */
8936         { PR_1B_DUP_BLOCK,
8937           " %b",
8938           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8939
8940         /* Duplicate/bad block(s) end */
8941         { PR_1B_DUP_BLOCK_END,
8942           "\n",
8943           PROMPT_NONE, PR_PREEN_NOHDR },
8944
8945         /* Error while scanning inodes */
8946         { PR_1B_ISCAN_ERROR,
8947           N_("Error while scanning inodes (%i): %m\n"),
8948           PROMPT_NONE, PR_FATAL },
8949
8950         /* Error allocating inode bitmap */
8951         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8952           N_("@A @i @B (@i_dup_map): %m\n"),
8953           PROMPT_NONE, PR_FATAL },
8954
8955         /* Error while iterating over blocks */
8956         { PR_1B_BLOCK_ITERATE,
8957           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8958           PROMPT_NONE, 0 },
8959
8960         /* Error adjusting EA refcount */
8961         { PR_1B_ADJ_EA_REFCOUNT,
8962           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8963           PROMPT_NONE, 0 },
8964
8965
8966         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8967         { PR_1C_PASS_HEADER,
8968           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8969           PROMPT_NONE, 0 },
8970
8971
8972         /* Pass 1D: Reconciling multiply-claimed blocks */
8973         { PR_1D_PASS_HEADER,
8974           N_("Pass 1D: Reconciling @m @bs\n"),
8975           PROMPT_NONE, 0 },
8976
8977         /* File has duplicate blocks */
8978         { PR_1D_DUP_FILE,
8979           N_("File %Q (@i #%i, mod time %IM) \n"
8980           "  has %B @m @b(s), shared with %N file(s):\n"),
8981           PROMPT_NONE, 0 },
8982
8983         /* List of files sharing duplicate blocks */
8984         { PR_1D_DUP_FILE_LIST,
8985           N_("\t%Q (@i #%i, mod time %IM)\n"),
8986           PROMPT_NONE, 0 },
8987
8988         /* File sharing blocks with filesystem metadata  */
8989         { PR_1D_SHARE_METADATA,
8990           N_("\t<@f metadata>\n"),
8991           PROMPT_NONE, 0 },
8992
8993         /* Report of how many duplicate/bad inodes */
8994         { PR_1D_NUM_DUP_INODES,
8995           N_("(There are %N @is containing @m @bs.)\n\n"),
8996           PROMPT_NONE, 0 },
8997
8998         /* Duplicated blocks already reassigned or cloned. */
8999         { PR_1D_DUP_BLOCKS_DEALT,
9000           N_("@m @bs already reassigned or cloned.\n\n"),
9001           PROMPT_NONE, 0 },
9002
9003         /* Clone duplicate/bad blocks? */
9004         { PR_1D_CLONE_QUESTION,
9005           "", PROMPT_CLONE, PR_NO_OK },
9006
9007         /* Delete file? */
9008         { PR_1D_DELETE_QUESTION,
9009           "", PROMPT_DELETE, 0 },
9010
9011         /* Couldn't clone file (error) */
9012         { PR_1D_CLONE_ERROR,
9013           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
9014
9015         /* Pass 2 errors */
9016
9017         /* Pass 2: Checking directory structure */
9018         { PR_2_PASS_HEADER,
9019           N_("Pass 2: Checking @d structure\n"),
9020           PROMPT_NONE, 0 },
9021
9022         /* Bad inode number for '.' */
9023         { PR_2_BAD_INODE_DOT,
9024           N_("@n @i number for '.' in @d @i %i.\n"),
9025           PROMPT_FIX, 0 },
9026
9027         /* Directory entry has bad inode number */
9028         { PR_2_BAD_INO,
9029           N_("@E has @n @i #: %Di.\n"),
9030           PROMPT_CLEAR, 0 },
9031
9032         /* Directory entry has deleted or unused inode */
9033         { PR_2_UNUSED_INODE,
9034           N_("@E has @D/unused @i %Di.  "),
9035           PROMPT_CLEAR, PR_PREEN_OK },
9036
9037         /* Directry entry is link to '.' */
9038         { PR_2_LINK_DOT,
9039           N_("@E @L to '.'  "),
9040           PROMPT_CLEAR, 0 },
9041
9042         /* Directory entry points to inode now located in a bad block */
9043         { PR_2_BB_INODE,
9044           N_("@E points to @i (%Di) located in a bad @b.\n"),
9045           PROMPT_CLEAR, 0 },
9046
9047         /* Directory entry contains a link to a directory */
9048         { PR_2_LINK_DIR,
9049           N_("@E @L to @d %P (%Di).\n"),
9050           PROMPT_CLEAR, 0 },
9051
9052         /* Directory entry contains a link to the root directry */
9053         { PR_2_LINK_ROOT,
9054           N_("@E @L to the @r.\n"),
9055           PROMPT_CLEAR, 0 },
9056
9057         /* Directory entry has illegal characters in its name */
9058         { PR_2_BAD_NAME,
9059           N_("@E has illegal characters in its name.\n"),
9060           PROMPT_FIX, 0 },
9061
9062         /* Missing '.' in directory inode */
9063         { PR_2_MISSING_DOT,
9064           N_("Missing '.' in @d @i %i.\n"),
9065           PROMPT_FIX, 0 },
9066
9067         /* Missing '..' in directory inode */
9068         { PR_2_MISSING_DOT_DOT,
9069           N_("Missing '..' in @d @i %i.\n"),
9070           PROMPT_FIX, 0 },
9071
9072         /* First entry in directory inode doesn't contain '.' */
9073         { PR_2_1ST_NOT_DOT,
9074           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9075           PROMPT_FIX, 0 },
9076
9077         /* Second entry in directory inode doesn't contain '..' */
9078         { PR_2_2ND_NOT_DOT_DOT,
9079           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9080           PROMPT_FIX, 0 },
9081
9082         /* i_faddr should be zero */
9083         { PR_2_FADDR_ZERO,
9084           N_("i_faddr @F %IF, @s zero.\n"),
9085           PROMPT_CLEAR, 0 },
9086
9087         /* i_file_acl should be zero */
9088         { PR_2_FILE_ACL_ZERO,
9089           N_("i_file_acl @F %If, @s zero.\n"),
9090           PROMPT_CLEAR, 0 },
9091
9092         /* i_dir_acl should be zero */
9093         { PR_2_DIR_ACL_ZERO,
9094           N_("i_dir_acl @F %Id, @s zero.\n"),
9095           PROMPT_CLEAR, 0 },
9096
9097         /* i_frag should be zero */
9098         { PR_2_FRAG_ZERO,
9099           N_("i_frag @F %N, @s zero.\n"),
9100           PROMPT_CLEAR, 0 },
9101
9102         /* i_fsize should be zero */
9103         { PR_2_FSIZE_ZERO,
9104           N_("i_fsize @F %N, @s zero.\n"),
9105           PROMPT_CLEAR, 0 },
9106
9107         /* inode has bad mode */
9108         { PR_2_BAD_MODE,
9109           N_("@i %i (%Q) has @n mode (%Im).\n"),
9110           PROMPT_CLEAR, 0 },
9111
9112         /* directory corrupted */
9113         { PR_2_DIR_CORRUPTED,
9114           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9115           PROMPT_SALVAGE, 0 },
9116
9117         /* filename too long */
9118         { PR_2_FILENAME_LONG,
9119           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9120           PROMPT_TRUNCATE, 0 },
9121
9122         /* Directory inode has a missing block (hole) */
9123         { PR_2_DIRECTORY_HOLE,
9124           N_("@d @i %i has an unallocated @b #%B.  "),
9125           PROMPT_ALLOCATE, 0 },
9126
9127         /* '.' is not NULL terminated */
9128         { PR_2_DOT_NULL_TERM,
9129           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9130           PROMPT_FIX, 0 },
9131
9132         /* '..' is not NULL terminated */
9133         { PR_2_DOT_DOT_NULL_TERM,
9134           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9135           PROMPT_FIX, 0 },
9136
9137         /* Illegal character device inode */
9138         { PR_2_BAD_CHAR_DEV,
9139           N_("@i %i (%Q) is an @I character @v.\n"),
9140           PROMPT_CLEAR, 0 },
9141
9142         /* Illegal block device inode */
9143         { PR_2_BAD_BLOCK_DEV,
9144           N_("@i %i (%Q) is an @I @b @v.\n"),
9145           PROMPT_CLEAR, 0 },
9146
9147         /* Duplicate '.' entry */
9148         { PR_2_DUP_DOT,
9149           N_("@E is duplicate '.' @e.\n"),
9150           PROMPT_FIX, 0 },
9151
9152         /* Duplicate '..' entry */
9153         { PR_2_DUP_DOT_DOT,
9154           N_("@E is duplicate '..' @e.\n"),
9155           PROMPT_FIX, 0 },
9156
9157         /* Internal error: couldn't find dir_info */
9158         { PR_2_NO_DIRINFO,
9159           N_("Internal error: couldn't find dir_info for %i.\n"),
9160           PROMPT_NONE, PR_FATAL },
9161
9162         /* Final rec_len is wrong */
9163         { PR_2_FINAL_RECLEN,
9164           N_("@E has rec_len of %Dr, @s %N.\n"),
9165           PROMPT_FIX, 0 },
9166
9167         /* Error allocating icount structure */
9168         { PR_2_ALLOCATE_ICOUNT,
9169           N_("@A icount structure: %m\n"),
9170           PROMPT_NONE, PR_FATAL },
9171
9172         /* Error iterating over directory blocks */
9173         { PR_2_DBLIST_ITERATE,
9174           N_("Error iterating over @d @bs: %m\n"),
9175           PROMPT_NONE, PR_FATAL },
9176
9177         /* Error reading directory block */
9178         { PR_2_READ_DIRBLOCK,
9179           N_("Error reading @d @b %b (@i %i): %m\n"),
9180           PROMPT_CONTINUE, 0 },
9181
9182         /* Error writing directory block */
9183         { PR_2_WRITE_DIRBLOCK,
9184           N_("Error writing @d @b %b (@i %i): %m\n"),
9185           PROMPT_CONTINUE, 0 },
9186
9187         /* Error allocating new directory block */
9188         { PR_2_ALLOC_DIRBOCK,
9189           N_("@A new @d @b for @i %i (%s): %m\n"),
9190           PROMPT_NONE, 0 },
9191
9192         /* Error deallocating inode */
9193         { PR_2_DEALLOC_INODE,
9194           N_("Error deallocating @i %i: %m\n"),
9195           PROMPT_NONE, PR_FATAL },
9196
9197         /* Directory entry for '.' is big.  Split? */
9198         { PR_2_SPLIT_DOT,
9199           N_("@d @e for '.' is big.  "),
9200           PROMPT_SPLIT, PR_NO_OK },
9201
9202         /* Illegal FIFO inode */
9203         { PR_2_BAD_FIFO,
9204           N_("@i %i (%Q) is an @I FIFO.\n"),
9205           PROMPT_CLEAR, 0 },
9206
9207         /* Illegal socket inode */
9208         { PR_2_BAD_SOCKET,
9209           N_("@i %i (%Q) is an @I socket.\n"),
9210           PROMPT_CLEAR, 0 },
9211
9212         /* Directory filetype not set */
9213         { PR_2_SET_FILETYPE,
9214           N_("Setting filetype for @E to %N.\n"),
9215           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9216
9217         /* Directory filetype incorrect */
9218         { PR_2_BAD_FILETYPE,
9219           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9220           PROMPT_FIX, 0 },
9221
9222         /* Directory filetype set on filesystem */
9223         { PR_2_CLEAR_FILETYPE,
9224           N_("@E has filetype set.\n"),
9225           PROMPT_CLEAR, PR_PREEN_OK },
9226
9227         /* Directory filename is null */
9228         { PR_2_NULL_NAME,
9229           N_("@E has a @z name.\n"),
9230           PROMPT_CLEAR, 0 },
9231
9232         /* Invalid symlink */
9233         { PR_2_INVALID_SYMLINK,
9234           N_("Symlink %Q (@i #%i) is @n.\n"),
9235           PROMPT_CLEAR, 0 },
9236
9237         /* i_file_acl (extended attribute block) is bad */
9238         { PR_2_FILE_ACL_BAD,
9239           N_("@a @b @F @n (%If).\n"),
9240           PROMPT_CLEAR, 0 },
9241
9242         /* Filesystem contains large files, but has no such flag in sb */
9243         { PR_2_FEATURE_LARGE_FILES,
9244           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9245           PROMPT_FIX, 0 },
9246
9247         /* Node in HTREE directory not referenced */
9248         { PR_2_HTREE_NOTREF,
9249           N_("@p @h %d: node (%B) not referenced\n"),
9250           PROMPT_NONE, 0 },
9251
9252         /* Node in HTREE directory referenced twice */
9253         { PR_2_HTREE_DUPREF,
9254           N_("@p @h %d: node (%B) referenced twice\n"),
9255           PROMPT_NONE, 0 },
9256
9257         /* Node in HTREE directory has bad min hash */
9258         { PR_2_HTREE_MIN_HASH,
9259           N_("@p @h %d: node (%B) has bad min hash\n"),
9260           PROMPT_NONE, 0 },
9261
9262         /* Node in HTREE directory has bad max hash */
9263         { PR_2_HTREE_MAX_HASH,
9264           N_("@p @h %d: node (%B) has bad max hash\n"),
9265           PROMPT_NONE, 0 },
9266
9267         /* Clear invalid HTREE directory */
9268         { PR_2_HTREE_CLEAR,
9269           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9270
9271         /* Bad block in htree interior node */
9272         { PR_2_HTREE_BADBLK,
9273           N_("@p @h %d (%q): bad @b number %b.\n"),
9274           PROMPT_CLEAR_HTREE, 0 },
9275
9276         /* Error adjusting EA refcount */
9277         { PR_2_ADJ_EA_REFCOUNT,
9278           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9279           PROMPT_NONE, PR_FATAL },
9280
9281         /* Invalid HTREE root node */
9282         { PR_2_HTREE_BAD_ROOT,
9283           N_("@p @h %d: root node is @n\n"),
9284           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9285
9286         /* Invalid HTREE limit */
9287         { PR_2_HTREE_BAD_LIMIT,
9288           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9289           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9290
9291         /* Invalid HTREE count */
9292         { PR_2_HTREE_BAD_COUNT,
9293           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9294           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9295
9296         /* HTREE interior node has out-of-order hashes in table */
9297         { PR_2_HTREE_HASH_ORDER,
9298           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9299           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9300
9301         /* Node in HTREE directory has invalid depth */
9302         { PR_2_HTREE_BAD_DEPTH,
9303           N_("@p @h %d: node (%B) has @n depth\n"),
9304           PROMPT_NONE, 0 },
9305
9306         /* Duplicate directory entry found */
9307         { PR_2_DUPLICATE_DIRENT,
9308           N_("Duplicate @E found.  "),
9309           PROMPT_CLEAR, 0 },
9310
9311         /* Non-unique filename found */
9312         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9313           N_("@E has a non-unique filename.\nRename to %s"),
9314           PROMPT_NULL, 0 },
9315
9316         /* Duplicate directory entry found */
9317         { PR_2_REPORT_DUP_DIRENT,
9318           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9319           PROMPT_NONE, 0 },
9320
9321         /* Pass 3 errors */
9322
9323         /* Pass 3: Checking directory connectivity */
9324         { PR_3_PASS_HEADER,
9325           N_("Pass 3: Checking @d connectivity\n"),
9326           PROMPT_NONE, 0 },
9327
9328         /* Root inode not allocated */
9329         { PR_3_NO_ROOT_INODE,
9330           N_("@r not allocated.  "),
9331           PROMPT_ALLOCATE, 0 },
9332
9333         /* No room in lost+found */
9334         { PR_3_EXPAND_LF_DIR,
9335           N_("No room in @l @d.  "),
9336           PROMPT_EXPAND, 0 },
9337
9338         /* Unconnected directory inode */
9339         { PR_3_UNCONNECTED_DIR,
9340           N_("Unconnected @d @i %i (%p)\n"),
9341           PROMPT_CONNECT, 0 },
9342
9343         /* /lost+found not found */
9344         { PR_3_NO_LF_DIR,
9345           N_("/@l not found.  "),
9346           PROMPT_CREATE, PR_PREEN_OK },
9347
9348         /* .. entry is incorrect */
9349         { PR_3_BAD_DOT_DOT,
9350           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9351           PROMPT_FIX, 0 },
9352
9353         /* Bad or non-existent /lost+found.  Cannot reconnect */
9354         { PR_3_NO_LPF,
9355           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9356           PROMPT_NONE, 0 },
9357
9358         /* Could not expand /lost+found */
9359         { PR_3_CANT_EXPAND_LPF,
9360           N_("Could not expand /@l: %m\n"),
9361           PROMPT_NONE, 0 },
9362
9363         /* Could not reconnect inode */
9364         { PR_3_CANT_RECONNECT,
9365           N_("Could not reconnect %i: %m\n"),
9366           PROMPT_NONE, 0 },
9367
9368         /* Error while trying to find /lost+found */
9369         { PR_3_ERR_FIND_LPF,
9370           N_("Error while trying to find /@l: %m\n"),
9371           PROMPT_NONE, 0 },
9372
9373         /* Error in ext2fs_new_block while creating /lost+found */
9374         { PR_3_ERR_LPF_NEW_BLOCK,
9375           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9376           PROMPT_NONE, 0 },
9377
9378         /* Error in ext2fs_new_inode while creating /lost+found */
9379         { PR_3_ERR_LPF_NEW_INODE,
9380           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9381           PROMPT_NONE, 0 },
9382
9383         /* Error in ext2fs_new_dir_block while creating /lost+found */
9384         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9385           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9386           PROMPT_NONE, 0 },
9387
9388         /* Error while writing directory block for /lost+found */
9389         { PR_3_ERR_LPF_WRITE_BLOCK,
9390           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9391           PROMPT_NONE, 0 },
9392
9393         /* Error while adjusting inode count */
9394         { PR_3_ADJUST_INODE,
9395           N_("Error while adjusting @i count on @i %i\n"),
9396           PROMPT_NONE, 0 },
9397
9398         /* Couldn't fix parent directory -- error */
9399         { PR_3_FIX_PARENT_ERR,
9400           N_("Couldn't fix parent of @i %i: %m\n\n"),
9401           PROMPT_NONE, 0 },
9402
9403         /* Couldn't fix parent directory -- couldn't find it */
9404         { PR_3_FIX_PARENT_NOFIND,
9405           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9406           PROMPT_NONE, 0 },
9407
9408         /* Error allocating inode bitmap */
9409         { PR_3_ALLOCATE_IBITMAP_ERROR,
9410           N_("@A @i @B (%N): %m\n"),
9411           PROMPT_NONE, PR_FATAL },
9412
9413         /* Error creating root directory */
9414         { PR_3_CREATE_ROOT_ERROR,
9415           N_("Error creating root @d (%s): %m\n"),
9416           PROMPT_NONE, PR_FATAL },
9417
9418         /* Error creating lost and found directory */
9419         { PR_3_CREATE_LPF_ERROR,
9420           N_("Error creating /@l @d (%s): %m\n"),
9421           PROMPT_NONE, PR_FATAL },
9422
9423         /* Root inode is not directory; aborting */
9424         { PR_3_ROOT_NOT_DIR_ABORT,
9425           N_("@r is not a @d; aborting.\n"),
9426           PROMPT_NONE, PR_FATAL },
9427
9428         /* Cannot proceed without a root inode. */
9429         { PR_3_NO_ROOT_INODE_ABORT,
9430           N_("Cannot proceed without a @r.\n"),
9431           PROMPT_NONE, PR_FATAL },
9432
9433         /* Internal error: couldn't find dir_info */
9434         { PR_3_NO_DIRINFO,
9435           N_("Internal error: couldn't find dir_info for %i.\n"),
9436           PROMPT_NONE, PR_FATAL },
9437
9438         /* Lost+found not a directory */
9439         { PR_3_LPF_NOTDIR,
9440           N_("/@l is not a @d (ino=%i)\n"),
9441           PROMPT_UNLINK, 0 },
9442
9443         /* Pass 3A Directory Optimization       */
9444
9445         /* Pass 3A: Optimizing directories */
9446         { PR_3A_PASS_HEADER,
9447           N_("Pass 3A: Optimizing directories\n"),
9448           PROMPT_NONE, PR_PREEN_NOMSG },
9449
9450         /* Error iterating over directories */
9451         { PR_3A_OPTIMIZE_ITER,
9452           N_("Failed to create dirs_to_hash iterator: %m"),
9453           PROMPT_NONE, 0 },
9454
9455         /* Error rehash directory */
9456         { PR_3A_OPTIMIZE_DIR_ERR,
9457           N_("Failed to optimize directory %q (%d): %m"),
9458           PROMPT_NONE, 0 },
9459
9460         /* Rehashing dir header */
9461         { PR_3A_OPTIMIZE_DIR_HEADER,
9462           N_("Optimizing directories: "),
9463           PROMPT_NONE, PR_MSG_ONLY },
9464
9465         /* Rehashing directory %d */
9466         { PR_3A_OPTIMIZE_DIR,
9467           " %d",
9468           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9469
9470         /* Rehashing dir end */
9471         { PR_3A_OPTIMIZE_DIR_END,
9472           "\n",
9473           PROMPT_NONE, PR_PREEN_NOHDR },
9474
9475         /* Pass 4 errors */
9476
9477         /* Pass 4: Checking reference counts */
9478         { PR_4_PASS_HEADER,
9479           N_("Pass 4: Checking reference counts\n"),
9480           PROMPT_NONE, 0 },
9481
9482         /* Unattached zero-length inode */
9483         { PR_4_ZERO_LEN_INODE,
9484           N_("@u @z @i %i.  "),
9485           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9486
9487         /* Unattached inode */
9488         { PR_4_UNATTACHED_INODE,
9489           N_("@u @i %i\n"),
9490           PROMPT_CONNECT, 0 },
9491
9492         /* Inode ref count wrong */
9493         { PR_4_BAD_REF_COUNT,
9494           N_("@i %i ref count is %Il, @s %N.  "),
9495           PROMPT_FIX, PR_PREEN_OK },
9496
9497         { PR_4_INCONSISTENT_COUNT,
9498           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9499           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9500           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9501           "They @s the same!\n"),
9502           PROMPT_NONE, 0 },
9503
9504         /* Pass 5 errors */
9505
9506         /* Pass 5: Checking group summary information */
9507         { PR_5_PASS_HEADER,
9508           N_("Pass 5: Checking @g summary information\n"),
9509           PROMPT_NONE, 0 },
9510
9511         /* Padding at end of inode bitmap is not set. */
9512         { PR_5_INODE_BMAP_PADDING,
9513           N_("Padding at end of @i @B is not set. "),
9514           PROMPT_FIX, PR_PREEN_OK },
9515
9516         /* Padding at end of block bitmap is not set. */
9517         { PR_5_BLOCK_BMAP_PADDING,
9518           N_("Padding at end of @b @B is not set. "),
9519           PROMPT_FIX, PR_PREEN_OK },
9520
9521         /* Block bitmap differences header */
9522         { PR_5_BLOCK_BITMAP_HEADER,
9523           N_("@b @B differences: "),
9524           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9525
9526         /* Block not used, but marked in bitmap */
9527         { PR_5_BLOCK_UNUSED,
9528           " -%b",
9529           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9530
9531         /* Block used, but not marked used in bitmap */
9532         { PR_5_BLOCK_USED,
9533           " +%b",
9534           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9535
9536         /* Block bitmap differences end */
9537         { PR_5_BLOCK_BITMAP_END,
9538           "\n",
9539           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9540
9541         /* Inode bitmap differences header */
9542         { PR_5_INODE_BITMAP_HEADER,
9543           N_("@i @B differences: "),
9544           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9545
9546         /* Inode not used, but marked in bitmap */
9547         { PR_5_INODE_UNUSED,
9548           " -%i",
9549           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9550
9551         /* Inode used, but not marked used in bitmap */
9552         { PR_5_INODE_USED,
9553           " +%i",
9554           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9555
9556         /* Inode bitmap differences end */
9557         { PR_5_INODE_BITMAP_END,
9558           "\n",
9559           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9560
9561         /* Free inodes count for group wrong */
9562         { PR_5_FREE_INODE_COUNT_GROUP,
9563           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9564           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9565
9566         /* Directories count for group wrong */
9567         { PR_5_FREE_DIR_COUNT_GROUP,
9568           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9569           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9570
9571         /* Free inodes count wrong */
9572         { PR_5_FREE_INODE_COUNT,
9573           N_("Free @is count wrong (%i, counted=%j).\n"),
9574           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9575
9576         /* Free blocks count for group wrong */
9577         { PR_5_FREE_BLOCK_COUNT_GROUP,
9578           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9579           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9580
9581         /* Free blocks count wrong */
9582         { PR_5_FREE_BLOCK_COUNT,
9583           N_("Free @bs count wrong (%b, counted=%c).\n"),
9584           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9585
9586         /* Programming error: bitmap endpoints don't match */
9587         { PR_5_BMAP_ENDPOINTS,
9588           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9589           "match calculated @B endpoints (%i, %j)\n"),
9590           PROMPT_NONE, PR_FATAL },
9591
9592         /* Internal error: fudging end of bitmap */
9593         { PR_5_FUDGE_BITMAP_ERROR,
9594           N_("Internal error: fudging end of bitmap (%N)\n"),
9595           PROMPT_NONE, PR_FATAL },
9596
9597         /* Error copying in replacement inode bitmap */
9598         { PR_5_COPY_IBITMAP_ERROR,
9599           N_("Error copying in replacement @i @B: %m\n"),
9600           PROMPT_NONE, PR_FATAL },
9601
9602         /* Error copying in replacement block bitmap */
9603         { PR_5_COPY_BBITMAP_ERROR,
9604           N_("Error copying in replacement @b @B: %m\n"),
9605           PROMPT_NONE, PR_FATAL },
9606
9607         /* Block range not used, but marked in bitmap */
9608         { PR_5_BLOCK_RANGE_UNUSED,
9609           " -(%b--%c)",
9610           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9611
9612         /* Block range used, but not marked used in bitmap */
9613         { PR_5_BLOCK_RANGE_USED,
9614           " +(%b--%c)",
9615           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9616
9617         /* Inode range not used, but marked in bitmap */
9618         { PR_5_INODE_RANGE_UNUSED,
9619           " -(%i--%j)",
9620           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9621
9622         /* Inode range used, but not marked used in bitmap */
9623         { PR_5_INODE_RANGE_USED,
9624           " +(%i--%j)",
9625           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9626
9627         { 0 }
9628 };
9629
9630 /*
9631  * This is the latch flags register.  It allows several problems to be
9632  * "latched" together.  This means that the user has to answer but one
9633  * question for the set of problems, and all of the associated
9634  * problems will be either fixed or not fixed.
9635  */
9636 static struct latch_descr pr_latch_info[] = {
9637         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9638         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9639         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9640         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9641         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9642         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9643         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9644         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9645         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9646         { -1, 0, 0 },
9647 };
9648
9649 static const struct e2fsck_problem *find_problem(problem_t code)
9650 {
9651         int     i;
9652
9653         for (i=0; problem_table[i].e2p_code; i++) {
9654                 if (problem_table[i].e2p_code == code)
9655                         return &problem_table[i];
9656         }
9657         return 0;
9658 }
9659
9660 static struct latch_descr *find_latch(int code)
9661 {
9662         int     i;
9663
9664         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9665                 if (pr_latch_info[i].latch_code == code)
9666                         return &pr_latch_info[i];
9667         }
9668         return 0;
9669 }
9670
9671 int end_problem_latch(e2fsck_t ctx, int mask)
9672 {
9673         struct latch_descr *ldesc;
9674         struct problem_context pctx;
9675         int answer = -1;
9676
9677         ldesc = find_latch(mask);
9678         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9679                 clear_problem_context(&pctx);
9680                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9681         }
9682         ldesc->flags &= ~(PRL_VARIABLE);
9683         return answer;
9684 }
9685
9686 int set_latch_flags(int mask, int setflags, int clearflags)
9687 {
9688         struct latch_descr *ldesc;
9689
9690         ldesc = find_latch(mask);
9691         if (!ldesc)
9692                 return -1;
9693         ldesc->flags |= setflags;
9694         ldesc->flags &= ~clearflags;
9695         return 0;
9696 }
9697
9698 void clear_problem_context(struct problem_context *ctx)
9699 {
9700         memset(ctx, 0, sizeof(struct problem_context));
9701         ctx->blkcount = -1;
9702         ctx->group = -1;
9703 }
9704
9705 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9706 {
9707         ext2_filsys fs = ctx->fs;
9708         const struct e2fsck_problem *ptr;
9709         struct latch_descr *ldesc = 0;
9710         const char *message;
9711         int             def_yn, answer, ans;
9712         int             print_answer = 0;
9713         int             suppress = 0;
9714
9715         ptr = find_problem(code);
9716         if (!ptr) {
9717                 printf(_("Unhandled error code (0x%x)!\n"), code);
9718                 return 0;
9719         }
9720         def_yn = 1;
9721         if ((ptr->flags & PR_NO_DEFAULT) ||
9722             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9723             (ctx->options & E2F_OPT_NO))
9724                 def_yn= 0;
9725
9726         /*
9727          * Do special latch processing.  This is where we ask the
9728          * latch question, if it exists
9729          */
9730         if (ptr->flags & PR_LATCH_MASK) {
9731                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9732                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9733                         ans = fix_problem(ctx, ldesc->question, pctx);
9734                         if (ans == 1)
9735                                 ldesc->flags |= PRL_YES;
9736                         if (ans == 0)
9737                                 ldesc->flags |= PRL_NO;
9738                         ldesc->flags |= PRL_LATCHED;
9739                 }
9740                 if (ldesc->flags & PRL_SUPPRESS)
9741                         suppress++;
9742         }
9743         if ((ptr->flags & PR_PREEN_NOMSG) &&
9744             (ctx->options & E2F_OPT_PREEN))
9745                 suppress++;
9746         if ((ptr->flags & PR_NO_NOMSG) &&
9747             (ctx->options & E2F_OPT_NO))
9748                 suppress++;
9749         if (!suppress) {
9750                 message = ptr->e2p_description;
9751                 if ((ctx->options & E2F_OPT_PREEN) &&
9752                     !(ptr->flags & PR_PREEN_NOHDR)) {
9753                         printf("%s: ", ctx->device_name ?
9754                                ctx->device_name : ctx->filesystem_name);
9755                 }
9756                 if (*message)
9757                         print_e2fsck_message(ctx, _(message), pctx, 1);
9758         }
9759         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9760                 preenhalt(ctx);
9761
9762         if (ptr->flags & PR_FATAL)
9763                 bb_error_msg_and_die(0);
9764
9765         if (ptr->prompt == PROMPT_NONE) {
9766                 if (ptr->flags & PR_NOCOLLATE)
9767                         answer = -1;
9768                 else
9769                         answer = def_yn;
9770         } else {
9771                 if (ctx->options & E2F_OPT_PREEN) {
9772                         answer = def_yn;
9773                         if (!(ptr->flags & PR_PREEN_NOMSG))
9774                                 print_answer = 1;
9775                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9776                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9777                         if (!suppress)
9778                                 print_answer = 1;
9779                         if (ldesc->flags & PRL_YES)
9780                                 answer = 1;
9781                         else
9782                                 answer = 0;
9783                 } else
9784                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9785                 if (!answer && !(ptr->flags & PR_NO_OK))
9786                         ext2fs_unmark_valid(fs);
9787
9788                 if (print_answer)
9789                         printf("%s.\n", answer ?
9790                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9791
9792         }
9793
9794         if ((ptr->prompt == PROMPT_ABORT) && answer)
9795                 bb_error_msg_and_die(0);
9796
9797         if (ptr->flags & PR_AFTER_CODE)
9798                 answer = fix_problem(ctx, ptr->second_code, pctx);
9799
9800         return answer;
9801 }
9802
9803 /*
9804  * linux/fs/recovery.c
9805  *
9806  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9807  */
9808
9809 /*
9810  * Maintain information about the progress of the recovery job, so that
9811  * the different passes can carry information between them.
9812  */
9813 struct recovery_info
9814 {
9815         tid_t           start_transaction;
9816         tid_t           end_transaction;
9817
9818         int             nr_replays;
9819         int             nr_revokes;
9820         int             nr_revoke_hits;
9821 };
9822
9823 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9824 static int do_one_pass(journal_t *journal,
9825                                 struct recovery_info *info, enum passtype pass);
9826 static int scan_revoke_records(journal_t *, struct buffer_head *,
9827                                 tid_t, struct recovery_info *);
9828
9829 /*
9830  * Read a block from the journal
9831  */
9832
9833 static int jread(struct buffer_head **bhp, journal_t *journal,
9834                  unsigned int offset)
9835 {
9836         int err;
9837         unsigned long blocknr;
9838         struct buffer_head *bh;
9839
9840         *bhp = NULL;
9841
9842         err = journal_bmap(journal, offset, &blocknr);
9843
9844         if (err) {
9845                 printf ("JBD: bad block at offset %u\n", offset);
9846                 return err;
9847         }
9848
9849         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9850         if (!bh)
9851                 return -ENOMEM;
9852
9853         if (!buffer_uptodate(bh)) {
9854                 /* If this is a brand new buffer, start readahead.
9855                    Otherwise, we assume we are already reading it.  */
9856                 if (!buffer_req(bh))
9857                         do_readahead(journal, offset);
9858                 wait_on_buffer(bh);
9859         }
9860
9861         if (!buffer_uptodate(bh)) {
9862                 printf ("JBD: Failed to read block at offset %u\n", offset);
9863                 brelse(bh);
9864                 return -EIO;
9865         }
9866
9867         *bhp = bh;
9868         return 0;
9869 }
9870
9871
9872 /*
9873  * Count the number of in-use tags in a journal descriptor block.
9874  */
9875
9876 static int count_tags(struct buffer_head *bh, int size)
9877 {
9878         char *                  tagp;
9879         journal_block_tag_t *   tag;
9880         int                     nr = 0;
9881
9882         tagp = &bh->b_data[sizeof(journal_header_t)];
9883
9884         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9885                 tag = (journal_block_tag_t *) tagp;
9886
9887                 nr++;
9888                 tagp += sizeof(journal_block_tag_t);
9889                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9890                         tagp += 16;
9891
9892                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9893                         break;
9894         }
9895
9896         return nr;
9897 }
9898
9899
9900 /* Make sure we wrap around the log correctly! */
9901 #define wrap(journal, var)                                            \
9902 do {                                                                \
9903         if (var >= (journal)->j_last)                                   \
9904                 var -= ((journal)->j_last - (journal)->j_first);        \
9905 } while (0)
9906
9907 /**
9908  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9909  * @journal: the journal to recover
9910  *
9911  * The primary function for recovering the log contents when mounting a
9912  * journaled device.
9913  *
9914  * Recovery is done in three passes.  In the first pass, we look for the
9915  * end of the log.  In the second, we assemble the list of revoke
9916  * blocks.  In the third and final pass, we replay any un-revoked blocks
9917  * in the log.
9918  */
9919 int journal_recover(journal_t *journal)
9920 {
9921         int                     err;
9922         journal_superblock_t *  sb;
9923
9924         struct recovery_info    info;
9925
9926         memset(&info, 0, sizeof(info));
9927         sb = journal->j_superblock;
9928
9929         /*
9930          * The journal superblock's s_start field (the current log head)
9931          * is always zero if, and only if, the journal was cleanly
9932          * unmounted.
9933          */
9934
9935         if (!sb->s_start) {
9936                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9937                 return 0;
9938         }
9939
9940         err = do_one_pass(journal, &info, PASS_SCAN);
9941         if (!err)
9942                 err = do_one_pass(journal, &info, PASS_REVOKE);
9943         if (!err)
9944                 err = do_one_pass(journal, &info, PASS_REPLAY);
9945
9946         /* Restart the log at the next transaction ID, thus invalidating
9947          * any existing commit records in the log. */
9948         journal->j_transaction_sequence = ++info.end_transaction;
9949
9950         journal_clear_revoke(journal);
9951         sync_blockdev(journal->j_fs_dev);
9952         return err;
9953 }
9954
9955 static int do_one_pass(journal_t *journal,
9956                         struct recovery_info *info, enum passtype pass)
9957 {
9958         unsigned int            first_commit_ID, next_commit_ID;
9959         unsigned long           next_log_block;
9960         int                     err, success = 0;
9961         journal_superblock_t *  sb;
9962         journal_header_t *      tmp;
9963         struct buffer_head *    bh;
9964         unsigned int            sequence;
9965         int                     blocktype;
9966
9967         /* Precompute the maximum metadata descriptors in a descriptor block */
9968         int                     MAX_BLOCKS_PER_DESC;
9969         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9970                                / sizeof(journal_block_tag_t));
9971
9972         /*
9973          * First thing is to establish what we expect to find in the log
9974          * (in terms of transaction IDs), and where (in terms of log
9975          * block offsets): query the superblock.
9976          */
9977
9978         sb = journal->j_superblock;
9979         next_commit_ID = ntohl(sb->s_sequence);
9980         next_log_block = ntohl(sb->s_start);
9981
9982         first_commit_ID = next_commit_ID;
9983         if (pass == PASS_SCAN)
9984                 info->start_transaction = first_commit_ID;
9985
9986         /*
9987          * Now we walk through the log, transaction by transaction,
9988          * making sure that each transaction has a commit block in the
9989          * expected place.  Each complete transaction gets replayed back
9990          * into the main filesystem.
9991          */
9992
9993         while (1) {
9994                 int                     flags;
9995                 char *                  tagp;
9996                 journal_block_tag_t *   tag;
9997                 struct buffer_head *    obh;
9998                 struct buffer_head *    nbh;
9999
10000                 /* If we already know where to stop the log traversal,
10001                  * check right now that we haven't gone past the end of
10002                  * the log. */
10003
10004                 if (pass != PASS_SCAN)
10005                         if (tid_geq(next_commit_ID, info->end_transaction))
10006                                 break;
10007
10008                 /* Skip over each chunk of the transaction looking
10009                  * either the next descriptor block or the final commit
10010                  * record. */
10011
10012                 err = jread(&bh, journal, next_log_block);
10013                 if (err)
10014                         goto failed;
10015
10016                 next_log_block++;
10017                 wrap(journal, next_log_block);
10018
10019                 /* What kind of buffer is it?
10020                  *
10021                  * If it is a descriptor block, check that it has the
10022                  * expected sequence number.  Otherwise, we're all done
10023                  * here. */
10024
10025                 tmp = (journal_header_t *)bh->b_data;
10026
10027                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10028                         brelse(bh);
10029                         break;
10030                 }
10031
10032                 blocktype = ntohl(tmp->h_blocktype);
10033                 sequence = ntohl(tmp->h_sequence);
10034
10035                 if (sequence != next_commit_ID) {
10036                         brelse(bh);
10037                         break;
10038                 }
10039
10040                 /* OK, we have a valid descriptor block which matches
10041                  * all of the sequence number checks.  What are we going
10042                  * to do with it?  That depends on the pass... */
10043
10044                 switch(blocktype) {
10045                 case JFS_DESCRIPTOR_BLOCK:
10046                         /* If it is a valid descriptor block, replay it
10047                          * in pass REPLAY; otherwise, just skip over the
10048                          * blocks it describes. */
10049                         if (pass != PASS_REPLAY) {
10050                                 next_log_block +=
10051                                         count_tags(bh, journal->j_blocksize);
10052                                 wrap(journal, next_log_block);
10053                                 brelse(bh);
10054                                 continue;
10055                         }
10056
10057                         /* A descriptor block: we can now write all of
10058                          * the data blocks.  Yay, useful work is finally
10059                          * getting done here! */
10060
10061                         tagp = &bh->b_data[sizeof(journal_header_t)];
10062                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10063                                <= journal->j_blocksize) {
10064                                 unsigned long io_block;
10065
10066                                 tag = (journal_block_tag_t *) tagp;
10067                                 flags = ntohl(tag->t_flags);
10068
10069                                 io_block = next_log_block++;
10070                                 wrap(journal, next_log_block);
10071                                 err = jread(&obh, journal, io_block);
10072                                 if (err) {
10073                                         /* Recover what we can, but
10074                                          * report failure at the end. */
10075                                         success = err;
10076                                         printf ("JBD: IO error %d recovering "
10077                                                 "block %ld in log\n",
10078                                                 err, io_block);
10079                                 } else {
10080                                         unsigned long blocknr;
10081
10082                                         blocknr = ntohl(tag->t_blocknr);
10083
10084                                         /* If the block has been
10085                                          * revoked, then we're all done
10086                                          * here. */
10087                                         if (journal_test_revoke
10088                                             (journal, blocknr,
10089                                              next_commit_ID)) {
10090                                                 brelse(obh);
10091                                                 ++info->nr_revoke_hits;
10092                                                 goto skip_write;
10093                                         }
10094
10095                                         /* Find a buffer for the new
10096                                          * data being restored */
10097                                         nbh = getblk(journal->j_fs_dev,
10098                                                        blocknr,
10099                                                      journal->j_blocksize);
10100                                         if (nbh == NULL) {
10101                                                 printf ("JBD: Out of memory "
10102                                                        "during recovery.\n");
10103                                                 err = -ENOMEM;
10104                                                 brelse(bh);
10105                                                 brelse(obh);
10106                                                 goto failed;
10107                                         }
10108
10109                                         lock_buffer(nbh);
10110                                         memcpy(nbh->b_data, obh->b_data,
10111                                                         journal->j_blocksize);
10112                                         if (flags & JFS_FLAG_ESCAPE) {
10113                                                 *((unsigned int *)bh->b_data) =
10114                                                         htonl(JFS_MAGIC_NUMBER);
10115                                         }
10116
10117                                         mark_buffer_uptodate(nbh, 1);
10118                                         mark_buffer_dirty(nbh);
10119                                         ++info->nr_replays;
10120                                         /* ll_rw_block(WRITE, 1, &nbh); */
10121                                         unlock_buffer(nbh);
10122                                         brelse(obh);
10123                                         brelse(nbh);
10124                                 }
10125
10126                         skip_write:
10127                                 tagp += sizeof(journal_block_tag_t);
10128                                 if (!(flags & JFS_FLAG_SAME_UUID))
10129                                         tagp += 16;
10130
10131                                 if (flags & JFS_FLAG_LAST_TAG)
10132                                         break;
10133                         }
10134
10135                         brelse(bh);
10136                         continue;
10137
10138                 case JFS_COMMIT_BLOCK:
10139                         /* Found an expected commit block: not much to
10140                          * do other than move on to the next sequence
10141                          * number. */
10142                         brelse(bh);
10143                         next_commit_ID++;
10144                         continue;
10145
10146                 case JFS_REVOKE_BLOCK:
10147                         /* If we aren't in the REVOKE pass, then we can
10148                          * just skip over this block. */
10149                         if (pass != PASS_REVOKE) {
10150                                 brelse(bh);
10151                                 continue;
10152                         }
10153
10154                         err = scan_revoke_records(journal, bh,
10155                                                   next_commit_ID, info);
10156                         brelse(bh);
10157                         if (err)
10158                                 goto failed;
10159                         continue;
10160
10161                 default:
10162                         goto done;
10163                 }
10164         }
10165
10166  done:
10167         /*
10168          * We broke out of the log scan loop: either we came to the
10169          * known end of the log or we found an unexpected block in the
10170          * log.  If the latter happened, then we know that the "current"
10171          * transaction marks the end of the valid log.
10172          */
10173
10174         if (pass == PASS_SCAN)
10175                 info->end_transaction = next_commit_ID;
10176         else {
10177                 /* It's really bad news if different passes end up at
10178                  * different places (but possible due to IO errors). */
10179                 if (info->end_transaction != next_commit_ID) {
10180                         printf ("JBD: recovery pass %d ended at "
10181                                 "transaction %u, expected %u\n",
10182                                 pass, next_commit_ID, info->end_transaction);
10183                         if (!success)
10184                                 success = -EIO;
10185                 }
10186         }
10187
10188         return success;
10189
10190  failed:
10191         return err;
10192 }
10193
10194
10195 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10196
10197 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10198                                tid_t sequence, struct recovery_info *info)
10199 {
10200         journal_revoke_header_t *header;
10201         int offset, max;
10202
10203         header = (journal_revoke_header_t *) bh->b_data;
10204         offset = sizeof(journal_revoke_header_t);
10205         max = ntohl(header->r_count);
10206
10207         while (offset < max) {
10208                 unsigned long blocknr;
10209                 int err;
10210
10211                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10212                 offset += 4;
10213                 err = journal_set_revoke(journal, blocknr, sequence);
10214                 if (err)
10215                         return err;
10216                 ++info->nr_revokes;
10217         }
10218         return 0;
10219 }
10220
10221
10222 /*
10223  * rehash.c --- rebuild hash tree directories
10224  *
10225  * This algorithm is designed for simplicity of implementation and to
10226  * pack the directory as much as possible.  It however requires twice
10227  * as much memory as the size of the directory.  The maximum size
10228  * directory supported using a 4k blocksize is roughly a gigabyte, and
10229  * so there may very well be problems with machines that don't have
10230  * virtual memory, and obscenely large directories.
10231  *
10232  * An alternate algorithm which is much more disk intensive could be
10233  * written, and probably will need to be written in the future.  The
10234  * design goals of such an algorithm are: (a) use (roughly) constant
10235  * amounts of memory, no matter how large the directory, (b) the
10236  * directory must be safe at all times, even if e2fsck is interrupted
10237  * in the middle, (c) we must use minimal amounts of extra disk
10238  * blocks.  This pretty much requires an incremental approach, where
10239  * we are reading from one part of the directory, and inserting into
10240  * the front half.  So the algorithm will have to keep track of a
10241  * moving block boundary between the new tree and the old tree, and
10242  * files will need to be moved from the old directory and inserted
10243  * into the new tree.  If the new directory requires space which isn't
10244  * yet available, blocks from the beginning part of the old directory
10245  * may need to be moved to the end of the directory to make room for
10246  * the new tree:
10247  *
10248  *    --------------------------------------------------------
10249  *    |  new tree   |        | old tree                      |
10250  *    --------------------------------------------------------
10251  *                  ^ ptr    ^ptr
10252  *                tail new   head old
10253  *
10254  * This is going to be a pain in the tuckus to implement, and will
10255  * require a lot more disk accesses.  So I'm going to skip it for now;
10256  * it's only really going to be an issue for really, really big
10257  * filesystems (when we reach the level of tens of millions of files
10258  * in a single directory).  It will probably be easier to simply
10259  * require that e2fsck use VM first.
10260  */
10261
10262 struct fill_dir_struct {
10263         char *buf;
10264         struct ext2_inode *inode;
10265         int err;
10266         e2fsck_t ctx;
10267         struct hash_entry *harray;
10268         int max_array, num_array;
10269         int dir_size;
10270         int compress;
10271         ino_t parent;
10272 };
10273
10274 struct hash_entry {
10275         ext2_dirhash_t  hash;
10276         ext2_dirhash_t  minor_hash;
10277         struct ext2_dir_entry   *dir;
10278 };
10279
10280 struct out_dir {
10281         int             num;
10282         int             max;
10283         char            *buf;
10284         ext2_dirhash_t  *hashes;
10285 };
10286
10287 static int fill_dir_block(ext2_filsys fs,
10288                           blk_t *block_nr,
10289                           e2_blkcnt_t blockcnt,
10290                           blk_t ref_block FSCK_ATTR((unused)),
10291                           int ref_offset FSCK_ATTR((unused)),
10292                           void *priv_data)
10293 {
10294         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10295         struct hash_entry       *new_array, *ent;
10296         struct ext2_dir_entry   *dirent;
10297         char                    *dir;
10298         unsigned int            offset, dir_offset;
10299
10300         if (blockcnt < 0)
10301                 return 0;
10302
10303         offset = blockcnt * fs->blocksize;
10304         if (offset + fs->blocksize > fd->inode->i_size) {
10305                 fd->err = EXT2_ET_DIR_CORRUPTED;
10306                 return BLOCK_ABORT;
10307         }
10308         dir = (fd->buf+offset);
10309         if (HOLE_BLKADDR(*block_nr)) {
10310                 memset(dir, 0, fs->blocksize);
10311                 dirent = (struct ext2_dir_entry *) dir;
10312                 dirent->rec_len = fs->blocksize;
10313         } else {
10314                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10315                 if (fd->err)
10316                         return BLOCK_ABORT;
10317         }
10318         /* While the directory block is "hot", index it. */
10319         dir_offset = 0;
10320         while (dir_offset < fs->blocksize) {
10321                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10322                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10323                     (dirent->rec_len < 8) ||
10324                     ((dirent->rec_len % 4) != 0) ||
10325                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10326                         fd->err = EXT2_ET_DIR_CORRUPTED;
10327                         return BLOCK_ABORT;
10328                 }
10329                 dir_offset += dirent->rec_len;
10330                 if (dirent->inode == 0)
10331                         continue;
10332                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10333                     (dirent->name[0] == '.'))
10334                         continue;
10335                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10336                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10337                         fd->parent = dirent->inode;
10338                         continue;
10339                 }
10340                 if (fd->num_array >= fd->max_array) {
10341                         new_array = realloc(fd->harray,
10342                             sizeof(struct hash_entry) * (fd->max_array+500));
10343                         if (!new_array) {
10344                                 fd->err = ENOMEM;
10345                                 return BLOCK_ABORT;
10346                         }
10347                         fd->harray = new_array;
10348                         fd->max_array += 500;
10349                 }
10350                 ent = fd->harray + fd->num_array++;
10351                 ent->dir = dirent;
10352                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10353                 if (fd->compress)
10354                         ent->hash = ent->minor_hash = 0;
10355                 else {
10356                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10357                                                  dirent->name,
10358                                                  dirent->name_len & 0xFF,
10359                                                  fs->super->s_hash_seed,
10360                                                  &ent->hash, &ent->minor_hash);
10361                         if (fd->err)
10362                                 return BLOCK_ABORT;
10363                 }
10364         }
10365
10366         return 0;
10367 }
10368
10369 /* Used for sorting the hash entry */
10370 static int name_cmp(const void *a, const void *b)
10371 {
10372         const struct hash_entry *he_a = (const struct hash_entry *) a;
10373         const struct hash_entry *he_b = (const struct hash_entry *) b;
10374         int     ret;
10375         int     min_len;
10376
10377         min_len = he_a->dir->name_len;
10378         if (min_len > he_b->dir->name_len)
10379                 min_len = he_b->dir->name_len;
10380
10381         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10382         if (ret == 0) {
10383                 if (he_a->dir->name_len > he_b->dir->name_len)
10384                         ret = 1;
10385                 else if (he_a->dir->name_len < he_b->dir->name_len)
10386                         ret = -1;
10387                 else
10388                         ret = he_b->dir->inode - he_a->dir->inode;
10389         }
10390         return ret;
10391 }
10392
10393 /* Used for sorting the hash entry */
10394 static int hash_cmp(const void *a, const void *b)
10395 {
10396         const struct hash_entry *he_a = (const struct hash_entry *) a;
10397         const struct hash_entry *he_b = (const struct hash_entry *) b;
10398         int     ret;
10399
10400         if (he_a->hash > he_b->hash)
10401                 ret = 1;
10402         else if (he_a->hash < he_b->hash)
10403                 ret = -1;
10404         else {
10405                 if (he_a->minor_hash > he_b->minor_hash)
10406                         ret = 1;
10407                 else if (he_a->minor_hash < he_b->minor_hash)
10408                         ret = -1;
10409                 else
10410                         ret = name_cmp(a, b);
10411         }
10412         return ret;
10413 }
10414
10415 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10416                                 int blocks)
10417 {
10418         void                    *new_mem;
10419
10420         if (outdir->max) {
10421                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
10422                 if (!new_mem)
10423                         return ENOMEM;
10424                 outdir->buf = new_mem;
10425                 new_mem = realloc(outdir->hashes,
10426                                   blocks * sizeof(ext2_dirhash_t));
10427                 if (!new_mem)
10428                         return ENOMEM;
10429                 outdir->hashes = new_mem;
10430         } else {
10431                 outdir->buf = malloc(blocks * fs->blocksize);
10432                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
10433                 outdir->num = 0;
10434         }
10435         outdir->max = blocks;
10436         return 0;
10437 }
10438
10439 static void free_out_dir(struct out_dir *outdir)
10440 {
10441         free(outdir->buf);
10442         free(outdir->hashes);
10443         outdir->max = 0;
10444         outdir->num =0;
10445 }
10446
10447 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10448                          char ** ret)
10449 {
10450         errcode_t       retval;
10451
10452         if (outdir->num >= outdir->max) {
10453                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10454                 if (retval)
10455                         return retval;
10456         }
10457         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10458         memset(*ret, 0, fs->blocksize);
10459         return 0;
10460 }
10461
10462 /*
10463  * This function is used to make a unique filename.  We do this by
10464  * appending ~0, and then incrementing the number.  However, we cannot
10465  * expand the length of the filename beyond the padding available in
10466  * the directory entry.
10467  */
10468 static void mutate_name(char *str, __u16 *len)
10469 {
10470         int     i;
10471         __u16   l = *len & 0xFF, h = *len & 0xff00;
10472
10473         /*
10474          * First check to see if it looks the name has been mutated
10475          * already
10476          */
10477         for (i = l-1; i > 0; i--) {
10478                 if (!isdigit(str[i]))
10479                         break;
10480         }
10481         if ((i == l-1) || (str[i] != '~')) {
10482                 if (((l-1) & 3) < 2)
10483                         l += 2;
10484                 else
10485                         l = (l+3) & ~3;
10486                 str[l-2] = '~';
10487                 str[l-1] = '0';
10488                 *len = l | h;
10489                 return;
10490         }
10491         for (i = l-1; i >= 0; i--) {
10492                 if (isdigit(str[i])) {
10493                         if (str[i] == '9')
10494                                 str[i] = '0';
10495                         else {
10496                                 str[i]++;
10497                                 return;
10498                         }
10499                         continue;
10500                 }
10501                 if (i == 1) {
10502                         if (str[0] == 'z')
10503                                 str[0] = 'A';
10504                         else if (str[0] == 'Z') {
10505                                 str[0] = '~';
10506                                 str[1] = '0';
10507                         } else
10508                                 str[0]++;
10509                 } else if (i > 0) {
10510                         str[i] = '1';
10511                         str[i-1] = '~';
10512                 } else {
10513                         if (str[0] == '~')
10514                                 str[0] = 'a';
10515                         else
10516                                 str[0]++;
10517                 }
10518                 break;
10519         }
10520 }
10521
10522 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10523                                     ext2_ino_t ino,
10524                                     struct fill_dir_struct *fd)
10525 {
10526         struct problem_context  pctx;
10527         struct hash_entry       *ent, *prev;
10528         int                     i, j;
10529         int                     fixed = 0;
10530         char                    new_name[256];
10531         __u16                   new_len;
10532
10533         clear_problem_context(&pctx);
10534         pctx.ino = ino;
10535
10536         for (i=1; i < fd->num_array; i++) {
10537                 ent = fd->harray + i;
10538                 prev = ent - 1;
10539                 if (!ent->dir->inode ||
10540                     ((ent->dir->name_len & 0xFF) !=
10541                      (prev->dir->name_len & 0xFF)) ||
10542                     (strncmp(ent->dir->name, prev->dir->name,
10543                              ent->dir->name_len & 0xFF)))
10544                         continue;
10545                 pctx.dirent = ent->dir;
10546                 if ((ent->dir->inode == prev->dir->inode) &&
10547                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10548                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10549                         ent->dir->inode = 0;
10550                         fixed++;
10551                         continue;
10552                 }
10553                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10554                 new_len = ent->dir->name_len;
10555                 mutate_name(new_name, &new_len);
10556                 for (j=0; j < fd->num_array; j++) {
10557                         if ((i==j) ||
10558                             ((ent->dir->name_len & 0xFF) !=
10559                              (fd->harray[j].dir->name_len & 0xFF)) ||
10560                             (strncmp(new_name, fd->harray[j].dir->name,
10561                                      new_len & 0xFF)))
10562                                 continue;
10563                         mutate_name(new_name, &new_len);
10564
10565                         j = -1;
10566                 }
10567                 new_name[new_len & 0xFF] = 0;
10568                 pctx.str = new_name;
10569                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10570                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10571                         ent->dir->name_len = new_len;
10572                         ext2fs_dirhash(fs->super->s_def_hash_version,
10573                                        ent->dir->name,
10574                                        ent->dir->name_len & 0xFF,
10575                                        fs->super->s_hash_seed,
10576                                        &ent->hash, &ent->minor_hash);
10577                         fixed++;
10578                 }
10579         }
10580         return fixed;
10581 }
10582
10583
10584 static errcode_t copy_dir_entries(ext2_filsys fs,
10585                                   struct fill_dir_struct *fd,
10586                                   struct out_dir *outdir)
10587 {
10588         errcode_t               retval;
10589         char                    *block_start;
10590         struct hash_entry       *ent;
10591         struct ext2_dir_entry   *dirent;
10592         int                     i, rec_len, left;
10593         ext2_dirhash_t          prev_hash;
10594         int                     offset;
10595
10596         outdir->max = 0;
10597         retval = alloc_size_dir(fs, outdir,
10598                                 (fd->dir_size / fs->blocksize) + 2);
10599         if (retval)
10600                 return retval;
10601         outdir->num = fd->compress ? 0 : 1;
10602         offset = 0;
10603         outdir->hashes[0] = 0;
10604         prev_hash = 1;
10605         if ((retval = get_next_block(fs, outdir, &block_start)))
10606                 return retval;
10607         dirent = (struct ext2_dir_entry *) block_start;
10608         left = fs->blocksize;
10609         for (i=0; i < fd->num_array; i++) {
10610                 ent = fd->harray + i;
10611                 if (ent->dir->inode == 0)
10612                         continue;
10613                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10614                 if (rec_len > left) {
10615                         if (left)
10616                                 dirent->rec_len += left;
10617                         if ((retval = get_next_block(fs, outdir,
10618                                                       &block_start)))
10619                                 return retval;
10620                         offset = 0;
10621                 }
10622                 left = fs->blocksize - offset;
10623                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10624                 if (offset == 0) {
10625                         if (ent->hash == prev_hash)
10626                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10627                         else
10628                                 outdir->hashes[outdir->num-1] = ent->hash;
10629                 }
10630                 dirent->inode = ent->dir->inode;
10631                 dirent->name_len = ent->dir->name_len;
10632                 dirent->rec_len = rec_len;
10633                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10634                 offset += rec_len;
10635                 left -= rec_len;
10636                 if (left < 12) {
10637                         dirent->rec_len += left;
10638                         offset += left;
10639                         left = 0;
10640                 }
10641                 prev_hash = ent->hash;
10642         }
10643         if (left)
10644                 dirent->rec_len += left;
10645
10646         return 0;
10647 }
10648
10649
10650 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10651                                     ext2_ino_t ino, ext2_ino_t parent)
10652 {
10653         struct ext2_dir_entry           *dir;
10654         struct ext2_dx_root_info        *root;
10655         struct ext2_dx_countlimit       *limits;
10656         int                             filetype = 0;
10657
10658         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10659                 filetype = EXT2_FT_DIR << 8;
10660
10661         memset(buf, 0, fs->blocksize);
10662         dir = (struct ext2_dir_entry *) buf;
10663         dir->inode = ino;
10664         dir->name[0] = '.';
10665         dir->name_len = 1 | filetype;
10666         dir->rec_len = 12;
10667         dir = (struct ext2_dir_entry *) (buf + 12);
10668         dir->inode = parent;
10669         dir->name[0] = '.';
10670         dir->name[1] = '.';
10671         dir->name_len = 2 | filetype;
10672         dir->rec_len = fs->blocksize - 12;
10673
10674         root = (struct ext2_dx_root_info *) (buf+24);
10675         root->reserved_zero = 0;
10676         root->hash_version = fs->super->s_def_hash_version;
10677         root->info_length = 8;
10678         root->indirect_levels = 0;
10679         root->unused_flags = 0;
10680
10681         limits = (struct ext2_dx_countlimit *) (buf+32);
10682         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10683         limits->count = 0;
10684
10685         return root;
10686 }
10687
10688
10689 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10690 {
10691         struct ext2_dir_entry           *dir;
10692         struct ext2_dx_countlimit       *limits;
10693
10694         memset(buf, 0, fs->blocksize);
10695         dir = (struct ext2_dir_entry *) buf;
10696         dir->inode = 0;
10697         dir->rec_len = fs->blocksize;
10698
10699         limits = (struct ext2_dx_countlimit *) (buf+8);
10700         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10701         limits->count = 0;
10702
10703         return (struct ext2_dx_entry *) limits;
10704 }
10705
10706 /*
10707  * This function takes the leaf nodes which have been written in
10708  * outdir, and populates the root node and any necessary interior nodes.
10709  */
10710 static errcode_t calculate_tree(ext2_filsys fs,
10711                                 struct out_dir *outdir,
10712                                 ext2_ino_t ino,
10713                                 ext2_ino_t parent)
10714 {
10715         struct ext2_dx_root_info        *root_info;
10716         struct ext2_dx_entry            *root, *dx_ent = 0;
10717         struct ext2_dx_countlimit       *root_limit, *limit;
10718         errcode_t                       retval;
10719         char                            * block_start;
10720         int                             i, c1, c2, nblks;
10721         int                             limit_offset, root_offset;
10722
10723         root_info = set_root_node(fs, outdir->buf, ino, parent);
10724         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10725                 root_info->info_length;
10726         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10727         c1 = root_limit->limit;
10728         nblks = outdir->num;
10729
10730         /* Write out the pointer blocks */
10731         if (nblks-1 <= c1) {
10732                 /* Just write out the root block, and we're done */
10733                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10734                 for (i=1; i < nblks; i++) {
10735                         root->block = ext2fs_cpu_to_le32(i);
10736                         if (i != 1)
10737                                 root->hash =
10738                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10739                         root++;
10740                         c1--;
10741                 }
10742         } else {
10743                 c2 = 0;
10744                 limit = 0;
10745                 root_info->indirect_levels = 1;
10746                 for (i=1; i < nblks; i++) {
10747                         if (c1 == 0)
10748                                 return ENOSPC;
10749                         if (c2 == 0) {
10750                                 if (limit)
10751                                         limit->limit = limit->count =
10752                 ext2fs_cpu_to_le16(limit->limit);
10753                                 root = (struct ext2_dx_entry *)
10754                                         (outdir->buf + root_offset);
10755                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10756                                 if (i != 1)
10757                                         root->hash =
10758                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10759                                 if ((retval =  get_next_block(fs, outdir,
10760                                                               &block_start)))
10761                                         return retval;
10762                                 dx_ent = set_int_node(fs, block_start);
10763                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10764                                 c2 = limit->limit;
10765                                 root_offset += sizeof(struct ext2_dx_entry);
10766                                 c1--;
10767                         }
10768                         dx_ent->block = ext2fs_cpu_to_le32(i);
10769                         if (c2 != limit->limit)
10770                                 dx_ent->hash =
10771                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10772                         dx_ent++;
10773                         c2--;
10774                 }
10775                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10776                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10777         }
10778         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10779         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10780         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10781
10782         return 0;
10783 }
10784
10785 struct write_dir_struct {
10786         struct out_dir *outdir;
10787         errcode_t       err;
10788         e2fsck_t        ctx;
10789         int             cleared;
10790 };
10791
10792 /*
10793  * Helper function which writes out a directory block.
10794  */
10795 static int write_dir_block(ext2_filsys fs,
10796                            blk_t        *block_nr,
10797                            e2_blkcnt_t blockcnt,
10798                            blk_t ref_block FSCK_ATTR((unused)),
10799                            int ref_offset FSCK_ATTR((unused)),
10800                            void *priv_data)
10801 {
10802         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10803         blk_t   blk;
10804         char    *dir;
10805
10806         if (*block_nr == 0)
10807                 return 0;
10808         if (blockcnt >= wd->outdir->num) {
10809                 e2fsck_read_bitmaps(wd->ctx);
10810                 blk = *block_nr;
10811                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10812                 ext2fs_block_alloc_stats(fs, blk, -1);
10813                 *block_nr = 0;
10814                 wd->cleared++;
10815                 return BLOCK_CHANGED;
10816         }
10817         if (blockcnt < 0)
10818                 return 0;
10819
10820         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10821         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10822         if (wd->err)
10823                 return BLOCK_ABORT;
10824         return 0;
10825 }
10826
10827 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10828                                  struct out_dir *outdir,
10829                                  ext2_ino_t ino, int compress)
10830 {
10831         struct write_dir_struct wd;
10832         errcode_t       retval;
10833         struct ext2_inode       inode;
10834
10835         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10836         if (retval)
10837                 return retval;
10838
10839         wd.outdir = outdir;
10840         wd.err = 0;
10841         wd.ctx = ctx;
10842         wd.cleared = 0;
10843
10844         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10845                                        write_dir_block, &wd);
10846         if (retval)
10847                 return retval;
10848         if (wd.err)
10849                 return wd.err;
10850
10851         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10852         if (compress)
10853                 inode.i_flags &= ~EXT2_INDEX_FL;
10854         else
10855                 inode.i_flags |= EXT2_INDEX_FL;
10856         inode.i_size = outdir->num * fs->blocksize;
10857         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10858         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10859
10860         return 0;
10861 }
10862
10863 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10864 {
10865         ext2_filsys             fs = ctx->fs;
10866         errcode_t               retval;
10867         struct ext2_inode       inode;
10868         char                    *dir_buf = 0;
10869         struct fill_dir_struct  fd;
10870         struct out_dir          outdir;
10871
10872         outdir.max = outdir.num = 0;
10873         outdir.buf = 0;
10874         outdir.hashes = 0;
10875         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10876
10877         retval = ENOMEM;
10878         fd.harray = 0;
10879         dir_buf = malloc(inode.i_size);
10880         if (!dir_buf)
10881                 goto errout;
10882
10883         fd.max_array = inode.i_size / 32;
10884         fd.num_array = 0;
10885         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
10886         if (!fd.harray)
10887                 goto errout;
10888
10889         fd.ctx = ctx;
10890         fd.buf = dir_buf;
10891         fd.inode = &inode;
10892         fd.err = 0;
10893         fd.dir_size = 0;
10894         fd.compress = 0;
10895         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10896             (inode.i_size / fs->blocksize) < 2)
10897                 fd.compress = 1;
10898         fd.parent = 0;
10899
10900         /* Read in the entire directory into memory */
10901         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10902                                        fill_dir_block, &fd);
10903         if (fd.err) {
10904                 retval = fd.err;
10905                 goto errout;
10906         }
10907
10908         /* Sort the list */
10909 resort:
10910         if (fd.compress)
10911                 qsort(fd.harray+2, fd.num_array-2,
10912                       sizeof(struct hash_entry), name_cmp);
10913         else
10914                 qsort(fd.harray, fd.num_array,
10915                       sizeof(struct hash_entry), hash_cmp);
10916
10917         /*
10918          * Look for duplicates
10919          */
10920         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10921                 goto resort;
10922
10923         if (ctx->options & E2F_OPT_NO) {
10924                 retval = 0;
10925                 goto errout;
10926         }
10927
10928         /*
10929          * Copy the directory entries.  In a htree directory these
10930          * will become the leaf nodes.
10931          */
10932         retval = copy_dir_entries(fs, &fd, &outdir);
10933         if (retval)
10934                 goto errout;
10935
10936         free(dir_buf); dir_buf = 0;
10937
10938         if (!fd.compress) {
10939                 /* Calculate the interior nodes */
10940                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10941                 if (retval)
10942                         goto errout;
10943         }
10944
10945         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10946
10947 errout:
10948         free(dir_buf);
10949         free(fd.harray);
10950
10951         free_out_dir(&outdir);
10952         return retval;
10953 }
10954
10955 void e2fsck_rehash_directories(e2fsck_t ctx)
10956 {
10957         struct problem_context  pctx;
10958         struct dir_info         *dir;
10959         ext2_u32_iterate        iter;
10960         ext2_ino_t              ino;
10961         errcode_t               retval;
10962         int                     i, cur, max, all_dirs, dir_index, first = 1;
10963
10964         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10965
10966         if (!ctx->dirs_to_hash && !all_dirs)
10967                 return;
10968
10969         e2fsck_get_lost_and_found(ctx, 0);
10970
10971         clear_problem_context(&pctx);
10972
10973         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10974         cur = 0;
10975         if (all_dirs) {
10976                 i = 0;
10977                 max = e2fsck_get_num_dirinfo(ctx);
10978         } else {
10979                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10980                                                        &iter);
10981                 if (retval) {
10982                         pctx.errcode = retval;
10983                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10984                         return;
10985                 }
10986                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10987         }
10988         while (1) {
10989                 if (all_dirs) {
10990                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10991                                 break;
10992                         ino = dir->ino;
10993                 } else {
10994                         if (!ext2fs_u32_list_iterate(iter, &ino))
10995                                 break;
10996                 }
10997                 if (ino == ctx->lost_and_found)
10998                         continue;
10999                 pctx.dir = ino;
11000                 if (first) {
11001                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
11002                         first = 0;
11003                 }
11004                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
11005                 if (pctx.errcode) {
11006                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
11007                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
11008                 }
11009                 if (ctx->progress && !ctx->progress_fd)
11010                         e2fsck_simple_progress(ctx, "Rebuilding directory",
11011                                100.0 * (float) (++cur) / (float) max, ino);
11012         }
11013         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
11014         if (!all_dirs)
11015                 ext2fs_u32_list_iterate_end(iter);
11016
11017         ext2fs_u32_list_free(ctx->dirs_to_hash);
11018         ctx->dirs_to_hash = 0;
11019 }
11020
11021 /*
11022  * linux/fs/revoke.c
11023  *
11024  * Journal revoke routines for the generic filesystem journaling code;
11025  * part of the ext2fs journaling system.
11026  *
11027  * Revoke is the mechanism used to prevent old log records for deleted
11028  * metadata from being replayed on top of newer data using the same
11029  * blocks.  The revoke mechanism is used in two separate places:
11030  *
11031  * + Commit: during commit we write the entire list of the current
11032  *   transaction's revoked blocks to the journal
11033  *
11034  * + Recovery: during recovery we record the transaction ID of all
11035  *   revoked blocks.  If there are multiple revoke records in the log
11036  *   for a single block, only the last one counts, and if there is a log
11037  *   entry for a block beyond the last revoke, then that log entry still
11038  *   gets replayed.
11039  *
11040  * We can get interactions between revokes and new log data within a
11041  * single transaction:
11042  *
11043  * Block is revoked and then journaled:
11044  *   The desired end result is the journaling of the new block, so we
11045  *   cancel the revoke before the transaction commits.
11046  *
11047  * Block is journaled and then revoked:
11048  *   The revoke must take precedence over the write of the block, so we
11049  *   need either to cancel the journal entry or to write the revoke
11050  *   later in the log than the log block.  In this case, we choose the
11051  *   latter: journaling a block cancels any revoke record for that block
11052  *   in the current transaction, so any revoke for that block in the
11053  *   transaction must have happened after the block was journaled and so
11054  *   the revoke must take precedence.
11055  *
11056  * Block is revoked and then written as data:
11057  *   The data write is allowed to succeed, but the revoke is _not_
11058  *   cancelled.  We still need to prevent old log records from
11059  *   overwriting the new data.  We don't even need to clear the revoke
11060  *   bit here.
11061  *
11062  * Revoke information on buffers is a tri-state value:
11063  *
11064  * RevokeValid clear:   no cached revoke status, need to look it up
11065  * RevokeValid set, Revoked clear:
11066  *                      buffer has not been revoked, and cancel_revoke
11067  *                      need do nothing.
11068  * RevokeValid set, Revoked set:
11069  *                      buffer has been revoked.
11070  */
11071
11072 static kmem_cache_t *revoke_record_cache;
11073 static kmem_cache_t *revoke_table_cache;
11074
11075 /* Each revoke record represents one single revoked block.  During
11076    journal replay, this involves recording the transaction ID of the
11077    last transaction to revoke this block. */
11078
11079 struct jbd_revoke_record_s
11080 {
11081         struct list_head  hash;
11082         tid_t             sequence;     /* Used for recovery only */
11083         unsigned long     blocknr;
11084 };
11085
11086
11087 /* The revoke table is just a simple hash table of revoke records. */
11088 struct jbd_revoke_table_s
11089 {
11090         /* It is conceivable that we might want a larger hash table
11091          * for recovery.  Must be a power of two. */
11092         int               hash_size;
11093         int               hash_shift;
11094         struct list_head *hash_table;
11095 };
11096
11097
11098 /* Utility functions to maintain the revoke table */
11099
11100 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11101 static inline int hash(journal_t *journal, unsigned long block)
11102 {
11103         struct jbd_revoke_table_s *table = journal->j_revoke;
11104         int hash_shift = table->hash_shift;
11105
11106         return ((block << (hash_shift - 6)) ^
11107                 (block >> 13) ^
11108                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11109 }
11110
11111 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11112                               tid_t seq)
11113 {
11114         struct list_head *hash_list;
11115         struct jbd_revoke_record_s *record;
11116
11117         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11118         if (!record)
11119                 goto oom;
11120
11121         record->sequence = seq;
11122         record->blocknr = blocknr;
11123         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11124         list_add(&record->hash, hash_list);
11125         return 0;
11126
11127 oom:
11128         return -ENOMEM;
11129 }
11130
11131 /* Find a revoke record in the journal's hash table. */
11132
11133 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11134                                                       unsigned long blocknr)
11135 {
11136         struct list_head *hash_list;
11137         struct jbd_revoke_record_s *record;
11138
11139         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11140
11141         record = (struct jbd_revoke_record_s *) hash_list->next;
11142         while (&(record->hash) != hash_list) {
11143                 if (record->blocknr == blocknr)
11144                         return record;
11145                 record = (struct jbd_revoke_record_s *) record->hash.next;
11146         }
11147         return NULL;
11148 }
11149
11150 int journal_init_revoke_caches(void)
11151 {
11152         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11153         if (revoke_record_cache == 0)
11154                 return -ENOMEM;
11155
11156         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11157         if (revoke_table_cache == 0) {
11158                 do_cache_destroy(revoke_record_cache);
11159                 revoke_record_cache = NULL;
11160                 return -ENOMEM;
11161         }
11162         return 0;
11163 }
11164
11165 void journal_destroy_revoke_caches(void)
11166 {
11167         do_cache_destroy(revoke_record_cache);
11168         revoke_record_cache = 0;
11169         do_cache_destroy(revoke_table_cache);
11170         revoke_table_cache = 0;
11171 }
11172
11173 /* Initialise the revoke table for a given journal to a given size. */
11174
11175 int journal_init_revoke(journal_t *journal, int hash_size)
11176 {
11177         int shift, tmp;
11178
11179         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11180         if (!journal->j_revoke)
11181                 return -ENOMEM;
11182
11183         /* Check that the hash_size is a power of two */
11184         journal->j_revoke->hash_size = hash_size;
11185
11186         shift = 0;
11187         tmp = hash_size;
11188         while((tmp >>= 1UL) != 0UL)
11189                 shift++;
11190         journal->j_revoke->hash_shift = shift;
11191
11192         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
11193         if (!journal->j_revoke->hash_table) {
11194                 free(journal->j_revoke);
11195                 journal->j_revoke = NULL;
11196                 return -ENOMEM;
11197         }
11198
11199         for (tmp = 0; tmp < hash_size; tmp++)
11200                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11201
11202         return 0;
11203 }
11204
11205 /* Destoy a journal's revoke table.  The table must already be empty! */
11206
11207 void journal_destroy_revoke(journal_t *journal)
11208 {
11209         struct jbd_revoke_table_s *table;
11210         struct list_head *hash_list;
11211         int i;
11212
11213         table = journal->j_revoke;
11214         if (!table)
11215                 return;
11216
11217         for (i=0; i<table->hash_size; i++) {
11218                 hash_list = &table->hash_table[i];
11219         }
11220
11221         free(table->hash_table);
11222         free(table);
11223         journal->j_revoke = NULL;
11224 }
11225
11226 /*
11227  * Revoke support for recovery.
11228  *
11229  * Recovery needs to be able to:
11230  *
11231  *  record all revoke records, including the tid of the latest instance
11232  *  of each revoke in the journal
11233  *
11234  *  check whether a given block in a given transaction should be replayed
11235  *  (ie. has not been revoked by a revoke record in that or a subsequent
11236  *  transaction)
11237  *
11238  *  empty the revoke table after recovery.
11239  */
11240
11241 /*
11242  * First, setting revoke records.  We create a new revoke record for
11243  * every block ever revoked in the log as we scan it for recovery, and
11244  * we update the existing records if we find multiple revokes for a
11245  * single block.
11246  */
11247
11248 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11249                        tid_t sequence)
11250 {
11251         struct jbd_revoke_record_s *record;
11252
11253         record = find_revoke_record(journal, blocknr);
11254         if (record) {
11255                 /* If we have multiple occurences, only record the
11256                  * latest sequence number in the hashed record */
11257                 if (tid_gt(sequence, record->sequence))
11258                         record->sequence = sequence;
11259                 return 0;
11260         }
11261         return insert_revoke_hash(journal, blocknr, sequence);
11262 }
11263
11264 /*
11265  * Test revoke records.  For a given block referenced in the log, has
11266  * that block been revoked?  A revoke record with a given transaction
11267  * sequence number revokes all blocks in that transaction and earlier
11268  * ones, but later transactions still need replayed.
11269  */
11270
11271 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11272                         tid_t sequence)
11273 {
11274         struct jbd_revoke_record_s *record;
11275
11276         record = find_revoke_record(journal, blocknr);
11277         if (!record)
11278                 return 0;
11279         if (tid_gt(sequence, record->sequence))
11280                 return 0;
11281         return 1;
11282 }
11283
11284 /*
11285  * Finally, once recovery is over, we need to clear the revoke table so
11286  * that it can be reused by the running filesystem.
11287  */
11288
11289 void journal_clear_revoke(journal_t *journal)
11290 {
11291         int i;
11292         struct list_head *hash_list;
11293         struct jbd_revoke_record_s *record;
11294         struct jbd_revoke_table_s *revoke_var;
11295
11296         revoke_var = journal->j_revoke;
11297
11298         for (i = 0; i < revoke_var->hash_size; i++) {
11299                 hash_list = &revoke_var->hash_table[i];
11300                 while (!list_empty(hash_list)) {
11301                         record = (struct jbd_revoke_record_s*) hash_list->next;
11302                         list_del(&record->hash);
11303                         free(record);
11304                 }
11305         }
11306 }
11307
11308 /*
11309  * e2fsck.c - superblock checks
11310  */
11311
11312 #define MIN_CHECK 1
11313 #define MAX_CHECK 2
11314
11315 static void check_super_value(e2fsck_t ctx, const char *descr,
11316                               unsigned long value, int flags,
11317                               unsigned long min_val, unsigned long max_val)
11318 {
11319         struct          problem_context pctx;
11320
11321         if (((flags & MIN_CHECK) && (value < min_val)) ||
11322             ((flags & MAX_CHECK) && (value > max_val))) {
11323                 clear_problem_context(&pctx);
11324                 pctx.num = value;
11325                 pctx.str = descr;
11326                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11327                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11328         }
11329 }
11330
11331 /*
11332  * This routine may get stubbed out in special compilations of the
11333  * e2fsck code..
11334  */
11335 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11336 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11337 {
11338         return (ext2fs_get_device_size(ctx->filesystem_name,
11339                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11340                                        &ctx->num_blocks));
11341 }
11342 #endif
11343
11344 /*
11345  * helper function to release an inode
11346  */
11347 struct process_block_struct {
11348         e2fsck_t        ctx;
11349         char            *buf;
11350         struct problem_context *pctx;
11351         int             truncating;
11352         int             truncate_offset;
11353         e2_blkcnt_t     truncate_block;
11354         int             truncated_blocks;
11355         int             abort;
11356         errcode_t       errcode;
11357 };
11358
11359 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11360                                e2_blkcnt_t blockcnt,
11361                                blk_t    ref_blk FSCK_ATTR((unused)),
11362                                int      ref_offset FSCK_ATTR((unused)),
11363                                void *priv_data)
11364 {
11365         struct process_block_struct *pb;
11366         e2fsck_t                ctx;
11367         struct problem_context  *pctx;
11368         blk_t                   blk = *block_nr;
11369         int                     retval = 0;
11370
11371         pb = (struct process_block_struct *) priv_data;
11372         ctx = pb->ctx;
11373         pctx = pb->pctx;
11374
11375         pctx->blk = blk;
11376         pctx->blkcount = blockcnt;
11377
11378         if (HOLE_BLKADDR(blk))
11379                 return 0;
11380
11381         if ((blk < fs->super->s_first_data_block) ||
11382             (blk >= fs->super->s_blocks_count)) {
11383                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11384         return_abort:
11385                 pb->abort = 1;
11386                 return BLOCK_ABORT;
11387         }
11388
11389         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11390                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11391                 goto return_abort;
11392         }
11393
11394         /*
11395          * If we are deleting an orphan, then we leave the fields alone.
11396          * If we are truncating an orphan, then update the inode fields
11397          * and clean up any partial block data.
11398          */
11399         if (pb->truncating) {
11400                 /*
11401                  * We only remove indirect blocks if they are
11402                  * completely empty.
11403                  */
11404                 if (blockcnt < 0) {
11405                         int     i, limit;
11406                         blk_t   *bp;
11407
11408                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11409                                                         pb->buf);
11410                         if (pb->errcode)
11411                                 goto return_abort;
11412
11413                         limit = fs->blocksize >> 2;
11414                         for (i = 0, bp = (blk_t *) pb->buf;
11415                              i < limit;  i++, bp++)
11416                                 if (*bp)
11417                                         return 0;
11418                 }
11419                 /*
11420                  * We don't remove direct blocks until we've reached
11421                  * the truncation block.
11422                  */
11423                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11424                         return 0;
11425                 /*
11426                  * If part of the last block needs truncating, we do
11427                  * it here.
11428                  */
11429                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11430                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11431                                                         pb->buf);
11432                         if (pb->errcode)
11433                                 goto return_abort;
11434                         memset(pb->buf + pb->truncate_offset, 0,
11435                                fs->blocksize - pb->truncate_offset);
11436                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11437                                                          pb->buf);
11438                         if (pb->errcode)
11439                                 goto return_abort;
11440                 }
11441                 pb->truncated_blocks++;
11442                 *block_nr = 0;
11443                 retval |= BLOCK_CHANGED;
11444         }
11445
11446         ext2fs_block_alloc_stats(fs, blk, -1);
11447         return retval;
11448 }
11449
11450 /*
11451  * This function releases an inode.  Returns 1 if an inconsistency was
11452  * found.  If the inode has a link count, then it is being truncated and
11453  * not deleted.
11454  */
11455 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11456                                 struct ext2_inode *inode, char *block_buf,
11457                                 struct problem_context *pctx)
11458 {
11459         struct process_block_struct     pb;
11460         ext2_filsys                     fs = ctx->fs;
11461         errcode_t                       retval;
11462         __u32                           count;
11463
11464         if (!ext2fs_inode_has_valid_blocks(inode))
11465                 return 0;
11466
11467         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11468         pb.ctx = ctx;
11469         pb.abort = 0;
11470         pb.errcode = 0;
11471         pb.pctx = pctx;
11472         if (inode->i_links_count) {
11473                 pb.truncating = 1;
11474                 pb.truncate_block = (e2_blkcnt_t)
11475                         ((((long long)inode->i_size_high << 32) +
11476                           inode->i_size + fs->blocksize - 1) /
11477                          fs->blocksize);
11478                 pb.truncate_offset = inode->i_size % fs->blocksize;
11479         } else {
11480                 pb.truncating = 0;
11481                 pb.truncate_block = 0;
11482                 pb.truncate_offset = 0;
11483         }
11484         pb.truncated_blocks = 0;
11485         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11486                                       block_buf, release_inode_block, &pb);
11487         if (retval) {
11488                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11489                         ino);
11490                 return 1;
11491         }
11492         if (pb.abort)
11493                 return 1;
11494
11495         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11496         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11497
11498         if (pb.truncated_blocks)
11499                 inode->i_blocks -= pb.truncated_blocks *
11500                         (fs->blocksize / 512);
11501
11502         if (inode->i_file_acl) {
11503                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11504                                                    block_buf, -1, &count);
11505                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11506                         retval = 0;
11507                         count = 1;
11508                 }
11509                 if (retval) {
11510                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11511                                 ino);
11512                         return 1;
11513                 }
11514                 if (count == 0)
11515                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11516                 inode->i_file_acl = 0;
11517         }
11518         return 0;
11519 }
11520
11521 /*
11522  * This function releases all of the orphan inodes.  It returns 1 if
11523  * it hit some error, and 0 on success.
11524  */
11525 static int release_orphan_inodes(e2fsck_t ctx)
11526 {
11527         ext2_filsys fs = ctx->fs;
11528         ext2_ino_t      ino, next_ino;
11529         struct ext2_inode inode;
11530         struct problem_context pctx;
11531         char *block_buf;
11532
11533         if ((ino = fs->super->s_last_orphan) == 0)
11534                 return 0;
11535
11536         /*
11537          * Win or lose, we won't be using the head of the orphan inode
11538          * list again.
11539          */
11540         fs->super->s_last_orphan = 0;
11541         ext2fs_mark_super_dirty(fs);
11542
11543         /*
11544          * If the filesystem contains errors, don't run the orphan
11545          * list, since the orphan list can't be trusted; and we're
11546          * going to be running a full e2fsck run anyway...
11547          */
11548         if (fs->super->s_state & EXT2_ERROR_FS)
11549                 return 0;
11550
11551         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11552             (ino > fs->super->s_inodes_count)) {
11553                 clear_problem_context(&pctx);
11554                 pctx.ino = ino;
11555                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11556                 return 1;
11557         }
11558
11559         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11560                                                     "block iterate buffer");
11561         e2fsck_read_bitmaps(ctx);
11562
11563         while (ino) {
11564                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11565                 clear_problem_context(&pctx);
11566                 pctx.ino = ino;
11567                 pctx.inode = &inode;
11568                 pctx.str = inode.i_links_count ? _("Truncating") :
11569                         _("Clearing");
11570
11571                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11572
11573                 next_ino = inode.i_dtime;
11574                 if (next_ino &&
11575                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11576                      (next_ino > fs->super->s_inodes_count))) {
11577                         pctx.ino = next_ino;
11578                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11579                         goto return_abort;
11580                 }
11581
11582                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11583                         goto return_abort;
11584
11585                 if (!inode.i_links_count) {
11586                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11587                                                   LINUX_S_ISDIR(inode.i_mode));
11588                         inode.i_dtime = time(0);
11589                 } else {
11590                         inode.i_dtime = 0;
11591                 }
11592                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11593                 ino = next_ino;
11594         }
11595         ext2fs_free_mem(&block_buf);
11596         return 0;
11597 return_abort:
11598         ext2fs_free_mem(&block_buf);
11599         return 1;
11600 }
11601
11602 /*
11603  * Check the resize inode to make sure it is sane.  We check both for
11604  * the case where on-line resizing is not enabled (in which case the
11605  * resize inode should be cleared) as well as the case where on-line
11606  * resizing is enabled.
11607  */
11608 static void check_resize_inode(e2fsck_t ctx)
11609 {
11610         ext2_filsys fs = ctx->fs;
11611         struct ext2_inode inode;
11612         struct problem_context  pctx;
11613         int             i, j, gdt_off, ind_off;
11614         blk_t           blk, pblk, expect;
11615         __u32           *dind_buf = 0, *ind_buf;
11616         errcode_t       retval;
11617
11618         clear_problem_context(&pctx);
11619
11620         /*
11621          * If the resize inode feature isn't set, then
11622          * s_reserved_gdt_blocks must be zero.
11623          */
11624         if (!(fs->super->s_feature_compat &
11625               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11626                 if (fs->super->s_reserved_gdt_blocks) {
11627                         pctx.num = fs->super->s_reserved_gdt_blocks;
11628                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11629                                         &pctx)) {
11630                                 fs->super->s_reserved_gdt_blocks = 0;
11631                                 ext2fs_mark_super_dirty(fs);
11632                         }
11633                 }
11634         }
11635
11636         /* Read the resize inode */
11637         pctx.ino = EXT2_RESIZE_INO;
11638         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11639         if (retval) {
11640                 if (fs->super->s_feature_compat &
11641                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11642                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11643                 return;
11644         }
11645
11646         /*
11647          * If the resize inode feature isn't set, check to make sure
11648          * the resize inode is cleared; then we're done.
11649          */
11650         if (!(fs->super->s_feature_compat &
11651               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11652                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11653                         if (inode.i_block[i])
11654                                 break;
11655                 }
11656                 if ((i < EXT2_N_BLOCKS) &&
11657                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11658                         memset(&inode, 0, sizeof(inode));
11659                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11660                                            "clear_resize");
11661                 }
11662                 return;
11663         }
11664
11665         /*
11666          * The resize inode feature is enabled; check to make sure the
11667          * only block in use is the double indirect block
11668          */
11669         blk = inode.i_block[EXT2_DIND_BLOCK];
11670         for (i=0; i < EXT2_N_BLOCKS; i++) {
11671                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11672                         break;
11673         }
11674         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11675             !(inode.i_mode & LINUX_S_IFREG) ||
11676             (blk < fs->super->s_first_data_block ||
11677              blk >= fs->super->s_blocks_count)) {
11678         resize_inode_invalid:
11679                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11680                         memset(&inode, 0, sizeof(inode));
11681                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11682                                            "clear_resize");
11683                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11684                 }
11685                 if (!(ctx->options & E2F_OPT_READONLY)) {
11686                         fs->super->s_state &= ~EXT2_VALID_FS;
11687                         ext2fs_mark_super_dirty(fs);
11688                 }
11689                 goto cleanup;
11690         }
11691         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11692                                                     "resize dind buffer");
11693         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11694
11695         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11696         if (retval)
11697                 goto resize_inode_invalid;
11698
11699         gdt_off = fs->desc_blocks;
11700         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11701         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11702              i++, gdt_off++, pblk++) {
11703                 gdt_off %= fs->blocksize/4;
11704                 if (dind_buf[gdt_off] != pblk)
11705                         goto resize_inode_invalid;
11706                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11707                 if (retval)
11708                         goto resize_inode_invalid;
11709                 ind_off = 0;
11710                 for (j = 1; j < fs->group_desc_count; j++) {
11711                         if (!ext2fs_bg_has_super(fs, j))
11712                                 continue;
11713                         expect = pblk + (j * fs->super->s_blocks_per_group);
11714                         if (ind_buf[ind_off] != expect)
11715                                 goto resize_inode_invalid;
11716                         ind_off++;
11717                 }
11718         }
11719
11720 cleanup:
11721         ext2fs_free_mem(&dind_buf);
11722
11723  }
11724
11725 static void check_super_block(e2fsck_t ctx)
11726 {
11727         ext2_filsys fs = ctx->fs;
11728         blk_t   first_block, last_block;
11729         struct ext2_super_block *sb = fs->super;
11730         struct ext2_group_desc *gd;
11731         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11732         blk_t   bpg_max;
11733         int     inodes_per_block;
11734         int     ipg_max;
11735         int     inode_size;
11736         dgrp_t  i;
11737         blk_t   should_be;
11738         struct problem_context  pctx;
11739         __u32   free_blocks = 0, free_inodes = 0;
11740
11741         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11742         ipg_max = inodes_per_block * (blocks_per_group - 4);
11743         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11744                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11745         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11746         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11747                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11748
11749         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11750                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11751         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11752                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11753         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11754                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11755
11756         clear_problem_context(&pctx);
11757
11758         /*
11759          * Verify the super block constants...
11760          */
11761         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11762                           MIN_CHECK, 1, 0);
11763         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11764                           MIN_CHECK, 1, 0);
11765         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11766                           MAX_CHECK, 0, sb->s_blocks_count);
11767         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11768                           MIN_CHECK | MAX_CHECK, 0,
11769                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11770         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11771                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11772         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11773                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11774                           bpg_max);
11775         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11776                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11777         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11778                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11779         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11780                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11781         check_super_value(ctx, "reserved_gdt_blocks",
11782                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11783                           fs->blocksize/4);
11784         inode_size = EXT2_INODE_SIZE(sb);
11785         check_super_value(ctx, "inode_size",
11786                           inode_size, MIN_CHECK | MAX_CHECK,
11787                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11788         if (inode_size & (inode_size - 1)) {
11789                 pctx.num = inode_size;
11790                 pctx.str = "inode_size";
11791                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11792                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11793                 return;
11794         }
11795
11796         if (!ctx->num_blocks) {
11797                 pctx.errcode = e2fsck_get_device_size(ctx);
11798                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11799                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11800                         ctx->flags |= E2F_FLAG_ABORT;
11801                         return;
11802                 }
11803                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11804                     (ctx->num_blocks < sb->s_blocks_count)) {
11805                         pctx.blk = sb->s_blocks_count;
11806                         pctx.blk2 = ctx->num_blocks;
11807                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11808                                 ctx->flags |= E2F_FLAG_ABORT;
11809                                 return;
11810                         }
11811                 }
11812         }
11813
11814         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11815                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11816                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11817                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11818                 ctx->flags |= E2F_FLAG_ABORT;
11819                 return;
11820         }
11821
11822         should_be = sb->s_frags_per_group >>
11823                 (sb->s_log_block_size - sb->s_log_frag_size);
11824         if (sb->s_blocks_per_group != should_be) {
11825                 pctx.blk = sb->s_blocks_per_group;
11826                 pctx.blk2 = should_be;
11827                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11828                 ctx->flags |= E2F_FLAG_ABORT;
11829                 return;
11830         }
11831
11832         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11833         if (sb->s_first_data_block != should_be) {
11834                 pctx.blk = sb->s_first_data_block;
11835                 pctx.blk2 = should_be;
11836                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11837                 ctx->flags |= E2F_FLAG_ABORT;
11838                 return;
11839         }
11840
11841         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11842         if (sb->s_inodes_count != should_be) {
11843                 pctx.ino = sb->s_inodes_count;
11844                 pctx.ino2 = should_be;
11845                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11846                         sb->s_inodes_count = should_be;
11847                         ext2fs_mark_super_dirty(fs);
11848                 }
11849         }
11850
11851         /*
11852          * Verify the group descriptors....
11853          */
11854         first_block =  sb->s_first_data_block;
11855         last_block = first_block + blocks_per_group;
11856
11857         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11858                 pctx.group = i;
11859
11860                 if (i == fs->group_desc_count - 1)
11861                         last_block = sb->s_blocks_count;
11862                 if ((gd->bg_block_bitmap < first_block) ||
11863                     (gd->bg_block_bitmap >= last_block)) {
11864                         pctx.blk = gd->bg_block_bitmap;
11865                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11866                                 gd->bg_block_bitmap = 0;
11867                 }
11868                 if (gd->bg_block_bitmap == 0) {
11869                         ctx->invalid_block_bitmap_flag[i]++;
11870                         ctx->invalid_bitmaps++;
11871                 }
11872                 if ((gd->bg_inode_bitmap < first_block) ||
11873                     (gd->bg_inode_bitmap >= last_block)) {
11874                         pctx.blk = gd->bg_inode_bitmap;
11875                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11876                                 gd->bg_inode_bitmap = 0;
11877                 }
11878                 if (gd->bg_inode_bitmap == 0) {
11879                         ctx->invalid_inode_bitmap_flag[i]++;
11880                         ctx->invalid_bitmaps++;
11881                 }
11882                 if ((gd->bg_inode_table < first_block) ||
11883                     ((gd->bg_inode_table +
11884                       fs->inode_blocks_per_group - 1) >= last_block)) {
11885                         pctx.blk = gd->bg_inode_table;
11886                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11887                                 gd->bg_inode_table = 0;
11888                 }
11889                 if (gd->bg_inode_table == 0) {
11890                         ctx->invalid_inode_table_flag[i]++;
11891                         ctx->invalid_bitmaps++;
11892                 }
11893                 free_blocks += gd->bg_free_blocks_count;
11894                 free_inodes += gd->bg_free_inodes_count;
11895                 first_block += sb->s_blocks_per_group;
11896                 last_block += sb->s_blocks_per_group;
11897
11898                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11899                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11900                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11901                         ext2fs_unmark_valid(fs);
11902
11903         }
11904
11905         /*
11906          * Update the global counts from the block group counts.  This
11907          * is needed for an experimental patch which eliminates
11908          * locking the entire filesystem when allocating blocks or
11909          * inodes; if the filesystem is not unmounted cleanly, the
11910          * global counts may not be accurate.
11911          */
11912         if ((free_blocks != sb->s_free_blocks_count) ||
11913             (free_inodes != sb->s_free_inodes_count)) {
11914                 if (ctx->options & E2F_OPT_READONLY)
11915                         ext2fs_unmark_valid(fs);
11916                 else {
11917                         sb->s_free_blocks_count = free_blocks;
11918                         sb->s_free_inodes_count = free_inodes;
11919                         ext2fs_mark_super_dirty(fs);
11920                 }
11921         }
11922
11923         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11924             (sb->s_free_inodes_count > sb->s_inodes_count))
11925                 ext2fs_unmark_valid(fs);
11926
11927
11928         /*
11929          * If we have invalid bitmaps, set the error state of the
11930          * filesystem.
11931          */
11932         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11933                 sb->s_state &= ~EXT2_VALID_FS;
11934                 ext2fs_mark_super_dirty(fs);
11935         }
11936
11937         clear_problem_context(&pctx);
11938
11939         /*
11940          * If the UUID field isn't assigned, assign it.
11941          */
11942         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11943                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11944                         uuid_generate(sb->s_uuid);
11945                         ext2fs_mark_super_dirty(fs);
11946                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11947                 }
11948         }
11949
11950         /* FIXME - HURD support?
11951          * For the Hurd, check to see if the filetype option is set,
11952          * since it doesn't support it.
11953          */
11954         if (!(ctx->options & E2F_OPT_READONLY) &&
11955             fs->super->s_creator_os == EXT2_OS_HURD &&
11956             (fs->super->s_feature_incompat &
11957              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11958                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11959                         fs->super->s_feature_incompat &=
11960                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11961                         ext2fs_mark_super_dirty(fs);
11962
11963                 }
11964         }
11965
11966         /*
11967          * If we have any of the compatibility flags set, we need to have a
11968          * revision 1 filesystem.  Most kernels will not check the flags on
11969          * a rev 0 filesystem and we may have corruption issues because of
11970          * the incompatible changes to the filesystem.
11971          */
11972         if (!(ctx->options & E2F_OPT_READONLY) &&
11973             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11974             (fs->super->s_feature_compat ||
11975              fs->super->s_feature_ro_compat ||
11976              fs->super->s_feature_incompat) &&
11977             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11978                 ext2fs_update_dynamic_rev(fs);
11979                 ext2fs_mark_super_dirty(fs);
11980         }
11981
11982         check_resize_inode(ctx);
11983
11984         /*
11985          * Clean up any orphan inodes, if present.
11986          */
11987         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11988                 fs->super->s_state &= ~EXT2_VALID_FS;
11989                 ext2fs_mark_super_dirty(fs);
11990         }
11991
11992         /*
11993          * Move the ext3 journal file, if necessary.
11994          */
11995         e2fsck_move_ext3_journal(ctx);
11996         return;
11997 }
11998
11999 /*
12000  * swapfs.c --- byte-swap an ext2 filesystem
12001  */
12002
12003 #ifdef ENABLE_SWAPFS
12004
12005 struct swap_block_struct {
12006         ext2_ino_t      ino;
12007         int             isdir;
12008         errcode_t       errcode;
12009         char            *dir_buf;
12010         struct ext2_inode *inode;
12011 };
12012
12013 /*
12014  * This is a helper function for block_iterate.  We mark all of the
12015  * indirect and direct blocks as changed, so that block_iterate will
12016  * write them out.
12017  */
12018 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
12019                       void *priv_data)
12020 {
12021         errcode_t       retval;
12022
12023         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
12024
12025         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
12026                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
12027                 if (retval) {
12028                         sb->errcode = retval;
12029                         return BLOCK_ABORT;
12030                 }
12031                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
12032                 if (retval) {
12033                         sb->errcode = retval;
12034                         return BLOCK_ABORT;
12035                 }
12036         }
12037         if (blockcnt >= 0) {
12038                 if (blockcnt < EXT2_NDIR_BLOCKS)
12039                         return 0;
12040                 return BLOCK_CHANGED;
12041         }
12042         if (blockcnt == BLOCK_COUNT_IND) {
12043                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
12044                         return 0;
12045                 return BLOCK_CHANGED;
12046         }
12047         if (blockcnt == BLOCK_COUNT_DIND) {
12048                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12049                         return 0;
12050                 return BLOCK_CHANGED;
12051         }
12052         if (blockcnt == BLOCK_COUNT_TIND) {
12053                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12054                         return 0;
12055                 return BLOCK_CHANGED;
12056         }
12057         return BLOCK_CHANGED;
12058 }
12059
12060 /*
12061  * This function is responsible for byte-swapping all of the indirect,
12062  * block pointers.  It is also responsible for byte-swapping directories.
12063  */
12064 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12065                               struct ext2_inode *inode)
12066 {
12067         errcode_t                       retval;
12068         struct swap_block_struct        sb;
12069
12070         sb.ino = ino;
12071         sb.inode = inode;
12072         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12073         sb.errcode = 0;
12074         sb.isdir = 0;
12075         if (LINUX_S_ISDIR(inode->i_mode))
12076                 sb.isdir = 1;
12077
12078         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12079                                       swap_block, &sb);
12080         if (retval) {
12081                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12082                 ctx->flags |= E2F_FLAG_ABORT;
12083                 return;
12084         }
12085         if (sb.errcode) {
12086                 bb_error_msg(_("while calling iterator function"));
12087                 ctx->flags |= E2F_FLAG_ABORT;
12088                 return;
12089         }
12090 }
12091
12092 static void swap_inodes(e2fsck_t ctx)
12093 {
12094         ext2_filsys fs = ctx->fs;
12095         dgrp_t                  group;
12096         unsigned int            i;
12097         ext2_ino_t              ino = 1;
12098         char                    *buf, *block_buf;
12099         errcode_t               retval;
12100         struct ext2_inode *     inode;
12101
12102         e2fsck_use_inode_shortcuts(ctx, 1);
12103
12104         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12105                                 &buf);
12106         if (retval) {
12107                 bb_error_msg(_("while allocating inode buffer"));
12108                 ctx->flags |= E2F_FLAG_ABORT;
12109                 return;
12110         }
12111         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12112                                                     "block interate buffer");
12113         for (group = 0; group < fs->group_desc_count; group++) {
12114                 retval = io_channel_read_blk(fs->io,
12115                       fs->group_desc[group].bg_inode_table,
12116                       fs->inode_blocks_per_group, buf);
12117                 if (retval) {
12118                         bb_error_msg(_("while reading inode table (group %d)"),
12119                                 group);
12120                         ctx->flags |= E2F_FLAG_ABORT;
12121                         return;
12122                 }
12123                 inode = (struct ext2_inode *) buf;
12124                 for (i=0; i < fs->super->s_inodes_per_group;
12125                      i++, ino++, inode++) {
12126                         ctx->stashed_ino = ino;
12127                         ctx->stashed_inode = inode;
12128
12129                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12130                                 ext2fs_swap_inode(fs, inode, inode, 0);
12131
12132                         /*
12133                          * Skip deleted files.
12134                          */
12135                         if (inode->i_links_count == 0)
12136                                 continue;
12137
12138                         if (LINUX_S_ISDIR(inode->i_mode) ||
12139                             ((inode->i_block[EXT2_IND_BLOCK] ||
12140                               inode->i_block[EXT2_DIND_BLOCK] ||
12141                               inode->i_block[EXT2_TIND_BLOCK]) &&
12142                              ext2fs_inode_has_valid_blocks(inode)))
12143                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12144
12145                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12146                                 return;
12147
12148                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12149                                 ext2fs_swap_inode(fs, inode, inode, 1);
12150                 }
12151                 retval = io_channel_write_blk(fs->io,
12152                       fs->group_desc[group].bg_inode_table,
12153                       fs->inode_blocks_per_group, buf);
12154                 if (retval) {
12155                         bb_error_msg(_("while writing inode table (group %d)"),
12156                                 group);
12157                         ctx->flags |= E2F_FLAG_ABORT;
12158                         return;
12159                 }
12160         }
12161         ext2fs_free_mem(&buf);
12162         ext2fs_free_mem(&block_buf);
12163         e2fsck_use_inode_shortcuts(ctx, 0);
12164         ext2fs_flush_icache(fs);
12165 }
12166
12167 #if defined(__powerpc__) && BB_BIG_ENDIAN
12168 /*
12169  * On the PowerPC, the big-endian variant of the ext2 filesystem
12170  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12171  * of each word.  Thus a bitmap with only bit 0 set would be, as
12172  * a string of bytes, 00 00 00 01 00 ...
12173  * To cope with this, we byte-reverse each word of a bitmap if
12174  * we have a big-endian filesystem, that is, if we are *not*
12175  * byte-swapping other word-sized numbers.
12176  */
12177 #define EXT2_BIG_ENDIAN_BITMAPS
12178 #endif
12179
12180 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12181 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12182 {
12183         __u32 *p = (__u32 *) bmap->bitmap;
12184         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12185
12186         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12187                 *p = ext2fs_swab32(*p);
12188 }
12189 #endif
12190
12191
12192 #ifdef ENABLE_SWAPFS
12193 static void swap_filesys(e2fsck_t ctx)
12194 {
12195         ext2_filsys fs = ctx->fs;
12196         if (!(ctx->options & E2F_OPT_PREEN))
12197                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12198
12199         /* Byte swap */
12200
12201         if (fs->super->s_mnt_count) {
12202                 fprintf(stderr, _("%s: the filesystem must be freshly "
12203                         "checked using fsck\n"
12204                         "and not mounted before trying to "
12205                         "byte-swap it.\n"), ctx->device_name);
12206                 ctx->flags |= E2F_FLAG_ABORT;
12207                 return;
12208         }
12209         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12210                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12211                                EXT2_FLAG_SWAP_BYTES_WRITE);
12212                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12213         } else {
12214                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12215                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12216         }
12217         swap_inodes(ctx);
12218         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12219                 return;
12220         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12221                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12222         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12223                        EXT2_FLAG_SWAP_BYTES_WRITE);
12224
12225 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12226         e2fsck_read_bitmaps(ctx);
12227         ext2fs_swap_bitmap(fs->inode_map);
12228         ext2fs_swap_bitmap(fs->block_map);
12229         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12230 #endif
12231         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12232         ext2fs_flush(fs);
12233         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12234 }
12235 #endif  /* ENABLE_SWAPFS */
12236
12237 #endif
12238
12239 /*
12240  * util.c --- miscellaneous utilities
12241  */
12242
12243
12244 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12245                              const char *description)
12246 {
12247         void *ret;
12248         char buf[256];
12249
12250         ret = malloc(size);
12251         if (!ret) {
12252                 sprintf(buf, "Can't allocate %s\n", description);
12253                 bb_error_msg_and_die(buf);
12254         }
12255         memset(ret, 0, size);
12256         return ret;
12257 }
12258
12259 static char *string_copy(const char *str, int len)
12260 {
12261         char    *ret;
12262
12263         if (!str)
12264                 return NULL;
12265         if (!len)
12266                 len = strlen(str);
12267         ret = malloc(len+1);
12268         if (ret) {
12269                 strncpy(ret, str, len);
12270                 ret[len] = 0;
12271         }
12272         return ret;
12273 }
12274
12275 #ifndef HAVE_CONIO_H
12276 static int read_a_char(void)
12277 {
12278         char    c;
12279         int     r;
12280         int     fail = 0;
12281
12282         while(1) {
12283                 if (e2fsck_global_ctx &&
12284                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12285                         return 3;
12286                 }
12287                 r = read(0, &c, 1);
12288                 if (r == 1)
12289                         return c;
12290                 if (fail++ > 100)
12291                         break;
12292         }
12293         return EOF;
12294 }
12295 #endif
12296
12297 static int ask_yn(const char * string, int def)
12298 {
12299         int             c;
12300         const char      *defstr;
12301         static const char short_yes[] = "yY";
12302         static const char short_no[] = "nN";
12303
12304 #ifdef HAVE_TERMIOS_H
12305         struct termios  termios, tmp;
12306
12307         tcgetattr (0, &termios);
12308         tmp = termios;
12309         tmp.c_lflag &= ~(ICANON | ECHO);
12310         tmp.c_cc[VMIN] = 1;
12311         tmp.c_cc[VTIME] = 0;
12312         tcsetattr (0, TCSANOW, &tmp);
12313 #endif
12314
12315         if (def == 1)
12316                 defstr = "<y>";
12317         else if (def == 0)
12318                 defstr = "<n>";
12319         else
12320                 defstr = " (y/n)";
12321         printf("%s%s? ", string, defstr);
12322         while (1) {
12323                 fflush (stdout);
12324                 if ((c = read_a_char()) == EOF)
12325                         break;
12326                 if (c == 3) {
12327 #ifdef HAVE_TERMIOS_H
12328                         tcsetattr (0, TCSANOW, &termios);
12329 #endif
12330                         if (e2fsck_global_ctx &&
12331                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12332                                 puts("\n");
12333                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12334                         }
12335                         puts(_("cancelled!\n"));
12336                         return 0;
12337                 }
12338                 if (strchr(short_yes, (char) c)) {
12339                         def = 1;
12340                         break;
12341                 }
12342                 else if (strchr(short_no, (char) c)) {
12343                         def = 0;
12344                         break;
12345                 }
12346                 else if ((c == ' ' || c == '\n') && (def != -1))
12347                         break;
12348         }
12349         if (def)
12350                 puts("yes\n");
12351         else
12352                 puts ("no\n");
12353 #ifdef HAVE_TERMIOS_H
12354         tcsetattr (0, TCSANOW, &termios);
12355 #endif
12356         return def;
12357 }
12358
12359 int ask (e2fsck_t ctx, const char * string, int def)
12360 {
12361         if (ctx->options & E2F_OPT_NO) {
12362                 printf (_("%s? no\n\n"), string);
12363                 return 0;
12364         }
12365         if (ctx->options & E2F_OPT_YES) {
12366                 printf (_("%s? yes\n\n"), string);
12367                 return 1;
12368         }
12369         if (ctx->options & E2F_OPT_PREEN) {
12370                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
12371                 return def;
12372         }
12373         return ask_yn(string, def);
12374 }
12375
12376 void e2fsck_read_bitmaps(e2fsck_t ctx)
12377 {
12378         ext2_filsys fs = ctx->fs;
12379         errcode_t       retval;
12380
12381         if (ctx->invalid_bitmaps) {
12382                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12383                         ctx->device_name);
12384                 bb_error_msg_and_die(0);
12385         }
12386
12387         ehandler_operation(_("reading inode and block bitmaps"));
12388         retval = ext2fs_read_bitmaps(fs);
12389         ehandler_operation(0);
12390         if (retval) {
12391                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12392                         ctx->device_name);
12393                 bb_error_msg_and_die(0);
12394         }
12395 }
12396
12397 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12398 {
12399         ext2_filsys fs = ctx->fs;
12400         errcode_t       retval;
12401
12402         if (ext2fs_test_bb_dirty(fs)) {
12403                 ehandler_operation(_("writing block bitmaps"));
12404                 retval = ext2fs_write_block_bitmap(fs);
12405                 ehandler_operation(0);
12406                 if (retval) {
12407                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12408                                 ctx->device_name);
12409                         bb_error_msg_and_die(0);
12410                 }
12411         }
12412
12413         if (ext2fs_test_ib_dirty(fs)) {
12414                 ehandler_operation(_("writing inode bitmaps"));
12415                 retval = ext2fs_write_inode_bitmap(fs);
12416                 ehandler_operation(0);
12417                 if (retval) {
12418                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12419                                 ctx->device_name);
12420                         bb_error_msg_and_die(0);
12421                 }
12422         }
12423 }
12424
12425 void preenhalt(e2fsck_t ctx)
12426 {
12427         ext2_filsys fs = ctx->fs;
12428
12429         if (!(ctx->options & E2F_OPT_PREEN))
12430                 return;
12431         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12432                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12433                ctx->device_name);
12434         if (fs != NULL) {
12435                 fs->super->s_state |= EXT2_ERROR_FS;
12436                 ext2fs_mark_super_dirty(fs);
12437                 ext2fs_close(fs);
12438         }
12439         exit(EXIT_UNCORRECTED);
12440 }
12441
12442 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12443                               struct ext2_inode * inode, const char *proc)
12444 {
12445         int retval;
12446
12447         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12448         if (retval) {
12449                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12450                 bb_error_msg_and_die(0);
12451         }
12452 }
12453
12454 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12455                                struct ext2_inode * inode, int bufsize,
12456                                const char *proc)
12457 {
12458         int retval;
12459
12460         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12461         if (retval) {
12462                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12463                 bb_error_msg_and_die(0);
12464         }
12465 }
12466
12467 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12468                                struct ext2_inode * inode, const char *proc)
12469 {
12470         int retval;
12471
12472         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12473         if (retval) {
12474                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12475                 bb_error_msg_and_die(0);
12476         }
12477 }
12478
12479 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12480                    io_manager manager)
12481 {
12482         struct ext2_super_block *sb;
12483         io_channel              io = NULL;
12484         void                    *buf = NULL;
12485         int                     blocksize;
12486         blk_t                   superblock, ret_sb = 8193;
12487
12488         if (fs && fs->super) {
12489                 ret_sb = (fs->super->s_blocks_per_group +
12490                           fs->super->s_first_data_block);
12491                 if (ctx) {
12492                         ctx->superblock = ret_sb;
12493                         ctx->blocksize = fs->blocksize;
12494                 }
12495                 return ret_sb;
12496         }
12497
12498         if (ctx) {
12499                 if (ctx->blocksize) {
12500                         ret_sb = ctx->blocksize * 8;
12501                         if (ctx->blocksize == 1024)
12502                                 ret_sb++;
12503                         ctx->superblock = ret_sb;
12504                         return ret_sb;
12505                 }
12506                 ctx->superblock = ret_sb;
12507                 ctx->blocksize = 1024;
12508         }
12509
12510         if (!name || !manager)
12511                 goto cleanup;
12512
12513         if (manager->open(name, 0, &io) != 0)
12514                 goto cleanup;
12515
12516         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12517                 goto cleanup;
12518         sb = (struct ext2_super_block *) buf;
12519
12520         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12521              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
12522                 superblock = blocksize*8;
12523                 if (blocksize == 1024)
12524                         superblock++;
12525                 io_channel_set_blksize(io, blocksize);
12526                 if (io_channel_read_blk(io, superblock,
12527                                         -SUPERBLOCK_SIZE, buf))
12528                         continue;
12529 #if BB_BIG_ENDIAN
12530                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12531                         ext2fs_swap_super(sb);
12532 #endif
12533                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12534                         ret_sb = superblock;
12535                         if (ctx) {
12536                                 ctx->superblock = superblock;
12537                                 ctx->blocksize = blocksize;
12538                         }
12539                         break;
12540                 }
12541         }
12542
12543 cleanup:
12544         if (io)
12545                 io_channel_close(io);
12546         ext2fs_free_mem(&buf);
12547         return (ret_sb);
12548 }
12549
12550
12551 /*
12552  * This function runs through the e2fsck passes and calls them all,
12553  * returning restart, abort, or cancel as necessary...
12554  */
12555 typedef void (*pass_t)(e2fsck_t ctx);
12556
12557 static const pass_t e2fsck_passes[] = {
12558         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12559         e2fsck_pass5, 0 };
12560
12561 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12562
12563 static int e2fsck_run(e2fsck_t ctx)
12564 {
12565         int     i;
12566         pass_t  e2fsck_pass;
12567
12568         if (setjmp(ctx->abort_loc)) {
12569                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12570                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12571         }
12572         ctx->flags |= E2F_FLAG_SETJMP_OK;
12573
12574         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12575                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12576                         break;
12577                 e2fsck_pass(ctx);
12578                 if (ctx->progress)
12579                         (void) (ctx->progress)(ctx, 0, 0, 0);
12580         }
12581         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12582
12583         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12584                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12585         return 0;
12586 }
12587
12588
12589 /*
12590  * unix.c - The unix-specific code for e2fsck
12591  */
12592
12593
12594 /* Command line options */
12595 static int swapfs;
12596 #ifdef ENABLE_SWAPFS
12597 static int normalize_swapfs;
12598 #endif
12599 static int cflag;               /* check disk */
12600 static int show_version_only;
12601 static int verbose;
12602
12603 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12604
12605 static void show_stats(e2fsck_t ctx)
12606 {
12607         ext2_filsys fs = ctx->fs;
12608         int inodes, inodes_used, blocks, blocks_used;
12609         int dir_links;
12610         int num_files, num_links;
12611         int frag_percent;
12612
12613         dir_links = 2 * ctx->fs_directory_count - 1;
12614         num_files = ctx->fs_total_count - dir_links;
12615         num_links = ctx->fs_links_count - dir_links;
12616         inodes = fs->super->s_inodes_count;
12617         inodes_used = (fs->super->s_inodes_count -
12618                        fs->super->s_free_inodes_count);
12619         blocks = fs->super->s_blocks_count;
12620         blocks_used = (fs->super->s_blocks_count -
12621                        fs->super->s_free_blocks_count);
12622
12623         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12624         frag_percent = (frag_percent + 5) / 10;
12625
12626         if (!verbose) {
12627                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12628                        ctx->device_name, inodes_used, inodes,
12629                        frag_percent / 10, frag_percent % 10,
12630                        blocks_used, blocks);
12631                 return;
12632         }
12633         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12634                 100 * inodes_used / inodes);
12635         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
12636                 P_E2("", "s", ctx->fs_fragmented),
12637                 frag_percent / 10, frag_percent % 10);
12638         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12639                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12640         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12641                 (int) ((long long) 100 * blocks_used / blocks));
12642         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12643         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12644         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12645         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12646         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12647         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12648         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12649         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12650         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12651         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12652         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12653 }
12654
12655 static void check_mount(e2fsck_t ctx)
12656 {
12657         errcode_t       retval;
12658         int             cont;
12659
12660         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12661                                          &ctx->mount_flags);
12662         if (retval) {
12663                 bb_error_msg(_("while determining whether %s is mounted."),
12664                         ctx->filesystem_name);
12665                 return;
12666         }
12667
12668         /*
12669          * If the filesystem isn't mounted, or it's the root filesystem
12670          * and it's mounted read-only, then everything's fine.
12671          */
12672         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12673             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12674              (ctx->mount_flags & EXT2_MF_READONLY)))
12675                 return;
12676
12677         if (ctx->options & E2F_OPT_READONLY) {
12678                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12679                 return;
12680         }
12681
12682         printf(_("%s is mounted.  "), ctx->filesystem_name);
12683         if (!ctx->interactive)
12684                 bb_error_msg_and_die(_("Cannot continue, aborting.\n\n"));
12685         printf(_("\n\n\007\007\007\007WARNING!!!  "
12686                "Running e2fsck on a mounted filesystem may cause\n"
12687                "SEVERE filesystem damage.\007\007\007\n\n"));
12688         cont = ask_yn(_("Do you really want to continue"), -1);
12689         if (!cont) {
12690                 printf (_("check aborted.\n"));
12691                 exit (0);
12692         }
12693         return;
12694 }
12695
12696 static int is_on_batt(void)
12697 {
12698         FILE    *f;
12699         DIR     *d;
12700         char    tmp[80], tmp2[80], fname[80];
12701         unsigned int    acflag;
12702         struct dirent*  de;
12703
12704         f = fopen("/proc/apm", "r");
12705         if (f) {
12706                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12707                         acflag = 1;
12708                 fclose(f);
12709                 return (acflag != 1);
12710         }
12711         d = opendir("/proc/acpi/ac_adapter");
12712         if (d) {
12713                 while ((de=readdir(d)) != NULL) {
12714                         if (!strncmp(".", de->d_name, 1))
12715                                 continue;
12716                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12717                                  de->d_name);
12718                         f = fopen(fname, "r");
12719                         if (!f)
12720                                 continue;
12721                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12722                                 tmp[0] = 0;
12723                         fclose(f);
12724                         if (strncmp(tmp, "off-line", 8) == 0) {
12725                                 closedir(d);
12726                                 return 1;
12727                         }
12728                 }
12729                 closedir(d);
12730         }
12731         return 0;
12732 }
12733
12734 /*
12735  * This routine checks to see if a filesystem can be skipped; if so,
12736  * it will exit with EXIT_OK.  Under some conditions it will print a
12737  * message explaining why a check is being forced.
12738  */
12739 static void check_if_skip(e2fsck_t ctx)
12740 {
12741         ext2_filsys fs = ctx->fs;
12742         const char *reason = NULL;
12743         unsigned int reason_arg = 0;
12744         long next_check;
12745         int batt = is_on_batt();
12746         time_t now = time(0);
12747
12748         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12749                 return;
12750
12751         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12752             !ext2fs_test_valid(fs))
12753                 reason = _(" contains a file system with errors");
12754         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12755                 reason = _(" was not cleanly unmounted");
12756         else if ((fs->super->s_max_mnt_count > 0) &&
12757                  (fs->super->s_mnt_count >=
12758                   (unsigned) fs->super->s_max_mnt_count)) {
12759                 reason = _(" has been mounted %u times without being checked");
12760                 reason_arg = fs->super->s_mnt_count;
12761                 if (batt && (fs->super->s_mnt_count <
12762                              (unsigned) fs->super->s_max_mnt_count*2))
12763                         reason = 0;
12764         } else if (fs->super->s_checkinterval &&
12765                    ((now - fs->super->s_lastcheck) >=
12766                     fs->super->s_checkinterval)) {
12767                 reason = _(" has gone %u days without being checked");
12768                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12769                 if (batt && ((now - fs->super->s_lastcheck) <
12770                              fs->super->s_checkinterval*2))
12771                         reason = 0;
12772         }
12773         if (reason) {
12774                 fputs(ctx->device_name, stdout);
12775                 printf(reason, reason_arg);
12776                 fputs(_(", check forced.\n"), stdout);
12777                 return;
12778         }
12779         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12780                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12781                fs->super->s_inodes_count,
12782                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12783                fs->super->s_blocks_count);
12784         next_check = 100000;
12785         if (fs->super->s_max_mnt_count > 0) {
12786                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12787                 if (next_check <= 0)
12788                         next_check = 1;
12789         }
12790         if (fs->super->s_checkinterval &&
12791             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12792                 next_check = 1;
12793         if (next_check <= 5) {
12794                 if (next_check == 1)
12795                         fputs(_(" (check after next mount)"), stdout);
12796                 else
12797                         printf(_(" (check in %ld mounts)"), next_check);
12798         }
12799         fputc('\n', stdout);
12800         ext2fs_close(fs);
12801         ctx->fs = NULL;
12802         e2fsck_free_context(ctx);
12803         exit(EXIT_OK);
12804 }
12805
12806 /*
12807  * For completion notice
12808  */
12809 struct percent_tbl {
12810         int     max_pass;
12811         int     table[32];
12812 };
12813 static const struct percent_tbl e2fsck_tbl = {
12814         5, { 0, 70, 90, 92,  95, 100 }
12815 };
12816
12817 static char bar[128], spaces[128];
12818
12819 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12820                           int max)
12821 {
12822         float   percent;
12823
12824         if (pass <= 0)
12825                 return 0.0;
12826         if (pass > tbl->max_pass || max == 0)
12827                 return 100.0;
12828         percent = ((float) curr) / ((float) max);
12829         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12830                 + tbl->table[pass-1]);
12831 }
12832
12833 void e2fsck_clear_progbar(e2fsck_t ctx)
12834 {
12835         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12836                 return;
12837
12838         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12839                ctx->stop_meta);
12840         fflush(stdout);
12841         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12842 }
12843
12844 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12845                            unsigned int dpynum)
12846 {
12847         static const char spinner[] = "\\|/-";
12848         int     i;
12849         unsigned int    tick;
12850         struct timeval  tv;
12851         int dpywidth;
12852         int fixed_percent;
12853
12854         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12855                 return 0;
12856
12857         /*
12858          * Calculate the new progress position.  If the
12859          * percentage hasn't changed, then we skip out right
12860          * away.
12861          */
12862         fixed_percent = (int) ((10 * percent) + 0.5);
12863         if (ctx->progress_last_percent == fixed_percent)
12864                 return 0;
12865         ctx->progress_last_percent = fixed_percent;
12866
12867         /*
12868          * If we've already updated the spinner once within
12869          * the last 1/8th of a second, no point doing it
12870          * again.
12871          */
12872         gettimeofday(&tv, NULL);
12873         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12874         if ((tick == ctx->progress_last_time) &&
12875             (fixed_percent != 0) && (fixed_percent != 1000))
12876                 return 0;
12877         ctx->progress_last_time = tick;
12878
12879         /*
12880          * Advance the spinner, and note that the progress bar
12881          * will be on the screen
12882          */
12883         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12884         ctx->flags |= E2F_FLAG_PROG_BAR;
12885
12886         dpywidth = 66 - strlen(label);
12887         dpywidth = 8 * (dpywidth / 8);
12888         if (dpynum)
12889                 dpywidth -= 8;
12890
12891         i = ((percent * dpywidth) + 50) / 100;
12892         printf("%s%s: |%s%s", ctx->start_meta, label,
12893                bar + (sizeof(bar) - (i+1)),
12894                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12895         if (fixed_percent == 1000)
12896                 fputc('|', stdout);
12897         else
12898                 fputc(spinner[ctx->progress_pos & 3], stdout);
12899         printf(" %4.1f%%  ", percent);
12900         if (dpynum)
12901                 printf("%u\r", dpynum);
12902         else
12903                 fputs(" \r", stdout);
12904         fputs(ctx->stop_meta, stdout);
12905
12906         if (fixed_percent == 1000)
12907                 e2fsck_clear_progbar(ctx);
12908         fflush(stdout);
12909
12910         return 0;
12911 }
12912
12913 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12914                                   unsigned long cur, unsigned long max)
12915 {
12916         char buf[80];
12917         float percent;
12918
12919         if (pass == 0)
12920                 return 0;
12921
12922         if (ctx->progress_fd) {
12923                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12924                 write(ctx->progress_fd, buf, strlen(buf));
12925         } else {
12926                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12927                 e2fsck_simple_progress(ctx, ctx->device_name,
12928                                        percent, 0);
12929         }
12930         return 0;
12931 }
12932
12933 static void reserve_stdio_fds(void)
12934 {
12935         int     fd;
12936
12937         while (1) {
12938                 fd = open(bb_dev_null, O_RDWR);
12939                 if (fd > 2)
12940                         break;
12941                 if (fd < 0) {
12942                         fprintf(stderr, _("ERROR: Couldn't open "
12943                                 "/dev/null (%s)\n"),
12944                                 strerror(errno));
12945                         break;
12946                 }
12947         }
12948         close(fd);
12949 }
12950
12951 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12952 {
12953         e2fsck_t ctx = e2fsck_global_ctx;
12954
12955         if (!ctx)
12956                 return;
12957
12958         ctx->progress = e2fsck_update_progress;
12959         ctx->progress_fd = 0;
12960 }
12961
12962 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12963 {
12964         e2fsck_t ctx = e2fsck_global_ctx;
12965
12966         if (!ctx)
12967                 return;
12968
12969         e2fsck_clear_progbar(ctx);
12970         ctx->progress = 0;
12971 }
12972
12973 static void signal_cancel(int sig FSCK_ATTR((unused)))
12974 {
12975         e2fsck_t ctx = e2fsck_global_ctx;
12976
12977         if (!ctx)
12978                 exit(FSCK_CANCELED);
12979
12980         ctx->flags |= E2F_FLAG_CANCEL;
12981 }
12982
12983 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12984 {
12985         char    *buf, *token, *next, *p, *arg;
12986         int     ea_ver;
12987         int     extended_usage = 0;
12988
12989         buf = string_copy(opts, 0);
12990         for (token = buf; token && *token; token = next) {
12991                 p = strchr(token, ',');
12992                 next = 0;
12993                 if (p) {
12994                         *p = 0;
12995                         next = p+1;
12996                 }
12997                 arg = strchr(token, '=');
12998                 if (arg) {
12999                         *arg = 0;
13000                         arg++;
13001                 }
13002                 if (strcmp(token, "ea_ver") == 0) {
13003                         if (!arg) {
13004                                 extended_usage++;
13005                                 continue;
13006                         }
13007                         ea_ver = strtoul(arg, &p, 0);
13008                         if (*p ||
13009                             ((ea_ver != 1) && (ea_ver != 2))) {
13010                                 fprintf(stderr,
13011                                         _("Invalid EA version.\n"));
13012                                 extended_usage++;
13013                                 continue;
13014                         }
13015                         ctx->ext_attr_ver = ea_ver;
13016                 } else {
13017                         fprintf(stderr, _("Unknown extended option: %s\n"),
13018                                 token);
13019                         extended_usage++;
13020                 }
13021         }
13022         if (extended_usage) {
13023                 bb_error_msg_and_die(
13024                         "Extended options are separated by commas, "
13025                         "and may take an argument which\n"
13026                         "is set off by an equals ('=') sign.  "
13027                         "Valid extended options are:\n"
13028                         "\tea_ver=<ea_version (1 or 2)>\n\n");
13029         }
13030 }
13031
13032
13033 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
13034 {
13035         int             flush = 0;
13036         int             c, fd;
13037         e2fsck_t        ctx;
13038         errcode_t       retval;
13039         struct sigaction        sa;
13040         char            *extended_opts = 0;
13041
13042         retval = e2fsck_allocate_context(&ctx);
13043         if (retval)
13044                 return retval;
13045
13046         *ret_ctx = ctx;
13047
13048         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
13049         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
13050         if (isatty(0) && isatty(1)) {
13051                 ctx->interactive = 1;
13052         } else {
13053                 ctx->start_meta[0] = '\001';
13054                 ctx->stop_meta[0] = '\002';
13055         }
13056         memset(bar, '=', sizeof(bar)-1);
13057         memset(spaces, ' ', sizeof(spaces)-1);
13058         blkid_get_cache(&ctx->blkid, NULL);
13059
13060         if (argc && *argv)
13061                 ctx->program_name = *argv;
13062         else
13063                 ctx->program_name = "e2fsck";
13064         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13065                 switch (c) {
13066                 case 'C':
13067                         ctx->progress = e2fsck_update_progress;
13068                         ctx->progress_fd = atoi(optarg);
13069                         if (!ctx->progress_fd)
13070                                 break;
13071                         /* Validate the file descriptor to avoid disasters */
13072                         fd = dup(ctx->progress_fd);
13073                         if (fd < 0) {
13074                                 fprintf(stderr,
13075                                 _("Error validating file descriptor %d: %s\n"),
13076                                         ctx->progress_fd,
13077                                         error_message(errno));
13078                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13079                         } else
13080                                 close(fd);
13081                         break;
13082                 case 'D':
13083                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13084                         break;
13085                 case 'E':
13086                         extended_opts = optarg;
13087                         break;
13088                 case 'p':
13089                 case 'a':
13090                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13091                         conflict_opt:
13092                                 bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
13093                         }
13094                         ctx->options |= E2F_OPT_PREEN;
13095                         break;
13096                 case 'n':
13097                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13098                                 goto conflict_opt;
13099                         ctx->options |= E2F_OPT_NO;
13100                         break;
13101                 case 'y':
13102                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13103                                 goto conflict_opt;
13104                         ctx->options |= E2F_OPT_YES;
13105                         break;
13106                 case 't':
13107                         /* FIXME - This needs to go away in a future path - will change binary */
13108                         fprintf(stderr, _("The -t option is not "
13109                                 "supported on this version of e2fsck.\n"));
13110                         break;
13111                 case 'c':
13112                         if (cflag++)
13113                                 ctx->options |= E2F_OPT_WRITECHECK;
13114                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13115                         break;
13116                 case 'r':
13117                         /* What we do by default, anyway! */
13118                         break;
13119                 case 'b':
13120                         ctx->use_superblock = atoi(optarg);
13121                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13122                         break;
13123                 case 'B':
13124                         ctx->blocksize = atoi(optarg);
13125                         break;
13126                 case 'I':
13127                         ctx->inode_buffer_blocks = atoi(optarg);
13128                         break;
13129                 case 'j':
13130                         ctx->journal_name = string_copy(optarg, 0);
13131                         break;
13132                 case 'P':
13133                         ctx->process_inode_size = atoi(optarg);
13134                         break;
13135                 case 'd':
13136                         ctx->options |= E2F_OPT_DEBUG;
13137                         break;
13138                 case 'f':
13139                         ctx->options |= E2F_OPT_FORCE;
13140                         break;
13141                 case 'F':
13142                         flush = 1;
13143                         break;
13144                 case 'v':
13145                         verbose = 1;
13146                         break;
13147                 case 'V':
13148                         show_version_only = 1;
13149                         break;
13150                 case 'N':
13151                         ctx->device_name = optarg;
13152                         break;
13153 #ifdef ENABLE_SWAPFS
13154                 case 's':
13155                         normalize_swapfs = 1;
13156                 case 'S':
13157                         swapfs = 1;
13158                         break;
13159 #else
13160                 case 's':
13161                 case 'S':
13162                         fprintf(stderr, _("Byte-swapping filesystems "
13163                                           "not compiled in this version "
13164                                           "of e2fsck\n"));
13165                         exit(1);
13166 #endif
13167                 default:
13168                         bb_show_usage();
13169                 }
13170         if (show_version_only)
13171                 return 0;
13172         if (optind != argc - 1)
13173                 bb_show_usage();
13174         if ((ctx->options & E2F_OPT_NO) &&
13175             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13176                 ctx->options |= E2F_OPT_READONLY;
13177         ctx->io_options = strchr(argv[optind], '?');
13178         if (ctx->io_options)
13179                 *ctx->io_options++ = 0;
13180         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13181         if (!ctx->filesystem_name) {
13182                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13183                 bb_error_msg_and_die(0);
13184         }
13185         if (extended_opts)
13186                 parse_extended_opts(ctx, extended_opts);
13187
13188         if (flush) {
13189                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13190                 if (fd < 0) {
13191                         bb_error_msg(_("while opening %s for flushing"),
13192                                 ctx->filesystem_name);
13193                         bb_error_msg_and_die(0);
13194                 }
13195                 if ((retval = ext2fs_sync_device(fd, 1))) {
13196                         bb_error_msg(_("while trying to flush %s"),
13197                                 ctx->filesystem_name);
13198                         bb_error_msg_and_die(0);
13199                 }
13200                 close(fd);
13201         }
13202 #ifdef ENABLE_SWAPFS
13203         if (swapfs && cflag) {
13204                         fprintf(stderr, _("Incompatible options not "
13205                                           "allowed when byte-swapping.\n"));
13206                         exit(EXIT_USAGE);
13207         }
13208 #endif
13209         /*
13210          * Set up signal action
13211          */
13212         memset(&sa, 0, sizeof(struct sigaction));
13213         sa.sa_handler = signal_cancel;
13214         sigaction(SIGINT, &sa, 0);
13215         sigaction(SIGTERM, &sa, 0);
13216 #ifdef SA_RESTART
13217         sa.sa_flags = SA_RESTART;
13218 #endif
13219         e2fsck_global_ctx = ctx;
13220         sa.sa_handler = signal_progress_on;
13221         sigaction(SIGUSR1, &sa, 0);
13222         sa.sa_handler = signal_progress_off;
13223         sigaction(SIGUSR2, &sa, 0);
13224
13225         /* Update our PATH to include /sbin if we need to run badblocks  */
13226         if (cflag)
13227                 e2fs_set_sbin_path();
13228         return 0;
13229 }
13230
13231 static const char my_ver_string[] = E2FSPROGS_VERSION;
13232 static const char my_ver_date[] = E2FSPROGS_DATE;
13233
13234 int e2fsck_main (int argc, char *argv[])
13235 {
13236         errcode_t       retval;
13237         int             exit_value = EXIT_OK;
13238         ext2_filsys     fs = 0;
13239         io_manager      io_ptr;
13240         struct ext2_super_block *sb;
13241         const char      *lib_ver_date;
13242         int             my_ver, lib_ver;
13243         e2fsck_t        ctx;
13244         struct problem_context pctx;
13245         int flags, run_result;
13246
13247         clear_problem_context(&pctx);
13248
13249         my_ver = ext2fs_parse_version_string(my_ver_string);
13250         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13251         if (my_ver > lib_ver) {
13252                 fprintf( stderr, _("Error: ext2fs library version "
13253                         "out of date!\n"));
13254                 show_version_only++;
13255         }
13256
13257         retval = PRS(argc, argv, &ctx);
13258         if (retval) {
13259                 bb_error_msg(_("while trying to initialize program"));
13260                 exit(EXIT_ERROR);
13261         }
13262         reserve_stdio_fds();
13263
13264         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13265                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13266                          my_ver_date);
13267
13268         if (show_version_only) {
13269                 fprintf(stderr, _("\tUsing %s, %s\n"),
13270                         error_message(EXT2_ET_BASE), lib_ver_date);
13271                 exit(EXIT_OK);
13272         }
13273
13274         check_mount(ctx);
13275
13276         if (!(ctx->options & E2F_OPT_PREEN) &&
13277             !(ctx->options & E2F_OPT_NO) &&
13278             !(ctx->options & E2F_OPT_YES)) {
13279                 if (!ctx->interactive)
13280                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13281         }
13282         ctx->superblock = ctx->use_superblock;
13283 restart:
13284 #ifdef CONFIG_TESTIO_DEBUG
13285         io_ptr = test_io_manager;
13286         test_io_backing_manager = unix_io_manager;
13287 #else
13288         io_ptr = unix_io_manager;
13289 #endif
13290         flags = 0;
13291         if ((ctx->options & E2F_OPT_READONLY) == 0)
13292                 flags |= EXT2_FLAG_RW;
13293
13294         if (ctx->superblock && ctx->blocksize) {
13295                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13296                                       flags, ctx->superblock, ctx->blocksize,
13297                                       io_ptr, &fs);
13298         } else if (ctx->superblock) {
13299                 int blocksize;
13300                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13301                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13302                         retval = ext2fs_open2(ctx->filesystem_name,
13303                                               ctx->io_options, flags,
13304                                               ctx->superblock, blocksize,
13305                                               io_ptr, &fs);
13306                         if (!retval)
13307                                 break;
13308                 }
13309         } else
13310                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13311                                       flags, 0, 0, io_ptr, &fs);
13312         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13313             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13314             ((retval == EXT2_ET_BAD_MAGIC) ||
13315              ((retval == 0) && ext2fs_check_desc(fs)))) {
13316                 if (!fs || (fs->group_desc_count > 1)) {
13317                         printf(_("%s trying backup blocks...\n"),
13318                                retval ? _("Couldn't find ext2 superblock,") :
13319                                _("Group descriptors look bad..."));
13320                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13321                         if (fs)
13322                                 ext2fs_close(fs);
13323                         goto restart;
13324                 }
13325         }
13326         if (retval) {
13327                 bb_error_msg(_("while trying to open %s"),
13328                         ctx->filesystem_name);
13329                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13330                         printf(_("The filesystem revision is apparently "
13331                                "too high for this version of e2fsck.\n"
13332                                "(Or the filesystem superblock "
13333                                "is corrupt)\n\n"));
13334                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13335                 } else if (retval == EXT2_ET_SHORT_READ)
13336                         printf(_("Could this be a zero-length partition?\n"));
13337                 else if ((retval == EPERM) || (retval == EACCES))
13338                         printf(_("You must have %s access to the "
13339                                "filesystem or be root\n"),
13340                                (ctx->options & E2F_OPT_READONLY) ?
13341                                "r/o" : "r/w");
13342                 else if (retval == ENXIO)
13343                         printf(_("Possibly non-existent or swap device?\n"));
13344 #ifdef EROFS
13345                 else if (retval == EROFS)
13346                         printf(_("Disk write-protected; use the -n option "
13347                                "to do a read-only\n"
13348                                "check of the device.\n"));
13349 #endif
13350                 else
13351                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13352                 bb_error_msg_and_die(0);
13353         }
13354         ctx->fs = fs;
13355         fs->priv_data = ctx;
13356         sb = fs->super;
13357         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13358                 bb_error_msg(_("while trying to open %s"),
13359                         ctx->filesystem_name);
13360         get_newer:
13361                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13362         }
13363
13364         /*
13365          * Set the device name, which is used whenever we print error
13366          * or informational messages to the user.
13367          */
13368         if (ctx->device_name == 0 &&
13369             (sb->s_volume_name[0] != 0)) {
13370                 ctx->device_name = string_copy(sb->s_volume_name,
13371                                                sizeof(sb->s_volume_name));
13372         }
13373         if (ctx->device_name == 0)
13374                 ctx->device_name = ctx->filesystem_name;
13375
13376         /*
13377          * Make sure the ext3 superblock fields are consistent.
13378          */
13379         retval = e2fsck_check_ext3_journal(ctx);
13380         if (retval) {
13381                 bb_error_msg(_("while checking ext3 journal for %s"),
13382                         ctx->device_name);
13383                 bb_error_msg_and_die(0);
13384         }
13385
13386         /*
13387          * Check to see if we need to do ext3-style recovery.  If so,
13388          * do it, and then restart the fsck.
13389          */
13390         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13391                 if (ctx->options & E2F_OPT_READONLY) {
13392                         printf(_("Warning: skipping journal recovery "
13393                                  "because doing a read-only filesystem "
13394                                  "check.\n"));
13395                         io_channel_flush(ctx->fs->io);
13396                 } else {
13397                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13398                                 /*
13399                                  * Whoops, we attempted to run the
13400                                  * journal twice.  This should never
13401                                  * happen, unless the hardware or
13402                                  * device driver is being bogus.
13403                                  */
13404                                 bb_error_msg(_("unable to set superblock flags on %s\n"), ctx->device_name);
13405                                 bb_error_msg_and_die(0);
13406                         }
13407                         retval = e2fsck_run_ext3_journal(ctx);
13408                         if (retval) {
13409                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13410                                         ctx->device_name);
13411                                 bb_error_msg_and_die(0);
13412                         }
13413                         ext2fs_close(ctx->fs);
13414                         ctx->fs = 0;
13415                         ctx->flags |= E2F_FLAG_RESTARTED;
13416                         goto restart;
13417                 }
13418         }
13419
13420         /*
13421          * Check for compatibility with the feature sets.  We need to
13422          * be more stringent than ext2fs_open().
13423          */
13424         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13425             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13426                 bb_error_msg("(%s)", ctx->device_name);
13427                 goto get_newer;
13428         }
13429         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13430                 bb_error_msg("(%s)", ctx->device_name);
13431                 goto get_newer;
13432         }
13433 #ifdef ENABLE_COMPRESSION
13434         /* FIXME - do we support this at all? */
13435         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13436                 bb_error_msg(_("Warning: compression support is experimental.\n"));
13437 #endif
13438 #ifndef ENABLE_HTREE
13439         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13440                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13441                           "but filesystem %s has HTREE directories.\n"),
13442                         ctx->device_name);
13443                 goto get_newer;
13444         }
13445 #endif
13446
13447         /*
13448          * If the user specified a specific superblock, presumably the
13449          * master superblock has been trashed.  So we mark the
13450          * superblock as dirty, so it can be written out.
13451          */
13452         if (ctx->superblock &&
13453             !(ctx->options & E2F_OPT_READONLY))
13454                 ext2fs_mark_super_dirty(fs);
13455
13456         /*
13457          * We only update the master superblock because (a) paranoia;
13458          * we don't want to corrupt the backup superblocks, and (b) we
13459          * don't need to update the mount count and last checked
13460          * fields in the backup superblock (the kernel doesn't
13461          * update the backup superblocks anyway).
13462          */
13463         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13464
13465         ehandler_init(fs->io);
13466
13467         if (ctx->superblock)
13468                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13469         ext2fs_mark_valid(fs);
13470         check_super_block(ctx);
13471         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13472                 bb_error_msg_and_die(0);
13473         check_if_skip(ctx);
13474         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13475                 bb_error_msg_and_die(0);
13476 #ifdef ENABLE_SWAPFS
13477
13478 #ifdef WORDS_BIGENDIAN
13479 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13480 #else
13481 #define NATIVE_FLAG 0
13482 #endif
13483
13484
13485         if (normalize_swapfs) {
13486                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13487                         fprintf(stderr, _("%s: Filesystem byte order "
13488                                 "already normalized.\n"), ctx->device_name);
13489                         bb_error_msg_and_die(0);
13490                 }
13491         }
13492         if (swapfs) {
13493                 swap_filesys(ctx);
13494                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13495                         bb_error_msg_and_die(0);
13496         }
13497 #endif
13498
13499         /*
13500          * Mark the system as valid, 'til proven otherwise
13501          */
13502         ext2fs_mark_valid(fs);
13503
13504         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13505         if (retval) {
13506                 bb_error_msg(_("while reading bad blocks inode"));
13507                 preenhalt(ctx);
13508                 printf(_("This doesn't bode well,"
13509                          " but we'll try to go on...\n"));
13510         }
13511
13512         run_result = e2fsck_run(ctx);
13513         e2fsck_clear_progbar(ctx);
13514         if (run_result == E2F_FLAG_RESTART) {
13515                 printf(_("Restarting e2fsck from the beginning...\n"));
13516                 retval = e2fsck_reset_context(ctx);
13517                 if (retval) {
13518                         bb_error_msg(_("while resetting context"));
13519                         bb_error_msg_and_die(0);
13520                 }
13521                 ext2fs_close(fs);
13522                 goto restart;
13523         }
13524         if (run_result & E2F_FLAG_CANCEL) {
13525                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13526                        ctx->device_name : ctx->filesystem_name);
13527                 exit_value |= FSCK_CANCELED;
13528         }
13529         if (run_result & E2F_FLAG_ABORT)
13530                 bb_error_msg_and_die(_("aborted"));
13531
13532         /* Cleanup */
13533         if (ext2fs_test_changed(fs)) {
13534                 exit_value |= EXIT_NONDESTRUCT;
13535                 if (!(ctx->options & E2F_OPT_PREEN))
13536                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13537                                ctx->device_name);
13538                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13539                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13540                                ctx->device_name);
13541                         exit_value |= EXIT_DESTRUCT;
13542                 }
13543         }
13544         if (!ext2fs_test_valid(fs)) {
13545                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13546                          "errors **********\n\n"), ctx->device_name);
13547                 exit_value |= EXIT_UNCORRECTED;
13548                 exit_value &= ~EXIT_NONDESTRUCT;
13549         }
13550         if (exit_value & FSCK_CANCELED)
13551                 exit_value &= ~EXIT_NONDESTRUCT;
13552         else {
13553                 show_stats(ctx);
13554                 if (!(ctx->options & E2F_OPT_READONLY)) {
13555                         if (ext2fs_test_valid(fs)) {
13556                                 if (!(sb->s_state & EXT2_VALID_FS))
13557                                         exit_value |= EXIT_NONDESTRUCT;
13558                                 sb->s_state = EXT2_VALID_FS;
13559                         } else
13560                                 sb->s_state &= ~EXT2_VALID_FS;
13561                         sb->s_mnt_count = 0;
13562                         sb->s_lastcheck = time(NULL);
13563                         ext2fs_mark_super_dirty(fs);
13564                 }
13565         }
13566
13567         e2fsck_write_bitmaps(ctx);
13568
13569         ext2fs_close(fs);
13570         ctx->fs = NULL;
13571         free(ctx->filesystem_name);
13572         free(ctx->journal_name);
13573         e2fsck_free_context(ctx);
13574
13575         return exit_value;
13576 }