Initial public busybox upstream commit
[busybox4maemo] / e2fsprogs / old_e2fsprogs / e2fsck.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * e2fsck
4  *
5  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6  * Copyright (C) 2006 Garrett Kajmowicz
7  *
8  * Dictionary Abstract Data Type
9  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10  * Free Software License:
11  * All rights are reserved by the author, with the following exceptions:
12  * Permission is granted to freely reproduce and distribute this software,
13  * possibly in exchange for a fee, provided that this copyright notice appears
14  * intact. Permission is also granted to adapt this software to produce
15  * derivative works, as long as the modified versions carry this copyright
16  * notice and additional notices stating that the work has been modified.
17  * This source code may be translated into executable form and incorporated
18  * into proprietary software; there is no requirement for such software to
19  * contain a copyright notice related to this source.
20  *
21  * linux/fs/recovery  and linux/fs/revoke
22  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23  *
24  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25  *
26  * Journal recovery routines for the generic filesystem journaling code;
27  * part of the ext2fs journaling system.
28  *
29  * Licensed under GPLv2 or later, see file License in this tarball for details.
30  */
31
32 #ifndef _GNU_SOURCE
33 #define _GNU_SOURCE 1 /* get strnlen() */
34 #endif
35
36 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
37
38 #define _(x) x
39 #define N_(x) x
40
41 /*
42  * Procedure declarations
43  */
44
45 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
46
47 /* pass1.c */
48 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
49
50 /* pass2.c */
51 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
52                                     ext2_ino_t ino, char *buf);
53
54 /* pass3.c */
55 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
56 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
57                                          int num, int gauranteed_size);
58 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
59 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
60                                            int adj);
61
62 /* rehash.c */
63 static void e2fsck_rehash_directories(e2fsck_t ctx);
64
65 /* util.c */
66 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
67                                     const char *description);
68 static int ask(e2fsck_t ctx, const char * string, int def);
69 static void e2fsck_read_bitmaps(e2fsck_t ctx);
70 static void preenhalt(e2fsck_t ctx);
71 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
72                               struct ext2_inode * inode, const char * proc);
73 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
74                                struct ext2_inode * inode, const char * proc);
75 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
76                            const char *name, io_manager manager);
77
78 /* unix.c */
79 static void e2fsck_clear_progbar(e2fsck_t ctx);
80 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
81                                   float percent, unsigned int dpynum);
82
83
84 /*
85  * problem.h --- e2fsck problem error codes
86  */
87
88 typedef __u32 problem_t;
89
90 struct problem_context {
91         errcode_t       errcode;
92         ext2_ino_t ino, ino2, dir;
93         struct ext2_inode *inode;
94         struct ext2_dir_entry *dirent;
95         blk_t   blk, blk2;
96         e2_blkcnt_t     blkcount;
97         int             group;
98         __u64   num;
99         const char *str;
100 };
101
102
103 /*
104  * Function declarations
105  */
106 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
107 static int end_problem_latch(e2fsck_t ctx, int mask);
108 static int set_latch_flags(int mask, int setflags, int clearflags);
109 static void clear_problem_context(struct problem_context *ctx);
110
111 /*
112  * Dictionary Abstract Data Type
113  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
114  *
115  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
116  * kazlib_1_20
117  */
118
119 #ifndef DICT_H
120 #define DICT_H
121
122 /*
123  * Blurb for inclusion into C++ translation units
124  */
125
126 typedef unsigned long dictcount_t;
127 #define DICTCOUNT_T_MAX ULONG_MAX
128
129 /*
130  * The dictionary is implemented as a red-black tree
131  */
132
133 typedef enum { dnode_red, dnode_black } dnode_color_t;
134
135 typedef struct dnode_t {
136     struct dnode_t *dict_left;
137     struct dnode_t *dict_right;
138     struct dnode_t *dict_parent;
139     dnode_color_t dict_color;
140     const void *dict_key;
141     void *dict_data;
142 } dnode_t;
143
144 typedef int (*dict_comp_t)(const void *, const void *);
145 typedef void (*dnode_free_t)(dnode_t *);
146
147 typedef struct dict_t {
148     dnode_t dict_nilnode;
149     dictcount_t dict_nodecount;
150     dictcount_t dict_maxcount;
151     dict_comp_t dict_compare;
152     dnode_free_t dict_freenode;
153     int dict_dupes;
154 } dict_t;
155
156 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
157
158 typedef struct dict_load_t {
159     dict_t *dict_dictptr;
160     dnode_t dict_nilnode;
161 } dict_load_t;
162
163 #define dict_count(D) ((D)->dict_nodecount)
164 #define dnode_get(N) ((N)->dict_data)
165 #define dnode_getkey(N) ((N)->dict_key)
166
167 #endif
168
169 /*
170  * Compatibility header file for e2fsck which should be included
171  * instead of linux/jfs.h
172  *
173  * Copyright (C) 2000 Stephen C. Tweedie
174  */
175
176 /*
177  * Pull in the definition of the e2fsck context structure
178  */
179
180 struct buffer_head {
181         char            b_data[8192];
182         e2fsck_t        b_ctx;
183         io_channel      b_io;
184         int             b_size;
185         blk_t           b_blocknr;
186         int             b_dirty;
187         int             b_uptodate;
188         int             b_err;
189 };
190
191
192 #define K_DEV_FS        1
193 #define K_DEV_JOURNAL   2
194
195 #define lock_buffer(bh) do {} while(0)
196 #define unlock_buffer(bh) do {} while(0)
197 #define buffer_req(bh) 1
198 #define do_readahead(journal, start) do {} while(0)
199
200 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
201
202 typedef struct {
203         int     object_length;
204 } kmem_cache_t;
205
206 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
207
208 /*
209  * We use the standard libext2fs portability tricks for inline
210  * functions.
211  */
212
213 static kmem_cache_t * do_cache_create(int len)
214 {
215         kmem_cache_t *new_cache;
216
217         new_cache = malloc(sizeof(*new_cache));
218         if (new_cache)
219                 new_cache->object_length = len;
220         return new_cache;
221 }
222
223 static void do_cache_destroy(kmem_cache_t *cache)
224 {
225         free(cache);
226 }
227
228
229 /*
230  * Dictionary Abstract Data Type
231  */
232
233
234 /*
235  * These macros provide short convenient names for structure members,
236  * which are embellished with dict_ prefixes so that they are
237  * properly confined to the documented namespace. It's legal for a
238  * program which uses dict to define, for instance, a macro called ``parent''.
239  * Such a macro would interfere with the dnode_t struct definition.
240  * In general, highly portable and reusable C modules which expose their
241  * structures need to confine structure member names to well-defined spaces.
242  * The resulting identifiers aren't necessarily convenient to use, nor
243  * readable, in the implementation, however!
244  */
245
246 #define left dict_left
247 #define right dict_right
248 #define parent dict_parent
249 #define color dict_color
250 #define key dict_key
251 #define data dict_data
252
253 #define nilnode dict_nilnode
254 #define maxcount dict_maxcount
255 #define compare dict_compare
256 #define dupes dict_dupes
257
258 #define dict_root(D) ((D)->nilnode.left)
259 #define dict_nil(D) (&(D)->nilnode)
260
261 static void dnode_free(dnode_t *node);
262
263 /*
264  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
265  * its right child C are rearranged so that the P instead becomes the left
266  * child of C.   The left subtree of C is inherited as the new right subtree
267  * for P.  The ordering of the keys within the tree is thus preserved.
268  */
269
270 static void rotate_left(dnode_t *upper)
271 {
272     dnode_t *lower, *lowleft, *upparent;
273
274     lower = upper->right;
275     upper->right = lowleft = lower->left;
276     lowleft->parent = upper;
277
278     lower->parent = upparent = upper->parent;
279
280     /* don't need to check for root node here because root->parent is
281        the sentinel nil node, and root->parent->left points back to root */
282
283     if (upper == upparent->left) {
284         upparent->left = lower;
285     } else {
286         assert (upper == upparent->right);
287         upparent->right = lower;
288     }
289
290     lower->left = upper;
291     upper->parent = lower;
292 }
293
294 /*
295  * This operation is the ``mirror'' image of rotate_left. It is
296  * the same procedure, but with left and right interchanged.
297  */
298
299 static void rotate_right(dnode_t *upper)
300 {
301     dnode_t *lower, *lowright, *upparent;
302
303     lower = upper->left;
304     upper->left = lowright = lower->right;
305     lowright->parent = upper;
306
307     lower->parent = upparent = upper->parent;
308
309     if (upper == upparent->right) {
310         upparent->right = lower;
311     } else {
312         assert (upper == upparent->left);
313         upparent->left = lower;
314     }
315
316     lower->right = upper;
317     upper->parent = lower;
318 }
319
320 /*
321  * Do a postorder traversal of the tree rooted at the specified
322  * node and free everything under it.  Used by dict_free().
323  */
324
325 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
326 {
327     if (node == nil)
328         return;
329     free_nodes(dict, node->left, nil);
330     free_nodes(dict, node->right, nil);
331     dict->dict_freenode(node);
332 }
333
334 /*
335  * Verify that the tree contains the given node. This is done by
336  * traversing all of the nodes and comparing their pointers to the
337  * given pointer. Returns 1 if the node is found, otherwise
338  * returns zero. It is intended for debugging purposes.
339  */
340
341 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
342 {
343     if (root != nil) {
344         return root == node
345                 || verify_dict_has_node(nil, root->left, node)
346                 || verify_dict_has_node(nil, root->right, node);
347     }
348     return 0;
349 }
350
351
352 /*
353  * Select a different set of node allocator routines.
354  */
355
356 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
357 {
358     assert (dict_count(dict) == 0);
359     dict->dict_freenode = fr;
360 }
361
362 /*
363  * Free all the nodes in the dictionary by using the dictionary's
364  * installed free routine. The dictionary is emptied.
365  */
366
367 static void dict_free_nodes(dict_t *dict)
368 {
369     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
370     free_nodes(dict, root, nil);
371     dict->dict_nodecount = 0;
372     dict->nilnode.left = &dict->nilnode;
373     dict->nilnode.right = &dict->nilnode;
374 }
375
376 /*
377  * Initialize a user-supplied dictionary object.
378  */
379
380 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
381 {
382     dict->compare = comp;
383     dict->dict_freenode = dnode_free;
384     dict->dict_nodecount = 0;
385     dict->maxcount = maxcount;
386     dict->nilnode.left = &dict->nilnode;
387     dict->nilnode.right = &dict->nilnode;
388     dict->nilnode.parent = &dict->nilnode;
389     dict->nilnode.color = dnode_black;
390     dict->dupes = 0;
391     return dict;
392 }
393
394 /*
395  * Locate a node in the dictionary having the given key.
396  * If the node is not found, a null a pointer is returned (rather than
397  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
398  * located node is returned.
399  */
400
401 static dnode_t *dict_lookup(dict_t *dict, const void *key)
402 {
403     dnode_t *root = dict_root(dict);
404     dnode_t *nil = dict_nil(dict);
405     dnode_t *saved;
406     int result;
407
408     /* simple binary search adapted for trees that contain duplicate keys */
409
410     while (root != nil) {
411         result = dict->compare(key, root->key);
412         if (result < 0)
413             root = root->left;
414         else if (result > 0)
415             root = root->right;
416         else {
417             if (!dict->dupes) { /* no duplicates, return match          */
418                 return root;
419             } else {            /* could be dupes, find leftmost one    */
420                 do {
421                     saved = root;
422                     root = root->left;
423                     while (root != nil && dict->compare(key, root->key))
424                         root = root->right;
425                 } while (root != nil);
426                 return saved;
427             }
428         }
429     }
430
431     return NULL;
432 }
433
434 /*
435  * Insert a node into the dictionary. The node should have been
436  * initialized with a data field. All other fields are ignored.
437  * The behavior is undefined if the user attempts to insert into
438  * a dictionary that is already full (for which the dict_isfull()
439  * function returns true).
440  */
441
442 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
443 {
444     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
445     dnode_t *parent = nil, *uncle, *grandpa;
446     int result = -1;
447
448     node->key = key;
449
450     /* basic binary tree insert */
451
452     while (where != nil) {
453         parent = where;
454         result = dict->compare(key, where->key);
455         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
456         assert (dict->dupes || result != 0);
457         if (result < 0)
458             where = where->left;
459         else
460             where = where->right;
461     }
462
463     assert (where == nil);
464
465     if (result < 0)
466         parent->left = node;
467     else
468         parent->right = node;
469
470     node->parent = parent;
471     node->left = nil;
472     node->right = nil;
473
474     dict->dict_nodecount++;
475
476     /* red black adjustments */
477
478     node->color = dnode_red;
479
480     while (parent->color == dnode_red) {
481         grandpa = parent->parent;
482         if (parent == grandpa->left) {
483             uncle = grandpa->right;
484             if (uncle->color == dnode_red) {    /* red parent, red uncle */
485                 parent->color = dnode_black;
486                 uncle->color = dnode_black;
487                 grandpa->color = dnode_red;
488                 node = grandpa;
489                 parent = grandpa->parent;
490             } else {                            /* red parent, black uncle */
491                 if (node == parent->right) {
492                     rotate_left(parent);
493                     parent = node;
494                     assert (grandpa == parent->parent);
495                     /* rotation between parent and child preserves grandpa */
496                 }
497                 parent->color = dnode_black;
498                 grandpa->color = dnode_red;
499                 rotate_right(grandpa);
500                 break;
501             }
502         } else {        /* symmetric cases: parent == parent->parent->right */
503             uncle = grandpa->left;
504             if (uncle->color == dnode_red) {
505                 parent->color = dnode_black;
506                 uncle->color = dnode_black;
507                 grandpa->color = dnode_red;
508                 node = grandpa;
509                 parent = grandpa->parent;
510             } else {
511                 if (node == parent->left) {
512                     rotate_right(parent);
513                     parent = node;
514                     assert (grandpa == parent->parent);
515                 }
516                 parent->color = dnode_black;
517                 grandpa->color = dnode_red;
518                 rotate_left(grandpa);
519                 break;
520             }
521         }
522     }
523
524     dict_root(dict)->color = dnode_black;
525
526 }
527
528 /*
529  * Allocate a node using the dictionary's allocator routine, give it
530  * the data item.
531  */
532
533 static dnode_t *dnode_init(dnode_t *dnode, void *data)
534 {
535     dnode->data = data;
536     dnode->parent = NULL;
537     dnode->left = NULL;
538     dnode->right = NULL;
539     return dnode;
540 }
541
542 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
543 {
544     dnode_t *node = malloc(sizeof(dnode_t));
545
546     if (node) {
547         dnode_init(node, data);
548         dict_insert(dict, node, key);
549         return 1;
550     }
551     return 0;
552 }
553
554 /*
555  * Return the node with the lowest (leftmost) key. If the dictionary is empty
556  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
557  */
558
559 static dnode_t *dict_first(dict_t *dict)
560 {
561     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
562
563     if (root != nil)
564         while ((left = root->left) != nil)
565             root = left;
566
567     return (root == nil) ? NULL : root;
568 }
569
570 /*
571  * Return the given node's successor node---the node which has the
572  * next key in the the left to right ordering. If the node has
573  * no successor, a null pointer is returned rather than a pointer to
574  * the nil node.
575  */
576
577 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
578 {
579     dnode_t *nil = dict_nil(dict), *parent, *left;
580
581     if (curr->right != nil) {
582         curr = curr->right;
583         while ((left = curr->left) != nil)
584             curr = left;
585         return curr;
586     }
587
588     parent = curr->parent;
589
590     while (parent != nil && curr == parent->right) {
591         curr = parent;
592         parent = curr->parent;
593     }
594
595     return (parent == nil) ? NULL : parent;
596 }
597
598
599 static void dnode_free(dnode_t *node)
600 {
601     free(node);
602 }
603
604
605 #undef left
606 #undef right
607 #undef parent
608 #undef color
609 #undef key
610 #undef data
611
612 #undef nilnode
613 #undef maxcount
614 #undef compare
615 #undef dupes
616
617
618 /*
619  * dirinfo.c --- maintains the directory information table for e2fsck.
620  */
621
622 /*
623  * This subroutine is called during pass1 to create a directory info
624  * entry.  During pass1, the passed-in parent is 0; it will get filled
625  * in during pass2.
626  */
627 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
628 {
629         struct dir_info *dir;
630         int             i, j;
631         ext2_ino_t      num_dirs;
632         errcode_t       retval;
633         unsigned long   old_size;
634
635         if (!ctx->dir_info) {
636                 ctx->dir_info_count = 0;
637                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
638                 if (retval)
639                         num_dirs = 1024;        /* Guess */
640                 ctx->dir_info_size = num_dirs + 10;
641                 ctx->dir_info  = (struct dir_info *)
642                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
643                                                * sizeof (struct dir_info),
644                                                "directory map");
645         }
646
647         if (ctx->dir_info_count >= ctx->dir_info_size) {
648                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
649                 ctx->dir_info_size += 10;
650                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
651                                            sizeof(struct dir_info),
652                                            &ctx->dir_info);
653                 if (retval) {
654                         ctx->dir_info_size -= 10;
655                         return;
656                 }
657         }
658
659         /*
660          * Normally, add_dir_info is called with each inode in
661          * sequential order; but once in a while (like when pass 3
662          * needs to recreate the root directory or lost+found
663          * directory) it is called out of order.  In those cases, we
664          * need to move the dir_info entries down to make room, since
665          * the dir_info array needs to be sorted by inode number for
666          * get_dir_info()'s sake.
667          */
668         if (ctx->dir_info_count &&
669             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
670                 for (i = ctx->dir_info_count-1; i > 0; i--)
671                         if (ctx->dir_info[i-1].ino < ino)
672                                 break;
673                 dir = &ctx->dir_info[i];
674                 if (dir->ino != ino)
675                         for (j = ctx->dir_info_count++; j > i; j--)
676                                 ctx->dir_info[j] = ctx->dir_info[j-1];
677         } else
678                 dir = &ctx->dir_info[ctx->dir_info_count++];
679
680         dir->ino = ino;
681         dir->dotdot = parent;
682         dir->parent = parent;
683 }
684
685 /*
686  * get_dir_info() --- given an inode number, try to find the directory
687  * information entry for it.
688  */
689 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
690 {
691         int     low, high, mid;
692
693         low = 0;
694         high = ctx->dir_info_count-1;
695         if (!ctx->dir_info)
696                 return 0;
697         if (ino == ctx->dir_info[low].ino)
698                 return &ctx->dir_info[low];
699         if  (ino == ctx->dir_info[high].ino)
700                 return &ctx->dir_info[high];
701
702         while (low < high) {
703                 mid = (low+high)/2;
704                 if (mid == low || mid == high)
705                         break;
706                 if (ino == ctx->dir_info[mid].ino)
707                         return &ctx->dir_info[mid];
708                 if (ino < ctx->dir_info[mid].ino)
709                         high = mid;
710                 else
711                         low = mid;
712         }
713         return 0;
714 }
715
716 /*
717  * Free the dir_info structure when it isn't needed any more.
718  */
719 static void e2fsck_free_dir_info(e2fsck_t ctx)
720 {
721         ext2fs_free_mem(&ctx->dir_info);
722         ctx->dir_info_size = 0;
723         ctx->dir_info_count = 0;
724 }
725
726 /*
727  * Return the count of number of directories in the dir_info structure
728  */
729 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
730 {
731         return ctx->dir_info_count;
732 }
733
734 /*
735  * A simple interator function
736  */
737 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
738 {
739         if (*control >= ctx->dir_info_count)
740                 return 0;
741
742         return ctx->dir_info + (*control)++;
743 }
744
745 /*
746  * dirinfo.c --- maintains the directory information table for e2fsck.
747  *
748  */
749
750 #ifdef ENABLE_HTREE
751
752 /*
753  * This subroutine is called during pass1 to create a directory info
754  * entry.  During pass1, the passed-in parent is 0; it will get filled
755  * in during pass2.
756  */
757 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
758 {
759         struct dx_dir_info *dir;
760         int             i, j;
761         errcode_t       retval;
762         unsigned long   old_size;
763
764         if (!ctx->dx_dir_info) {
765                 ctx->dx_dir_info_count = 0;
766                 ctx->dx_dir_info_size = 100; /* Guess */
767                 ctx->dx_dir_info  = (struct dx_dir_info *)
768                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
769                                                * sizeof (struct dx_dir_info),
770                                                "directory map");
771         }
772
773         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
774                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
775                 ctx->dx_dir_info_size += 10;
776                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
777                                            sizeof(struct dx_dir_info),
778                                            &ctx->dx_dir_info);
779                 if (retval) {
780                         ctx->dx_dir_info_size -= 10;
781                         return;
782                 }
783         }
784
785         /*
786          * Normally, add_dx_dir_info is called with each inode in
787          * sequential order; but once in a while (like when pass 3
788          * needs to recreate the root directory or lost+found
789          * directory) it is called out of order.  In those cases, we
790          * need to move the dx_dir_info entries down to make room, since
791          * the dx_dir_info array needs to be sorted by inode number for
792          * get_dx_dir_info()'s sake.
793          */
794         if (ctx->dx_dir_info_count &&
795             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
796                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
797                         if (ctx->dx_dir_info[i-1].ino < ino)
798                                 break;
799                 dir = &ctx->dx_dir_info[i];
800                 if (dir->ino != ino)
801                         for (j = ctx->dx_dir_info_count++; j > i; j--)
802                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
803         } else
804                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
805
806         dir->ino = ino;
807         dir->numblocks = num_blocks;
808         dir->hashversion = 0;
809         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
810                                        * sizeof (struct dx_dirblock_info),
811                                        "dx_block info array");
812
813 }
814
815 /*
816  * get_dx_dir_info() --- given an inode number, try to find the directory
817  * information entry for it.
818  */
819 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
820 {
821         int     low, high, mid;
822
823         low = 0;
824         high = ctx->dx_dir_info_count-1;
825         if (!ctx->dx_dir_info)
826                 return 0;
827         if (ino == ctx->dx_dir_info[low].ino)
828                 return &ctx->dx_dir_info[low];
829         if  (ino == ctx->dx_dir_info[high].ino)
830                 return &ctx->dx_dir_info[high];
831
832         while (low < high) {
833                 mid = (low+high)/2;
834                 if (mid == low || mid == high)
835                         break;
836                 if (ino == ctx->dx_dir_info[mid].ino)
837                         return &ctx->dx_dir_info[mid];
838                 if (ino < ctx->dx_dir_info[mid].ino)
839                         high = mid;
840                 else
841                         low = mid;
842         }
843         return 0;
844 }
845
846 /*
847  * Free the dx_dir_info structure when it isn't needed any more.
848  */
849 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
850 {
851         int     i;
852         struct dx_dir_info *dir;
853
854         if (ctx->dx_dir_info) {
855                 dir = ctx->dx_dir_info;
856                 for (i=0; i < ctx->dx_dir_info_count; i++) {
857                         ext2fs_free_mem(&dir->dx_block);
858                 }
859                 ext2fs_free_mem(&ctx->dx_dir_info);
860         }
861         ctx->dx_dir_info_size = 0;
862         ctx->dx_dir_info_count = 0;
863 }
864
865 /*
866  * A simple interator function
867  */
868 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
869 {
870         if (*control >= ctx->dx_dir_info_count)
871                 return 0;
872
873         return ctx->dx_dir_info + (*control)++;
874 }
875
876 #endif /* ENABLE_HTREE */
877 /*
878  * e2fsck.c - a consistency checker for the new extended file system.
879  *
880  */
881
882 /*
883  * This function allocates an e2fsck context
884  */
885 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
886 {
887         e2fsck_t        context;
888         errcode_t       retval;
889
890         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
891         if (retval)
892                 return retval;
893
894         memset(context, 0, sizeof(struct e2fsck_struct));
895
896         context->process_inode_size = 256;
897         context->ext_attr_ver = 2;
898
899         *ret = context;
900         return 0;
901 }
902
903 struct ea_refcount_el {
904         blk_t   ea_blk;
905         int     ea_count;
906 };
907
908 struct ea_refcount {
909         blk_t           count;
910         blk_t           size;
911         blk_t           cursor;
912         struct ea_refcount_el   *list;
913 };
914
915 static void ea_refcount_free(ext2_refcount_t refcount)
916 {
917         if (!refcount)
918                 return;
919
920         ext2fs_free_mem(&refcount->list);
921         ext2fs_free_mem(&refcount);
922 }
923
924 /*
925  * This function resets an e2fsck context; it is called when e2fsck
926  * needs to be restarted.
927  */
928 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
929 {
930         ctx->flags = 0;
931         ctx->lost_and_found = 0;
932         ctx->bad_lost_and_found = 0;
933         ext2fs_free_inode_bitmap(ctx->inode_used_map);
934         ctx->inode_used_map = 0;
935         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
936         ctx->inode_dir_map = 0;
937         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
938         ctx->inode_reg_map = 0;
939         ext2fs_free_block_bitmap(ctx->block_found_map);
940         ctx->block_found_map = 0;
941         ext2fs_free_icount(ctx->inode_link_info);
942         ctx->inode_link_info = 0;
943         if (ctx->journal_io) {
944                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
945                         io_channel_close(ctx->journal_io);
946                 ctx->journal_io = 0;
947         }
948         if (ctx->fs) {
949                 ext2fs_free_dblist(ctx->fs->dblist);
950                 ctx->fs->dblist = 0;
951         }
952         e2fsck_free_dir_info(ctx);
953 #ifdef ENABLE_HTREE
954         e2fsck_free_dx_dir_info(ctx);
955 #endif
956         ea_refcount_free(ctx->refcount);
957         ctx->refcount = 0;
958         ea_refcount_free(ctx->refcount_extra);
959         ctx->refcount_extra = 0;
960         ext2fs_free_block_bitmap(ctx->block_dup_map);
961         ctx->block_dup_map = 0;
962         ext2fs_free_block_bitmap(ctx->block_ea_map);
963         ctx->block_ea_map = 0;
964         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
965         ctx->inode_bad_map = 0;
966         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
967         ctx->inode_imagic_map = 0;
968         ext2fs_u32_list_free(ctx->dirs_to_hash);
969         ctx->dirs_to_hash = 0;
970
971         /*
972          * Clear the array of invalid meta-data flags
973          */
974         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
975         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
976         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
977
978         /* Clear statistic counters */
979         ctx->fs_directory_count = 0;
980         ctx->fs_regular_count = 0;
981         ctx->fs_blockdev_count = 0;
982         ctx->fs_chardev_count = 0;
983         ctx->fs_links_count = 0;
984         ctx->fs_symlinks_count = 0;
985         ctx->fs_fast_symlinks_count = 0;
986         ctx->fs_fifo_count = 0;
987         ctx->fs_total_count = 0;
988         ctx->fs_sockets_count = 0;
989         ctx->fs_ind_count = 0;
990         ctx->fs_dind_count = 0;
991         ctx->fs_tind_count = 0;
992         ctx->fs_fragmented = 0;
993         ctx->large_files = 0;
994
995         /* Reset the superblock to the user's requested value */
996         ctx->superblock = ctx->use_superblock;
997
998         return 0;
999 }
1000
1001 static void e2fsck_free_context(e2fsck_t ctx)
1002 {
1003         if (!ctx)
1004                 return;
1005
1006         e2fsck_reset_context(ctx);
1007         if (ctx->blkid)
1008                 blkid_put_cache(ctx->blkid);
1009
1010         ext2fs_free_mem(&ctx);
1011 }
1012
1013 /*
1014  * ea_refcount.c
1015  */
1016
1017 /*
1018  * The strategy we use for keeping track of EA refcounts is as
1019  * follows.  We keep a sorted array of first EA blocks and its
1020  * reference counts.  Once the refcount has dropped to zero, it is
1021  * removed from the array to save memory space.  Once the EA block is
1022  * checked, its bit is set in the block_ea_map bitmap.
1023  */
1024
1025
1026 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1027 {
1028         ext2_refcount_t refcount;
1029         errcode_t       retval;
1030         size_t          bytes;
1031
1032         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1033         if (retval)
1034                 return retval;
1035         memset(refcount, 0, sizeof(struct ea_refcount));
1036
1037         if (!size)
1038                 size = 500;
1039         refcount->size = size;
1040         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1041 #ifdef DEBUG
1042         printf("Refcount allocated %d entries, %d bytes.\n",
1043                refcount->size, bytes);
1044 #endif
1045         retval = ext2fs_get_mem(bytes, &refcount->list);
1046         if (retval)
1047                 goto errout;
1048         memset(refcount->list, 0, bytes);
1049
1050         refcount->count = 0;
1051         refcount->cursor = 0;
1052
1053         *ret = refcount;
1054         return 0;
1055
1056 errout:
1057         ea_refcount_free(refcount);
1058         return retval;
1059 }
1060
1061 /*
1062  * collapse_refcount() --- go through the refcount array, and get rid
1063  * of any count == zero entries
1064  */
1065 static void refcount_collapse(ext2_refcount_t refcount)
1066 {
1067         unsigned int    i, j;
1068         struct ea_refcount_el   *list;
1069
1070         list = refcount->list;
1071         for (i = 0, j = 0; i < refcount->count; i++) {
1072                 if (list[i].ea_count) {
1073                         if (i != j)
1074                                 list[j] = list[i];
1075                         j++;
1076                 }
1077         }
1078 #if defined(DEBUG) || defined(TEST_PROGRAM)
1079         printf("Refcount_collapse: size was %d, now %d\n",
1080                refcount->count, j);
1081 #endif
1082         refcount->count = j;
1083 }
1084
1085
1086 /*
1087  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1088  *      specified position.
1089  */
1090 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1091                                                  blk_t blk, int pos)
1092 {
1093         struct ea_refcount_el   *el;
1094         errcode_t               retval;
1095         blk_t                   new_size = 0;
1096         int                     num;
1097
1098         if (refcount->count >= refcount->size) {
1099                 new_size = refcount->size + 100;
1100 #ifdef DEBUG
1101                 printf("Reallocating refcount %d entries...\n", new_size);
1102 #endif
1103                 retval = ext2fs_resize_mem((size_t) refcount->size *
1104                                            sizeof(struct ea_refcount_el),
1105                                            (size_t) new_size *
1106                                            sizeof(struct ea_refcount_el),
1107                                            &refcount->list);
1108                 if (retval)
1109                         return 0;
1110                 refcount->size = new_size;
1111         }
1112         num = (int) refcount->count - pos;
1113         if (num < 0)
1114                 return 0;       /* should never happen */
1115         if (num) {
1116                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1117                         sizeof(struct ea_refcount_el) * num);
1118         }
1119         refcount->count++;
1120         el = &refcount->list[pos];
1121         el->ea_count = 0;
1122         el->ea_blk = blk;
1123         return el;
1124 }
1125
1126
1127 /*
1128  * get_refcount_el() --- given an block number, try to find refcount
1129  *      information in the sorted list.  If the create flag is set,
1130  *      and we can't find an entry, create one in the sorted list.
1131  */
1132 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1133                                               blk_t blk, int create)
1134 {
1135         float   range;
1136         int     low, high, mid;
1137         blk_t   lowval, highval;
1138
1139         if (!refcount || !refcount->list)
1140                 return 0;
1141 retry:
1142         low = 0;
1143         high = (int) refcount->count-1;
1144         if (create && ((refcount->count == 0) ||
1145                        (blk > refcount->list[high].ea_blk))) {
1146                 if (refcount->count >= refcount->size)
1147                         refcount_collapse(refcount);
1148
1149                 return insert_refcount_el(refcount, blk,
1150                                           (unsigned) refcount->count);
1151         }
1152         if (refcount->count == 0)
1153                 return 0;
1154
1155         if (refcount->cursor >= refcount->count)
1156                 refcount->cursor = 0;
1157         if (blk == refcount->list[refcount->cursor].ea_blk)
1158                 return &refcount->list[refcount->cursor++];
1159 #ifdef DEBUG
1160         printf("Non-cursor get_refcount_el: %u\n", blk);
1161 #endif
1162         while (low <= high) {
1163                 if (low == high)
1164                         mid = low;
1165                 else {
1166                         /* Interpolate for efficiency */
1167                         lowval = refcount->list[low].ea_blk;
1168                         highval = refcount->list[high].ea_blk;
1169
1170                         if (blk < lowval)
1171                                 range = 0;
1172                         else if (blk > highval)
1173                                 range = 1;
1174                         else
1175                                 range = ((float) (blk - lowval)) /
1176                                         (highval - lowval);
1177                         mid = low + ((int) (range * (high-low)));
1178                 }
1179
1180                 if (blk == refcount->list[mid].ea_blk) {
1181                         refcount->cursor = mid+1;
1182                         return &refcount->list[mid];
1183                 }
1184                 if (blk < refcount->list[mid].ea_blk)
1185                         high = mid-1;
1186                 else
1187                         low = mid+1;
1188         }
1189         /*
1190          * If we need to create a new entry, it should be right at
1191          * low (where high will be left at low-1).
1192          */
1193         if (create) {
1194                 if (refcount->count >= refcount->size) {
1195                         refcount_collapse(refcount);
1196                         if (refcount->count < refcount->size)
1197                                 goto retry;
1198                 }
1199                 return insert_refcount_el(refcount, blk, low);
1200         }
1201         return 0;
1202 }
1203
1204 static errcode_t
1205 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1206 {
1207         struct ea_refcount_el   *el;
1208
1209         el = get_refcount_el(refcount, blk, 1);
1210         if (!el)
1211                 return EXT2_ET_NO_MEMORY;
1212         el->ea_count++;
1213
1214         if (ret)
1215                 *ret = el->ea_count;
1216         return 0;
1217 }
1218
1219 static errcode_t
1220 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1221 {
1222         struct ea_refcount_el   *el;
1223
1224         el = get_refcount_el(refcount, blk, 0);
1225         if (!el || el->ea_count == 0)
1226                 return EXT2_ET_INVALID_ARGUMENT;
1227
1228         el->ea_count--;
1229
1230         if (ret)
1231                 *ret = el->ea_count;
1232         return 0;
1233 }
1234
1235 static errcode_t
1236 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1237 {
1238         struct ea_refcount_el   *el;
1239
1240         /*
1241          * Get the refcount element
1242          */
1243         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1244         if (!el)
1245                 return count ? EXT2_ET_NO_MEMORY : 0;
1246         el->ea_count = count;
1247         return 0;
1248 }
1249
1250 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1251 {
1252         refcount->cursor = 0;
1253 }
1254
1255
1256 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1257 {
1258         struct ea_refcount_el   *list;
1259
1260         while (1) {
1261                 if (refcount->cursor >= refcount->count)
1262                         return 0;
1263                 list = refcount->list;
1264                 if (list[refcount->cursor].ea_count) {
1265                         if (ret)
1266                                 *ret = list[refcount->cursor].ea_count;
1267                         return list[refcount->cursor++].ea_blk;
1268                 }
1269                 refcount->cursor++;
1270         }
1271 }
1272
1273
1274 /*
1275  * ehandler.c --- handle bad block errors which come up during the
1276  *      course of an e2fsck session.
1277  */
1278
1279
1280 static const char *operation;
1281
1282 static errcode_t
1283 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1284                          void *data, size_t size FSCK_ATTR((unused)),
1285                          int actual FSCK_ATTR((unused)), errcode_t error)
1286 {
1287         int     i;
1288         char    *p;
1289         ext2_filsys fs = (ext2_filsys) channel->app_data;
1290         e2fsck_t ctx;
1291
1292         ctx = (e2fsck_t) fs->priv_data;
1293
1294         /*
1295          * If more than one block was read, try reading each block
1296          * separately.  We could use the actual bytes read to figure
1297          * out where to start, but we don't bother.
1298          */
1299         if (count > 1) {
1300                 p = (char *) data;
1301                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1302                         error = io_channel_read_blk(channel, block,
1303                                                     1, p);
1304                         if (error)
1305                                 return error;
1306                 }
1307                 return 0;
1308         }
1309         if (operation)
1310                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1311                        error_message(error), operation);
1312         else
1313                 printf(_("Error reading block %lu (%s).  "), block,
1314                        error_message(error));
1315         preenhalt(ctx);
1316         if (ask(ctx, _("Ignore error"), 1)) {
1317                 if (ask(ctx, _("Force rewrite"), 1))
1318                         io_channel_write_blk(channel, block, 1, data);
1319                 return 0;
1320         }
1321
1322         return error;
1323 }
1324
1325 static errcode_t
1326 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1327                         const void *data, size_t size FSCK_ATTR((unused)),
1328                         int actual FSCK_ATTR((unused)), errcode_t error)
1329 {
1330         int             i;
1331         const char      *p;
1332         ext2_filsys fs = (ext2_filsys) channel->app_data;
1333         e2fsck_t ctx;
1334
1335         ctx = (e2fsck_t) fs->priv_data;
1336
1337         /*
1338          * If more than one block was written, try writing each block
1339          * separately.  We could use the actual bytes read to figure
1340          * out where to start, but we don't bother.
1341          */
1342         if (count > 1) {
1343                 p = (const char *) data;
1344                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1345                         error = io_channel_write_blk(channel, block,
1346                                                      1, p);
1347                         if (error)
1348                                 return error;
1349                 }
1350                 return 0;
1351         }
1352
1353         if (operation)
1354                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1355                        error_message(error), operation);
1356         else
1357                 printf(_("Error writing block %lu (%s).  "), block,
1358                        error_message(error));
1359         preenhalt(ctx);
1360         if (ask(ctx, _("Ignore error"), 1))
1361                 return 0;
1362
1363         return error;
1364 }
1365
1366 static const char *ehandler_operation(const char *op)
1367 {
1368         const char *ret = operation;
1369
1370         operation = op;
1371         return ret;
1372 }
1373
1374 static void ehandler_init(io_channel channel)
1375 {
1376         channel->read_error = e2fsck_handle_read_error;
1377         channel->write_error = e2fsck_handle_write_error;
1378 }
1379
1380 /*
1381  * journal.c --- code for handling the "ext3" journal
1382  *
1383  * Copyright (C) 2000 Andreas Dilger
1384  * Copyright (C) 2000 Theodore Ts'o
1385  *
1386  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1387  * Copyright (C) 1999 Red Hat Software
1388  *
1389  * This file may be redistributed under the terms of the
1390  * GNU General Public License version 2 or at your discretion
1391  * any later version.
1392  */
1393
1394 /*
1395  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1396  * This creates a larger static binary, and a smaller binary using
1397  * shared libraries.  It's also probably slightly less CPU-efficient,
1398  * which is why it's not on by default.  But, it's a good way of
1399  * testing the functions in inode_io.c and fileio.c.
1400  */
1401 #undef USE_INODE_IO
1402
1403 /* Kernel compatibility functions for handling the journal.  These allow us
1404  * to use the recovery.c file virtually unchanged from the kernel, so we
1405  * don't have to do much to keep kernel and user recovery in sync.
1406  */
1407 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1408 {
1409 #ifdef USE_INODE_IO
1410         *phys = block;
1411         return 0;
1412 #else
1413         struct inode    *inode = journal->j_inode;
1414         errcode_t       retval;
1415         blk_t           pblk;
1416
1417         if (!inode) {
1418                 *phys = block;
1419                 return 0;
1420         }
1421
1422         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1423                             &inode->i_ext2, NULL, 0, block, &pblk);
1424         *phys = pblk;
1425         return retval;
1426 #endif
1427 }
1428
1429 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1430 {
1431         struct buffer_head *bh;
1432
1433         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1434         if (!bh)
1435                 return NULL;
1436
1437         bh->b_ctx = kdev->k_ctx;
1438         if (kdev->k_dev == K_DEV_FS)
1439                 bh->b_io = kdev->k_ctx->fs->io;
1440         else
1441                 bh->b_io = kdev->k_ctx->journal_io;
1442         bh->b_size = blocksize;
1443         bh->b_blocknr = blocknr;
1444
1445         return bh;
1446 }
1447
1448 static void sync_blockdev(kdev_t kdev)
1449 {
1450         io_channel      io;
1451
1452         if (kdev->k_dev == K_DEV_FS)
1453                 io = kdev->k_ctx->fs->io;
1454         else
1455                 io = kdev->k_ctx->journal_io;
1456
1457         io_channel_flush(io);
1458 }
1459
1460 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1461 {
1462         int retval;
1463         struct buffer_head *bh;
1464
1465         for (; nr > 0; --nr) {
1466                 bh = *bhp++;
1467                 if (rw == READ && !bh->b_uptodate) {
1468                         retval = io_channel_read_blk(bh->b_io,
1469                                                      bh->b_blocknr,
1470                                                      1, bh->b_data);
1471                         if (retval) {
1472                                 bb_error_msg("while reading block %lu",
1473                                         (unsigned long) bh->b_blocknr);
1474                                 bh->b_err = retval;
1475                                 continue;
1476                         }
1477                         bh->b_uptodate = 1;
1478                 } else if (rw == WRITE && bh->b_dirty) {
1479                         retval = io_channel_write_blk(bh->b_io,
1480                                                       bh->b_blocknr,
1481                                                       1, bh->b_data);
1482                         if (retval) {
1483                                 bb_error_msg("while writing block %lu",
1484                                         (unsigned long) bh->b_blocknr);
1485                                 bh->b_err = retval;
1486                                 continue;
1487                         }
1488                         bh->b_dirty = 0;
1489                         bh->b_uptodate = 1;
1490                 }
1491         }
1492 }
1493
1494 static void mark_buffer_dirty(struct buffer_head *bh)
1495 {
1496         bh->b_dirty = 1;
1497 }
1498
1499 static inline void mark_buffer_clean(struct buffer_head * bh)
1500 {
1501         bh->b_dirty = 0;
1502 }
1503
1504 static void brelse(struct buffer_head *bh)
1505 {
1506         if (bh->b_dirty)
1507                 ll_rw_block(WRITE, 1, &bh);
1508         ext2fs_free_mem(&bh);
1509 }
1510
1511 static int buffer_uptodate(struct buffer_head *bh)
1512 {
1513         return bh->b_uptodate;
1514 }
1515
1516 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1517 {
1518         bh->b_uptodate = val;
1519 }
1520
1521 static void wait_on_buffer(struct buffer_head *bh)
1522 {
1523         if (!bh->b_uptodate)
1524                 ll_rw_block(READ, 1, &bh);
1525 }
1526
1527
1528 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1529 {
1530         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1531
1532         /* if we had an error doing journal recovery, we need a full fsck */
1533         if (error)
1534                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1535         ext2fs_mark_super_dirty(ctx->fs);
1536 }
1537
1538 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1539 {
1540         struct ext2_super_block *sb = ctx->fs->super;
1541         struct ext2_super_block jsuper;
1542         struct problem_context  pctx;
1543         struct buffer_head      *bh;
1544         struct inode            *j_inode = NULL;
1545         struct kdev_s           *dev_fs = NULL, *dev_journal;
1546         const char              *journal_name = 0;
1547         journal_t               *journal = NULL;
1548         errcode_t               retval = 0;
1549         io_manager              io_ptr = 0;
1550         unsigned long           start = 0;
1551         blk_t                   blk;
1552         int                     ext_journal = 0;
1553         int                     tried_backup_jnl = 0;
1554         int                     i;
1555
1556         clear_problem_context(&pctx);
1557
1558         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1559         if (!journal) {
1560                 return EXT2_ET_NO_MEMORY;
1561         }
1562
1563         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1564         if (!dev_fs) {
1565                 retval = EXT2_ET_NO_MEMORY;
1566                 goto errout;
1567         }
1568         dev_journal = dev_fs+1;
1569
1570         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1571         dev_fs->k_dev = K_DEV_FS;
1572         dev_journal->k_dev = K_DEV_JOURNAL;
1573
1574         journal->j_dev = dev_journal;
1575         journal->j_fs_dev = dev_fs;
1576         journal->j_inode = NULL;
1577         journal->j_blocksize = ctx->fs->blocksize;
1578
1579         if (uuid_is_null(sb->s_journal_uuid)) {
1580                 if (!sb->s_journal_inum)
1581                         return EXT2_ET_BAD_INODE_NUM;
1582                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1583                                                  "journal inode");
1584                 if (!j_inode) {
1585                         retval = EXT2_ET_NO_MEMORY;
1586                         goto errout;
1587                 }
1588
1589                 j_inode->i_ctx = ctx;
1590                 j_inode->i_ino = sb->s_journal_inum;
1591
1592                 if ((retval = ext2fs_read_inode(ctx->fs,
1593                                                 sb->s_journal_inum,
1594                                                 &j_inode->i_ext2))) {
1595                 try_backup_journal:
1596                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1597                             tried_backup_jnl)
1598                                 goto errout;
1599                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1600                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1601                                EXT2_N_BLOCKS*4);
1602                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1603                         j_inode->i_ext2.i_links_count = 1;
1604                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1605                         tried_backup_jnl++;
1606                 }
1607                 if (!j_inode->i_ext2.i_links_count ||
1608                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1609                         retval = EXT2_ET_NO_JOURNAL;
1610                         goto try_backup_journal;
1611                 }
1612                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1613                     JFS_MIN_JOURNAL_BLOCKS) {
1614                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1615                         goto try_backup_journal;
1616                 }
1617                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1618                         blk = j_inode->i_ext2.i_block[i];
1619                         if (!blk) {
1620                                 if (i < EXT2_NDIR_BLOCKS) {
1621                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1622                                         goto try_backup_journal;
1623                                 }
1624                                 continue;
1625                         }
1626                         if (blk < sb->s_first_data_block ||
1627                             blk >= sb->s_blocks_count) {
1628                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1629                                 goto try_backup_journal;
1630                         }
1631                 }
1632                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1633
1634 #ifdef USE_INODE_IO
1635                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1636                                                  &j_inode->i_ext2,
1637                                                  &journal_name);
1638                 if (retval)
1639                         goto errout;
1640
1641                 io_ptr = inode_io_manager;
1642 #else
1643                 journal->j_inode = j_inode;
1644                 ctx->journal_io = ctx->fs->io;
1645                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1646                         goto errout;
1647 #endif
1648         } else {
1649                 ext_journal = 1;
1650                 if (!ctx->journal_name) {
1651                         char uuid[37];
1652
1653                         uuid_unparse(sb->s_journal_uuid, uuid);
1654                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1655                                                               "UUID", uuid);
1656                         if (!ctx->journal_name)
1657                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1658                 }
1659                 journal_name = ctx->journal_name;
1660
1661                 if (!journal_name) {
1662                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1663                         return EXT2_ET_LOAD_EXT_JOURNAL;
1664                 }
1665
1666                 io_ptr = unix_io_manager;
1667         }
1668
1669 #ifndef USE_INODE_IO
1670         if (ext_journal)
1671 #endif
1672                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1673                                       &ctx->journal_io);
1674         if (retval)
1675                 goto errout;
1676
1677         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1678
1679         if (ext_journal) {
1680                 if (ctx->fs->blocksize == 1024)
1681                         start = 1;
1682                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1683                 if (!bh) {
1684                         retval = EXT2_ET_NO_MEMORY;
1685                         goto errout;
1686                 }
1687                 ll_rw_block(READ, 1, &bh);
1688                 if ((retval = bh->b_err) != 0)
1689                         goto errout;
1690                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1691                        sizeof(jsuper));
1692                 brelse(bh);
1693 #if BB_BIG_ENDIAN
1694                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1695                         ext2fs_swap_super(&jsuper);
1696 #endif
1697                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1698                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1699                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1700                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1701                         goto errout;
1702                 }
1703                 /* Make sure the journal UUID is correct */
1704                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1705                            sizeof(jsuper.s_uuid))) {
1706                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1707                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1708                         goto errout;
1709                 }
1710
1711                 journal->j_maxlen = jsuper.s_blocks_count;
1712                 start++;
1713         }
1714
1715         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1716                 retval = EXT2_ET_NO_MEMORY;
1717                 goto errout;
1718         }
1719
1720         journal->j_sb_buffer = bh;
1721         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1722
1723 #ifdef USE_INODE_IO
1724         ext2fs_free_mem(&j_inode);
1725 #endif
1726
1727         *ret_journal = journal;
1728         return 0;
1729
1730 errout:
1731         ext2fs_free_mem(&dev_fs);
1732         ext2fs_free_mem(&j_inode);
1733         ext2fs_free_mem(&journal);
1734         return retval;
1735
1736 }
1737
1738 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1739                                               struct problem_context *pctx)
1740 {
1741         struct ext2_super_block *sb = ctx->fs->super;
1742         int recover = ctx->fs->super->s_feature_incompat &
1743                 EXT3_FEATURE_INCOMPAT_RECOVER;
1744         int has_journal = ctx->fs->super->s_feature_compat &
1745                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1746
1747         if (has_journal || sb->s_journal_inum) {
1748                 /* The journal inode is bogus, remove and force full fsck */
1749                 pctx->ino = sb->s_journal_inum;
1750                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1751                         if (has_journal && sb->s_journal_inum)
1752                                 printf("*** ext3 journal has been deleted - "
1753                                        "filesystem is now ext2 only ***\n\n");
1754                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1755                         sb->s_journal_inum = 0;
1756                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1757                         e2fsck_clear_recover(ctx, 1);
1758                         return 0;
1759                 }
1760                 return EXT2_ET_BAD_INODE_NUM;
1761         } else if (recover) {
1762                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1763                         e2fsck_clear_recover(ctx, 1);
1764                         return 0;
1765                 }
1766                 return EXT2_ET_UNSUPP_FEATURE;
1767         }
1768         return 0;
1769 }
1770
1771 #define V1_SB_SIZE      0x0024
1772 static void clear_v2_journal_fields(journal_t *journal)
1773 {
1774         e2fsck_t ctx = journal->j_dev->k_ctx;
1775         struct problem_context pctx;
1776
1777         clear_problem_context(&pctx);
1778
1779         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1780                 return;
1781
1782         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1783                ctx->fs->blocksize-V1_SB_SIZE);
1784         mark_buffer_dirty(journal->j_sb_buffer);
1785 }
1786
1787
1788 static errcode_t e2fsck_journal_load(journal_t *journal)
1789 {
1790         e2fsck_t ctx = journal->j_dev->k_ctx;
1791         journal_superblock_t *jsb;
1792         struct buffer_head *jbh = journal->j_sb_buffer;
1793         struct problem_context pctx;
1794
1795         clear_problem_context(&pctx);
1796
1797         ll_rw_block(READ, 1, &jbh);
1798         if (jbh->b_err) {
1799                 bb_error_msg(_("reading journal superblock"));
1800                 return jbh->b_err;
1801         }
1802
1803         jsb = journal->j_superblock;
1804         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1805         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1806                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1807
1808         switch (ntohl(jsb->s_header.h_blocktype)) {
1809         case JFS_SUPERBLOCK_V1:
1810                 journal->j_format_version = 1;
1811                 if (jsb->s_feature_compat ||
1812                     jsb->s_feature_incompat ||
1813                     jsb->s_feature_ro_compat ||
1814                     jsb->s_nr_users)
1815                         clear_v2_journal_fields(journal);
1816                 break;
1817
1818         case JFS_SUPERBLOCK_V2:
1819                 journal->j_format_version = 2;
1820                 if (ntohl(jsb->s_nr_users) > 1 &&
1821                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1822                         clear_v2_journal_fields(journal);
1823                 if (ntohl(jsb->s_nr_users) > 1) {
1824                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1825                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1826                 }
1827                 break;
1828
1829         /*
1830          * These should never appear in a journal super block, so if
1831          * they do, the journal is badly corrupted.
1832          */
1833         case JFS_DESCRIPTOR_BLOCK:
1834         case JFS_COMMIT_BLOCK:
1835         case JFS_REVOKE_BLOCK:
1836                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1837
1838         /* If we don't understand the superblock major type, but there
1839          * is a magic number, then it is likely to be a new format we
1840          * just don't understand, so leave it alone. */
1841         default:
1842                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1843         }
1844
1845         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1846                 return EXT2_ET_UNSUPP_FEATURE;
1847
1848         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1849                 return EXT2_ET_RO_UNSUPP_FEATURE;
1850
1851         /* We have now checked whether we know enough about the journal
1852          * format to be able to proceed safely, so any other checks that
1853          * fail we should attempt to recover from. */
1854         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1855                 bb_error_msg(_("%s: no valid journal superblock found"),
1856                         ctx->device_name);
1857                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1858         }
1859
1860         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1861                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1862         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1863                 bb_error_msg(_("%s: journal too short"),
1864                         ctx->device_name);
1865                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1866         }
1867
1868         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1869         journal->j_transaction_sequence = journal->j_tail_sequence;
1870         journal->j_tail = ntohl(jsb->s_start);
1871         journal->j_first = ntohl(jsb->s_first);
1872         journal->j_last = ntohl(jsb->s_maxlen);
1873
1874         return 0;
1875 }
1876
1877 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1878                                        journal_t *journal)
1879 {
1880         char *p;
1881         union {
1882                 uuid_t uuid;
1883                 __u32 val[4];
1884         } u;
1885         __u32 new_seq = 0;
1886         int i;
1887
1888         /* Leave a valid existing V1 superblock signature alone.
1889          * Anything unrecognisable we overwrite with a new V2
1890          * signature. */
1891
1892         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1893             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1894                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1895                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1896         }
1897
1898         /* Zero out everything else beyond the superblock header */
1899
1900         p = ((char *) jsb) + sizeof(journal_header_t);
1901         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1902
1903         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1904         jsb->s_maxlen = htonl(journal->j_maxlen);
1905         jsb->s_first = htonl(1);
1906
1907         /* Initialize the journal sequence number so that there is "no"
1908          * chance we will find old "valid" transactions in the journal.
1909          * This avoids the need to zero the whole journal (slow to do,
1910          * and risky when we are just recovering the filesystem).
1911          */
1912         uuid_generate(u.uuid);
1913         for (i = 0; i < 4; i ++)
1914                 new_seq ^= u.val[i];
1915         jsb->s_sequence = htonl(new_seq);
1916
1917         mark_buffer_dirty(journal->j_sb_buffer);
1918         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1919 }
1920
1921 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1922                                                   journal_t *journal,
1923                                                   struct problem_context *pctx)
1924 {
1925         struct ext2_super_block *sb = ctx->fs->super;
1926         int recover = ctx->fs->super->s_feature_incompat &
1927                 EXT3_FEATURE_INCOMPAT_RECOVER;
1928
1929         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1930                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1931                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1932                                                    journal);
1933                         journal->j_transaction_sequence = 1;
1934                         e2fsck_clear_recover(ctx, recover);
1935                         return 0;
1936                 }
1937                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1938         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1939                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1940
1941         return 0;
1942 }
1943
1944 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1945                                    int reset, int drop)
1946 {
1947         journal_superblock_t *jsb;
1948
1949         if (drop)
1950                 mark_buffer_clean(journal->j_sb_buffer);
1951         else if (!(ctx->options & E2F_OPT_READONLY)) {
1952                 jsb = journal->j_superblock;
1953                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1954                 if (reset)
1955                         jsb->s_start = 0; /* this marks the journal as empty */
1956                 mark_buffer_dirty(journal->j_sb_buffer);
1957         }
1958         brelse(journal->j_sb_buffer);
1959
1960         if (ctx->journal_io) {
1961                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1962                         io_channel_close(ctx->journal_io);
1963                 ctx->journal_io = 0;
1964         }
1965
1966 #ifndef USE_INODE_IO
1967         ext2fs_free_mem(&journal->j_inode);
1968 #endif
1969         ext2fs_free_mem(&journal->j_fs_dev);
1970         ext2fs_free_mem(&journal);
1971 }
1972
1973 /*
1974  * This function makes sure that the superblock fields regarding the
1975  * journal are consistent.
1976  */
1977 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1978 {
1979         struct ext2_super_block *sb = ctx->fs->super;
1980         journal_t *journal;
1981         int recover = ctx->fs->super->s_feature_incompat &
1982                 EXT3_FEATURE_INCOMPAT_RECOVER;
1983         struct problem_context pctx;
1984         problem_t problem;
1985         int reset = 0, force_fsck = 0;
1986         int retval;
1987
1988         /* If we don't have any journal features, don't do anything more */
1989         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1990             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1991             uuid_is_null(sb->s_journal_uuid))
1992                 return 0;
1993
1994         clear_problem_context(&pctx);
1995         pctx.num = sb->s_journal_inum;
1996
1997         retval = e2fsck_get_journal(ctx, &journal);
1998         if (retval) {
1999                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2000                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2001                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2002                     (retval == EXT2_ET_NO_JOURNAL))
2003                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2004                 return retval;
2005         }
2006
2007         retval = e2fsck_journal_load(journal);
2008         if (retval) {
2009                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2010                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2011                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2012                                   &pctx))) ||
2013                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2014                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2015                                   &pctx))) ||
2016                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2017                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2018                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2019                                                                   &pctx);
2020                 e2fsck_journal_release(ctx, journal, 0, 1);
2021                 return retval;
2022         }
2023
2024         /*
2025          * We want to make the flags consistent here.  We will not leave with
2026          * needs_recovery set but has_journal clear.  We can't get in a loop
2027          * with -y, -n, or -p, only if a user isn't making up their mind.
2028          */
2029 no_has_journal:
2030         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2031                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2032                 pctx.str = "inode";
2033                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2034                         if (recover &&
2035                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2036                                 goto no_has_journal;
2037                         /*
2038                          * Need a full fsck if we are releasing a
2039                          * journal stored on a reserved inode.
2040                          */
2041                         force_fsck = recover ||
2042                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2043                         /* Clear all of the journal fields */
2044                         sb->s_journal_inum = 0;
2045                         sb->s_journal_dev = 0;
2046                         memset(sb->s_journal_uuid, 0,
2047                                sizeof(sb->s_journal_uuid));
2048                         e2fsck_clear_recover(ctx, force_fsck);
2049                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2050                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2051                         ext2fs_mark_super_dirty(ctx->fs);
2052                 }
2053         }
2054
2055         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2056             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2057             journal->j_superblock->s_start != 0) {
2058                 /* Print status information */
2059                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2060                 if (ctx->superblock)
2061                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2062                 else
2063                         problem = PR_0_JOURNAL_RUN;
2064                 if (fix_problem(ctx, problem, &pctx)) {
2065                         ctx->options |= E2F_OPT_FORCE;
2066                         sb->s_feature_incompat |=
2067                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2068                         ext2fs_mark_super_dirty(ctx->fs);
2069                 } else if (fix_problem(ctx,
2070                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2071                         reset = 1;
2072                         sb->s_state &= ~EXT2_VALID_FS;
2073                         ext2fs_mark_super_dirty(ctx->fs);
2074                 }
2075                 /*
2076                  * If the user answers no to the above question, we
2077                  * ignore the fact that journal apparently has data;
2078                  * accidentally replaying over valid data would be far
2079                  * worse than skipping a questionable recovery.
2080                  *
2081                  * XXX should we abort with a fatal error here?  What
2082                  * will the ext3 kernel code do if a filesystem with
2083                  * !NEEDS_RECOVERY but with a non-zero
2084                  * journal->j_superblock->s_start is mounted?
2085                  */
2086         }
2087
2088         e2fsck_journal_release(ctx, journal, reset, 0);
2089         return retval;
2090 }
2091
2092 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2093 {
2094         journal_t *journal;
2095         int retval;
2096
2097         journal_init_revoke_caches();
2098         retval = e2fsck_get_journal(ctx, &journal);
2099         if (retval)
2100                 return retval;
2101
2102         retval = e2fsck_journal_load(journal);
2103         if (retval)
2104                 goto errout;
2105
2106         retval = journal_init_revoke(journal, 1024);
2107         if (retval)
2108                 goto errout;
2109
2110         retval = -journal_recover(journal);
2111         if (retval)
2112                 goto errout;
2113
2114         if (journal->j_superblock->s_errno) {
2115                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2116                 ext2fs_mark_super_dirty(ctx->fs);
2117                 journal->j_superblock->s_errno = 0;
2118                 mark_buffer_dirty(journal->j_sb_buffer);
2119         }
2120
2121 errout:
2122         journal_destroy_revoke(journal);
2123         journal_destroy_revoke_caches();
2124         e2fsck_journal_release(ctx, journal, 1, 0);
2125         return retval;
2126 }
2127
2128 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2129 {
2130         io_manager io_ptr = ctx->fs->io->manager;
2131         int blocksize = ctx->fs->blocksize;
2132         errcode_t       retval, recover_retval;
2133
2134         printf(_("%s: recovering journal\n"), ctx->device_name);
2135         if (ctx->options & E2F_OPT_READONLY) {
2136                 printf(_("%s: won't do journal recovery while read-only\n"),
2137                        ctx->device_name);
2138                 return EXT2_ET_FILE_RO;
2139         }
2140
2141         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2142                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2143
2144         recover_retval = recover_ext3_journal(ctx);
2145
2146         /*
2147          * Reload the filesystem context to get up-to-date data from disk
2148          * because journal recovery will change the filesystem under us.
2149          */
2150         ext2fs_close(ctx->fs);
2151         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2152                              ctx->superblock, blocksize, io_ptr,
2153                              &ctx->fs);
2154
2155         if (retval) {
2156                 bb_error_msg(_("while trying to re-open %s"),
2157                         ctx->device_name);
2158                 bb_error_msg_and_die(0);
2159         }
2160         ctx->fs->priv_data = ctx;
2161
2162         /* Set the superblock flags */
2163         e2fsck_clear_recover(ctx, recover_retval);
2164         return recover_retval;
2165 }
2166
2167 /*
2168  * This function will move the journal inode from a visible file in
2169  * the filesystem directory hierarchy to the reserved inode if necessary.
2170  */
2171 static const char *const journal_names[] = {
2172         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2173
2174 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2175 {
2176         struct ext2_super_block *sb = ctx->fs->super;
2177         struct problem_context  pctx;
2178         struct ext2_inode       inode;
2179         ext2_filsys             fs = ctx->fs;
2180         ext2_ino_t              ino;
2181         errcode_t               retval;
2182         const char *const *    cpp;
2183         int                     group, mount_flags;
2184
2185         clear_problem_context(&pctx);
2186
2187         /*
2188          * If the filesystem is opened read-only, or there is no
2189          * journal, then do nothing.
2190          */
2191         if ((ctx->options & E2F_OPT_READONLY) ||
2192             (sb->s_journal_inum == 0) ||
2193             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2194                 return;
2195
2196         /*
2197          * Read in the journal inode
2198          */
2199         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2200                 return;
2201
2202         /*
2203          * If it's necessary to backup the journal inode, do so.
2204          */
2205         if ((sb->s_jnl_backup_type == 0) ||
2206             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2207              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2208                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2209                         memcpy(sb->s_jnl_blocks, inode.i_block,
2210                                EXT2_N_BLOCKS*4);
2211                         sb->s_jnl_blocks[16] = inode.i_size;
2212                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2213                         ext2fs_mark_super_dirty(fs);
2214                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2215                 }
2216         }
2217
2218         /*
2219          * If the journal is already the hidden inode, then do nothing
2220          */
2221         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2222                 return;
2223
2224         /*
2225          * The journal inode had better have only one link and not be readable.
2226          */
2227         if (inode.i_links_count != 1)
2228                 return;
2229
2230         /*
2231          * If the filesystem is mounted, or we can't tell whether
2232          * or not it's mounted, do nothing.
2233          */
2234         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2235         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2236                 return;
2237
2238         /*
2239          * If we can't find the name of the journal inode, then do
2240          * nothing.
2241          */
2242         for (cpp = journal_names; *cpp; cpp++) {
2243                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2244                                        strlen(*cpp), 0, &ino);
2245                 if ((retval == 0) && (ino == sb->s_journal_inum))
2246                         break;
2247         }
2248         if (*cpp == 0)
2249                 return;
2250
2251         /* We need the inode bitmap to be loaded */
2252         retval = ext2fs_read_bitmaps(fs);
2253         if (retval)
2254                 return;
2255
2256         pctx.str = *cpp;
2257         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2258                 return;
2259
2260         /*
2261          * OK, we've done all the checks, let's actually move the
2262          * journal inode.  Errors at this point mean we need to force
2263          * an ext2 filesystem check.
2264          */
2265         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2266                 goto err_out;
2267         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2268                 goto err_out;
2269         sb->s_journal_inum = EXT2_JOURNAL_INO;
2270         ext2fs_mark_super_dirty(fs);
2271         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2272         inode.i_links_count = 0;
2273         inode.i_dtime = time(0);
2274         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2275                 goto err_out;
2276
2277         group = ext2fs_group_of_ino(fs, ino);
2278         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2279         ext2fs_mark_ib_dirty(fs);
2280         fs->group_desc[group].bg_free_inodes_count++;
2281         fs->super->s_free_inodes_count++;
2282         return;
2283
2284 err_out:
2285         pctx.errcode = retval;
2286         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2287         fs->super->s_state &= ~EXT2_VALID_FS;
2288         ext2fs_mark_super_dirty(fs);
2289 }
2290
2291 /*
2292  * message.c --- print e2fsck messages (with compression)
2293  *
2294  * print_e2fsck_message() prints a message to the user, using
2295  * compression techniques and expansions of abbreviations.
2296  *
2297  * The following % expansions are supported:
2298  *
2299  *      %b      <blk>                   block number
2300  *      %B      <blkcount>              integer
2301  *      %c      <blk2>                  block number
2302  *      %Di     <dirent>->ino           inode number
2303  *      %Dn     <dirent>->name          string
2304  *      %Dr     <dirent>->rec_len
2305  *      %Dl     <dirent>->name_len
2306  *      %Dt     <dirent>->filetype
2307  *      %d      <dir>                   inode number
2308  *      %g      <group>                 integer
2309  *      %i      <ino>                   inode number
2310  *      %Is     <inode> -> i_size
2311  *      %IS     <inode> -> i_extra_isize
2312  *      %Ib     <inode> -> i_blocks
2313  *      %Il     <inode> -> i_links_count
2314  *      %Im     <inode> -> i_mode
2315  *      %IM     <inode> -> i_mtime
2316  *      %IF     <inode> -> i_faddr
2317  *      %If     <inode> -> i_file_acl
2318  *      %Id     <inode> -> i_dir_acl
2319  *      %Iu     <inode> -> i_uid
2320  *      %Ig     <inode> -> i_gid
2321  *      %j      <ino2>                  inode number
2322  *      %m      <com_err error message>
2323  *      %N      <num>
2324  *      %p      ext2fs_get_pathname of directory <ino>
2325  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2326  *                      the containing directory.  (If dirent is NULL
2327  *                      then return the pathname of directory <ino2>)
2328  *      %q      ext2fs_get_pathname of directory <dir>
2329  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2330  *                      the containing directory.
2331  *      %s      <str>                   miscellaneous string
2332  *      %S      backup superblock
2333  *      %X      <num> hexadecimal format
2334  *
2335  * The following '@' expansions are supported:
2336  *
2337  *      @a      extended attribute
2338  *      @A      error allocating
2339  *      @b      block
2340  *      @B      bitmap
2341  *      @c      compress
2342  *      @C      conflicts with some other fs block
2343  *      @D      deleted
2344  *      @d      directory
2345  *      @e      entry
2346  *      @E      Entry '%Dn' in %p (%i)
2347  *      @f      filesystem
2348  *      @F      for @i %i (%Q) is
2349  *      @g      group
2350  *      @h      HTREE directory inode
2351  *      @i      inode
2352  *      @I      illegal
2353  *      @j      journal
2354  *      @l      lost+found
2355  *      @L      is a link
2356  *      @m      multiply-claimed
2357  *      @n      invalid
2358  *      @o      orphaned
2359  *      @p      problem in
2360  *      @r      root inode
2361  *      @s      should be
2362  *      @S      superblock
2363  *      @u      unattached
2364  *      @v      device
2365  *      @z      zero-length
2366  */
2367
2368
2369 /*
2370  * This structure defines the abbreviations used by the text strings
2371  * below.  The first character in the string is the index letter.  An
2372  * abbreviation of the form '@<i>' is expanded by looking up the index
2373  * letter <i> in the table below.
2374  */
2375 static const char *const abbrevs[] = {
2376         N_("aextended attribute"),
2377         N_("Aerror allocating"),
2378         N_("bblock"),
2379         N_("Bbitmap"),
2380         N_("ccompress"),
2381         N_("Cconflicts with some other fs @b"),
2382         N_("iinode"),
2383         N_("Iillegal"),
2384         N_("jjournal"),
2385         N_("Ddeleted"),
2386         N_("ddirectory"),
2387         N_("eentry"),
2388         N_("E@e '%Dn' in %p (%i)"),
2389         N_("ffilesystem"),
2390         N_("Ffor @i %i (%Q) is"),
2391         N_("ggroup"),
2392         N_("hHTREE @d @i"),
2393         N_("llost+found"),
2394         N_("Lis a link"),
2395     N_("mmultiply-claimed"),
2396     N_("ninvalid"),
2397         N_("oorphaned"),
2398         N_("pproblem in"),
2399         N_("rroot @i"),
2400         N_("sshould be"),
2401         N_("Ssuper@b"),
2402         N_("uunattached"),
2403         N_("vdevice"),
2404         N_("zzero-length"),
2405         "@@",
2406         0
2407         };
2408
2409 /*
2410  * Give more user friendly names to the "special" inodes.
2411  */
2412 #define num_special_inodes      11
2413 static const char *const special_inode_name[] =
2414 {
2415         N_("<The NULL inode>"),                 /* 0 */
2416         N_("<The bad blocks inode>"),           /* 1 */
2417         "/",                                    /* 2 */
2418         N_("<The ACL index inode>"),            /* 3 */
2419         N_("<The ACL data inode>"),             /* 4 */
2420         N_("<The boot loader inode>"),          /* 5 */
2421         N_("<The undelete directory inode>"),   /* 6 */
2422         N_("<The group descriptor inode>"),     /* 7 */
2423         N_("<The journal inode>"),              /* 8 */
2424         N_("<Reserved inode 9>"),               /* 9 */
2425         N_("<Reserved inode 10>"),              /* 10 */
2426 };
2427
2428 /*
2429  * This function does "safe" printing.  It will convert non-printable
2430  * ASCII characters using '^' and M- notation.
2431  */
2432 static void safe_print(const char *cp, int len)
2433 {
2434         unsigned char   ch;
2435
2436         if (len < 0)
2437                 len = strlen(cp);
2438
2439         while (len--) {
2440                 ch = *cp++;
2441                 if (ch > 128) {
2442                         fputs("M-", stdout);
2443                         ch -= 128;
2444                 }
2445                 if ((ch < 32) || (ch == 0x7f)) {
2446                         bb_putchar('^');
2447                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2448                 }
2449                 bb_putchar(ch);
2450         }
2451 }
2452
2453
2454 /*
2455  * This function prints a pathname, using the ext2fs_get_pathname
2456  * function
2457  */
2458 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2459 {
2460         errcode_t       retval;
2461         char            *path;
2462
2463         if (!dir && (ino < num_special_inodes)) {
2464                 fputs(_(special_inode_name[ino]), stdout);
2465                 return;
2466         }
2467
2468         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2469         if (retval)
2470                 fputs("???", stdout);
2471         else {
2472                 safe_print(path, -1);
2473                 ext2fs_free_mem(&path);
2474         }
2475 }
2476
2477 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2478                           struct problem_context *pctx, int first);
2479 /*
2480  * This function handles the '@' expansion.  We allow recursive
2481  * expansion; an @ expression can contain further '@' and '%'
2482  * expressions.
2483  */
2484 static void expand_at_expression(e2fsck_t ctx, char ch,
2485                                           struct problem_context *pctx,
2486                                           int *first)
2487 {
2488         const char *const *cpp;
2489         const char *str;
2490
2491         /* Search for the abbreviation */
2492         for (cpp = abbrevs; *cpp; cpp++) {
2493                 if (ch == *cpp[0])
2494                         break;
2495         }
2496         if (*cpp) {
2497                 str = _(*cpp) + 1;
2498                 if (*first && islower(*str)) {
2499                         *first = 0;
2500                         bb_putchar(toupper(*str++));
2501                 }
2502                 print_e2fsck_message(ctx, str, pctx, *first);
2503         } else
2504                 printf("@%c", ch);
2505 }
2506
2507 /*
2508  * This function expands '%IX' expressions
2509  */
2510 static void expand_inode_expression(char ch,
2511                                              struct problem_context *ctx)
2512 {
2513         struct ext2_inode       *inode;
2514         struct ext2_inode_large *large_inode;
2515         char *                  time_str;
2516         time_t                  t;
2517         int                     do_gmt = -1;
2518
2519         if (!ctx || !ctx->inode)
2520                 goto no_inode;
2521
2522         inode = ctx->inode;
2523         large_inode = (struct ext2_inode_large *) inode;
2524
2525         switch (ch) {
2526         case 's':
2527                 if (LINUX_S_ISDIR(inode->i_mode))
2528                         printf("%u", inode->i_size);
2529                 else {
2530                         printf("%"PRIu64, (inode->i_size |
2531                                         ((uint64_t) inode->i_size_high << 32)));
2532                 }
2533                 break;
2534         case 'S':
2535                 printf("%u", large_inode->i_extra_isize);
2536                 break;
2537         case 'b':
2538                 printf("%u", inode->i_blocks);
2539                 break;
2540         case 'l':
2541                 printf("%d", inode->i_links_count);
2542                 break;
2543         case 'm':
2544                 printf("0%o", inode->i_mode);
2545                 break;
2546         case 'M':
2547                 /* The diet libc doesn't respect the TZ environemnt variable */
2548                 if (do_gmt == -1) {
2549                         time_str = getenv("TZ");
2550                         if (!time_str)
2551                                 time_str = "";
2552                         do_gmt = !strcmp(time_str, "GMT");
2553                 }
2554                 t = inode->i_mtime;
2555                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2556                 printf("%.24s", time_str);
2557                 break;
2558         case 'F':
2559                 printf("%u", inode->i_faddr);
2560                 break;
2561         case 'f':
2562                 printf("%u", inode->i_file_acl);
2563                 break;
2564         case 'd':
2565                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2566                               inode->i_dir_acl : 0));
2567                 break;
2568         case 'u':
2569                 printf("%d", (inode->i_uid |
2570                               (inode->osd2.linux2.l_i_uid_high << 16)));
2571                 break;
2572         case 'g':
2573                 printf("%d", (inode->i_gid |
2574                               (inode->osd2.linux2.l_i_gid_high << 16)));
2575                 break;
2576         default:
2577         no_inode:
2578                 printf("%%I%c", ch);
2579                 break;
2580         }
2581 }
2582
2583 /*
2584  * This function expands '%dX' expressions
2585  */
2586 static void expand_dirent_expression(char ch,
2587                                               struct problem_context *ctx)
2588 {
2589         struct ext2_dir_entry   *dirent;
2590         int     len;
2591
2592         if (!ctx || !ctx->dirent)
2593                 goto no_dirent;
2594
2595         dirent = ctx->dirent;
2596
2597         switch (ch) {
2598         case 'i':
2599                 printf("%u", dirent->inode);
2600                 break;
2601         case 'n':
2602                 len = dirent->name_len & 0xFF;
2603                 if (len > EXT2_NAME_LEN)
2604                         len = EXT2_NAME_LEN;
2605                 if (len > dirent->rec_len)
2606                         len = dirent->rec_len;
2607                 safe_print(dirent->name, len);
2608                 break;
2609         case 'r':
2610                 printf("%u", dirent->rec_len);
2611                 break;
2612         case 'l':
2613                 printf("%u", dirent->name_len & 0xFF);
2614                 break;
2615         case 't':
2616                 printf("%u", dirent->name_len >> 8);
2617                 break;
2618         default:
2619         no_dirent:
2620                 printf("%%D%c", ch);
2621                 break;
2622         }
2623 }
2624
2625 static void expand_percent_expression(ext2_filsys fs, char ch,
2626                                                struct problem_context *ctx)
2627 {
2628         if (!ctx)
2629                 goto no_context;
2630
2631         switch (ch) {
2632         case '%':
2633                 bb_putchar('%');
2634                 break;
2635         case 'b':
2636                 printf("%u", ctx->blk);
2637                 break;
2638         case 'B':
2639                 printf("%"PRIi64, ctx->blkcount);
2640                 break;
2641         case 'c':
2642                 printf("%u", ctx->blk2);
2643                 break;
2644         case 'd':
2645                 printf("%u", ctx->dir);
2646                 break;
2647         case 'g':
2648                 printf("%d", ctx->group);
2649                 break;
2650         case 'i':
2651                 printf("%u", ctx->ino);
2652                 break;
2653         case 'j':
2654                 printf("%u", ctx->ino2);
2655                 break;
2656         case 'm':
2657                 fputs(error_message(ctx->errcode), stdout);
2658                 break;
2659         case 'N':
2660                 printf("%"PRIi64, ctx->num);
2661                 break;
2662         case 'p':
2663                 print_pathname(fs, ctx->ino, 0);
2664                 break;
2665         case 'P':
2666                 print_pathname(fs, ctx->ino2,
2667                                ctx->dirent ? ctx->dirent->inode : 0);
2668                 break;
2669         case 'q':
2670                 print_pathname(fs, ctx->dir, 0);
2671                 break;
2672         case 'Q':
2673                 print_pathname(fs, ctx->dir, ctx->ino);
2674                 break;
2675         case 'S':
2676                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2677                 break;
2678         case 's':
2679                 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2680                 break;
2681         case 'X':
2682                 printf("0x%"PRIi64, ctx->num);
2683                 break;
2684         default:
2685         no_context:
2686                 printf("%%%c", ch);
2687                 break;
2688         }
2689 }
2690
2691
2692 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2693                           struct problem_context *pctx, int first)
2694 {
2695         ext2_filsys fs = ctx->fs;
2696         const char *    cp;
2697         int             i;
2698
2699         e2fsck_clear_progbar(ctx);
2700         for (cp = msg; *cp; cp++) {
2701                 if (cp[0] == '@') {
2702                         cp++;
2703                         expand_at_expression(ctx, *cp, pctx, &first);
2704                 } else if (cp[0] == '%' && cp[1] == 'I') {
2705                         cp += 2;
2706                         expand_inode_expression(*cp, pctx);
2707                 } else if (cp[0] == '%' && cp[1] == 'D') {
2708                         cp += 2;
2709                         expand_dirent_expression(*cp, pctx);
2710                 } else if ((cp[0] == '%')) {
2711                         cp++;
2712                         expand_percent_expression(fs, *cp, pctx);
2713                 } else {
2714                         for (i=0; cp[i]; i++)
2715                                 if ((cp[i] == '@') || cp[i] == '%')
2716                                         break;
2717                         printf("%.*s", i, cp);
2718                         cp += i-1;
2719                 }
2720                 first = 0;
2721         }
2722 }
2723
2724
2725 /*
2726  * region.c --- code which manages allocations within a region.
2727  */
2728
2729 struct region_el {
2730         region_addr_t   start;
2731         region_addr_t   end;
2732         struct region_el *next;
2733 };
2734
2735 struct region_struct {
2736         region_addr_t   min;
2737         region_addr_t   max;
2738         struct region_el *allocated;
2739 };
2740
2741 static region_t region_create(region_addr_t min, region_addr_t max)
2742 {
2743         region_t        region;
2744
2745         region = malloc(sizeof(struct region_struct));
2746         if (!region)
2747                 return NULL;
2748         memset(region, 0, sizeof(struct region_struct));
2749         region->min = min;
2750         region->max = max;
2751         return region;
2752 }
2753
2754 static void region_free(region_t region)
2755 {
2756         struct region_el        *r, *next;
2757
2758         for (r = region->allocated; r; r = next) {
2759                 next = r->next;
2760                 free(r);
2761         }
2762         memset(region, 0, sizeof(struct region_struct));
2763         free(region);
2764 }
2765
2766 static int region_allocate(region_t region, region_addr_t start, int n)
2767 {
2768         struct region_el        *r, *new_region, *prev, *next;
2769         region_addr_t end;
2770
2771         end = start+n;
2772         if ((start < region->min) || (end > region->max))
2773                 return -1;
2774         if (n == 0)
2775                 return 1;
2776
2777         /*
2778          * Search through the linked list.  If we find that it
2779          * conflicts witih something that's already allocated, return
2780          * 1; if we can find an existing region which we can grow, do
2781          * so.  Otherwise, stop when we find the appropriate place
2782          * insert a new region element into the linked list.
2783          */
2784         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2785                 if (((start >= r->start) && (start < r->end)) ||
2786                     ((end > r->start) && (end <= r->end)) ||
2787                     ((start <= r->start) && (end >= r->end)))
2788                         return 1;
2789                 if (end == r->start) {
2790                         r->start = start;
2791                         return 0;
2792                 }
2793                 if (start == r->end) {
2794                         if ((next = r->next)) {
2795                                 if (end > next->start)
2796                                         return 1;
2797                                 if (end == next->start) {
2798                                         r->end = next->end;
2799                                         r->next = next->next;
2800                                         free(next);
2801                                         return 0;
2802                                 }
2803                         }
2804                         r->end = end;
2805                         return 0;
2806                 }
2807                 if (start < r->start)
2808                         break;
2809         }
2810         /*
2811          * Insert a new region element structure into the linked list
2812          */
2813         new_region = malloc(sizeof(struct region_el));
2814         if (!new_region)
2815                 return -1;
2816         new_region->start = start;
2817         new_region->end = start + n;
2818         new_region->next = r;
2819         if (prev)
2820                 prev->next = new_region;
2821         else
2822                 region->allocated = new_region;
2823         return 0;
2824 }
2825
2826 /*
2827  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2828  *
2829  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2830  * and applies the following tests to each inode:
2831  *
2832  *      - The mode field of the inode must be legal.
2833  *      - The size and block count fields of the inode are correct.
2834  *      - A data block must not be used by another inode
2835  *
2836  * Pass 1 also gathers the collects the following information:
2837  *
2838  *      - A bitmap of which inodes are in use.          (inode_used_map)
2839  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2840  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2841  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2842  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2843  *      - A bitmap of which blocks are in use.          (block_found_map)
2844  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2845  *      - The data blocks of the directory inodes.      (dir_map)
2846  *
2847  * Pass 1 is designed to stash away enough information so that the
2848  * other passes should not need to read in the inode information
2849  * during the normal course of a filesystem check.  (Althogh if an
2850  * inconsistency is detected, other passes may need to read in an
2851  * inode to fix it.)
2852  *
2853  * Note that pass 1B will be invoked if there are any duplicate blocks
2854  * found.
2855  */
2856
2857
2858 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2859                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2860                          int ref_offset, void *priv_data);
2861 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2862                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2863                              int ref_offset, void *priv_data);
2864 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2865                          char *block_buf);
2866 static void mark_table_blocks(e2fsck_t ctx);
2867 static void alloc_imagic_map(e2fsck_t ctx);
2868 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2869 static void handle_fs_bad_blocks(e2fsck_t ctx);
2870 static void process_inodes(e2fsck_t ctx, char *block_buf);
2871 static int process_inode_cmp(const void *a, const void *b);
2872 static errcode_t scan_callback(ext2_filsys fs,
2873                                   dgrp_t group, void * priv_data);
2874 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2875                                     char *block_buf, int adjust_sign);
2876 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2877
2878 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2879                                struct ext2_inode * inode, int bufsize,
2880                                const char *proc);
2881
2882 struct process_block_struct_1 {
2883         ext2_ino_t      ino;
2884         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2885                                 fragmented:1, compressed:1, bbcheck:1;
2886         blk_t           num_blocks;
2887         blk_t           max_blocks;
2888         e2_blkcnt_t     last_block;
2889         int             num_illegal_blocks;
2890         blk_t           previous_block;
2891         struct ext2_inode *inode;
2892         struct problem_context *pctx;
2893         ext2fs_block_bitmap fs_meta_blocks;
2894         e2fsck_t        ctx;
2895 };
2896
2897 struct process_inode_block {
2898         ext2_ino_t ino;
2899         struct ext2_inode inode;
2900 };
2901
2902 struct scan_callback_struct {
2903         e2fsck_t        ctx;
2904         char            *block_buf;
2905 };
2906
2907 /*
2908  * For the inodes to process list.
2909  */
2910 static struct process_inode_block *inodes_to_process;
2911 static int process_inode_count;
2912
2913 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2914                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2915
2916 /*
2917  * Free all memory allocated by pass1 in preparation for restarting
2918  * things.
2919  */
2920 static void unwind_pass1(void)
2921 {
2922         ext2fs_free_mem(&inodes_to_process);
2923 }
2924
2925 /*
2926  * Check to make sure a device inode is real.  Returns 1 if the device
2927  * checks out, 0 if not.
2928  *
2929  * Note: this routine is now also used to check FIFO's and Sockets,
2930  * since they have the same requirement; the i_block fields should be
2931  * zero.
2932  */
2933 static int
2934 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2935 {
2936         int     i;
2937
2938         /*
2939          * If i_blocks is non-zero, or the index flag is set, then
2940          * this is a bogus device/fifo/socket
2941          */
2942         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2943             (inode->i_flags & EXT2_INDEX_FL))
2944                 return 0;
2945
2946         /*
2947          * We should be able to do the test below all the time, but
2948          * because the kernel doesn't forcibly clear the device
2949          * inode's additional i_block fields, there are some rare
2950          * occasions when a legitimate device inode will have non-zero
2951          * additional i_block fields.  So for now, we only complain
2952          * when the immutable flag is set, which should never happen
2953          * for devices.  (And that's when the problem is caused, since
2954          * you can't set or clear immutable flags for devices.)  Once
2955          * the kernel has been fixed we can change this...
2956          */
2957         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2958                 for (i=4; i < EXT2_N_BLOCKS; i++)
2959                         if (inode->i_block[i])
2960                                 return 0;
2961         }
2962         return 1;
2963 }
2964
2965 /*
2966  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2967  * checks out, 0 if not.
2968  */
2969 static int
2970 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2971 {
2972         unsigned int len;
2973         int i;
2974         blk_t   blocks;
2975
2976         if ((inode->i_size_high || inode->i_size == 0) ||
2977             (inode->i_flags & EXT2_INDEX_FL))
2978                 return 0;
2979
2980         blocks = ext2fs_inode_data_blocks(fs, inode);
2981         if (blocks) {
2982                 if ((inode->i_size >= fs->blocksize) ||
2983                     (blocks != fs->blocksize >> 9) ||
2984                     (inode->i_block[0] < fs->super->s_first_data_block) ||
2985                     (inode->i_block[0] >= fs->super->s_blocks_count))
2986                         return 0;
2987
2988                 for (i = 1; i < EXT2_N_BLOCKS; i++)
2989                         if (inode->i_block[i])
2990                                 return 0;
2991
2992                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2993                         return 0;
2994
2995                 len = strnlen(buf, fs->blocksize);
2996                 if (len == fs->blocksize)
2997                         return 0;
2998         } else {
2999                 if (inode->i_size >= sizeof(inode->i_block))
3000                         return 0;
3001
3002                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3003                 if (len == sizeof(inode->i_block))
3004                         return 0;
3005         }
3006         if (len != inode->i_size)
3007                 return 0;
3008         return 1;
3009 }
3010
3011 /*
3012  * If the immutable (or append-only) flag is set on the inode, offer
3013  * to clear it.
3014  */
3015 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3016 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3017 {
3018         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3019                 return;
3020
3021         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3022                 return;
3023
3024         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3025         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3026 }
3027
3028 /*
3029  * If device, fifo or socket, check size is zero -- if not offer to
3030  * clear it
3031  */
3032 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3033 {
3034         struct ext2_inode *inode = pctx->inode;
3035
3036         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3037                 return;
3038
3039         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3040                 return;
3041
3042         inode->i_size = 0;
3043         inode->i_size_high = 0;
3044         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3045 }
3046
3047 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3048 {
3049         struct ext2_super_block *sb = ctx->fs->super;
3050         struct ext2_inode_large *inode;
3051         struct ext2_ext_attr_entry *entry;
3052         char *start, *end;
3053         int storage_size, remain, offs;
3054         int problem = 0;
3055
3056         inode = (struct ext2_inode_large *) pctx->inode;
3057         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3058                 inode->i_extra_isize;
3059         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3060                 inode->i_extra_isize + sizeof(__u32);
3061         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3062         entry = (struct ext2_ext_attr_entry *) start;
3063
3064         /* scan all entry's headers first */
3065
3066         /* take finish entry 0UL into account */
3067         remain = storage_size - sizeof(__u32);
3068         offs = end - start;
3069
3070         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3071
3072                 /* header eats this space */
3073                 remain -= sizeof(struct ext2_ext_attr_entry);
3074
3075                 /* is attribute name valid? */
3076                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3077                         pctx->num = entry->e_name_len;
3078                         problem = PR_1_ATTR_NAME_LEN;
3079                         goto fix;
3080                 }
3081
3082                 /* attribute len eats this space */
3083                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3084
3085                 /* check value size */
3086                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3087                         pctx->num = entry->e_value_size;
3088                         problem = PR_1_ATTR_VALUE_SIZE;
3089                         goto fix;
3090                 }
3091
3092                 /* check value placement */
3093                 if (entry->e_value_offs +
3094                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3095                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3096                         pctx->num = entry->e_value_offs;
3097                         problem = PR_1_ATTR_VALUE_OFFSET;
3098                         goto fix;
3099                 }
3100
3101                 /* e_value_block must be 0 in inode's ea */
3102                 if (entry->e_value_block != 0) {
3103                         pctx->num = entry->e_value_block;
3104                         problem = PR_1_ATTR_VALUE_BLOCK;
3105                         goto fix;
3106                 }
3107
3108                 /* e_hash must be 0 in inode's ea */
3109                 if (entry->e_hash != 0) {
3110                         pctx->num = entry->e_hash;
3111                         problem = PR_1_ATTR_HASH;
3112                         goto fix;
3113                 }
3114
3115                 remain -= entry->e_value_size;
3116                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3117
3118                 entry = EXT2_EXT_ATTR_NEXT(entry);
3119         }
3120 fix:
3121         /*
3122          * it seems like a corruption. it's very unlikely we could repair
3123          * EA(s) in automatic fashion -bzzz
3124          */
3125         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3126                 return;
3127
3128         /* simple remove all possible EA(s) */
3129         *((__u32 *)start) = 0UL;
3130         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3131                                 EXT2_INODE_SIZE(sb), "pass1");
3132 }
3133
3134 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3135 {
3136         struct ext2_super_block *sb = ctx->fs->super;
3137         struct ext2_inode_large *inode;
3138         __u32 *eamagic;
3139         int min, max;
3140
3141         inode = (struct ext2_inode_large *) pctx->inode;
3142         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3143                 /* this isn't large inode. so, nothing to check */
3144                 return;
3145         }
3146
3147         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3148         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3149         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3150         /*
3151          * For now we will allow i_extra_isize to be 0, but really
3152          * implementations should never allow i_extra_isize to be 0
3153          */
3154         if (inode->i_extra_isize &&
3155             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3156                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3157                         return;
3158                 inode->i_extra_isize = min;
3159                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3160                                         EXT2_INODE_SIZE(sb), "pass1");
3161                 return;
3162         }
3163
3164         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3165                         inode->i_extra_isize);
3166         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3167                 /* it seems inode has an extended attribute(s) in body */
3168                 check_ea_in_inode(ctx, pctx);
3169         }
3170 }
3171
3172 static void e2fsck_pass1(e2fsck_t ctx)
3173 {
3174         int     i;
3175         __u64   max_sizes;
3176         ext2_filsys fs = ctx->fs;
3177         ext2_ino_t      ino;
3178         struct ext2_inode *inode;
3179         ext2_inode_scan scan;
3180         char            *block_buf;
3181         unsigned char   frag, fsize;
3182         struct          problem_context pctx;
3183         struct          scan_callback_struct scan_struct;
3184         struct ext2_super_block *sb = ctx->fs->super;
3185         int             imagic_fs;
3186         int             busted_fs_time = 0;
3187         int             inode_size;
3188
3189         clear_problem_context(&pctx);
3190
3191         if (!(ctx->options & E2F_OPT_PREEN))
3192                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3193
3194         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3195             !(ctx->options & E2F_OPT_NO)) {
3196                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3197                         ctx->dirs_to_hash = 0;
3198         }
3199
3200         /* Pass 1 */
3201
3202 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3203
3204         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3205                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3206                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3207                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3208                 max_sizes = (max_sizes * (1UL << i)) - 1;
3209                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3210         }
3211 #undef EXT2_BPP
3212
3213         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3214
3215         /*
3216          * Allocate bitmaps structures
3217          */
3218         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3219                                               &ctx->inode_used_map);
3220         if (pctx.errcode) {
3221                 pctx.num = 1;
3222                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3223                 ctx->flags |= E2F_FLAG_ABORT;
3224                 return;
3225         }
3226         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3227                                 _("directory inode map"), &ctx->inode_dir_map);
3228         if (pctx.errcode) {
3229                 pctx.num = 2;
3230                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3231                 ctx->flags |= E2F_FLAG_ABORT;
3232                 return;
3233         }
3234         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3235                         _("regular file inode map"), &ctx->inode_reg_map);
3236         if (pctx.errcode) {
3237                 pctx.num = 6;
3238                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3239                 ctx->flags |= E2F_FLAG_ABORT;
3240                 return;
3241         }
3242         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3243                                               &ctx->block_found_map);
3244         if (pctx.errcode) {
3245                 pctx.num = 1;
3246                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3247                 ctx->flags |= E2F_FLAG_ABORT;
3248                 return;
3249         }
3250         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3251                                              &ctx->inode_link_info);
3252         if (pctx.errcode) {
3253                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3254                 ctx->flags |= E2F_FLAG_ABORT;
3255                 return;
3256         }
3257         inode_size = EXT2_INODE_SIZE(fs->super);
3258         inode = (struct ext2_inode *)
3259                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3260
3261         inodes_to_process = (struct process_inode_block *)
3262                 e2fsck_allocate_memory(ctx,
3263                                        (ctx->process_inode_size *
3264                                         sizeof(struct process_inode_block)),
3265                                        "array of inodes to process");
3266         process_inode_count = 0;
3267
3268         pctx.errcode = ext2fs_init_dblist(fs, 0);
3269         if (pctx.errcode) {
3270                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3271                 ctx->flags |= E2F_FLAG_ABORT;
3272                 return;
3273         }
3274
3275         /*
3276          * If the last orphan field is set, clear it, since the pass1
3277          * processing will automatically find and clear the orphans.
3278          * In the future, we may want to try using the last_orphan
3279          * linked list ourselves, but for now, we clear it so that the
3280          * ext3 mount code won't get confused.
3281          */
3282         if (!(ctx->options & E2F_OPT_READONLY)) {
3283                 if (fs->super->s_last_orphan) {
3284                         fs->super->s_last_orphan = 0;
3285                         ext2fs_mark_super_dirty(fs);
3286                 }
3287         }
3288
3289         mark_table_blocks(ctx);
3290         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3291                                                     "block interate buffer");
3292         e2fsck_use_inode_shortcuts(ctx, 1);
3293         ehandler_operation(_("doing inode scan"));
3294         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3295                                               &scan);
3296         if (pctx.errcode) {
3297                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3298                 ctx->flags |= E2F_FLAG_ABORT;
3299                 return;
3300         }
3301         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3302         ctx->stashed_inode = inode;
3303         scan_struct.ctx = ctx;
3304         scan_struct.block_buf = block_buf;
3305         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3306         if (ctx->progress)
3307                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3308                         return;
3309         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3310             (fs->super->s_mtime < fs->super->s_inodes_count))
3311                 busted_fs_time = 1;
3312
3313         while (1) {
3314                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3315                                                           inode, inode_size);
3316                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3317                         return;
3318                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3319                         continue;
3320                 }
3321                 if (pctx.errcode) {
3322                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3323                         ctx->flags |= E2F_FLAG_ABORT;
3324                         return;
3325                 }
3326                 if (!ino)
3327                         break;
3328                 pctx.ino = ino;
3329                 pctx.inode = inode;
3330                 ctx->stashed_ino = ino;
3331                 if (inode->i_links_count) {
3332                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3333                                            ino, inode->i_links_count);
3334                         if (pctx.errcode) {
3335                                 pctx.num = inode->i_links_count;
3336                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3337                                 ctx->flags |= E2F_FLAG_ABORT;
3338                                 return;
3339                         }
3340                 }
3341                 if (ino == EXT2_BAD_INO) {
3342                         struct process_block_struct_1 pb;
3343
3344                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3345                                                           &pb.fs_meta_blocks);
3346                         if (pctx.errcode) {
3347                                 pctx.num = 4;
3348                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3349                                 ctx->flags |= E2F_FLAG_ABORT;
3350                                 return;
3351                         }
3352                         pb.ino = EXT2_BAD_INO;
3353                         pb.num_blocks = pb.last_block = 0;
3354                         pb.num_illegal_blocks = 0;
3355                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3356                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3357                         pb.inode = inode;
3358                         pb.pctx = &pctx;
3359                         pb.ctx = ctx;
3360                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3361                                      block_buf, process_bad_block, &pb);
3362                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3363                         if (pctx.errcode) {
3364                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3365                                 ctx->flags |= E2F_FLAG_ABORT;
3366                                 return;
3367                         }
3368                         if (pb.bbcheck)
3369                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3370                                 ctx->flags |= E2F_FLAG_ABORT;
3371                                 return;
3372                         }
3373                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3374                         clear_problem_context(&pctx);
3375                         continue;
3376                 } else if (ino == EXT2_ROOT_INO) {
3377                         /*
3378                          * Make sure the root inode is a directory; if
3379                          * not, offer to clear it.  It will be
3380                          * regnerated in pass #3.
3381                          */
3382                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3383                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3384                                         inode->i_dtime = time(0);
3385                                         inode->i_links_count = 0;
3386                                         ext2fs_icount_store(ctx->inode_link_info,
3387                                                             ino, 0);
3388                                         e2fsck_write_inode(ctx, ino, inode,
3389                                                            "pass1");
3390                                 }
3391
3392                         }
3393                         /*
3394                          * If dtime is set, offer to clear it.  mke2fs
3395                          * version 0.2b created filesystems with the
3396                          * dtime field set for the root and lost+found
3397                          * directories.  We won't worry about
3398                          * /lost+found, since that can be regenerated
3399                          * easily.  But we will fix the root directory
3400                          * as a special case.
3401                          */
3402                         if (inode->i_dtime && inode->i_links_count) {
3403                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3404                                         inode->i_dtime = 0;
3405                                         e2fsck_write_inode(ctx, ino, inode,
3406                                                            "pass1");
3407                                 }
3408                         }
3409                 } else if (ino == EXT2_JOURNAL_INO) {
3410                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3411                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3412                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3413                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3414                                                 &pctx)) {
3415                                         inode->i_mode = LINUX_S_IFREG;
3416                                         e2fsck_write_inode(ctx, ino, inode,
3417                                                            "pass1");
3418                                 }
3419                                 check_blocks(ctx, &pctx, block_buf);
3420                                 continue;
3421                         }
3422                         if ((inode->i_links_count || inode->i_blocks ||
3423                              inode->i_blocks || inode->i_block[0]) &&
3424                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3425                                         &pctx)) {
3426                                 memset(inode, 0, inode_size);
3427                                 ext2fs_icount_store(ctx->inode_link_info,
3428                                                     ino, 0);
3429                                 e2fsck_write_inode_full(ctx, ino, inode,
3430                                                         inode_size, "pass1");
3431                         }
3432                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3433                         int     problem = 0;
3434
3435                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3436                         if (ino == EXT2_BOOT_LOADER_INO) {
3437                                 if (LINUX_S_ISDIR(inode->i_mode))
3438                                         problem = PR_1_RESERVED_BAD_MODE;
3439                         } else if (ino == EXT2_RESIZE_INO) {
3440                                 if (inode->i_mode &&
3441                                     !LINUX_S_ISREG(inode->i_mode))
3442                                         problem = PR_1_RESERVED_BAD_MODE;
3443                         } else {
3444                                 if (inode->i_mode != 0)
3445                                         problem = PR_1_RESERVED_BAD_MODE;
3446                         }
3447                         if (problem) {
3448                                 if (fix_problem(ctx, problem, &pctx)) {
3449                                         inode->i_mode = 0;
3450                                         e2fsck_write_inode(ctx, ino, inode,
3451                                                            "pass1");
3452                                 }
3453                         }
3454                         check_blocks(ctx, &pctx, block_buf);
3455                         continue;
3456                 }
3457                 /*
3458                  * Check for inodes who might have been part of the
3459                  * orphaned list linked list.  They should have gotten
3460                  * dealt with by now, unless the list had somehow been
3461                  * corrupted.
3462                  *
3463                  * FIXME: In the future, inodes which are still in use
3464                  * (and which are therefore) pending truncation should
3465                  * be handled specially.  Right now we just clear the
3466                  * dtime field, and the normal e2fsck handling of
3467                  * inodes where i_size and the inode blocks are
3468                  * inconsistent is to fix i_size, instead of releasing
3469                  * the extra blocks.  This won't catch the inodes that
3470                  * was at the end of the orphan list, but it's better
3471                  * than nothing.  The right answer is that there
3472                  * shouldn't be any bugs in the orphan list handling.  :-)
3473                  */
3474                 if (inode->i_dtime && !busted_fs_time &&
3475                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3476                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3477                                 inode->i_dtime = inode->i_links_count ?
3478                                         0 : time(0);
3479                                 e2fsck_write_inode(ctx, ino, inode,
3480                                                    "pass1");
3481                         }
3482                 }
3483
3484                 /*
3485                  * This code assumes that deleted inodes have
3486                  * i_links_count set to 0.
3487                  */
3488                 if (!inode->i_links_count) {
3489                         if (!inode->i_dtime && inode->i_mode) {
3490                                 if (fix_problem(ctx,
3491                                             PR_1_ZERO_DTIME, &pctx)) {
3492                                         inode->i_dtime = time(0);
3493                                         e2fsck_write_inode(ctx, ino, inode,
3494                                                            "pass1");
3495                                 }
3496                         }
3497                         continue;
3498                 }
3499                 /*
3500                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3501                  * deleted files.  Oops.
3502                  *
3503                  * Since all new ext2 implementations get this right,
3504                  * we now assume that the case of non-zero
3505                  * i_links_count and non-zero dtime means that we
3506                  * should keep the file, not delete it.
3507                  *
3508                  */
3509                 if (inode->i_dtime) {
3510                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3511                                 inode->i_dtime = 0;
3512                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3513                         }
3514                 }
3515
3516                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3517                 switch (fs->super->s_creator_os) {
3518                     case EXT2_OS_LINUX:
3519                         frag = inode->osd2.linux2.l_i_frag;
3520                         fsize = inode->osd2.linux2.l_i_fsize;
3521                         break;
3522                     case EXT2_OS_HURD:
3523                         frag = inode->osd2.hurd2.h_i_frag;
3524                         fsize = inode->osd2.hurd2.h_i_fsize;
3525                         break;
3526                     case EXT2_OS_MASIX:
3527                         frag = inode->osd2.masix2.m_i_frag;
3528                         fsize = inode->osd2.masix2.m_i_fsize;
3529                         break;
3530                     default:
3531                         frag = fsize = 0;
3532                 }
3533
3534                 if (inode->i_faddr || frag || fsize ||
3535                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3536                         mark_inode_bad(ctx, ino);
3537                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3538                         if (imagic_fs) {
3539                                 if (!ctx->inode_imagic_map)
3540                                         alloc_imagic_map(ctx);
3541                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3542                                                          ino);
3543                         } else {
3544                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3545                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3546                                         e2fsck_write_inode(ctx, ino,
3547                                                            inode, "pass1");
3548                                 }
3549                         }
3550                 }
3551
3552                 check_inode_extra_space(ctx, &pctx);
3553
3554                 if (LINUX_S_ISDIR(inode->i_mode)) {
3555                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3556                         e2fsck_add_dir_info(ctx, ino, 0);
3557                         ctx->fs_directory_count++;
3558                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3559                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3560                         ctx->fs_regular_count++;
3561                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3562                            e2fsck_pass1_check_device_inode(fs, inode)) {
3563                         check_immutable(ctx, &pctx);
3564                         check_size(ctx, &pctx);
3565                         ctx->fs_chardev_count++;
3566                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3567                            e2fsck_pass1_check_device_inode(fs, inode)) {
3568                         check_immutable(ctx, &pctx);
3569                         check_size(ctx, &pctx);
3570                         ctx->fs_blockdev_count++;
3571                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3572                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3573                         check_immutable(ctx, &pctx);
3574                         ctx->fs_symlinks_count++;
3575                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3576                                 ctx->fs_fast_symlinks_count++;
3577                                 check_blocks(ctx, &pctx, block_buf);
3578                                 continue;
3579                         }
3580                 }
3581                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3582                          e2fsck_pass1_check_device_inode(fs, inode)) {
3583                         check_immutable(ctx, &pctx);
3584                         check_size(ctx, &pctx);
3585                         ctx->fs_fifo_count++;
3586                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3587                            e2fsck_pass1_check_device_inode(fs, inode)) {
3588                         check_immutable(ctx, &pctx);
3589                         check_size(ctx, &pctx);
3590                         ctx->fs_sockets_count++;
3591                 } else
3592                         mark_inode_bad(ctx, ino);
3593                 if (inode->i_block[EXT2_IND_BLOCK])
3594                         ctx->fs_ind_count++;
3595                 if (inode->i_block[EXT2_DIND_BLOCK])
3596                         ctx->fs_dind_count++;
3597                 if (inode->i_block[EXT2_TIND_BLOCK])
3598                         ctx->fs_tind_count++;
3599                 if (inode->i_block[EXT2_IND_BLOCK] ||
3600                     inode->i_block[EXT2_DIND_BLOCK] ||
3601                     inode->i_block[EXT2_TIND_BLOCK] ||
3602                     inode->i_file_acl) {
3603                         inodes_to_process[process_inode_count].ino = ino;
3604                         inodes_to_process[process_inode_count].inode = *inode;
3605                         process_inode_count++;
3606                 } else
3607                         check_blocks(ctx, &pctx, block_buf);
3608
3609                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3610                         return;
3611
3612                 if (process_inode_count >= ctx->process_inode_size) {
3613                         process_inodes(ctx, block_buf);
3614
3615                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3616                                 return;
3617                 }
3618         }
3619         process_inodes(ctx, block_buf);
3620         ext2fs_close_inode_scan(scan);
3621         ehandler_operation(0);
3622
3623         /*
3624          * If any extended attribute blocks' reference counts need to
3625          * be adjusted, either up (ctx->refcount_extra), or down
3626          * (ctx->refcount), then fix them.
3627          */
3628         if (ctx->refcount) {
3629                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3630                 ea_refcount_free(ctx->refcount);
3631                 ctx->refcount = 0;
3632         }
3633         if (ctx->refcount_extra) {
3634                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3635                                         block_buf, +1);
3636                 ea_refcount_free(ctx->refcount_extra);
3637                 ctx->refcount_extra = 0;
3638         }
3639
3640         if (ctx->invalid_bitmaps)
3641                 handle_fs_bad_blocks(ctx);
3642
3643         /* We don't need the block_ea_map any more */
3644         ext2fs_free_block_bitmap(ctx->block_ea_map);
3645         ctx->block_ea_map = 0;
3646
3647         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3648                 ext2fs_block_bitmap save_bmap;
3649
3650                 save_bmap = fs->block_map;
3651                 fs->block_map = ctx->block_found_map;
3652                 clear_problem_context(&pctx);
3653                 pctx.errcode = ext2fs_create_resize_inode(fs);
3654                 if (pctx.errcode) {
3655                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3656                         /* Should never get here */
3657                         ctx->flags |= E2F_FLAG_ABORT;
3658                         return;
3659                 }
3660                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3661                                   "recreate inode");
3662                 inode->i_mtime = time(0);
3663                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3664                                   "recreate inode");
3665                 fs->block_map = save_bmap;
3666                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3667         }
3668
3669         if (ctx->flags & E2F_FLAG_RESTART) {
3670                 /*
3671                  * Only the master copy of the superblock and block
3672                  * group descriptors are going to be written during a
3673                  * restart, so set the superblock to be used to be the
3674                  * master superblock.
3675                  */
3676                 ctx->use_superblock = 0;
3677                 unwind_pass1();
3678                 goto endit;
3679         }
3680
3681         if (ctx->block_dup_map) {
3682                 if (ctx->options & E2F_OPT_PREEN) {
3683                         clear_problem_context(&pctx);
3684                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3685                 }
3686                 e2fsck_pass1_dupblocks(ctx, block_buf);
3687         }
3688         ext2fs_free_mem(&inodes_to_process);
3689 endit:
3690         e2fsck_use_inode_shortcuts(ctx, 0);
3691
3692         ext2fs_free_mem(&block_buf);
3693         ext2fs_free_mem(&inode);
3694
3695 }
3696
3697 /*
3698  * When the inode_scan routines call this callback at the end of the
3699  * glock group, call process_inodes.
3700  */
3701 static errcode_t scan_callback(ext2_filsys fs,
3702                                dgrp_t group, void * priv_data)
3703 {
3704         struct scan_callback_struct *scan_struct;
3705         e2fsck_t ctx;
3706
3707         scan_struct = (struct scan_callback_struct *) priv_data;
3708         ctx = scan_struct->ctx;
3709
3710         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3711
3712         if (ctx->progress)
3713                 if ((ctx->progress)(ctx, 1, group+1,
3714                                     ctx->fs->group_desc_count))
3715                         return EXT2_ET_CANCEL_REQUESTED;
3716
3717         return 0;
3718 }
3719
3720 /*
3721  * Process the inodes in the "inodes to process" list.
3722  */
3723 static void process_inodes(e2fsck_t ctx, char *block_buf)
3724 {
3725         int                     i;
3726         struct ext2_inode       *old_stashed_inode;
3727         ext2_ino_t              old_stashed_ino;
3728         const char              *old_operation;
3729         char                    buf[80];
3730         struct problem_context  pctx;
3731
3732         /* begin process_inodes */
3733         if (process_inode_count == 0)
3734                 return;
3735         old_operation = ehandler_operation(0);
3736         old_stashed_inode = ctx->stashed_inode;
3737         old_stashed_ino = ctx->stashed_ino;
3738         qsort(inodes_to_process, process_inode_count,
3739                       sizeof(struct process_inode_block), process_inode_cmp);
3740         clear_problem_context(&pctx);
3741         for (i=0; i < process_inode_count; i++) {
3742                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3743                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3744                 sprintf(buf, _("reading indirect blocks of inode %u"),
3745                         pctx.ino);
3746                 ehandler_operation(buf);
3747                 check_blocks(ctx, &pctx, block_buf);
3748                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3749                         break;
3750         }
3751         ctx->stashed_inode = old_stashed_inode;
3752         ctx->stashed_ino = old_stashed_ino;
3753         process_inode_count = 0;
3754         /* end process inodes */
3755
3756         ehandler_operation(old_operation);
3757 }
3758
3759 static int process_inode_cmp(const void *a, const void *b)
3760 {
3761         const struct process_inode_block *ib_a =
3762                 (const struct process_inode_block *) a;
3763         const struct process_inode_block *ib_b =
3764                 (const struct process_inode_block *) b;
3765         int     ret;
3766
3767         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3768                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3769         if (ret == 0)
3770                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3771         return ret;
3772 }
3773
3774 /*
3775  * Mark an inode as being bad in some what
3776  */
3777 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3778 {
3779         struct          problem_context pctx;
3780
3781         if (!ctx->inode_bad_map) {
3782                 clear_problem_context(&pctx);
3783
3784                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3785                             _("bad inode map"), &ctx->inode_bad_map);
3786                 if (pctx.errcode) {
3787                         pctx.num = 3;
3788                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3789                         /* Should never get here */
3790                         ctx->flags |= E2F_FLAG_ABORT;
3791                         return;
3792                 }
3793         }
3794         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3795 }
3796
3797
3798 /*
3799  * This procedure will allocate the inode imagic table
3800  */
3801 static void alloc_imagic_map(e2fsck_t ctx)
3802 {
3803         struct          problem_context pctx;
3804
3805         clear_problem_context(&pctx);
3806         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3807                                               _("imagic inode map"),
3808                                               &ctx->inode_imagic_map);
3809         if (pctx.errcode) {
3810                 pctx.num = 5;
3811                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3812                 /* Should never get here */
3813                 ctx->flags |= E2F_FLAG_ABORT;
3814                 return;
3815         }
3816 }
3817
3818 /*
3819  * Marks a block as in use, setting the dup_map if it's been set
3820  * already.  Called by process_block and process_bad_block.
3821  *
3822  * WARNING: Assumes checks have already been done to make sure block
3823  * is valid.  This is true in both process_block and process_bad_block.
3824  */
3825 static void mark_block_used(e2fsck_t ctx, blk_t block)
3826 {
3827         struct          problem_context pctx;
3828
3829         clear_problem_context(&pctx);
3830
3831         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3832                 if (!ctx->block_dup_map) {
3833                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3834                               _("multiply claimed block map"),
3835                               &ctx->block_dup_map);
3836                         if (pctx.errcode) {
3837                                 pctx.num = 3;
3838                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3839                                             &pctx);
3840                                 /* Should never get here */
3841                                 ctx->flags |= E2F_FLAG_ABORT;
3842                                 return;
3843                         }
3844                 }
3845                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3846         } else {
3847                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3848         }
3849 }
3850
3851 /*
3852  * Adjust the extended attribute block's reference counts at the end
3853  * of pass 1, either by subtracting out references for EA blocks that
3854  * are still referenced in ctx->refcount, or by adding references for
3855  * EA blocks that had extra references as accounted for in
3856  * ctx->refcount_extra.
3857  */
3858 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3859                                     char *block_buf, int adjust_sign)
3860 {
3861         struct ext2_ext_attr_header     *header;
3862         struct problem_context          pctx;
3863         ext2_filsys                     fs = ctx->fs;
3864         blk_t                           blk;
3865         __u32                           should_be;
3866         int                             count;
3867
3868         clear_problem_context(&pctx);
3869
3870         ea_refcount_intr_begin(refcount);
3871         while (1) {
3872                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3873                         break;
3874                 pctx.blk = blk;
3875                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3876                 if (pctx.errcode) {
3877                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3878                         return;
3879                 }
3880                 header = (struct ext2_ext_attr_header *) block_buf;
3881                 pctx.blkcount = header->h_refcount;
3882                 should_be = header->h_refcount + adjust_sign * count;
3883                 pctx.num = should_be;
3884                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3885                         header->h_refcount = should_be;
3886                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3887                                                              block_buf);
3888                         if (pctx.errcode) {
3889                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3890                                 continue;
3891                         }
3892                 }
3893         }
3894 }
3895
3896 /*
3897  * Handle processing the extended attribute blocks
3898  */
3899 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3900                            char *block_buf)
3901 {
3902         ext2_filsys fs = ctx->fs;
3903         ext2_ino_t      ino = pctx->ino;
3904         struct ext2_inode *inode = pctx->inode;
3905         blk_t           blk;
3906         char *          end;
3907         struct ext2_ext_attr_header *header;
3908         struct ext2_ext_attr_entry *entry;
3909         int             count;
3910         region_t        region;
3911
3912         blk = inode->i_file_acl;
3913         if (blk == 0)
3914                 return 0;
3915
3916         /*
3917          * If the Extended attribute flag isn't set, then a non-zero
3918          * file acl means that the inode is corrupted.
3919          *
3920          * Or if the extended attribute block is an invalid block,
3921          * then the inode is also corrupted.
3922          */
3923         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3924             (blk < fs->super->s_first_data_block) ||
3925             (blk >= fs->super->s_blocks_count)) {
3926                 mark_inode_bad(ctx, ino);
3927                 return 0;
3928         }
3929
3930         /* If ea bitmap hasn't been allocated, create it */
3931         if (!ctx->block_ea_map) {
3932                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3933                                                       _("ext attr block map"),
3934                                                       &ctx->block_ea_map);
3935                 if (pctx->errcode) {
3936                         pctx->num = 2;
3937                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3938                         ctx->flags |= E2F_FLAG_ABORT;
3939                         return 0;
3940                 }
3941         }
3942
3943         /* Create the EA refcount structure if necessary */
3944         if (!ctx->refcount) {
3945                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3946                 if (pctx->errcode) {
3947                         pctx->num = 1;
3948                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3949                         ctx->flags |= E2F_FLAG_ABORT;
3950                         return 0;
3951                 }
3952         }
3953
3954         /* Have we seen this EA block before? */
3955         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3956                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3957                         return 1;
3958                 /* Ooops, this EA was referenced more than it stated */
3959                 if (!ctx->refcount_extra) {
3960                         pctx->errcode = ea_refcount_create(0,
3961                                            &ctx->refcount_extra);
3962                         if (pctx->errcode) {
3963                                 pctx->num = 2;
3964                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3965                                 ctx->flags |= E2F_FLAG_ABORT;
3966                                 return 0;
3967                         }
3968                 }
3969                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3970                 return 1;
3971         }
3972
3973         /*
3974          * OK, we haven't seen this EA block yet.  So we need to
3975          * validate it
3976          */
3977         pctx->blk = blk;
3978         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3979         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3980                 goto clear_extattr;
3981         header = (struct ext2_ext_attr_header *) block_buf;
3982         pctx->blk = inode->i_file_acl;
3983         if (((ctx->ext_attr_ver == 1) &&
3984              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3985             ((ctx->ext_attr_ver == 2) &&
3986              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3987                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3988                         goto clear_extattr;
3989         }
3990
3991         if (header->h_blocks != 1) {
3992                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3993                         goto clear_extattr;
3994         }
3995
3996         region = region_create(0, fs->blocksize);
3997         if (!region) {
3998                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3999                 ctx->flags |= E2F_FLAG_ABORT;
4000                 return 0;
4001         }
4002         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4003                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4004                         goto clear_extattr;
4005         }
4006
4007         entry = (struct ext2_ext_attr_entry *)(header+1);
4008         end = block_buf + fs->blocksize;
4009         while ((char *)entry < end && *(__u32 *)entry) {
4010                 if (region_allocate(region, (char *)entry - (char *)header,
4011                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4012                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4013                                 goto clear_extattr;
4014                 }
4015                 if ((ctx->ext_attr_ver == 1 &&
4016                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4017                     (ctx->ext_attr_ver == 2 &&
4018                      entry->e_name_index == 0)) {
4019                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4020                                 goto clear_extattr;
4021                 }
4022                 if (entry->e_value_block != 0) {
4023                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4024                                 goto clear_extattr;
4025                 }
4026                 if (entry->e_value_size &&
4027                     region_allocate(region, entry->e_value_offs,
4028                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4029                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4030                                 goto clear_extattr;
4031                 }
4032                 entry = EXT2_EXT_ATTR_NEXT(entry);
4033         }
4034         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4035                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4036                         goto clear_extattr;
4037         }
4038         region_free(region);
4039
4040         count = header->h_refcount - 1;
4041         if (count)
4042                 ea_refcount_store(ctx->refcount, blk, count);
4043         mark_block_used(ctx, blk);
4044         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4045
4046         return 1;
4047
4048 clear_extattr:
4049         inode->i_file_acl = 0;
4050         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4051         return 0;
4052 }
4053
4054 /* Returns 1 if bad htree, 0 if OK */
4055 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4056                         ext2_ino_t ino FSCK_ATTR((unused)),
4057                         struct ext2_inode *inode,
4058                         char *block_buf)
4059 {
4060         struct ext2_dx_root_info        *root;
4061         ext2_filsys                     fs = ctx->fs;
4062         errcode_t                       retval;
4063         blk_t                           blk;
4064
4065         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4066              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4067             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4068              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4069                 return 1;
4070
4071         blk = inode->i_block[0];
4072         if (((blk == 0) ||
4073              (blk < fs->super->s_first_data_block) ||
4074              (blk >= fs->super->s_blocks_count)) &&
4075             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4076                 return 1;
4077
4078         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4079         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4080                 return 1;
4081
4082         /* XXX should check that beginning matches a directory */
4083         root = (struct ext2_dx_root_info *) (block_buf + 24);
4084
4085         if ((root->reserved_zero || root->info_length < 8) &&
4086             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4087                 return 1;
4088
4089         pctx->num = root->hash_version;
4090         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4091             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4092             (root->hash_version != EXT2_HASH_TEA) &&
4093             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4094                 return 1;
4095
4096         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4097             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4098                 return 1;
4099
4100         pctx->num = root->indirect_levels;
4101         if ((root->indirect_levels > 1) &&
4102             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4103                 return 1;
4104
4105         return 0;
4106 }
4107
4108 /*
4109  * This subroutine is called on each inode to account for all of the
4110  * blocks used by that inode.
4111  */
4112 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4113                          char *block_buf)
4114 {
4115         ext2_filsys fs = ctx->fs;
4116         struct process_block_struct_1 pb;
4117         ext2_ino_t      ino = pctx->ino;
4118         struct ext2_inode *inode = pctx->inode;
4119         int             bad_size = 0;
4120         int             dirty_inode = 0;
4121         __u64           size;
4122
4123         pb.ino = ino;
4124         pb.num_blocks = 0;
4125         pb.last_block = -1;
4126         pb.num_illegal_blocks = 0;
4127         pb.suppress = 0; pb.clear = 0;
4128         pb.fragmented = 0;
4129         pb.compressed = 0;
4130         pb.previous_block = 0;
4131         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4132         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4133         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4134         pb.inode = inode;
4135         pb.pctx = pctx;
4136         pb.ctx = ctx;
4137         pctx->ino = ino;
4138         pctx->errcode = 0;
4139
4140         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4141                 if (fs->super->s_feature_incompat &
4142                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4143                         pb.compressed = 1;
4144                 else {
4145                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4146                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4147                                 dirty_inode++;
4148                         }
4149                 }
4150         }
4151
4152         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4153                 pb.num_blocks++;
4154
4155         if (ext2fs_inode_has_valid_blocks(inode))
4156                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4157                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4158                                        block_buf, process_block, &pb);
4159         end_problem_latch(ctx, PR_LATCH_BLOCK);
4160         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4161         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4162                 goto out;
4163         if (pctx->errcode)
4164                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4165
4166         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4167                 ctx->fs_fragmented++;
4168
4169         if (pb.clear) {
4170                 inode->i_links_count = 0;
4171                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4172                 inode->i_dtime = time(0);
4173                 dirty_inode++;
4174                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4175                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4176                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4177                 /*
4178                  * The inode was probably partially accounted for
4179                  * before processing was aborted, so we need to
4180                  * restart the pass 1 scan.
4181                  */
4182                 ctx->flags |= E2F_FLAG_RESTART;
4183                 goto out;
4184         }
4185
4186         if (inode->i_flags & EXT2_INDEX_FL) {
4187                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4188                         inode->i_flags &= ~EXT2_INDEX_FL;
4189                         dirty_inode++;
4190                 } else {
4191 #ifdef ENABLE_HTREE
4192                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4193 #endif
4194                 }
4195         }
4196         if (ctx->dirs_to_hash && pb.is_dir &&
4197             !(inode->i_flags & EXT2_INDEX_FL) &&
4198             ((inode->i_size / fs->blocksize) >= 3))
4199                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4200
4201         if (!pb.num_blocks && pb.is_dir) {
4202                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4203                         inode->i_links_count = 0;
4204                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4205                         inode->i_dtime = time(0);
4206                         dirty_inode++;
4207                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4208                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4209                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4210                         ctx->fs_directory_count--;
4211                         goto out;
4212                 }
4213         }
4214
4215         pb.num_blocks *= (fs->blocksize / 512);
4216
4217         if (pb.is_dir) {
4218                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4219                 if (nblock > (pb.last_block + 1))
4220                         bad_size = 1;
4221                 else if (nblock < (pb.last_block + 1)) {
4222                         if (((pb.last_block + 1) - nblock) >
4223                             fs->super->s_prealloc_dir_blocks)
4224                                 bad_size = 2;
4225                 }
4226         } else {
4227                 size = EXT2_I_SIZE(inode);
4228                 if ((pb.last_block >= 0) &&
4229                     (size < (__u64) pb.last_block * fs->blocksize))
4230                         bad_size = 3;
4231                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4232                         bad_size = 4;
4233         }
4234         /* i_size for symlinks is checked elsewhere */
4235         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4236                 pctx->num = (pb.last_block+1) * fs->blocksize;
4237                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4238                         inode->i_size = pctx->num;
4239                         if (!LINUX_S_ISDIR(inode->i_mode))
4240                                 inode->i_size_high = pctx->num >> 32;
4241                         dirty_inode++;
4242                 }
4243                 pctx->num = 0;
4244         }
4245         if (LINUX_S_ISREG(inode->i_mode) &&
4246             (inode->i_size_high || inode->i_size & 0x80000000UL))
4247                 ctx->large_files++;
4248         if (pb.num_blocks != inode->i_blocks) {
4249                 pctx->num = pb.num_blocks;
4250                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4251                         inode->i_blocks = pb.num_blocks;
4252                         dirty_inode++;
4253                 }
4254                 pctx->num = 0;
4255         }
4256 out:
4257         if (dirty_inode)
4258                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4259 }
4260
4261
4262 /*
4263  * This is a helper function for check_blocks().
4264  */
4265 static int process_block(ext2_filsys fs,
4266                   blk_t *block_nr,
4267                   e2_blkcnt_t blockcnt,
4268                   blk_t ref_block FSCK_ATTR((unused)),
4269                   int ref_offset FSCK_ATTR((unused)),
4270                   void *priv_data)
4271 {
4272         struct process_block_struct_1 *p;
4273         struct problem_context *pctx;
4274         blk_t   blk = *block_nr;
4275         int     ret_code = 0;
4276         int     problem = 0;
4277         e2fsck_t        ctx;
4278
4279         p = (struct process_block_struct_1 *) priv_data;
4280         pctx = p->pctx;
4281         ctx = p->ctx;
4282
4283         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4284                 /* todo: Check that the comprblk_fl is high, that the
4285                    blkaddr pattern looks right (all non-holes up to
4286                    first EXT2FS_COMPRESSED_BLKADDR, then all
4287                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4288                    that the feature_incompat bit is high, and that the
4289                    inode is a regular file.  If we're doing a "full
4290                    check" (a concept introduced to e2fsck by e2compr,
4291                    meaning that we look at data blocks as well as
4292                    metadata) then call some library routine that
4293                    checks the compressed data.  I'll have to think
4294                    about this, because one particularly important
4295                    problem to be able to fix is to recalculate the
4296                    cluster size if necessary.  I think that perhaps
4297                    we'd better do most/all e2compr-specific checks
4298                    separately, after the non-e2compr checks.  If not
4299                    doing a full check, it may be useful to test that
4300                    the personality is linux; e.g. if it isn't then
4301                    perhaps this really is just an illegal block. */
4302                 return 0;
4303         }
4304
4305         if (blk == 0) {
4306                 if (p->is_dir == 0) {
4307                         /*
4308                          * Should never happen, since only directories
4309                          * get called with BLOCK_FLAG_HOLE
4310                          */
4311 #ifdef DEBUG_E2FSCK
4312                         printf("process_block() called with blk == 0, "
4313                                "blockcnt=%d, inode %lu???\n",
4314                                blockcnt, p->ino);
4315 #endif
4316                         return 0;
4317                 }
4318                 if (blockcnt < 0)
4319                         return 0;
4320                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4321                         goto mark_dir;
4322                 }
4323                 return 0;
4324         }
4325
4326         /*
4327          * Simplistic fragmentation check.  We merely require that the
4328          * file be contiguous.  (Which can never be true for really
4329          * big files that are greater than a block group.)
4330          */
4331         if (!HOLE_BLKADDR(p->previous_block)) {
4332                 if (p->previous_block+1 != blk)
4333                         p->fragmented = 1;
4334         }
4335         p->previous_block = blk;
4336
4337         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4338                 problem = PR_1_TOOBIG_DIR;
4339         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4340                 problem = PR_1_TOOBIG_REG;
4341         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4342                 problem = PR_1_TOOBIG_SYMLINK;
4343
4344         if (blk < fs->super->s_first_data_block ||
4345             blk >= fs->super->s_blocks_count)
4346                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4347
4348         if (problem) {
4349                 p->num_illegal_blocks++;
4350                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4351                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4352                                 p->clear = 1;
4353                                 return BLOCK_ABORT;
4354                         }
4355                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4356                                 p->suppress = 1;
4357                                 set_latch_flags(PR_LATCH_BLOCK,
4358                                                 PRL_SUPPRESS, 0);
4359                         }
4360                 }
4361                 pctx->blk = blk;
4362                 pctx->blkcount = blockcnt;
4363                 if (fix_problem(ctx, problem, pctx)) {
4364                         blk = *block_nr = 0;
4365                         ret_code = BLOCK_CHANGED;
4366                         goto mark_dir;
4367                 } else
4368                         return 0;
4369         }
4370
4371         if (p->ino == EXT2_RESIZE_INO) {
4372                 /*
4373                  * The resize inode has already be sanity checked
4374                  * during pass #0 (the superblock checks).  All we
4375                  * have to do is mark the double indirect block as
4376                  * being in use; all of the other blocks are handled
4377                  * by mark_table_blocks()).
4378                  */
4379                 if (blockcnt == BLOCK_COUNT_DIND)
4380                         mark_block_used(ctx, blk);
4381         } else
4382                 mark_block_used(ctx, blk);
4383         p->num_blocks++;
4384         if (blockcnt >= 0)
4385                 p->last_block = blockcnt;
4386 mark_dir:
4387         if (p->is_dir && (blockcnt >= 0)) {
4388                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4389                                                     blk, blockcnt);
4390                 if (pctx->errcode) {
4391                         pctx->blk = blk;
4392                         pctx->num = blockcnt;
4393                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4394                         /* Should never get here */
4395                         ctx->flags |= E2F_FLAG_ABORT;
4396                         return BLOCK_ABORT;
4397                 }
4398         }
4399         return ret_code;
4400 }
4401
4402 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4403                       blk_t *block_nr,
4404                       e2_blkcnt_t blockcnt,
4405                       blk_t ref_block FSCK_ATTR((unused)),
4406                       int ref_offset FSCK_ATTR((unused)),
4407                       void *priv_data EXT2FS_ATTR((unused)))
4408 {
4409         /*
4410          * Note: This function processes blocks for the bad blocks
4411          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4412          */
4413
4414         printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4415         return BLOCK_ERROR;
4416 }
4417
4418 /*
4419  * This routine gets called at the end of pass 1 if bad blocks are
4420  * detected in the superblock, group descriptors, inode_bitmaps, or
4421  * block bitmaps.  At this point, all of the blocks have been mapped
4422  * out, so we can try to allocate new block(s) to replace the bad
4423  * blocks.
4424  */
4425 static void handle_fs_bad_blocks(e2fsck_t ctx)
4426 {
4427         printf("Bad blocks detected on your filesystem\n"
4428                 "You should get your data off as the device will soon die\n");
4429 }
4430
4431 /*
4432  * This routine marks all blocks which are used by the superblock,
4433  * group descriptors, inode bitmaps, and block bitmaps.
4434  */
4435 static void mark_table_blocks(e2fsck_t ctx)
4436 {
4437         ext2_filsys fs = ctx->fs;
4438         blk_t   block, b;
4439         dgrp_t  i;
4440         int     j;
4441         struct problem_context pctx;
4442
4443         clear_problem_context(&pctx);
4444
4445         block = fs->super->s_first_data_block;
4446         for (i = 0; i < fs->group_desc_count; i++) {
4447                 pctx.group = i;
4448
4449                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4450
4451                 /*
4452                  * Mark the blocks used for the inode table
4453                  */
4454                 if (fs->group_desc[i].bg_inode_table) {
4455                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4456                              j < fs->inode_blocks_per_group;
4457                              j++, b++) {
4458                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4459                                                              b)) {
4460                                         pctx.blk = b;
4461                                         if (fix_problem(ctx,
4462                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4463                                                 ctx->invalid_inode_table_flag[i]++;
4464                                                 ctx->invalid_bitmaps++;
4465                                         }
4466                                 } else {
4467                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
4468                                                              b);
4469                                 }
4470                         }
4471                 }
4472
4473                 /*
4474                  * Mark block used for the block bitmap
4475                  */
4476                 if (fs->group_desc[i].bg_block_bitmap) {
4477                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4478                                      fs->group_desc[i].bg_block_bitmap)) {
4479                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4480                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4481                                         ctx->invalid_block_bitmap_flag[i]++;
4482                                         ctx->invalid_bitmaps++;
4483                                 }
4484                         } else {
4485                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4486                                      fs->group_desc[i].bg_block_bitmap);
4487                     }
4488
4489                 }
4490                 /*
4491                  * Mark block used for the inode bitmap
4492                  */
4493                 if (fs->group_desc[i].bg_inode_bitmap) {
4494                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4495                                      fs->group_desc[i].bg_inode_bitmap)) {
4496                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4497                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4498                                         ctx->invalid_inode_bitmap_flag[i]++;
4499                                         ctx->invalid_bitmaps++;
4500                                 }
4501                         } else {
4502                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4503                                      fs->group_desc[i].bg_inode_bitmap);
4504                         }
4505                 }
4506                 block += fs->super->s_blocks_per_group;
4507         }
4508 }
4509
4510 /*
4511  * Thes subroutines short circuits ext2fs_get_blocks and
4512  * ext2fs_check_directory; we use them since we already have the inode
4513  * structure, so there's no point in letting the ext2fs library read
4514  * the inode again.
4515  */
4516 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4517                                   blk_t *blocks)
4518 {
4519         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4520         int     i;
4521
4522         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4523                 return EXT2_ET_CALLBACK_NOTHANDLED;
4524
4525         for (i=0; i < EXT2_N_BLOCKS; i++)
4526                 blocks[i] = ctx->stashed_inode->i_block[i];
4527         return 0;
4528 }
4529
4530 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4531                                   struct ext2_inode *inode)
4532 {
4533         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4534
4535         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4536                 return EXT2_ET_CALLBACK_NOTHANDLED;
4537         *inode = *ctx->stashed_inode;
4538         return 0;
4539 }
4540
4541 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4542                             struct ext2_inode *inode)
4543 {
4544         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545
4546         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4547                 *ctx->stashed_inode = *inode;
4548         return EXT2_ET_CALLBACK_NOTHANDLED;
4549 }
4550
4551 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4552 {
4553         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4554
4555         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4556                 return EXT2_ET_CALLBACK_NOTHANDLED;
4557
4558         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4559                 return EXT2_ET_NO_DIRECTORY;
4560         return 0;
4561 }
4562
4563 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4564 {
4565         ext2_filsys fs = ctx->fs;
4566
4567         if (bool) {
4568                 fs->get_blocks = pass1_get_blocks;
4569                 fs->check_directory = pass1_check_directory;
4570                 fs->read_inode = pass1_read_inode;
4571                 fs->write_inode = pass1_write_inode;
4572                 ctx->stashed_ino = 0;
4573         } else {
4574                 fs->get_blocks = 0;
4575                 fs->check_directory = 0;
4576                 fs->read_inode = 0;
4577                 fs->write_inode = 0;
4578         }
4579 }
4580
4581 /*
4582  * pass1b.c --- Pass #1b of e2fsck
4583  *
4584  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4585  * only invoked if pass 1 discovered blocks which are in use by more
4586  * than one inode.
4587  *
4588  * Pass1B scans the data blocks of all the inodes again, generating a
4589  * complete list of duplicate blocks and which inodes have claimed
4590  * them.
4591  *
4592  * Pass1C does a tree-traversal of the filesystem, to determine the
4593  * parent directories of these inodes.  This step is necessary so that
4594  * e2fsck can print out the pathnames of affected inodes.
4595  *
4596  * Pass1D is a reconciliation pass.  For each inode with duplicate
4597  * blocks, the user is prompted if s/he would like to clone the file
4598  * (so that the file gets a fresh copy of the duplicated blocks) or
4599  * simply to delete the file.
4600  *
4601  */
4602
4603
4604 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4605 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4606 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4607
4608 /* Define an extension to the ext2 library's block count information */
4609 #define BLOCK_COUNT_EXTATTR     (-5)
4610
4611 struct block_el {
4612         blk_t   block;
4613         struct block_el *next;
4614 };
4615
4616 struct inode_el {
4617         ext2_ino_t      inode;
4618         struct inode_el *next;
4619 };
4620
4621 struct dup_block {
4622         int             num_bad;
4623         struct inode_el *inode_list;
4624 };
4625
4626 /*
4627  * This structure stores information about a particular inode which
4628  * is sharing blocks with other inodes.  This information is collected
4629  * to display to the user, so that the user knows what files he or she
4630  * is dealing with, when trying to decide how to resolve the conflict
4631  * of multiply-claimed blocks.
4632  */
4633 struct dup_inode {
4634         ext2_ino_t              dir;
4635         int                     num_dupblocks;
4636         struct ext2_inode       inode;
4637         struct block_el         *block_list;
4638 };
4639
4640 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4641                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4642                                 int ref_offset, void *priv_data);
4643 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4644                         struct dup_inode *dp, char *block_buf);
4645 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4646                       struct dup_inode *dp, char* block_buf);
4647 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4648
4649 static void pass1b(e2fsck_t ctx, char *block_buf);
4650 static void pass1c(e2fsck_t ctx, char *block_buf);
4651 static void pass1d(e2fsck_t ctx, char *block_buf);
4652
4653 static int dup_inode_count = 0;
4654
4655 static dict_t blk_dict, ino_dict;
4656
4657 static ext2fs_inode_bitmap inode_dup_map;
4658
4659 static int dict_int_cmp(const void *a, const void *b)
4660 {
4661         intptr_t        ia, ib;
4662
4663         ia = (intptr_t)a;
4664         ib = (intptr_t)b;
4665
4666         return (ia-ib);
4667 }
4668
4669 /*
4670  * Add a duplicate block record
4671  */
4672 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4673                      struct ext2_inode *inode)
4674 {
4675         dnode_t *n;
4676         struct dup_block        *db;
4677         struct dup_inode        *di;
4678         struct block_el         *blk_el;
4679         struct inode_el         *ino_el;
4680
4681         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4682         if (n)
4683                 db = (struct dup_block *) dnode_get(n);
4684         else {
4685                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4686                          sizeof(struct dup_block), "duplicate block header");
4687                 db->num_bad = 0;
4688                 db->inode_list = 0;
4689                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4690         }
4691         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4692                          sizeof(struct inode_el), "inode element");
4693         ino_el->inode = ino;
4694         ino_el->next = db->inode_list;
4695         db->inode_list = ino_el;
4696         db->num_bad++;
4697
4698         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4699         if (n)
4700                 di = (struct dup_inode *) dnode_get(n);
4701         else {
4702                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4703                          sizeof(struct dup_inode), "duplicate inode header");
4704                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4705                 di->num_dupblocks = 0;
4706                 di->block_list = 0;
4707                 di->inode = *inode;
4708                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4709         }
4710         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4711                          sizeof(struct block_el), "block element");
4712         blk_el->block = blk;
4713         blk_el->next = di->block_list;
4714         di->block_list = blk_el;
4715         di->num_dupblocks++;
4716 }
4717
4718 /*
4719  * Free a duplicate inode record
4720  */
4721 static void inode_dnode_free(dnode_t *node)
4722 {
4723         struct dup_inode        *di;
4724         struct block_el         *p, *next;
4725
4726         di = (struct dup_inode *) dnode_get(node);
4727         for (p = di->block_list; p; p = next) {
4728                 next = p->next;
4729                 free(p);
4730         }
4731         free(node);
4732 }
4733
4734 /*
4735  * Free a duplicate block record
4736  */
4737 static void block_dnode_free(dnode_t *node)
4738 {
4739         struct dup_block        *db;
4740         struct inode_el         *p, *next;
4741
4742         db = (struct dup_block *) dnode_get(node);
4743         for (p = db->inode_list; p; p = next) {
4744                 next = p->next;
4745                 free(p);
4746         }
4747         free(node);
4748 }
4749
4750
4751 /*
4752  * Main procedure for handling duplicate blocks
4753  */
4754 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4755 {
4756         ext2_filsys             fs = ctx->fs;
4757         struct problem_context  pctx;
4758
4759         clear_problem_context(&pctx);
4760
4761         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4762                       _("multiply claimed inode map"), &inode_dup_map);
4763         if (pctx.errcode) {
4764                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4765                 ctx->flags |= E2F_FLAG_ABORT;
4766                 return;
4767         }
4768
4769         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4770         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771         dict_set_allocator(&ino_dict, inode_dnode_free);
4772         dict_set_allocator(&blk_dict, block_dnode_free);
4773
4774         pass1b(ctx, block_buf);
4775         pass1c(ctx, block_buf);
4776         pass1d(ctx, block_buf);
4777
4778         /*
4779          * Time to free all of the accumulated data structures that we
4780          * don't need anymore.
4781          */
4782         dict_free_nodes(&ino_dict);
4783         dict_free_nodes(&blk_dict);
4784 }
4785
4786 /*
4787  * Scan the inodes looking for inodes that contain duplicate blocks.
4788  */
4789 struct process_block_struct_1b {
4790         e2fsck_t        ctx;
4791         ext2_ino_t      ino;
4792         int             dup_blocks;
4793         struct ext2_inode *inode;
4794         struct problem_context *pctx;
4795 };
4796
4797 static void pass1b(e2fsck_t ctx, char *block_buf)
4798 {
4799         ext2_filsys fs = ctx->fs;
4800         ext2_ino_t ino;
4801         struct ext2_inode inode;
4802         ext2_inode_scan scan;
4803         struct process_block_struct_1b pb;
4804         struct problem_context pctx;
4805
4806         clear_problem_context(&pctx);
4807
4808         if (!(ctx->options & E2F_OPT_PREEN))
4809                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4810         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4811                                               &scan);
4812         if (pctx.errcode) {
4813                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4814                 ctx->flags |= E2F_FLAG_ABORT;
4815                 return;
4816         }
4817         ctx->stashed_inode = &inode;
4818         pb.ctx = ctx;
4819         pb.pctx = &pctx;
4820         pctx.str = "pass1b";
4821         while (1) {
4822                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4823                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4824                         continue;
4825                 if (pctx.errcode) {
4826                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4827                         ctx->flags |= E2F_FLAG_ABORT;
4828                         return;
4829                 }
4830                 if (!ino)
4831                         break;
4832                 pctx.ino = ctx->stashed_ino = ino;
4833                 if ((ino != EXT2_BAD_INO) &&
4834                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4835                         continue;
4836
4837                 pb.ino = ino;
4838                 pb.dup_blocks = 0;
4839                 pb.inode = &inode;
4840
4841                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4842                     (ino == EXT2_BAD_INO))
4843                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4844                                      0, block_buf, process_pass1b_block, &pb);
4845                 if (inode.i_file_acl)
4846                         process_pass1b_block(fs, &inode.i_file_acl,
4847                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4848                 if (pb.dup_blocks) {
4849                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4850                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4851                             ino == EXT2_ROOT_INO)
4852                                 dup_inode_count++;
4853                 }
4854                 if (pctx.errcode)
4855                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4856         }
4857         ext2fs_close_inode_scan(scan);
4858         e2fsck_use_inode_shortcuts(ctx, 0);
4859 }
4860
4861 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4862                                 blk_t   *block_nr,
4863                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4864                                 blk_t ref_blk FSCK_ATTR((unused)),
4865                                 int ref_offset FSCK_ATTR((unused)),
4866                                 void *priv_data)
4867 {
4868         struct process_block_struct_1b *p;
4869         e2fsck_t ctx;
4870
4871         if (HOLE_BLKADDR(*block_nr))
4872                 return 0;
4873         p = (struct process_block_struct_1b *) priv_data;
4874         ctx = p->ctx;
4875
4876         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4877                 return 0;
4878
4879         /* OK, this is a duplicate block */
4880         if (p->ino != EXT2_BAD_INO) {
4881                 p->pctx->blk = *block_nr;
4882                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4883         }
4884         p->dup_blocks++;
4885         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4886
4887         add_dupe(ctx, p->ino, *block_nr, p->inode);
4888
4889         return 0;
4890 }
4891
4892 /*
4893  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4894  * is used so that we can print pathnames when prompting the user for
4895  * what to do.
4896  */
4897 struct search_dir_struct {
4898         int             count;
4899         ext2_ino_t      first_inode;
4900         ext2_ino_t      max_inode;
4901 };
4902
4903 static int search_dirent_proc(ext2_ino_t dir, int entry,
4904                               struct ext2_dir_entry *dirent,
4905                               int offset FSCK_ATTR((unused)),
4906                               int blocksize FSCK_ATTR((unused)),
4907                               char *buf FSCK_ATTR((unused)),
4908                               void *priv_data)
4909 {
4910         struct search_dir_struct *sd;
4911         struct dup_inode        *p;
4912         dnode_t                 *n;
4913
4914         sd = (struct search_dir_struct *) priv_data;
4915
4916         if (dirent->inode > sd->max_inode)
4917                 /* Should abort this inode, but not everything */
4918                 return 0;
4919
4920         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4921             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4922                 return 0;
4923
4924         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4925         if (!n)
4926                 return 0;
4927         p = (struct dup_inode *) dnode_get(n);
4928         p->dir = dir;
4929         sd->count--;
4930
4931         return sd->count ? 0 : DIRENT_ABORT;
4932 }
4933
4934
4935 static void pass1c(e2fsck_t ctx, char *block_buf)
4936 {
4937         ext2_filsys fs = ctx->fs;
4938         struct search_dir_struct sd;
4939         struct problem_context pctx;
4940
4941         clear_problem_context(&pctx);
4942
4943         if (!(ctx->options & E2F_OPT_PREEN))
4944                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4945
4946         /*
4947          * Search through all directories to translate inodes to names
4948          * (by searching for the containing directory for that inode.)
4949          */
4950         sd.count = dup_inode_count;
4951         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4952         sd.max_inode = fs->super->s_inodes_count;
4953         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4954                                   search_dirent_proc, &sd);
4955 }
4956
4957 static void pass1d(e2fsck_t ctx, char *block_buf)
4958 {
4959         ext2_filsys fs = ctx->fs;
4960         struct dup_inode        *p, *t;
4961         struct dup_block        *q;
4962         ext2_ino_t              *shared, ino;
4963         int     shared_len;
4964         int     i;
4965         int     file_ok;
4966         int     meta_data = 0;
4967         struct problem_context pctx;
4968         dnode_t *n, *m;
4969         struct block_el *s;
4970         struct inode_el *r;
4971
4972         clear_problem_context(&pctx);
4973
4974         if (!(ctx->options & E2F_OPT_PREEN))
4975                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4976         e2fsck_read_bitmaps(ctx);
4977
4978         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4979         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4980         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4981                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4982                                 "Shared inode list");
4983         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4984                 p = (struct dup_inode *) dnode_get(n);
4985                 shared_len = 0;
4986                 file_ok = 1;
4987                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4988                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4989                         continue;
4990
4991                 /*
4992                  * Find all of the inodes which share blocks with this
4993                  * one.  First we find all of the duplicate blocks
4994                  * belonging to this inode, and then search each block
4995                  * get the list of inodes, and merge them together.
4996                  */
4997                 for (s = p->block_list; s; s = s->next) {
4998                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4999                         if (!m)
5000                                 continue; /* Should never happen... */
5001                         q = (struct dup_block *) dnode_get(m);
5002                         if (q->num_bad > 1)
5003                                 file_ok = 0;
5004                         if (check_if_fs_block(ctx, s->block)) {
5005                                 file_ok = 0;
5006                                 meta_data = 1;
5007                         }
5008
5009                         /*
5010                          * Add all inodes used by this block to the
5011                          * shared[] --- which is a unique list, so
5012                          * if an inode is already in shared[], don't
5013                          * add it again.
5014                          */
5015                         for (r = q->inode_list; r; r = r->next) {
5016                                 if (r->inode == ino)
5017                                         continue;
5018                                 for (i = 0; i < shared_len; i++)
5019                                         if (shared[i] == r->inode)
5020                                                 break;
5021                                 if (i == shared_len) {
5022                                         shared[shared_len++] = r->inode;
5023                                 }
5024                         }
5025                 }
5026
5027                 /*
5028                  * Report the inode that we are working on
5029                  */
5030                 pctx.inode = &p->inode;
5031                 pctx.ino = ino;
5032                 pctx.dir = p->dir;
5033                 pctx.blkcount = p->num_dupblocks;
5034                 pctx.num = meta_data ? shared_len+1 : shared_len;
5035                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5036                 pctx.blkcount = 0;
5037                 pctx.num = 0;
5038
5039                 if (meta_data)
5040                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5041
5042                 for (i = 0; i < shared_len; i++) {
5043                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5044                         if (!m)
5045                                 continue; /* should never happen */
5046                         t = (struct dup_inode *) dnode_get(m);
5047                         /*
5048                          * Report the inode that we are sharing with
5049                          */
5050                         pctx.inode = &t->inode;
5051                         pctx.ino = shared[i];
5052                         pctx.dir = t->dir;
5053                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5054                 }
5055                 if (file_ok) {
5056                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5057                         continue;
5058                 }
5059                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5060                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5061                         if (pctx.errcode)
5062                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5063                         else
5064                                 continue;
5065                 }
5066                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5067                         delete_file(ctx, ino, p, block_buf);
5068                 else
5069                         ext2fs_unmark_valid(fs);
5070         }
5071         ext2fs_free_mem(&shared);
5072 }
5073
5074 /*
5075  * Drop the refcount on the dup_block structure, and clear the entry
5076  * in the block_dup_map if appropriate.
5077  */
5078 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5079 {
5080         p->num_bad--;
5081         if (p->num_bad <= 0 ||
5082             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5083                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5084 }
5085
5086 static int delete_file_block(ext2_filsys fs,
5087                              blk_t      *block_nr,
5088                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5089                              blk_t ref_block FSCK_ATTR((unused)),
5090                              int ref_offset FSCK_ATTR((unused)),
5091                              void *priv_data)
5092 {
5093         struct process_block_struct_1b *pb;
5094         struct dup_block *p;
5095         dnode_t *n;
5096         e2fsck_t ctx;
5097
5098         pb = (struct process_block_struct_1b *) priv_data;
5099         ctx = pb->ctx;
5100
5101         if (HOLE_BLKADDR(*block_nr))
5102                 return 0;
5103
5104         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5105                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5106                 if (n) {
5107                         p = (struct dup_block *) dnode_get(n);
5108                         decrement_badcount(ctx, *block_nr, p);
5109                 } else
5110                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5111                                 *block_nr);
5112         } else {
5113                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5114                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5115         }
5116
5117         return 0;
5118 }
5119
5120 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5121                         struct dup_inode *dp, char* block_buf)
5122 {
5123         ext2_filsys fs = ctx->fs;
5124         struct process_block_struct_1b pb;
5125         struct ext2_inode       inode;
5126         struct problem_context  pctx;
5127         unsigned int            count;
5128
5129         clear_problem_context(&pctx);
5130         pctx.ino = pb.ino = ino;
5131         pb.dup_blocks = dp->num_dupblocks;
5132         pb.ctx = ctx;
5133         pctx.str = "delete_file";
5134
5135         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5136         if (ext2fs_inode_has_valid_blocks(&inode))
5137                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5138                                                      delete_file_block, &pb);
5139         if (pctx.errcode)
5140                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5141         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5142         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5143         if (ctx->inode_bad_map)
5144                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5145         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5146
5147         /* Inode may have changed by block_iterate, so reread it */
5148         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5149         inode.i_links_count = 0;
5150         inode.i_dtime = time(0);
5151         if (inode.i_file_acl &&
5152             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5153                 count = 1;
5154                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5155                                                    block_buf, -1, &count);
5156                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5157                         pctx.errcode = 0;
5158                         count = 1;
5159                 }
5160                 if (pctx.errcode) {
5161                         pctx.blk = inode.i_file_acl;
5162                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5163                 }
5164                 /*
5165                  * If the count is zero, then arrange to have the
5166                  * block deleted.  If the block is in the block_dup_map,
5167                  * also call delete_file_block since it will take care
5168                  * of keeping the accounting straight.
5169                  */
5170                 if ((count == 0) ||
5171                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5172                                              inode.i_file_acl))
5173                         delete_file_block(fs, &inode.i_file_acl,
5174                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5175         }
5176         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5177 }
5178
5179 struct clone_struct {
5180         errcode_t       errcode;
5181         ext2_ino_t      dir;
5182         char    *buf;
5183         e2fsck_t ctx;
5184 };
5185
5186 static int clone_file_block(ext2_filsys fs,
5187                             blk_t       *block_nr,
5188                             e2_blkcnt_t blockcnt,
5189                             blk_t ref_block FSCK_ATTR((unused)),
5190                             int ref_offset FSCK_ATTR((unused)),
5191                             void *priv_data)
5192 {
5193         struct dup_block *p;
5194         blk_t   new_block;
5195         errcode_t       retval;
5196         struct clone_struct *cs = (struct clone_struct *) priv_data;
5197         dnode_t *n;
5198         e2fsck_t ctx;
5199
5200         ctx = cs->ctx;
5201
5202         if (HOLE_BLKADDR(*block_nr))
5203                 return 0;
5204
5205         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5206                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5207                 if (n) {
5208                         p = (struct dup_block *) dnode_get(n);
5209                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5210                                                   &new_block);
5211                         if (retval) {
5212                                 cs->errcode = retval;
5213                                 return BLOCK_ABORT;
5214                         }
5215                         if (cs->dir && (blockcnt >= 0)) {
5216                                 retval = ext2fs_set_dir_block(fs->dblist,
5217                                       cs->dir, new_block, blockcnt);
5218                                 if (retval) {
5219                                         cs->errcode = retval;
5220                                         return BLOCK_ABORT;
5221                                 }
5222                         }
5223
5224                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5225                                                      cs->buf);
5226                         if (retval) {
5227                                 cs->errcode = retval;
5228                                 return BLOCK_ABORT;
5229                         }
5230                         retval = io_channel_write_blk(fs->io, new_block, 1,
5231                                                       cs->buf);
5232                         if (retval) {
5233                                 cs->errcode = retval;
5234                                 return BLOCK_ABORT;
5235                         }
5236                         decrement_badcount(ctx, *block_nr, p);
5237                         *block_nr = new_block;
5238                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5239                                                  new_block);
5240                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5241                         return BLOCK_CHANGED;
5242                 } else
5243                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5244                                 *block_nr);
5245         }
5246         return 0;
5247 }
5248
5249 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5250                       struct dup_inode *dp, char* block_buf)
5251 {
5252         ext2_filsys fs = ctx->fs;
5253         errcode_t       retval;
5254         struct clone_struct cs;
5255         struct problem_context  pctx;
5256         blk_t           blk;
5257         dnode_t         *n;
5258         struct inode_el *ino_el;
5259         struct dup_block        *db;
5260         struct dup_inode        *di;
5261
5262         clear_problem_context(&pctx);
5263         cs.errcode = 0;
5264         cs.dir = 0;
5265         cs.ctx = ctx;
5266         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5267         if (retval)
5268                 return retval;
5269
5270         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5271                 cs.dir = ino;
5272
5273         pctx.ino = ino;
5274         pctx.str = "clone_file";
5275         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5276                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5277                                                      clone_file_block, &cs);
5278         ext2fs_mark_bb_dirty(fs);
5279         if (pctx.errcode) {
5280                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5281                 retval = pctx.errcode;
5282                 goto errout;
5283         }
5284         if (cs.errcode) {
5285                 bb_error_msg(_("returned from clone_file_block"));
5286                 retval = cs.errcode;
5287                 goto errout;
5288         }
5289         /* The inode may have changed on disk, so we have to re-read it */
5290         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5291         blk = dp->inode.i_file_acl;
5292         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5293                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5294                     BLOCK_CHANGED)) {
5295                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5296                 /*
5297                  * If we cloned the EA block, find all other inodes
5298                  * which refered to that EA block, and modify
5299                  * them to point to the new EA block.
5300                  */
5301                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5302                 db = (struct dup_block *) dnode_get(n);
5303                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5304                         if (ino_el->inode == ino)
5305                                 continue;
5306                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5307                         di = (struct dup_inode *) dnode_get(n);
5308                         if (di->inode.i_file_acl == blk) {
5309                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5310                                 e2fsck_write_inode(ctx, ino_el->inode,
5311                                            &di->inode, "clone file EA");
5312                                 decrement_badcount(ctx, blk, db);
5313                         }
5314                 }
5315         }
5316         retval = 0;
5317 errout:
5318         ext2fs_free_mem(&cs.buf);
5319         return retval;
5320 }
5321
5322 /*
5323  * This routine returns 1 if a block overlaps with one of the superblocks,
5324  * group descriptors, inode bitmaps, or block bitmaps.
5325  */
5326 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5327 {
5328         ext2_filsys fs = ctx->fs;
5329         blk_t   block;
5330         dgrp_t  i;
5331
5332         block = fs->super->s_first_data_block;
5333         for (i = 0; i < fs->group_desc_count; i++) {
5334
5335                 /* Check superblocks/block group descriptros */
5336                 if (ext2fs_bg_has_super(fs, i)) {
5337                         if (test_block >= block &&
5338                             (test_block <= block + fs->desc_blocks))
5339                                 return 1;
5340                 }
5341
5342                 /* Check the inode table */
5343                 if ((fs->group_desc[i].bg_inode_table) &&
5344                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5345                     (test_block < (fs->group_desc[i].bg_inode_table +
5346                                    fs->inode_blocks_per_group)))
5347                         return 1;
5348
5349                 /* Check the bitmap blocks */
5350                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5351                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5352                         return 1;
5353
5354                 block += fs->super->s_blocks_per_group;
5355         }
5356         return 0;
5357 }
5358 /*
5359  * pass2.c --- check directory structure
5360  *
5361  * Pass 2 of e2fsck iterates through all active directory inodes, and
5362  * applies to following tests to each directory entry in the directory
5363  * blocks in the inodes:
5364  *
5365  *      - The length of the directory entry (rec_len) should be at
5366  *              least 8 bytes, and no more than the remaining space
5367  *              left in the directory block.
5368  *      - The length of the name in the directory entry (name_len)
5369  *              should be less than (rec_len - 8).
5370  *      - The inode number in the directory entry should be within
5371  *              legal bounds.
5372  *      - The inode number should refer to a in-use inode.
5373  *      - The first entry should be '.', and its inode should be
5374  *              the inode of the directory.
5375  *      - The second entry should be '..'.
5376  *
5377  * To minimize disk seek time, the directory blocks are processed in
5378  * sorted order of block numbers.
5379  *
5380  * Pass 2 also collects the following information:
5381  *      - The inode numbers of the subdirectories for each directory.
5382  *
5383  * Pass 2 relies on the following information from previous passes:
5384  *      - The directory information collected in pass 1.
5385  *      - The inode_used_map bitmap
5386  *      - The inode_bad_map bitmap
5387  *      - The inode_dir_map bitmap
5388  *
5389  * Pass 2 frees the following data structures
5390  *      - The inode_bad_map bitmap
5391  *      - The inode_reg_map bitmap
5392  */
5393
5394 /*
5395  * Keeps track of how many times an inode is referenced.
5396  */
5397 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5398 static int check_dir_block(ext2_filsys fs,
5399                            struct ext2_db_entry *dir_blocks_info,
5400                            void *priv_data);
5401 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5402                               struct problem_context *pctx);
5403 static int update_dir_block(ext2_filsys fs,
5404                             blk_t       *block_nr,
5405                             e2_blkcnt_t blockcnt,
5406                             blk_t       ref_block,
5407                             int         ref_offset,
5408                             void        *priv_data);
5409 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5410 static int htree_depth(struct dx_dir_info *dx_dir,
5411                        struct dx_dirblock_info *dx_db);
5412 static int special_dir_block_cmp(const void *a, const void *b);
5413
5414 struct check_dir_struct {
5415         char *buf;
5416         struct problem_context  pctx;
5417         int     count, max;
5418         e2fsck_t ctx;
5419 };
5420
5421 static void e2fsck_pass2(e2fsck_t ctx)
5422 {
5423         struct ext2_super_block *sb = ctx->fs->super;
5424         struct problem_context  pctx;
5425         ext2_filsys             fs = ctx->fs;
5426         char                    *buf;
5427         struct dir_info         *dir;
5428         struct check_dir_struct cd;
5429         struct dx_dir_info      *dx_dir;
5430         struct dx_dirblock_info *dx_db, *dx_parent;
5431         int                     b;
5432         int                     i, depth;
5433         problem_t               code;
5434         int                     bad_dir;
5435
5436         clear_problem_context(&cd.pctx);
5437
5438         /* Pass 2 */
5439
5440         if (!(ctx->options & E2F_OPT_PREEN))
5441                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5442
5443         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5444                                                 0, ctx->inode_link_info,
5445                                                 &ctx->inode_count);
5446         if (cd.pctx.errcode) {
5447                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5448                 ctx->flags |= E2F_FLAG_ABORT;
5449                 return;
5450         }
5451         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5452                                               "directory scan buffer");
5453
5454         /*
5455          * Set up the parent pointer for the root directory, if
5456          * present.  (If the root directory is not present, we will
5457          * create it in pass 3.)
5458          */
5459         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5460         if (dir)
5461                 dir->parent = EXT2_ROOT_INO;
5462
5463         cd.buf = buf;
5464         cd.ctx = ctx;
5465         cd.count = 1;
5466         cd.max = ext2fs_dblist_count(fs->dblist);
5467
5468         if (ctx->progress)
5469                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5470
5471         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5472                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5473
5474         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5475                                                 &cd);
5476         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5477                 return;
5478         if (cd.pctx.errcode) {
5479                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5480                 ctx->flags |= E2F_FLAG_ABORT;
5481                 return;
5482         }
5483
5484 #ifdef ENABLE_HTREE
5485         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5486                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5487                         return;
5488                 if (dx_dir->numblocks == 0)
5489                         continue;
5490                 clear_problem_context(&pctx);
5491                 bad_dir = 0;
5492                 pctx.dir = dx_dir->ino;
5493                 dx_db = dx_dir->dx_block;
5494                 if (dx_db->flags & DX_FLAG_REFERENCED)
5495                         dx_db->flags |= DX_FLAG_DUP_REF;
5496                 else
5497                         dx_db->flags |= DX_FLAG_REFERENCED;
5498                 /*
5499                  * Find all of the first and last leaf blocks, and
5500                  * update their parent's min and max hash values
5501                  */
5502                 for (b=0, dx_db = dx_dir->dx_block;
5503                      b < dx_dir->numblocks;
5504                      b++, dx_db++) {
5505                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5506                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5507                                 continue;
5508                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5509                         /*
5510                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5511                          */
5512                         if (dx_db->flags & DX_FLAG_FIRST)
5513                                 dx_parent->min_hash = dx_db->min_hash;
5514                         /*
5515                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5516                          */
5517                         if (dx_db->flags & DX_FLAG_LAST)
5518                                 dx_parent->max_hash = dx_db->max_hash;
5519                 }
5520
5521                 for (b=0, dx_db = dx_dir->dx_block;
5522                      b < dx_dir->numblocks;
5523                      b++, dx_db++) {
5524                         pctx.blkcount = b;
5525                         pctx.group = dx_db->parent;
5526                         code = 0;
5527                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5528                             (dx_db->min_hash < dx_db->node_min_hash)) {
5529                                 pctx.blk = dx_db->min_hash;
5530                                 pctx.blk2 = dx_db->node_min_hash;
5531                                 code = PR_2_HTREE_MIN_HASH;
5532                                 fix_problem(ctx, code, &pctx);
5533                                 bad_dir++;
5534                         }
5535                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5536                                 depth = htree_depth(dx_dir, dx_db);
5537                                 if (depth != dx_dir->depth) {
5538                                         code = PR_2_HTREE_BAD_DEPTH;
5539                                         fix_problem(ctx, code, &pctx);
5540                                         bad_dir++;
5541                                 }
5542                         }
5543                         /*
5544                          * This test doesn't apply for the root block
5545                          * at block #0
5546                          */
5547                         if (b &&
5548                             (dx_db->max_hash > dx_db->node_max_hash)) {
5549                                 pctx.blk = dx_db->max_hash;
5550                                 pctx.blk2 = dx_db->node_max_hash;
5551                                 code = PR_2_HTREE_MAX_HASH;
5552                                 fix_problem(ctx, code, &pctx);
5553                                 bad_dir++;
5554                         }
5555                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5556                                 code = PR_2_HTREE_NOTREF;
5557                                 fix_problem(ctx, code, &pctx);
5558                                 bad_dir++;
5559                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5560                                 code = PR_2_HTREE_DUPREF;
5561                                 fix_problem(ctx, code, &pctx);
5562                                 bad_dir++;
5563                         }
5564                         if (code == 0)
5565                                 continue;
5566                 }
5567                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5568                         clear_htree(ctx, dx_dir->ino);
5569                         dx_dir->numblocks = 0;
5570                 }
5571         }
5572 #endif
5573         ext2fs_free_mem(&buf);
5574         ext2fs_free_dblist(fs->dblist);
5575
5576         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5577         ctx->inode_bad_map = 0;
5578         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5579         ctx->inode_reg_map = 0;
5580
5581         clear_problem_context(&pctx);
5582         if (ctx->large_files) {
5583                 if (!(sb->s_feature_ro_compat &
5584                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5585                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5586                         sb->s_feature_ro_compat |=
5587                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5588                         ext2fs_mark_super_dirty(fs);
5589                 }
5590                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5591                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5592                         ext2fs_update_dynamic_rev(fs);
5593                         ext2fs_mark_super_dirty(fs);
5594                 }
5595         } else if (!ctx->large_files &&
5596             (sb->s_feature_ro_compat &
5597               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5598                 if (fs->flags & EXT2_FLAG_RW) {
5599                         sb->s_feature_ro_compat &=
5600                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5601                         ext2fs_mark_super_dirty(fs);
5602                 }
5603         }
5604
5605 }
5606
5607 #define MAX_DEPTH 32000
5608 static int htree_depth(struct dx_dir_info *dx_dir,
5609                        struct dx_dirblock_info *dx_db)
5610 {
5611         int     depth = 0;
5612
5613         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614                 dx_db = &dx_dir->dx_block[dx_db->parent];
5615                 depth++;
5616         }
5617         return depth;
5618 }
5619
5620 static int dict_de_cmp(const void *a, const void *b)
5621 {
5622         const struct ext2_dir_entry *de_a, *de_b;
5623         int     a_len, b_len;
5624
5625         de_a = (const struct ext2_dir_entry *) a;
5626         a_len = de_a->name_len & 0xFF;
5627         de_b = (const struct ext2_dir_entry *) b;
5628         b_len = de_b->name_len & 0xFF;
5629
5630         if (a_len != b_len)
5631                 return (a_len - b_len);
5632
5633         return strncmp(de_a->name, de_b->name, a_len);
5634 }
5635
5636 /*
5637  * This is special sort function that makes sure that directory blocks
5638  * with a dirblock of zero are sorted to the beginning of the list.
5639  * This guarantees that the root node of the htree directories are
5640  * processed first, so we know what hash version to use.
5641  */
5642 static int special_dir_block_cmp(const void *a, const void *b)
5643 {
5644         const struct ext2_db_entry *db_a =
5645                 (const struct ext2_db_entry *) a;
5646         const struct ext2_db_entry *db_b =
5647                 (const struct ext2_db_entry *) b;
5648
5649         if (db_a->blockcnt && !db_b->blockcnt)
5650                 return 1;
5651
5652         if (!db_a->blockcnt && db_b->blockcnt)
5653                 return -1;
5654
5655         if (db_a->blk != db_b->blk)
5656                 return (int) (db_a->blk - db_b->blk);
5657
5658         if (db_a->ino != db_b->ino)
5659                 return (int) (db_a->ino - db_b->ino);
5660
5661         return (int) (db_a->blockcnt - db_b->blockcnt);
5662 }
5663
5664
5665 /*
5666  * Make sure the first entry in the directory is '.', and that the
5667  * directory entry is sane.
5668  */
5669 static int check_dot(e2fsck_t ctx,
5670                      struct ext2_dir_entry *dirent,
5671                      ext2_ino_t ino, struct problem_context *pctx)
5672 {
5673         struct ext2_dir_entry *nextdir;
5674         int     status = 0;
5675         int     created = 0;
5676         int     new_len;
5677         int     problem = 0;
5678
5679         if (!dirent->inode)
5680                 problem = PR_2_MISSING_DOT;
5681         else if (((dirent->name_len & 0xFF) != 1) ||
5682                  (dirent->name[0] != '.'))
5683                 problem = PR_2_1ST_NOT_DOT;
5684         else if (dirent->name[1] != '\0')
5685                 problem = PR_2_DOT_NULL_TERM;
5686
5687         if (problem) {
5688                 if (fix_problem(ctx, problem, pctx)) {
5689                         if (dirent->rec_len < 12)
5690                                 dirent->rec_len = 12;
5691                         dirent->inode = ino;
5692                         dirent->name_len = 1;
5693                         dirent->name[0] = '.';
5694                         dirent->name[1] = '\0';
5695                         status = 1;
5696                         created = 1;
5697                 }
5698         }
5699         if (dirent->inode != ino) {
5700                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701                         dirent->inode = ino;
5702                         status = 1;
5703                 }
5704         }
5705         if (dirent->rec_len > 12) {
5706                 new_len = dirent->rec_len - 12;
5707                 if (new_len > 12) {
5708                         if (created ||
5709                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710                                 nextdir = (struct ext2_dir_entry *)
5711                                         ((char *) dirent + 12);
5712                                 dirent->rec_len = 12;
5713                                 nextdir->rec_len = new_len;
5714                                 nextdir->inode = 0;
5715                                 nextdir->name_len = 0;
5716                                 status = 1;
5717                         }
5718                 }
5719         }
5720         return status;
5721 }
5722
5723 /*
5724  * Make sure the second entry in the directory is '..', and that the
5725  * directory entry is sane.  We do not check the inode number of '..'
5726  * here; this gets done in pass 3.
5727  */
5728 static int check_dotdot(e2fsck_t ctx,
5729                         struct ext2_dir_entry *dirent,
5730                         struct dir_info *dir, struct problem_context *pctx)
5731 {
5732         int             problem = 0;
5733
5734         if (!dirent->inode)
5735                 problem = PR_2_MISSING_DOT_DOT;
5736         else if (((dirent->name_len & 0xFF) != 2) ||
5737                  (dirent->name[0] != '.') ||
5738                  (dirent->name[1] != '.'))
5739                 problem = PR_2_2ND_NOT_DOT_DOT;
5740         else if (dirent->name[2] != '\0')
5741                 problem = PR_2_DOT_DOT_NULL_TERM;
5742
5743         if (problem) {
5744                 if (fix_problem(ctx, problem, pctx)) {
5745                         if (dirent->rec_len < 12)
5746                                 dirent->rec_len = 12;
5747                         /*
5748                          * Note: we don't have the parent inode just
5749                          * yet, so we will fill it in with the root
5750                          * inode.  This will get fixed in pass 3.
5751                          */
5752                         dirent->inode = EXT2_ROOT_INO;
5753                         dirent->name_len = 2;
5754                         dirent->name[0] = '.';
5755                         dirent->name[1] = '.';
5756                         dirent->name[2] = '\0';
5757                         return 1;
5758                 }
5759                 return 0;
5760         }
5761         dir->dotdot = dirent->inode;
5762         return 0;
5763 }
5764
5765 /*
5766  * Check to make sure a directory entry doesn't contain any illegal
5767  * characters.
5768  */
5769 static int check_name(e2fsck_t ctx,
5770                       struct ext2_dir_entry *dirent,
5771                       struct problem_context *pctx)
5772 {
5773         int     i;
5774         int     fixup = -1;
5775         int     ret = 0;
5776
5777         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779                         if (fixup < 0) {
5780                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5781                         }
5782                         if (fixup) {
5783                                 dirent->name[i] = '.';
5784                                 ret = 1;
5785                         }
5786                 }
5787         }
5788         return ret;
5789 }
5790
5791 /*
5792  * Check the directory filetype (if present)
5793  */
5794
5795 /*
5796  * Given a mode, return the ext2 file type
5797  */
5798 static int ext2_file_type(unsigned int mode)
5799 {
5800         if (LINUX_S_ISREG(mode))
5801                 return EXT2_FT_REG_FILE;
5802
5803         if (LINUX_S_ISDIR(mode))
5804                 return EXT2_FT_DIR;
5805
5806         if (LINUX_S_ISCHR(mode))
5807                 return EXT2_FT_CHRDEV;
5808
5809         if (LINUX_S_ISBLK(mode))
5810                 return EXT2_FT_BLKDEV;
5811
5812         if (LINUX_S_ISLNK(mode))
5813                 return EXT2_FT_SYMLINK;
5814
5815         if (LINUX_S_ISFIFO(mode))
5816                 return EXT2_FT_FIFO;
5817
5818         if (LINUX_S_ISSOCK(mode))
5819                 return EXT2_FT_SOCK;
5820
5821         return 0;
5822 }
5823
5824 static int check_filetype(e2fsck_t ctx,
5825                                    struct ext2_dir_entry *dirent,
5826                                    struct problem_context *pctx)
5827 {
5828         int     filetype = dirent->name_len >> 8;
5829         int     should_be = EXT2_FT_UNKNOWN;
5830         struct ext2_inode       inode;
5831
5832         if (!(ctx->fs->super->s_feature_incompat &
5833               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834                 if (filetype == 0 ||
5835                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836                         return 0;
5837                 dirent->name_len = dirent->name_len & 0xFF;
5838                 return 1;
5839         }
5840
5841         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842                 should_be = EXT2_FT_DIR;
5843         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844                                             dirent->inode)) {
5845                 should_be = EXT2_FT_REG_FILE;
5846         } else if (ctx->inode_bad_map &&
5847                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848                                             dirent->inode))
5849                 should_be = 0;
5850         else {
5851                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5852                                   "check_filetype");
5853                 should_be = ext2_file_type(inode.i_mode);
5854         }
5855         if (filetype == should_be)
5856                 return 0;
5857         pctx->num = should_be;
5858
5859         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860                         pctx) == 0)
5861                 return 0;
5862
5863         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864         return 1;
5865 }
5866
5867 #ifdef ENABLE_HTREE
5868 static void parse_int_node(ext2_filsys fs,
5869                            struct ext2_db_entry *db,
5870                            struct check_dir_struct *cd,
5871                            struct dx_dir_info   *dx_dir,
5872                            char *block_buf)
5873 {
5874         struct          ext2_dx_root_info  *root;
5875         struct          ext2_dx_entry *ent;
5876         struct          ext2_dx_countlimit *limit;
5877         struct dx_dirblock_info *dx_db;
5878         int             i, expect_limit, count;
5879         blk_t           blk;
5880         ext2_dirhash_t  min_hash = 0xffffffff;
5881         ext2_dirhash_t  max_hash = 0;
5882         ext2_dirhash_t  hash = 0, prev_hash;
5883
5884         if (db->blockcnt == 0) {
5885                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5886                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887         } else {
5888                 ent = (struct ext2_dx_entry *) (block_buf+8);
5889         }
5890         limit = (struct ext2_dx_countlimit *) ent;
5891
5892         count = ext2fs_le16_to_cpu(limit->count);
5893         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894                 sizeof(struct ext2_dx_entry);
5895         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898                         goto clear_and_exit;
5899         }
5900         if (count > expect_limit) {
5901                 cd->pctx.num = count;
5902                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903                         goto clear_and_exit;
5904                 count = expect_limit;
5905         }
5906
5907         for (i=0; i < count; i++) {
5908                 prev_hash = hash;
5909                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911                 /* Check to make sure the block is valid */
5912                 if (blk > (blk_t) dx_dir->numblocks) {
5913                         cd->pctx.blk = blk;
5914                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915                                         &cd->pctx))
5916                                 goto clear_and_exit;
5917                 }
5918                 if (hash < prev_hash &&
5919                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920                         goto clear_and_exit;
5921                 dx_db = &dx_dir->dx_block[blk];
5922                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5923                         dx_db->flags |= DX_FLAG_DUP_REF;
5924                 } else {
5925                         dx_db->flags |= DX_FLAG_REFERENCED;
5926                         dx_db->parent = db->blockcnt;
5927                 }
5928                 if (hash < min_hash)
5929                         min_hash = hash;
5930                 if (hash > max_hash)
5931                         max_hash = hash;
5932                 dx_db->node_min_hash = hash;
5933                 if ((i+1) < count)
5934                         dx_db->node_max_hash =
5935                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936                 else {
5937                         dx_db->node_max_hash = 0xfffffffe;
5938                         dx_db->flags |= DX_FLAG_LAST;
5939                 }
5940                 if (i == 0)
5941                         dx_db->flags |= DX_FLAG_FIRST;
5942         }
5943         dx_db = &dx_dir->dx_block[db->blockcnt];
5944         dx_db->min_hash = min_hash;
5945         dx_db->max_hash = max_hash;
5946         return;
5947
5948 clear_and_exit:
5949         clear_htree(cd->ctx, cd->pctx.ino);
5950         dx_dir->numblocks = 0;
5951 }
5952 #endif /* ENABLE_HTREE */
5953
5954 /*
5955  * Given a busted directory, try to salvage it somehow.
5956  *
5957  */
5958 static void salvage_directory(ext2_filsys fs,
5959                               struct ext2_dir_entry *dirent,
5960                               struct ext2_dir_entry *prev,
5961                               unsigned int *offset)
5962 {
5963         char    *cp = (char *) dirent;
5964         int left = fs->blocksize - *offset - dirent->rec_len;
5965         int name_len = dirent->name_len & 0xFF;
5966
5967         /*
5968          * Special case of directory entry of size 8: copy what's left
5969          * of the directory block up to cover up the invalid hole.
5970          */
5971         if ((left >= 12) && (dirent->rec_len == 8)) {
5972                 memmove(cp, cp+8, left);
5973                 memset(cp + left, 0, 8);
5974                 return;
5975         }
5976         /*
5977          * If the directory entry overruns the end of the directory
5978          * block, and the name is small enough to fit, then adjust the
5979          * record length.
5980          */
5981         if ((left < 0) &&
5982             (name_len + 8 <= dirent->rec_len + left) &&
5983             dirent->inode <= fs->super->s_inodes_count &&
5984             strnlen(dirent->name, name_len) == name_len) {
5985                 dirent->rec_len += left;
5986                 return;
5987         }
5988         /*
5989          * If the directory entry is a multiple of four, so it is
5990          * valid, let the previous directory entry absorb the invalid
5991          * one.
5992          */
5993         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994                 prev->rec_len += dirent->rec_len;
5995                 *offset += dirent->rec_len;
5996                 return;
5997         }
5998         /*
5999          * Default salvage method --- kill all of the directory
6000          * entries for the rest of the block.  We will either try to
6001          * absorb it into the previous directory entry, or create a
6002          * new empty directory entry the rest of the directory block.
6003          */
6004         if (prev) {
6005                 prev->rec_len += fs->blocksize - *offset;
6006                 *offset = fs->blocksize;
6007         } else {
6008                 dirent->rec_len = fs->blocksize - *offset;
6009                 dirent->name_len = 0;
6010                 dirent->inode = 0;
6011         }
6012 }
6013
6014 static int check_dir_block(ext2_filsys fs,
6015                            struct ext2_db_entry *db,
6016                            void *priv_data)
6017 {
6018         struct dir_info         *subdir, *dir;
6019         struct dx_dir_info      *dx_dir;
6020 #ifdef ENABLE_HTREE
6021         struct dx_dirblock_info *dx_db = 0;
6022 #endif /* ENABLE_HTREE */
6023         struct ext2_dir_entry   *dirent, *prev;
6024         ext2_dirhash_t          hash;
6025         unsigned int            offset = 0;
6026         int                     dir_modified = 0;
6027         int                     dot_state;
6028         blk_t                   block_nr = db->blk;
6029         ext2_ino_t              ino = db->ino;
6030         __u16                   links;
6031         struct check_dir_struct *cd;
6032         char                    *buf;
6033         e2fsck_t                ctx;
6034         int                     problem;
6035         struct ext2_dx_root_info *root;
6036         struct ext2_dx_countlimit *limit;
6037         static dict_t de_dict;
6038         struct problem_context  pctx;
6039         int     dups_found = 0;
6040
6041         cd = (struct check_dir_struct *) priv_data;
6042         buf = cd->buf;
6043         ctx = cd->ctx;
6044
6045         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046                 return DIRENT_ABORT;
6047
6048         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049                 return DIRENT_ABORT;
6050
6051         /*
6052          * Make sure the inode is still in use (could have been
6053          * deleted in the duplicate/bad blocks pass.
6054          */
6055         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056                 return 0;
6057
6058         cd->pctx.ino = ino;
6059         cd->pctx.blk = block_nr;
6060         cd->pctx.blkcount = db->blockcnt;
6061         cd->pctx.ino2 = 0;
6062         cd->pctx.dirent = 0;
6063         cd->pctx.num = 0;
6064
6065         if (db->blk == 0) {
6066                 if (allocate_dir_block(ctx, db, &cd->pctx))
6067                         return 0;
6068                 block_nr = db->blk;
6069         }
6070
6071         if (db->blockcnt)
6072                 dot_state = 2;
6073         else
6074                 dot_state = 0;
6075
6076         if (ctx->dirs_to_hash &&
6077             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078                 dups_found++;
6079
6080         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083         if (cd->pctx.errcode) {
6084                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085                         ctx->flags |= E2F_FLAG_ABORT;
6086                         return DIRENT_ABORT;
6087                 }
6088                 memset(buf, 0, fs->blocksize);
6089         }
6090 #ifdef ENABLE_HTREE
6091         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092         if (dx_dir && dx_dir->numblocks) {
6093                 if (db->blockcnt >= dx_dir->numblocks) {
6094                         printf("XXX should never happen!!!\n");
6095                         abort();
6096                 }
6097                 dx_db = &dx_dir->dx_block[db->blockcnt];
6098                 dx_db->type = DX_DIRBLOCK_LEAF;
6099                 dx_db->phys = block_nr;
6100                 dx_db->min_hash = ~0;
6101                 dx_db->max_hash = 0;
6102
6103                 dirent = (struct ext2_dir_entry *) buf;
6104                 limit = (struct ext2_dx_countlimit *) (buf+8);
6105                 if (db->blockcnt == 0) {
6106                         root = (struct ext2_dx_root_info *) (buf + 24);
6107                         dx_db->type = DX_DIRBLOCK_ROOT;
6108                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109                         if ((root->reserved_zero ||
6110                              root->info_length < 8 ||
6111                              root->indirect_levels > 1) &&
6112                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113                                 clear_htree(ctx, ino);
6114                                 dx_dir->numblocks = 0;
6115                                 dx_db = 0;
6116                         }
6117                         dx_dir->hashversion = root->hash_version;
6118                         dx_dir->depth = root->indirect_levels + 1;
6119                 } else if ((dirent->inode == 0) &&
6120                            (dirent->rec_len == fs->blocksize) &&
6121                            (dirent->name_len == 0) &&
6122                            (ext2fs_le16_to_cpu(limit->limit) ==
6123                             ((fs->blocksize-8) /
6124                              sizeof(struct ext2_dx_entry))))
6125                         dx_db->type = DX_DIRBLOCK_NODE;
6126         }
6127 #endif /* ENABLE_HTREE */
6128
6129         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130         prev = 0;
6131         do {
6132                 problem = 0;
6133                 dirent = (struct ext2_dir_entry *) (buf + offset);
6134                 cd->pctx.dirent = dirent;
6135                 cd->pctx.num = offset;
6136                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6137                     (dirent->rec_len < 12) ||
6138                     ((dirent->rec_len % 4) != 0) ||
6139                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141                                 salvage_directory(fs, dirent, prev, &offset);
6142                                 dir_modified++;
6143                                 continue;
6144                         } else
6145                                 goto abort_free_dict;
6146                 }
6147                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149                                 dirent->name_len = EXT2_NAME_LEN;
6150                                 dir_modified++;
6151                         }
6152                 }
6153
6154                 if (dot_state == 0) {
6155                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6156                                 dir_modified++;
6157                 } else if (dot_state == 1) {
6158                         dir = e2fsck_get_dir_info(ctx, ino);
6159                         if (!dir) {
6160                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161                                 goto abort_free_dict;
6162                         }
6163                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164                                 dir_modified++;
6165                 } else if (dirent->inode == ino) {
6166                         problem = PR_2_LINK_DOT;
6167                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168                                 dirent->inode = 0;
6169                                 dir_modified++;
6170                                 goto next;
6171                         }
6172                 }
6173                 if (!dirent->inode)
6174                         goto next;
6175
6176                 /*
6177                  * Make sure the inode listed is a legal one.
6178                  */
6179                 if (((dirent->inode != EXT2_ROOT_INO) &&
6180                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181                     (dirent->inode > fs->super->s_inodes_count)) {
6182                         problem = PR_2_BAD_INO;
6183                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184                                                dirent->inode))) {
6185                         /*
6186                          * If the inode is unused, offer to clear it.
6187                          */
6188                         problem = PR_2_UNUSED_INODE;
6189                 } else if ((dot_state > 1) &&
6190                            ((dirent->name_len & 0xFF) == 1) &&
6191                            (dirent->name[0] == '.')) {
6192                         /*
6193                          * If there's a '.' entry in anything other
6194                          * than the first directory entry, it's a
6195                          * duplicate entry that should be removed.
6196                          */
6197                         problem = PR_2_DUP_DOT;
6198                 } else if ((dot_state > 1) &&
6199                            ((dirent->name_len & 0xFF) == 2) &&
6200                            (dirent->name[0] == '.') &&
6201                            (dirent->name[1] == '.')) {
6202                         /*
6203                          * If there's a '..' entry in anything other
6204                          * than the second directory entry, it's a
6205                          * duplicate entry that should be removed.
6206                          */
6207                         problem = PR_2_DUP_DOT_DOT;
6208                 } else if ((dot_state > 1) &&
6209                            (dirent->inode == EXT2_ROOT_INO)) {
6210                         /*
6211                          * Don't allow links to the root directory.
6212                          * We check this specially to make sure we
6213                          * catch this error case even if the root
6214                          * directory hasn't been created yet.
6215                          */
6216                         problem = PR_2_LINK_ROOT;
6217                 } else if ((dot_state > 1) &&
6218                            (dirent->name_len & 0xFF) == 0) {
6219                         /*
6220                          * Don't allow zero-length directory names.
6221                          */
6222                         problem = PR_2_NULL_NAME;
6223                 }
6224
6225                 if (problem) {
6226                         if (fix_problem(ctx, problem, &cd->pctx)) {
6227                                 dirent->inode = 0;
6228                                 dir_modified++;
6229                                 goto next;
6230                         } else {
6231                                 ext2fs_unmark_valid(fs);
6232                                 if (problem == PR_2_BAD_INO)
6233                                         goto next;
6234                         }
6235                 }
6236
6237                 /*
6238                  * If the inode was marked as having bad fields in
6239                  * pass1, process it and offer to fix/clear it.
6240                  * (We wait until now so that we can display the
6241                  * pathname to the user.)
6242                  */
6243                 if (ctx->inode_bad_map &&
6244                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245                                              dirent->inode)) {
6246                         if (e2fsck_process_bad_inode(ctx, ino,
6247                                                      dirent->inode,
6248                                                      buf + fs->blocksize)) {
6249                                 dirent->inode = 0;
6250                                 dir_modified++;
6251                                 goto next;
6252                         }
6253                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254                                 return DIRENT_ABORT;
6255                 }
6256
6257                 if (check_name(ctx, dirent, &cd->pctx))
6258                         dir_modified++;
6259
6260                 if (check_filetype(ctx, dirent, &cd->pctx))
6261                         dir_modified++;
6262
6263 #ifdef ENABLE_HTREE
6264                 if (dx_db) {
6265                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266                                        (dirent->name_len & 0xFF),
6267                                        fs->super->s_hash_seed, &hash, 0);
6268                         if (hash < dx_db->min_hash)
6269                                 dx_db->min_hash = hash;
6270                         if (hash > dx_db->max_hash)
6271                                 dx_db->max_hash = hash;
6272                 }
6273 #endif
6274
6275                 /*
6276                  * If this is a directory, then mark its parent in its
6277                  * dir_info structure.  If the parent field is already
6278                  * filled in, then this directory has more than one
6279                  * hard link.  We assume the first link is correct,
6280                  * and ask the user if he/she wants to clear this one.
6281                  */
6282                 if ((dot_state > 1) &&
6283                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284                                               dirent->inode))) {
6285                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286                         if (!subdir) {
6287                                 cd->pctx.ino = dirent->inode;
6288                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289                                 goto abort_free_dict;
6290                         }
6291                         if (subdir->parent) {
6292                                 cd->pctx.ino2 = subdir->parent;
6293                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6294                                                 &cd->pctx)) {
6295                                         dirent->inode = 0;
6296                                         dir_modified++;
6297                                         goto next;
6298                                 }
6299                                 cd->pctx.ino2 = 0;
6300                         } else
6301                                 subdir->parent = ino;
6302                 }
6303
6304                 if (dups_found) {
6305                         ;
6306                 } else if (dict_lookup(&de_dict, dirent)) {
6307                         clear_problem_context(&pctx);
6308                         pctx.ino = ino;
6309                         pctx.dirent = dirent;
6310                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311                         if (!ctx->dirs_to_hash)
6312                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313                         if (ctx->dirs_to_hash)
6314                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315                         dups_found++;
6316                 } else
6317                         dict_alloc_insert(&de_dict, dirent, dirent);
6318
6319                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320                                         &links);
6321                 if (links > 1)
6322                         ctx->fs_links_count++;
6323                 ctx->fs_total_count++;
6324         next:
6325                 prev = dirent;
6326                 offset += dirent->rec_len;
6327                 dot_state++;
6328         } while (offset < fs->blocksize);
6329 #ifdef ENABLE_HTREE
6330         if (dx_db) {
6331                 cd->pctx.dir = cd->pctx.ino;
6332                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333                     (dx_db->type == DX_DIRBLOCK_NODE))
6334                         parse_int_node(fs, db, cd, dx_dir, buf);
6335         }
6336 #endif /* ENABLE_HTREE */
6337         if (offset != fs->blocksize) {
6338                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340                         dirent->rec_len = cd->pctx.num;
6341                         dir_modified++;
6342                 }
6343         }
6344         if (dir_modified) {
6345                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346                 if (cd->pctx.errcode) {
6347                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348                                          &cd->pctx))
6349                                 goto abort_free_dict;
6350                 }
6351                 ext2fs_mark_changed(fs);
6352         }
6353         dict_free_nodes(&de_dict);
6354         return 0;
6355 abort_free_dict:
6356         dict_free_nodes(&de_dict);
6357         ctx->flags |= E2F_FLAG_ABORT;
6358         return DIRENT_ABORT;
6359 }
6360
6361 /*
6362  * This function is called to deallocate a block, and is an interator
6363  * functioned called by deallocate inode via ext2fs_iterate_block().
6364  */
6365 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367                                   blk_t ref_block FSCK_ATTR((unused)),
6368                                   int ref_offset FSCK_ATTR((unused)),
6369                                   void *priv_data)
6370 {
6371         e2fsck_t        ctx = (e2fsck_t) priv_data;
6372
6373         if (HOLE_BLKADDR(*block_nr))
6374                 return 0;
6375         if ((*block_nr < fs->super->s_first_data_block) ||
6376             (*block_nr >= fs->super->s_blocks_count))
6377                 return 0;
6378         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380         return 0;
6381 }
6382
6383 /*
6384  * This fuction deallocates an inode
6385  */
6386 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6387 {
6388         ext2_filsys fs = ctx->fs;
6389         struct ext2_inode       inode;
6390         struct problem_context  pctx;
6391         __u32                   count;
6392
6393         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395         inode.i_links_count = 0;
6396         inode.i_dtime = time(0);
6397         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398         clear_problem_context(&pctx);
6399         pctx.ino = ino;
6400
6401         /*
6402          * Fix up the bitmaps...
6403          */
6404         e2fsck_read_bitmaps(ctx);
6405         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407         if (ctx->inode_bad_map)
6408                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6410
6411         if (inode.i_file_acl &&
6412             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414                                                    block_buf, -1, &count);
6415                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416                         pctx.errcode = 0;
6417                         count = 1;
6418                 }
6419                 if (pctx.errcode) {
6420                         pctx.blk = inode.i_file_acl;
6421                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422                         ctx->flags |= E2F_FLAG_ABORT;
6423                         return;
6424                 }
6425                 if (count == 0) {
6426                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427                                                    inode.i_file_acl);
6428                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6429                 }
6430                 inode.i_file_acl = 0;
6431         }
6432
6433         if (!ext2fs_inode_has_valid_blocks(&inode))
6434                 return;
6435
6436         if (LINUX_S_ISREG(inode.i_mode) &&
6437             (inode.i_size_high || inode.i_size & 0x80000000UL))
6438                 ctx->large_files--;
6439
6440         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441                                             deallocate_inode_block, ctx);
6442         if (pctx.errcode) {
6443                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444                 ctx->flags |= E2F_FLAG_ABORT;
6445                 return;
6446         }
6447 }
6448
6449 /*
6450  * This fuction clears the htree flag on an inode
6451  */
6452 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6453 {
6454         struct ext2_inode       inode;
6455
6456         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459         if (ctx->dirs_to_hash)
6460                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6461 }
6462
6463
6464 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465                                     ext2_ino_t ino, char *buf)
6466 {
6467         ext2_filsys fs = ctx->fs;
6468         struct ext2_inode       inode;
6469         int                     inode_modified = 0;
6470         int                     not_fixed = 0;
6471         unsigned char           *frag, *fsize;
6472         struct problem_context  pctx;
6473         int     problem = 0;
6474
6475         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6476
6477         clear_problem_context(&pctx);
6478         pctx.ino = ino;
6479         pctx.dir = dir;
6480         pctx.inode = &inode;
6481
6482         if (inode.i_file_acl &&
6483             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485                 inode.i_file_acl = 0;
6486 #if BB_BIG_ENDIAN
6487                 /*
6488                  * This is a special kludge to deal with long symlinks
6489                  * on big endian systems.  i_blocks had already been
6490                  * decremented earlier in pass 1, but since i_file_acl
6491                  * hadn't yet been cleared, ext2fs_read_inode()
6492                  * assumed that the file was short symlink and would
6493                  * not have byte swapped i_block[0].  Hence, we have
6494                  * to byte-swap it here.
6495                  */
6496                 if (LINUX_S_ISLNK(inode.i_mode) &&
6497                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498                     (inode.i_blocks == fs->blocksize >> 9))
6499                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500 #endif
6501                 inode_modified++;
6502         } else
6503                 not_fixed++;
6504
6505         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508             !(LINUX_S_ISSOCK(inode.i_mode)))
6509                 problem = PR_2_BAD_MODE;
6510         else if (LINUX_S_ISCHR(inode.i_mode)
6511                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6512                 problem = PR_2_BAD_CHAR_DEV;
6513         else if (LINUX_S_ISBLK(inode.i_mode)
6514                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6515                 problem = PR_2_BAD_BLOCK_DEV;
6516         else if (LINUX_S_ISFIFO(inode.i_mode)
6517                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6518                 problem = PR_2_BAD_FIFO;
6519         else if (LINUX_S_ISSOCK(inode.i_mode)
6520                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6521                 problem = PR_2_BAD_SOCKET;
6522         else if (LINUX_S_ISLNK(inode.i_mode)
6523                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524                 problem = PR_2_INVALID_SYMLINK;
6525         }
6526
6527         if (problem) {
6528                 if (fix_problem(ctx, problem, &pctx)) {
6529                         deallocate_inode(ctx, ino, 0);
6530                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531                                 return 0;
6532                         return 1;
6533                 } else
6534                         not_fixed++;
6535                 problem = 0;
6536         }
6537
6538         if (inode.i_faddr) {
6539                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540                         inode.i_faddr = 0;
6541                         inode_modified++;
6542                 } else
6543                         not_fixed++;
6544         }
6545
6546         switch (fs->super->s_creator_os) {
6547             case EXT2_OS_LINUX:
6548                 frag = &inode.osd2.linux2.l_i_frag;
6549                 fsize = &inode.osd2.linux2.l_i_fsize;
6550                 break;
6551             case EXT2_OS_HURD:
6552                 frag = &inode.osd2.hurd2.h_i_frag;
6553                 fsize = &inode.osd2.hurd2.h_i_fsize;
6554                 break;
6555             case EXT2_OS_MASIX:
6556                 frag = &inode.osd2.masix2.m_i_frag;
6557                 fsize = &inode.osd2.masix2.m_i_fsize;
6558                 break;
6559             default:
6560                 frag = fsize = 0;
6561         }
6562         if (frag && *frag) {
6563                 pctx.num = *frag;
6564                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565                         *frag = 0;
6566                         inode_modified++;
6567                 } else
6568                         not_fixed++;
6569                 pctx.num = 0;
6570         }
6571         if (fsize && *fsize) {
6572                 pctx.num = *fsize;
6573                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574                         *fsize = 0;
6575                         inode_modified++;
6576                 } else
6577                         not_fixed++;
6578                 pctx.num = 0;
6579         }
6580
6581         if (inode.i_file_acl &&
6582             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585                         inode.i_file_acl = 0;
6586                         inode_modified++;
6587                 } else
6588                         not_fixed++;
6589         }
6590         if (inode.i_dir_acl &&
6591             LINUX_S_ISDIR(inode.i_mode)) {
6592                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593                         inode.i_dir_acl = 0;
6594                         inode_modified++;
6595                 } else
6596                         not_fixed++;
6597         }
6598
6599         if (inode_modified)
6600                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601         if (!not_fixed)
6602                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603         return 0;
6604 }
6605
6606
6607 /*
6608  * allocate_dir_block --- this function allocates a new directory
6609  *      block for a particular inode; this is done if a directory has
6610  *      a "hole" in it, or if a directory has a illegal block number
6611  *      that was zeroed out and now needs to be replaced.
6612  */
6613 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614                               struct problem_context *pctx)
6615 {
6616         ext2_filsys fs = ctx->fs;
6617         blk_t                   blk;
6618         char                    *block;
6619         struct ext2_inode       inode;
6620
6621         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622                 return 1;
6623
6624         /*
6625          * Read the inode and block bitmaps in; we'll be messing with
6626          * them.
6627          */
6628         e2fsck_read_bitmaps(ctx);
6629
6630         /*
6631          * First, find a free block
6632          */
6633         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634         if (pctx->errcode) {
6635                 pctx->str = "ext2fs_new_block";
6636                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637                 return 1;
6638         }
6639         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640         ext2fs_mark_block_bitmap(fs->block_map, blk);
6641         ext2fs_mark_bb_dirty(fs);
6642
6643         /*
6644          * Now let's create the actual data block for the inode
6645          */
6646         if (db->blockcnt)
6647                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648         else
6649                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650                                                      EXT2_ROOT_INO, &block);
6651
6652         if (pctx->errcode) {
6653                 pctx->str = "ext2fs_new_dir_block";
6654                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655                 return 1;
6656         }
6657
6658         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659         ext2fs_free_mem(&block);
6660         if (pctx->errcode) {
6661                 pctx->str = "ext2fs_write_dir_block";
6662                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663                 return 1;
6664         }
6665
6666         /*
6667          * Update the inode block count
6668          */
6669         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670         inode.i_blocks += fs->blocksize / 512;
6671         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6674
6675         /*
6676          * Finally, update the block pointers for the inode
6677          */
6678         db->blk = blk;
6679         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680                                       0, update_dir_block, db);
6681         if (pctx->errcode) {
6682                 pctx->str = "ext2fs_block_iterate";
6683                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684                 return 1;
6685         }
6686
6687         return 0;
6688 }
6689
6690 /*
6691  * This is a helper function for allocate_dir_block().
6692  */
6693 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694                             blk_t       *block_nr,
6695                             e2_blkcnt_t blockcnt,
6696                             blk_t ref_block FSCK_ATTR((unused)),
6697                             int ref_offset FSCK_ATTR((unused)),
6698                             void *priv_data)
6699 {
6700         struct ext2_db_entry *db;
6701
6702         db = (struct ext2_db_entry *) priv_data;
6703         if (db->blockcnt == (int) blockcnt) {
6704                 *block_nr = db->blk;
6705                 return BLOCK_CHANGED;
6706         }
6707         return 0;
6708 }
6709
6710 /*
6711  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6712  *
6713  * Pass #3 assures that all directories are connected to the
6714  * filesystem tree, using the following algorithm:
6715  *
6716  * First, the root directory is checked to make sure it exists; if
6717  * not, e2fsck will offer to create a new one.  It is then marked as
6718  * "done".
6719  *
6720  * Then, pass3 interates over all directory inodes; for each directory
6721  * it attempts to trace up the filesystem tree, using dirinfo.parent
6722  * until it reaches a directory which has been marked "done".  If it
6723  * cannot do so, then the directory must be disconnected, and e2fsck
6724  * will offer to reconnect it to /lost+found.  While it is chasing
6725  * parent pointers up the filesystem tree, if pass3 sees a directory
6726  * twice, then it has detected a filesystem loop, and it will again
6727  * offer to reconnect the directory to /lost+found in to break the
6728  * filesystem loop.
6729  *
6730  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731  * reconnect inodes to /lost+found; this subroutine is also used by
6732  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6733  * is responsible for creating /lost+found if it does not exist.
6734  *
6735  * Pass 3 frees the following data structures:
6736  *      - The dirinfo directory information cache.
6737  */
6738
6739 static void check_root(e2fsck_t ctx);
6740 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741                            struct problem_context *pctx);
6742 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6743
6744 static ext2fs_inode_bitmap inode_loop_detect;
6745 static ext2fs_inode_bitmap inode_done_map;
6746
6747 static void e2fsck_pass3(e2fsck_t ctx)
6748 {
6749         ext2_filsys fs = ctx->fs;
6750         int             i;
6751         struct problem_context  pctx;
6752         struct dir_info *dir;
6753         unsigned long maxdirs, count;
6754
6755         clear_problem_context(&pctx);
6756
6757         /* Pass 3 */
6758
6759         if (!(ctx->options & E2F_OPT_PREEN))
6760                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6761
6762         /*
6763          * Allocate some bitmaps to do loop detection.
6764          */
6765         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766                                                     &inode_done_map);
6767         if (pctx.errcode) {
6768                 pctx.num = 2;
6769                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770                 ctx->flags |= E2F_FLAG_ABORT;
6771                 goto abort_exit;
6772         }
6773         check_root(ctx);
6774         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775                 goto abort_exit;
6776
6777         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6778
6779         maxdirs = e2fsck_get_num_dirinfo(ctx);
6780         count = 1;
6781
6782         if (ctx->progress)
6783                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784                         goto abort_exit;
6785
6786         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788                         goto abort_exit;
6789                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790                         goto abort_exit;
6791                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792                         if (check_directory(ctx, dir, &pctx))
6793                                 goto abort_exit;
6794         }
6795
6796         /*
6797          * Force the creation of /lost+found if not present
6798          */
6799         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800                 e2fsck_get_lost_and_found(ctx, 1);
6801
6802         /*
6803          * If there are any directories that need to be indexed or
6804          * optimized, do it here.
6805          */
6806         e2fsck_rehash_directories(ctx);
6807
6808 abort_exit:
6809         e2fsck_free_dir_info(ctx);
6810         ext2fs_free_inode_bitmap(inode_loop_detect);
6811         inode_loop_detect = 0;
6812         ext2fs_free_inode_bitmap(inode_done_map);
6813         inode_done_map = 0;
6814 }
6815
6816 /*
6817  * This makes sure the root inode is present; if not, we ask if the
6818  * user wants us to create it.  Not creating it is a fatal error.
6819  */
6820 static void check_root(e2fsck_t ctx)
6821 {
6822         ext2_filsys fs = ctx->fs;
6823         blk_t                   blk;
6824         struct ext2_inode       inode;
6825         char *                  block;
6826         struct problem_context  pctx;
6827
6828         clear_problem_context(&pctx);
6829
6830         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6831                 /*
6832                  * If the root inode is not a directory, die here.  The
6833                  * user must have answered 'no' in pass1 when we
6834                  * offered to clear it.
6835                  */
6836                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837                                                EXT2_ROOT_INO))) {
6838                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839                         ctx->flags |= E2F_FLAG_ABORT;
6840                 }
6841                 return;
6842         }
6843
6844         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846                 ctx->flags |= E2F_FLAG_ABORT;
6847                 return;
6848         }
6849
6850         e2fsck_read_bitmaps(ctx);
6851
6852         /*
6853          * First, find a free block
6854          */
6855         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856         if (pctx.errcode) {
6857                 pctx.str = "ext2fs_new_block";
6858                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859                 ctx->flags |= E2F_FLAG_ABORT;
6860                 return;
6861         }
6862         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863         ext2fs_mark_block_bitmap(fs->block_map, blk);
6864         ext2fs_mark_bb_dirty(fs);
6865
6866         /*
6867          * Now let's create the actual data block for the inode
6868          */
6869         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870                                             &block);
6871         if (pctx.errcode) {
6872                 pctx.str = "ext2fs_new_dir_block";
6873                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874                 ctx->flags |= E2F_FLAG_ABORT;
6875                 return;
6876         }
6877
6878         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879         if (pctx.errcode) {
6880                 pctx.str = "ext2fs_write_dir_block";
6881                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882                 ctx->flags |= E2F_FLAG_ABORT;
6883                 return;
6884         }
6885         ext2fs_free_mem(&block);
6886
6887         /*
6888          * Set up the inode structure
6889          */
6890         memset(&inode, 0, sizeof(inode));
6891         inode.i_mode = 040755;
6892         inode.i_size = fs->blocksize;
6893         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
6894         inode.i_links_count = 2;
6895         inode.i_blocks = fs->blocksize / 512;
6896         inode.i_block[0] = blk;
6897
6898         /*
6899          * Write out the inode.
6900          */
6901         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902         if (pctx.errcode) {
6903                 pctx.str = "ext2fs_write_inode";
6904                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905                 ctx->flags |= E2F_FLAG_ABORT;
6906                 return;
6907         }
6908
6909         /*
6910          * Miscellaneous bookkeeping...
6911          */
6912         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6915
6916         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919         ext2fs_mark_ib_dirty(fs);
6920 }
6921
6922 /*
6923  * This subroutine is responsible for making sure that a particular
6924  * directory is connected to the root; if it isn't we trace it up as
6925  * far as we can go, and then offer to connect the resulting parent to
6926  * the lost+found.  We have to do loop detection; if we ever discover
6927  * a loop, we treat that as a disconnected directory and offer to
6928  * reparent it to lost+found.
6929  *
6930  * However, loop detection is expensive, because for very large
6931  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932  * is non-trivial.  Loops in filesystems are also a rare error case,
6933  * and we shouldn't optimize for error cases.  So we try two passes of
6934  * the algorithm.  The first time, we ignore loop detection and merely
6935  * increment a counter; if the counter exceeds some extreme threshold,
6936  * then we try again with the loop detection bitmap enabled.
6937  */
6938 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939                            struct problem_context *pctx)
6940 {
6941         ext2_filsys     fs = ctx->fs;
6942         struct dir_info *p = dir;
6943         int             loop_pass = 0, parent_count = 0;
6944
6945         if (!p)
6946                 return 0;
6947
6948         while (1) {
6949                 /*
6950                  * Mark this inode as being "done"; by the time we
6951                  * return from this function, the inode we either be
6952                  * verified as being connected to the directory tree,
6953                  * or we will have offered to reconnect this to
6954                  * lost+found.
6955                  *
6956                  * If it was marked done already, then we've reached a
6957                  * parent we've already checked.
6958                  */
6959                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960                         break;
6961
6962                 /*
6963                  * If this directory doesn't have a parent, or we've
6964                  * seen the parent once already, then offer to
6965                  * reparent it to lost+found
6966                  */
6967                 if (!p->parent ||
6968                     (loop_pass &&
6969                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6970                                               p->parent)))) {
6971                         pctx->ino = p->ino;
6972                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6974                                         ext2fs_unmark_valid(fs);
6975                                 else {
6976                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
6977                                         p->parent = ctx->lost_and_found;
6978                                         fix_dotdot(ctx, p, ctx->lost_and_found);
6979                                 }
6980                         }
6981                         break;
6982                 }
6983                 p = e2fsck_get_dir_info(ctx, p->parent);
6984                 if (!p) {
6985                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986                         return 0;
6987                 }
6988                 if (loop_pass) {
6989                         ext2fs_mark_inode_bitmap(inode_loop_detect,
6990                                                  p->ino);
6991                 } else if (parent_count++ > 2048) {
6992                         /*
6993                          * If we've run into a path depth that's
6994                          * greater than 2048, try again with the inode
6995                          * loop bitmap turned on and start from the
6996                          * top.
6997                          */
6998                         loop_pass = 1;
6999                         if (inode_loop_detect)
7000                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
7001                         else {
7002                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003                                 if (pctx->errcode) {
7004                                         pctx->num = 1;
7005                                         fix_problem(ctx,
7006                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007                                         ctx->flags |= E2F_FLAG_ABORT;
7008                                         return -1;
7009                                 }
7010                         }
7011                         p = dir;
7012                 }
7013         }
7014
7015         /*
7016          * Make sure that .. and the parent directory are the same;
7017          * offer to fix it if not.
7018          */
7019         if (dir->parent != dir->dotdot) {
7020                 pctx->ino = dir->ino;
7021                 pctx->ino2 = dir->dotdot;
7022                 pctx->dir = dir->parent;
7023                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024                         fix_dotdot(ctx, dir, dir->parent);
7025         }
7026         return 0;
7027 }
7028
7029 /*
7030  * This routine gets the lost_and_found inode, making it a directory
7031  * if necessary
7032  */
7033 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7034 {
7035         ext2_filsys fs = ctx->fs;
7036         ext2_ino_t                      ino;
7037         blk_t                   blk;
7038         errcode_t               retval;
7039         struct ext2_inode       inode;
7040         char *                  block;
7041         static const char       name[] = "lost+found";
7042         struct  problem_context pctx;
7043         struct dir_info         *dirinfo;
7044
7045         if (ctx->lost_and_found)
7046                 return ctx->lost_and_found;
7047
7048         clear_problem_context(&pctx);
7049
7050         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051                                sizeof(name)-1, 0, &ino);
7052         if (retval && !fix)
7053                 return 0;
7054         if (!retval) {
7055                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056                         ctx->lost_and_found = ino;
7057                         return ino;
7058                 }
7059
7060                 /* Lost+found isn't a directory! */
7061                 if (!fix)
7062                         return 0;
7063                 pctx.ino = ino;
7064                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065                         return 0;
7066
7067                 /* OK, unlink the old /lost+found file. */
7068                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069                 if (pctx.errcode) {
7070                         pctx.str = "ext2fs_unlink";
7071                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072                         return 0;
7073                 }
7074                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7075                 if (dirinfo)
7076                         dirinfo->parent = 0;
7077                 e2fsck_adjust_inode_count(ctx, ino, -1);
7078         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079                 pctx.errcode = retval;
7080                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7081         }
7082         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083                 return 0;
7084
7085         /*
7086          * Read the inode and block bitmaps in; we'll be messing with
7087          * them.
7088          */
7089         e2fsck_read_bitmaps(ctx);
7090
7091         /*
7092          * First, find a free block
7093          */
7094         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095         if (retval) {
7096                 pctx.errcode = retval;
7097                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098                 return 0;
7099         }
7100         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101         ext2fs_block_alloc_stats(fs, blk, +1);
7102
7103         /*
7104          * Next find a free inode.
7105          */
7106         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107                                   ctx->inode_used_map, &ino);
7108         if (retval) {
7109                 pctx.errcode = retval;
7110                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111                 return 0;
7112         }
7113         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7116
7117         /*
7118          * Now let's create the actual data block for the inode
7119          */
7120         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121         if (retval) {
7122                 pctx.errcode = retval;
7123                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124                 return 0;
7125         }
7126
7127         retval = ext2fs_write_dir_block(fs, blk, block);
7128         ext2fs_free_mem(&block);
7129         if (retval) {
7130                 pctx.errcode = retval;
7131                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132                 return 0;
7133         }
7134
7135         /*
7136          * Set up the inode structure
7137          */
7138         memset(&inode, 0, sizeof(inode));
7139         inode.i_mode = 040700;
7140         inode.i_size = fs->blocksize;
7141         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
7142         inode.i_links_count = 2;
7143         inode.i_blocks = fs->blocksize / 512;
7144         inode.i_block[0] = blk;
7145
7146         /*
7147          * Next, write out the inode.
7148          */
7149         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150         if (pctx.errcode) {
7151                 pctx.str = "ext2fs_write_inode";
7152                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153                 return 0;
7154         }
7155         /*
7156          * Finally, create the directory link
7157          */
7158         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159         if (pctx.errcode) {
7160                 pctx.str = "ext2fs_link";
7161                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162                 return 0;
7163         }
7164
7165         /*
7166          * Miscellaneous bookkeeping that needs to be kept straight.
7167          */
7168         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170         ext2fs_icount_store(ctx->inode_count, ino, 2);
7171         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172         ctx->lost_and_found = ino;
7173         return ino;
7174 }
7175
7176 /*
7177  * This routine will connect a file to lost+found
7178  */
7179 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7180 {
7181         ext2_filsys fs = ctx->fs;
7182         errcode_t       retval;
7183         char            name[80];
7184         struct problem_context  pctx;
7185         struct ext2_inode       inode;
7186         int             file_type = 0;
7187
7188         clear_problem_context(&pctx);
7189         pctx.ino = ino;
7190
7191         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193                         ctx->bad_lost_and_found++;
7194         }
7195         if (ctx->bad_lost_and_found) {
7196                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197                 return 1;
7198         }
7199
7200         sprintf(name, "#%u", ino);
7201         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202                 file_type = ext2_file_type(inode.i_mode);
7203         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204         if (retval == EXT2_ET_DIR_NO_SPACE) {
7205                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206                         return 1;
7207                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208                                                  1, 0);
7209                 if (retval) {
7210                         pctx.errcode = retval;
7211                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212                         return 1;
7213                 }
7214                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215                                      ino, file_type);
7216         }
7217         if (retval) {
7218                 pctx.errcode = retval;
7219                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220                 return 1;
7221         }
7222         e2fsck_adjust_inode_count(ctx, ino, 1);
7223
7224         return 0;
7225 }
7226
7227 /*
7228  * Utility routine to adjust the inode counts on an inode.
7229  */
7230 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7231 {
7232         ext2_filsys fs = ctx->fs;
7233         errcode_t               retval;
7234         struct ext2_inode       inode;
7235
7236         if (!ino)
7237                 return 0;
7238
7239         retval = ext2fs_read_inode(fs, ino, &inode);
7240         if (retval)
7241                 return retval;
7242
7243         if (adj == 1) {
7244                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245                 if (inode.i_links_count == (__u16) ~0)
7246                         return 0;
7247                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248                 inode.i_links_count++;
7249         } else if (adj == -1) {
7250                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251                 if (inode.i_links_count == 0)
7252                         return 0;
7253                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254                 inode.i_links_count--;
7255         }
7256
7257         retval = ext2fs_write_inode(fs, ino, &inode);
7258         if (retval)
7259                 return retval;
7260
7261         return 0;
7262 }
7263
7264 /*
7265  * Fix parent --- this routine fixes up the parent of a directory.
7266  */
7267 struct fix_dotdot_struct {
7268         ext2_filsys     fs;
7269         ext2_ino_t      parent;
7270         int             done;
7271         e2fsck_t        ctx;
7272 };
7273
7274 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275                            int  offset FSCK_ATTR((unused)),
7276                            int  blocksize FSCK_ATTR((unused)),
7277                            char *buf FSCK_ATTR((unused)),
7278                            void *priv_data)
7279 {
7280         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281         errcode_t       retval;
7282         struct problem_context pctx;
7283
7284         if ((dirent->name_len & 0xFF) != 2)
7285                 return 0;
7286         if (strncmp(dirent->name, "..", 2))
7287                 return 0;
7288
7289         clear_problem_context(&pctx);
7290
7291         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292         if (retval) {
7293                 pctx.errcode = retval;
7294                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7295         }
7296         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297         if (retval) {
7298                 pctx.errcode = retval;
7299                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7300         }
7301         dirent->inode = fp->parent;
7302
7303         fp->done++;
7304         return DIRENT_ABORT | DIRENT_CHANGED;
7305 }
7306
7307 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7308 {
7309         ext2_filsys fs = ctx->fs;
7310         errcode_t       retval;
7311         struct fix_dotdot_struct fp;
7312         struct problem_context pctx;
7313
7314         fp.fs = fs;
7315         fp.parent = parent;
7316         fp.done = 0;
7317         fp.ctx = ctx;
7318
7319         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320                                     0, fix_dotdot_proc, &fp);
7321         if (retval || !fp.done) {
7322                 clear_problem_context(&pctx);
7323                 pctx.ino = dir->ino;
7324                 pctx.errcode = retval;
7325                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326                             PR_3_FIX_PARENT_NOFIND, &pctx);
7327                 ext2fs_unmark_valid(fs);
7328         }
7329         dir->dotdot = parent;
7330 }
7331
7332 /*
7333  * These routines are responsible for expanding a /lost+found if it is
7334  * too small.
7335  */
7336
7337 struct expand_dir_struct {
7338         int                     num;
7339         int                     guaranteed_size;
7340         int                     newblocks;
7341         int                     last_block;
7342         errcode_t               err;
7343         e2fsck_t                ctx;
7344 };
7345
7346 static int expand_dir_proc(ext2_filsys fs,
7347                            blk_t        *blocknr,
7348                            e2_blkcnt_t  blockcnt,
7349                            blk_t ref_block FSCK_ATTR((unused)),
7350                            int ref_offset FSCK_ATTR((unused)),
7351                            void *priv_data)
7352 {
7353         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354         blk_t   new_blk;
7355         static blk_t    last_blk = 0;
7356         char            *block;
7357         errcode_t       retval;
7358         e2fsck_t        ctx;
7359
7360         ctx = es->ctx;
7361
7362         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363                 return BLOCK_ABORT;
7364
7365         if (blockcnt > 0)
7366                 es->last_block = blockcnt;
7367         if (*blocknr) {
7368                 last_blk = *blocknr;
7369                 return 0;
7370         }
7371         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372                                   &new_blk);
7373         if (retval) {
7374                 es->err = retval;
7375                 return BLOCK_ABORT;
7376         }
7377         if (blockcnt > 0) {
7378                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379                 if (retval) {
7380                         es->err = retval;
7381                         return BLOCK_ABORT;
7382                 }
7383                 es->num--;
7384                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7385         } else {
7386                 retval = ext2fs_get_mem(fs->blocksize, &block);
7387                 if (retval) {
7388                         es->err = retval;
7389                         return BLOCK_ABORT;
7390                 }
7391                 memset(block, 0, fs->blocksize);
7392                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7393         }
7394         if (retval) {
7395                 es->err = retval;
7396                 return BLOCK_ABORT;
7397         }
7398         ext2fs_free_mem(&block);
7399         *blocknr = new_blk;
7400         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401         ext2fs_block_alloc_stats(fs, new_blk, +1);
7402         es->newblocks++;
7403
7404         if (es->num == 0)
7405                 return (BLOCK_CHANGED | BLOCK_ABORT);
7406         else
7407                 return BLOCK_CHANGED;
7408 }
7409
7410 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411                                   int num, int guaranteed_size)
7412 {
7413         ext2_filsys fs = ctx->fs;
7414         errcode_t       retval;
7415         struct expand_dir_struct es;
7416         struct ext2_inode       inode;
7417
7418         if (!(fs->flags & EXT2_FLAG_RW))
7419                 return EXT2_ET_RO_FILSYS;
7420
7421         /*
7422          * Read the inode and block bitmaps in; we'll be messing with
7423          * them.
7424          */
7425         e2fsck_read_bitmaps(ctx);
7426
7427         retval = ext2fs_check_directory(fs, dir);
7428         if (retval)
7429                 return retval;
7430
7431         es.num = num;
7432         es.guaranteed_size = guaranteed_size;
7433         es.last_block = 0;
7434         es.err = 0;
7435         es.newblocks = 0;
7436         es.ctx = ctx;
7437
7438         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439                                        0, expand_dir_proc, &es);
7440
7441         if (es.err)
7442                 return es.err;
7443
7444         /*
7445          * Update the size and block count fields in the inode.
7446          */
7447         retval = ext2fs_read_inode(fs, dir, &inode);
7448         if (retval)
7449                 return retval;
7450
7451         inode.i_size = (es.last_block + 1) * fs->blocksize;
7452         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7453
7454         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7455
7456         return 0;
7457 }
7458
7459 /*
7460  * pass4.c -- pass #4 of e2fsck: Check reference counts
7461  *
7462  * Pass 4 frees the following data structures:
7463  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7464  */
7465
7466 /*
7467  * This routine is called when an inode is not connected to the
7468  * directory tree.
7469  *
7470  * This subroutine returns 1 then the caller shouldn't bother with the
7471  * rest of the pass 4 tests.
7472  */
7473 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7474 {
7475         ext2_filsys fs = ctx->fs;
7476         struct ext2_inode       inode;
7477         struct problem_context  pctx;
7478
7479         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480         clear_problem_context(&pctx);
7481         pctx.ino = i;
7482         pctx.inode = &inode;
7483
7484         /*
7485          * Offer to delete any zero-length files that does not have
7486          * blocks.  If there is an EA block, it might have useful
7487          * information, so we won't prompt to delete it, but let it be
7488          * reconnected to lost+found.
7489          */
7490         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491                                 LINUX_S_ISDIR(inode.i_mode))) {
7492                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494                         inode.i_links_count = 0;
7495                         inode.i_dtime = time(0);
7496                         e2fsck_write_inode(ctx, i, &inode,
7497                                            "disconnect_inode");
7498                         /*
7499                          * Fix up the bitmaps...
7500                          */
7501                         e2fsck_read_bitmaps(ctx);
7502                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504                         ext2fs_inode_alloc_stats2(fs, i, -1,
7505                                                   LINUX_S_ISDIR(inode.i_mode));
7506                         return 0;
7507                 }
7508         }
7509
7510         /*
7511          * Prompt to reconnect.
7512          */
7513         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514                 if (e2fsck_reconnect_file(ctx, i))
7515                         ext2fs_unmark_valid(fs);
7516         } else {
7517                 /*
7518                  * If we don't attach the inode, then skip the
7519                  * i_links_test since there's no point in trying to
7520                  * force i_links_count to zero.
7521                  */
7522                 ext2fs_unmark_valid(fs);
7523                 return 1;
7524         }
7525         return 0;
7526 }
7527
7528
7529 static void e2fsck_pass4(e2fsck_t ctx)
7530 {
7531         ext2_filsys fs = ctx->fs;
7532         ext2_ino_t      i;
7533         struct ext2_inode       inode;
7534         struct problem_context  pctx;
7535         __u16   link_count, link_counted;
7536         char    *buf = 0;
7537         int     group, maxgroup;
7538
7539         /* Pass 4 */
7540
7541         clear_problem_context(&pctx);
7542
7543         if (!(ctx->options & E2F_OPT_PREEN))
7544                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7545
7546         group = 0;
7547         maxgroup = fs->group_desc_count;
7548         if (ctx->progress)
7549                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550                         return;
7551
7552         for (i=1; i <= fs->super->s_inodes_count; i++) {
7553                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554                         return;
7555                 if ((i % fs->super->s_inodes_per_group) == 0) {
7556                         group++;
7557                         if (ctx->progress)
7558                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7559                                         return;
7560                 }
7561                 if (i == EXT2_BAD_INO ||
7562                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563                         continue;
7564                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565                     (ctx->inode_imagic_map &&
7566                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567                         continue;
7568                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570                 if (link_counted == 0) {
7571                         if (!buf)
7572                                 buf = e2fsck_allocate_memory(ctx,
7573                                      fs->blocksize, "bad_inode buffer");
7574                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575                                 continue;
7576                         if (disconnect_inode(ctx, i))
7577                                 continue;
7578                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7579                                             &link_count);
7580                         ext2fs_icount_fetch(ctx->inode_count, i,
7581                                             &link_counted);
7582                 }
7583                 if (link_counted != link_count) {
7584                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7585                         pctx.ino = i;
7586                         pctx.inode = &inode;
7587                         if (link_count != inode.i_links_count) {
7588                                 pctx.num = link_count;
7589                                 fix_problem(ctx,
7590                                             PR_4_INCONSISTENT_COUNT, &pctx);
7591                         }
7592                         pctx.num = link_counted;
7593                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594                                 inode.i_links_count = link_counted;
7595                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7596                         }
7597                 }
7598         }
7599         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602         ctx->inode_imagic_map = 0;
7603         ext2fs_free_mem(&buf);
7604 }
7605
7606 /*
7607  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7608  */
7609
7610 #define NO_BLK ((blk_t) -1)
7611
7612 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613                             struct problem_context *pctx)
7614 {
7615         switch (problem) {
7616         case PR_5_BLOCK_UNUSED:
7617                 if (pctx->blk == pctx->blk2)
7618                         pctx->blk2 = 0;
7619                 else
7620                         problem = PR_5_BLOCK_RANGE_UNUSED;
7621                 break;
7622         case PR_5_BLOCK_USED:
7623                 if (pctx->blk == pctx->blk2)
7624                         pctx->blk2 = 0;
7625                 else
7626                         problem = PR_5_BLOCK_RANGE_USED;
7627                 break;
7628         case PR_5_INODE_UNUSED:
7629                 if (pctx->ino == pctx->ino2)
7630                         pctx->ino2 = 0;
7631                 else
7632                         problem = PR_5_INODE_RANGE_UNUSED;
7633                 break;
7634         case PR_5_INODE_USED:
7635                 if (pctx->ino == pctx->ino2)
7636                         pctx->ino2 = 0;
7637                 else
7638                         problem = PR_5_INODE_RANGE_USED;
7639                 break;
7640         }
7641         fix_problem(ctx, problem, pctx);
7642         pctx->blk = pctx->blk2 = NO_BLK;
7643         pctx->ino = pctx->ino2 = 0;
7644 }
7645
7646 static void check_block_bitmaps(e2fsck_t ctx)
7647 {
7648         ext2_filsys fs = ctx->fs;
7649         blk_t   i;
7650         int     *free_array;
7651         int     group = 0;
7652         unsigned int    blocks = 0;
7653         unsigned int    free_blocks = 0;
7654         int     group_free = 0;
7655         int     actual, bitmap;
7656         struct problem_context  pctx;
7657         int     problem, save_problem, fixit, had_problem;
7658         errcode_t       retval;
7659
7660         clear_problem_context(&pctx);
7661         free_array = (int *) e2fsck_allocate_memory(ctx,
7662             fs->group_desc_count * sizeof(int), "free block count array");
7663
7664         if ((fs->super->s_first_data_block <
7665              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666             (fs->super->s_blocks_count-1 >
7667              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668                 pctx.num = 1;
7669                 pctx.blk = fs->super->s_first_data_block;
7670                 pctx.blk2 = fs->super->s_blocks_count -1;
7671                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7674
7675                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676                 return;
7677         }
7678
7679         if ((fs->super->s_first_data_block <
7680              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681             (fs->super->s_blocks_count-1 >
7682              ext2fs_get_block_bitmap_end(fs->block_map))) {
7683                 pctx.num = 2;
7684                 pctx.blk = fs->super->s_first_data_block;
7685                 pctx.blk2 = fs->super->s_blocks_count -1;
7686                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7689
7690                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691                 return;
7692         }
7693
7694 redo_counts:
7695         had_problem = 0;
7696         save_problem = 0;
7697         pctx.blk = pctx.blk2 = NO_BLK;
7698         for (i = fs->super->s_first_data_block;
7699              i < fs->super->s_blocks_count;
7700              i++) {
7701                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7703
7704                 if (actual == bitmap)
7705                         goto do_counts;
7706
7707                 if (!actual && bitmap) {
7708                         /*
7709                          * Block not used, but marked in use in the bitmap.
7710                          */
7711                         problem = PR_5_BLOCK_UNUSED;
7712                 } else {
7713                         /*
7714                          * Block used, but not marked in use in the bitmap.
7715                          */
7716                         problem = PR_5_BLOCK_USED;
7717                 }
7718                 if (pctx.blk == NO_BLK) {
7719                         pctx.blk = pctx.blk2 = i;
7720                         save_problem = problem;
7721                 } else {
7722                         if ((problem == save_problem) &&
7723                             (pctx.blk2 == i-1))
7724                                 pctx.blk2++;
7725                         else {
7726                                 print_bitmap_problem(ctx, save_problem, &pctx);
7727                                 pctx.blk = pctx.blk2 = i;
7728                                 save_problem = problem;
7729                         }
7730                 }
7731                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732                 had_problem++;
7733
7734         do_counts:
7735                 if (!bitmap) {
7736                         group_free++;
7737                         free_blocks++;
7738                 }
7739                 blocks ++;
7740                 if ((blocks == fs->super->s_blocks_per_group) ||
7741                     (i == fs->super->s_blocks_count-1)) {
7742                         free_array[group] = group_free;
7743                         group ++;
7744                         blocks = 0;
7745                         group_free = 0;
7746                         if (ctx->progress)
7747                                 if ((ctx->progress)(ctx, 5, group,
7748                                                     fs->group_desc_count*2))
7749                                         return;
7750                 }
7751         }
7752         if (pctx.blk != NO_BLK)
7753                 print_bitmap_problem(ctx, save_problem, &pctx);
7754         if (had_problem)
7755                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756         else
7757                 fixit = -1;
7758         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7759
7760         if (fixit == 1) {
7761                 ext2fs_free_block_bitmap(fs->block_map);
7762                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763                                                   &fs->block_map);
7764                 if (retval) {
7765                         clear_problem_context(&pctx);
7766                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767                         ctx->flags |= E2F_FLAG_ABORT;
7768                         return;
7769                 }
7770                 ext2fs_set_bitmap_padding(fs->block_map);
7771                 ext2fs_mark_bb_dirty(fs);
7772
7773                 /* Redo the counts */
7774                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776                 goto redo_counts;
7777         } else if (fixit == 0)
7778                 ext2fs_unmark_valid(fs);
7779
7780         for (i = 0; i < fs->group_desc_count; i++) {
7781                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782                         pctx.group = i;
7783                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784                         pctx.blk2 = free_array[i];
7785
7786                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787                                         &pctx)) {
7788                                 fs->group_desc[i].bg_free_blocks_count =
7789                                         free_array[i];
7790                                 ext2fs_mark_super_dirty(fs);
7791                         } else
7792                                 ext2fs_unmark_valid(fs);
7793                 }
7794         }
7795         if (free_blocks != fs->super->s_free_blocks_count) {
7796                 pctx.group = 0;
7797                 pctx.blk = fs->super->s_free_blocks_count;
7798                 pctx.blk2 = free_blocks;
7799
7800                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801                         fs->super->s_free_blocks_count = free_blocks;
7802                         ext2fs_mark_super_dirty(fs);
7803                 } else
7804                         ext2fs_unmark_valid(fs);
7805         }
7806         ext2fs_free_mem(&free_array);
7807 }
7808
7809 static void check_inode_bitmaps(e2fsck_t ctx)
7810 {
7811         ext2_filsys fs = ctx->fs;
7812         ext2_ino_t      i;
7813         unsigned int    free_inodes = 0;
7814         int             group_free = 0;
7815         int             dirs_count = 0;
7816         int             group = 0;
7817         unsigned int    inodes = 0;
7818         int             *free_array;
7819         int             *dir_array;
7820         int             actual, bitmap;
7821         errcode_t       retval;
7822         struct problem_context  pctx;
7823         int             problem, save_problem, fixit, had_problem;
7824
7825         clear_problem_context(&pctx);
7826         free_array = (int *) e2fsck_allocate_memory(ctx,
7827             fs->group_desc_count * sizeof(int), "free inode count array");
7828
7829         dir_array = (int *) e2fsck_allocate_memory(ctx,
7830            fs->group_desc_count * sizeof(int), "directory count array");
7831
7832         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833             (fs->super->s_inodes_count >
7834              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835                 pctx.num = 3;
7836                 pctx.blk = 1;
7837                 pctx.blk2 = fs->super->s_inodes_count;
7838                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843                 return;
7844         }
7845         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846             (fs->super->s_inodes_count >
7847              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848                 pctx.num = 4;
7849                 pctx.blk = 1;
7850                 pctx.blk2 = fs->super->s_inodes_count;
7851                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7854
7855                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856                 return;
7857         }
7858
7859 redo_counts:
7860         had_problem = 0;
7861         save_problem = 0;
7862         pctx.ino = pctx.ino2 = 0;
7863         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7866
7867                 if (actual == bitmap)
7868                         goto do_counts;
7869
7870                 if (!actual && bitmap) {
7871                         /*
7872                          * Inode wasn't used, but marked in bitmap
7873                          */
7874                         problem = PR_5_INODE_UNUSED;
7875                 } else /* if (actual && !bitmap) */ {
7876                         /*
7877                          * Inode used, but not in bitmap
7878                          */
7879                         problem = PR_5_INODE_USED;
7880                 }
7881                 if (pctx.ino == 0) {
7882                         pctx.ino = pctx.ino2 = i;
7883                         save_problem = problem;
7884                 } else {
7885                         if ((problem == save_problem) &&
7886                             (pctx.ino2 == i-1))
7887                                 pctx.ino2++;
7888                         else {
7889                                 print_bitmap_problem(ctx, save_problem, &pctx);
7890                                 pctx.ino = pctx.ino2 = i;
7891                                 save_problem = problem;
7892                         }
7893                 }
7894                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895                 had_problem++;
7896
7897 do_counts:
7898                 if (!bitmap) {
7899                         group_free++;
7900                         free_inodes++;
7901                 } else {
7902                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903                                 dirs_count++;
7904                 }
7905                 inodes++;
7906                 if ((inodes == fs->super->s_inodes_per_group) ||
7907                     (i == fs->super->s_inodes_count)) {
7908                         free_array[group] = group_free;
7909                         dir_array[group] = dirs_count;
7910                         group ++;
7911                         inodes = 0;
7912                         group_free = 0;
7913                         dirs_count = 0;
7914                         if (ctx->progress)
7915                                 if ((ctx->progress)(ctx, 5,
7916                                             group + fs->group_desc_count,
7917                                             fs->group_desc_count*2))
7918                                         return;
7919                 }
7920         }
7921         if (pctx.ino)
7922                 print_bitmap_problem(ctx, save_problem, &pctx);
7923
7924         if (had_problem)
7925                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926         else
7927                 fixit = -1;
7928         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7929
7930         if (fixit == 1) {
7931                 ext2fs_free_inode_bitmap(fs->inode_map);
7932                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933                                                   &fs->inode_map);
7934                 if (retval) {
7935                         clear_problem_context(&pctx);
7936                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937                         ctx->flags |= E2F_FLAG_ABORT;
7938                         return;
7939                 }
7940                 ext2fs_set_bitmap_padding(fs->inode_map);
7941                 ext2fs_mark_ib_dirty(fs);
7942
7943                 /* redo counts */
7944                 inodes = 0; free_inodes = 0; group_free = 0;
7945                 dirs_count = 0; group = 0;
7946                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948                 goto redo_counts;
7949         } else if (fixit == 0)
7950                 ext2fs_unmark_valid(fs);
7951
7952         for (i = 0; i < fs->group_desc_count; i++) {
7953                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954                         pctx.group = i;
7955                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956                         pctx.ino2 = free_array[i];
7957                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958                                         &pctx)) {
7959                                 fs->group_desc[i].bg_free_inodes_count =
7960                                         free_array[i];
7961                                 ext2fs_mark_super_dirty(fs);
7962                         } else
7963                                 ext2fs_unmark_valid(fs);
7964                 }
7965                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966                         pctx.group = i;
7967                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968                         pctx.ino2 = dir_array[i];
7969
7970                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971                                         &pctx)) {
7972                                 fs->group_desc[i].bg_used_dirs_count =
7973                                         dir_array[i];
7974                                 ext2fs_mark_super_dirty(fs);
7975                         } else
7976                                 ext2fs_unmark_valid(fs);
7977                 }
7978         }
7979         if (free_inodes != fs->super->s_free_inodes_count) {
7980                 pctx.group = -1;
7981                 pctx.ino = fs->super->s_free_inodes_count;
7982                 pctx.ino2 = free_inodes;
7983
7984                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985                         fs->super->s_free_inodes_count = free_inodes;
7986                         ext2fs_mark_super_dirty(fs);
7987                 } else
7988                         ext2fs_unmark_valid(fs);
7989         }
7990         ext2fs_free_mem(&free_array);
7991         ext2fs_free_mem(&dir_array);
7992 }
7993
7994 static void check_inode_end(e2fsck_t ctx)
7995 {
7996         ext2_filsys fs = ctx->fs;
7997         ext2_ino_t      end, save_inodes_count, i;
7998         struct problem_context  pctx;
7999
8000         clear_problem_context(&pctx);
8001
8002         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004                                                      &save_inodes_count);
8005         if (pctx.errcode) {
8006                 pctx.num = 1;
8007                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009                 return;
8010         }
8011         if (save_inodes_count == end)
8012                 return;
8013
8014         for (i = save_inodes_count + 1; i <= end; i++) {
8015                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017                                 for (i = save_inodes_count + 1; i <= end; i++)
8018                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8019                                                                  i);
8020                                 ext2fs_mark_ib_dirty(fs);
8021                         } else
8022                                 ext2fs_unmark_valid(fs);
8023                         break;
8024                 }
8025         }
8026
8027         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028                                                      save_inodes_count, 0);
8029         if (pctx.errcode) {
8030                 pctx.num = 2;
8031                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033                 return;
8034         }
8035 }
8036
8037 static void check_block_end(e2fsck_t ctx)
8038 {
8039         ext2_filsys fs = ctx->fs;
8040         blk_t   end, save_blocks_count, i;
8041         struct problem_context  pctx;
8042
8043         clear_problem_context(&pctx);
8044
8045         end = fs->block_map->start +
8046                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048                                                      &save_blocks_count);
8049         if (pctx.errcode) {
8050                 pctx.num = 3;
8051                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053                 return;
8054         }
8055         if (save_blocks_count == end)
8056                 return;
8057
8058         for (i = save_blocks_count + 1; i <= end; i++) {
8059                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061                                 for (i = save_blocks_count + 1; i <= end; i++)
8062                                         ext2fs_mark_block_bitmap(fs->block_map,
8063                                                                  i);
8064                                 ext2fs_mark_bb_dirty(fs);
8065                         } else
8066                                 ext2fs_unmark_valid(fs);
8067                         break;
8068                 }
8069         }
8070
8071         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072                                                      save_blocks_count, 0);
8073         if (pctx.errcode) {
8074                 pctx.num = 4;
8075                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077                 return;
8078         }
8079 }
8080
8081 static void e2fsck_pass5(e2fsck_t ctx)
8082 {
8083         struct problem_context  pctx;
8084
8085         /* Pass 5 */
8086
8087         clear_problem_context(&pctx);
8088
8089         if (!(ctx->options & E2F_OPT_PREEN))
8090                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8091
8092         if (ctx->progress)
8093                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094                         return;
8095
8096         e2fsck_read_bitmaps(ctx);
8097
8098         check_block_bitmaps(ctx);
8099         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100                 return;
8101         check_inode_bitmaps(ctx);
8102         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103                 return;
8104         check_inode_end(ctx);
8105         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106                 return;
8107         check_block_end(ctx);
8108         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109                 return;
8110
8111         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112         ctx->inode_used_map = 0;
8113         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114         ctx->inode_dir_map = 0;
8115         ext2fs_free_block_bitmap(ctx->block_found_map);
8116         ctx->block_found_map = 0;
8117 }
8118
8119 /*
8120  * problem.c --- report filesystem problems to the user
8121  */
8122
8123 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8124 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8125 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8126 #define PR_MSG_ONLY     0x000008 /* Print message only */
8127
8128 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8129
8130 #define PR_FATAL        0x001000 /* Fatal error */
8131 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8132                                  /* ask another */
8133 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8134 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8135 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8136 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8137 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8138
8139
8140 #define PROMPT_NONE     0
8141 #define PROMPT_FIX      1
8142 #define PROMPT_CLEAR    2
8143 #define PROMPT_RELOCATE 3
8144 #define PROMPT_ALLOCATE 4
8145 #define PROMPT_EXPAND   5
8146 #define PROMPT_CONNECT  6
8147 #define PROMPT_CREATE   7
8148 #define PROMPT_SALVAGE  8
8149 #define PROMPT_TRUNCATE 9
8150 #define PROMPT_CLEAR_INODE 10
8151 #define PROMPT_ABORT    11
8152 #define PROMPT_SPLIT    12
8153 #define PROMPT_CONTINUE 13
8154 #define PROMPT_CLONE    14
8155 #define PROMPT_DELETE   15
8156 #define PROMPT_SUPPRESS 16
8157 #define PROMPT_UNLINK   17
8158 #define PROMPT_CLEAR_HTREE 18
8159 #define PROMPT_RECREATE 19
8160 #define PROMPT_NULL     20
8161
8162 struct e2fsck_problem {
8163         problem_t       e2p_code;
8164         const char *    e2p_description;
8165         char            prompt;
8166         int             flags;
8167         problem_t       second_code;
8168 };
8169
8170 struct latch_descr {
8171         int             latch_code;
8172         problem_t       question;
8173         problem_t       end_message;
8174         int             flags;
8175 };
8176
8177 /*
8178  * These are the prompts which are used to ask the user if they want
8179  * to fix a problem.
8180  */
8181 static const char *const prompt[] = {
8182         N_("(no prompt)"),      /* 0 */
8183         N_("Fix"),              /* 1 */
8184         N_("Clear"),            /* 2 */
8185         N_("Relocate"),         /* 3 */
8186         N_("Allocate"),         /* 4 */
8187         N_("Expand"),           /* 5 */
8188         N_("Connect to /lost+found"), /* 6 */
8189         N_("Create"),           /* 7 */
8190         N_("Salvage"),          /* 8 */
8191         N_("Truncate"),         /* 9 */
8192         N_("Clear inode"),      /* 10 */
8193         N_("Abort"),            /* 11 */
8194         N_("Split"),            /* 12 */
8195         N_("Continue"),         /* 13 */
8196         N_("Clone multiply-claimed blocks"), /* 14 */
8197         N_("Delete file"),      /* 15 */
8198         N_("Suppress messages"),/* 16 */
8199         N_("Unlink"),           /* 17 */
8200         N_("Clear HTree index"),/* 18 */
8201         N_("Recreate"),         /* 19 */
8202         "",                     /* 20 */
8203 };
8204
8205 /*
8206  * These messages are printed when we are preen mode and we will be
8207  * automatically fixing the problem.
8208  */
8209 static const char *const preen_msg[] = {
8210         N_("(NONE)"),           /* 0 */
8211         N_("FIXED"),            /* 1 */
8212         N_("CLEARED"),          /* 2 */
8213         N_("RELOCATED"),        /* 3 */
8214         N_("ALLOCATED"),        /* 4 */
8215         N_("EXPANDED"),         /* 5 */
8216         N_("RECONNECTED"),      /* 6 */
8217         N_("CREATED"),          /* 7 */
8218         N_("SALVAGED"),         /* 8 */
8219         N_("TRUNCATED"),        /* 9 */
8220         N_("INODE CLEARED"),    /* 10 */
8221         N_("ABORTED"),          /* 11 */
8222         N_("SPLIT"),            /* 12 */
8223         N_("CONTINUING"),       /* 13 */
8224         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225         N_("FILE DELETED"),     /* 15 */
8226         N_("SUPPRESSED"),       /* 16 */
8227         N_("UNLINKED"),         /* 17 */
8228         N_("HTREE INDEX CLEARED"),/* 18 */
8229         N_("WILL RECREATE"),    /* 19 */
8230         "",                     /* 20 */
8231 };
8232
8233 static const struct e2fsck_problem problem_table[] = {
8234
8235         /* Pre-Pass 1 errors */
8236
8237         /* Block bitmap not in group */
8238         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8239           PROMPT_RELOCATE, PR_LATCH_RELOC },
8240
8241         /* Inode bitmap not in group */
8242         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8243           PROMPT_RELOCATE, PR_LATCH_RELOC },
8244
8245         /* Inode table not in group */
8246         { PR_0_ITABLE_NOT_GROUP,
8247           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8248           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249           PROMPT_RELOCATE, PR_LATCH_RELOC },
8250
8251         /* Superblock corrupt */
8252         { PR_0_SB_CORRUPT,
8253           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254           "@f.  If the @v is valid and it really contains an ext2\n"
8255           "@f (and not swap or ufs or something else), then the @S\n"
8256           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257           "    e2fsck -b %S <@v>\n\n"),
8258           PROMPT_NONE, PR_FATAL },
8259
8260         /* Filesystem size is wrong */
8261         { PR_0_FS_SIZE_WRONG,
8262           N_("The @f size (according to the @S) is %b @bs\n"
8263           "The physical size of the @v is %c @bs\n"
8264           "Either the @S or the partition table is likely to be corrupt!\n"),
8265           PROMPT_ABORT, 0 },
8266
8267         /* Fragments not supported */
8268         { PR_0_NO_FRAGMENTS,
8269           N_("@S @b_size = %b, fragsize = %c.\n"
8270           "This version of e2fsck does not support fragment sizes different\n"
8271           "from the @b size.\n"),
8272           PROMPT_NONE, PR_FATAL },
8273
8274           /* Bad blocks_per_group */
8275         { PR_0_BLOCKS_PER_GROUP,
8276           N_("@S @bs_per_group = %b, should have been %c\n"),
8277           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8278
8279         /* Bad first_data_block */
8280         { PR_0_FIRST_DATA_BLOCK,
8281           N_("@S first_data_@b = %b, should have been %c\n"),
8282           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8283
8284         /* Adding UUID to filesystem */
8285         { PR_0_ADD_UUID,
8286           N_("@f did not have a UUID; generating one.\n\n"),
8287           PROMPT_NONE, 0 },
8288
8289         /* Relocate hint */
8290         { PR_0_RELOCATE_HINT,
8291           N_("Note: if several inode or block bitmap blocks or part\n"
8292           "of the inode table require relocation, you may wish to try\n"
8293           "running e2fsck with the '-b %S' option first.  The problem\n"
8294           "may lie only with the primary block group descriptors, and\n"
8295           "the backup block group descriptors may be OK.\n\n"),
8296           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8297
8298         /* Miscellaneous superblock corruption */
8299         { PR_0_MISC_CORRUPT_SUPER,
8300           N_("Corruption found in @S.  (%s = %N).\n"),
8301           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8302
8303         /* Error determing physical device size of filesystem */
8304         { PR_0_GETSIZE_ERROR,
8305           N_("Error determining size of the physical @v: %m\n"),
8306           PROMPT_NONE, PR_FATAL },
8307
8308         /* Inode count in superblock is incorrect */
8309         { PR_0_INODE_COUNT_WRONG,
8310           N_("@i count in @S is %i, @s %j.\n"),
8311           PROMPT_FIX, 0 },
8312
8313         { PR_0_HURD_CLEAR_FILETYPE,
8314           N_("The Hurd does not support the filetype feature.\n"),
8315           PROMPT_CLEAR, 0 },
8316
8317         /* Journal inode is invalid */
8318         { PR_0_JOURNAL_BAD_INODE,
8319           N_("@S has an @n ext3 @j (@i %i).\n"),
8320           PROMPT_CLEAR, PR_PREEN_OK },
8321
8322         /* The external journal has (unsupported) multiple filesystems */
8323         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324           N_("External @j has multiple @f users (unsupported).\n"),
8325           PROMPT_NONE, PR_FATAL },
8326
8327         /* Can't find external journal */
8328         { PR_0_CANT_FIND_JOURNAL,
8329           N_("Can't find external @j\n"),
8330           PROMPT_NONE, PR_FATAL },
8331
8332         /* External journal has bad superblock */
8333         { PR_0_EXT_JOURNAL_BAD_SUPER,
8334           N_("External @j has bad @S\n"),
8335           PROMPT_NONE, PR_FATAL },
8336
8337         /* Superblock has a bad journal UUID */
8338         { PR_0_JOURNAL_BAD_UUID,
8339           N_("External @j does not support this @f\n"),
8340           PROMPT_NONE, PR_FATAL },
8341
8342         /* Journal has an unknown superblock type */
8343         { PR_0_JOURNAL_UNSUPP_SUPER,
8344           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345              "It is likely that your copy of e2fsck is old and/or doesn't "
8346              "support this @j format.\n"
8347              "It is also possible the @j @S is corrupt.\n"),
8348           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8349
8350         /* Journal superblock is corrupt */
8351         { PR_0_JOURNAL_BAD_SUPER,
8352           N_("Ext3 @j @S is corrupt.\n"),
8353           PROMPT_FIX, PR_PREEN_OK },
8354
8355         /* Superblock flag should be cleared */
8356         { PR_0_JOURNAL_HAS_JOURNAL,
8357           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358           PROMPT_CLEAR, PR_PREEN_OK },
8359
8360         /* Superblock flag is incorrect */
8361         { PR_0_JOURNAL_RECOVER_SET,
8362           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363           PROMPT_CLEAR, PR_PREEN_OK },
8364
8365         /* Journal has data, but recovery flag is clear */
8366         { PR_0_JOURNAL_RECOVERY_CLEAR,
8367           N_("ext3 recovery flag is clear, but @j has data.\n"),
8368           PROMPT_NONE, 0 },
8369
8370         /* Ask if we should clear the journal */
8371         { PR_0_JOURNAL_RESET_JOURNAL,
8372           N_("Clear @j"),
8373           PROMPT_NULL, PR_PREEN_NOMSG },
8374
8375         /* Ask if we should run the journal anyway */
8376         { PR_0_JOURNAL_RUN,
8377           N_("Run @j anyway"),
8378           PROMPT_NULL, 0 },
8379
8380         /* Run the journal by default */
8381         { PR_0_JOURNAL_RUN_DEFAULT,
8382           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383           PROMPT_NONE, 0 },
8384
8385         /* Clearing orphan inode */
8386         { PR_0_ORPHAN_CLEAR_INODE,
8387           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388           PROMPT_NONE, 0 },
8389
8390         /* Illegal block found in orphaned inode */
8391         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393           PROMPT_NONE, 0 },
8394
8395         /* Already cleared block found in orphaned inode */
8396         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398           PROMPT_NONE, 0 },
8399
8400         /* Illegal orphan inode in superblock */
8401         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402           N_("@I @o @i %i in @S.\n"),
8403           PROMPT_NONE, 0 },
8404
8405         /* Illegal inode in orphaned inode list */
8406         { PR_0_ORPHAN_ILLEGAL_INODE,
8407           N_("@I @i %i in @o @i list.\n"),
8408           PROMPT_NONE, 0 },
8409
8410         /* Filesystem revision is 0, but feature flags are set */
8411         { PR_0_FS_REV_LEVEL,
8412           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8413           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8414
8415         /* Journal superblock has an unknown read-only feature flag set */
8416         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418           PROMPT_ABORT, 0 },
8419
8420         /* Journal superblock has an unknown incompatible feature flag set */
8421         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423           PROMPT_ABORT, 0 },
8424
8425         /* Journal has unsupported version number */
8426         { PR_0_JOURNAL_UNSUPP_VERSION,
8427           N_("@j version not supported by this e2fsck.\n"),
8428           PROMPT_ABORT, 0 },
8429
8430         /* Moving journal to hidden file */
8431         { PR_0_MOVE_JOURNAL,
8432           N_("Moving @j from /%s to hidden @i.\n\n"),
8433           PROMPT_NONE, 0 },
8434
8435         /* Error moving journal to hidden file */
8436         { PR_0_ERR_MOVE_JOURNAL,
8437           N_("Error moving @j: %m\n\n"),
8438           PROMPT_NONE, 0 },
8439
8440         /* Clearing V2 journal superblock */
8441         { PR_0_CLEAR_V2_JOURNAL,
8442           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443              "Clearing fields beyond the V1 @j @S...\n\n"),
8444           PROMPT_NONE, 0 },
8445
8446         /* Backup journal inode blocks */
8447         { PR_0_BACKUP_JNL,
8448           N_("Backing up @j @i @b information.\n\n"),
8449           PROMPT_NONE, 0 },
8450
8451         /* Reserved blocks w/o resize_inode */
8452         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454              "is %N; @s zero.  "),
8455           PROMPT_FIX, 0 },
8456
8457         /* Resize_inode not enabled, but resize inode is non-zero */
8458         { PR_0_CLEAR_RESIZE_INODE,
8459           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8460           PROMPT_CLEAR, 0 },
8461
8462         /* Resize inode invalid */
8463         { PR_0_RESIZE_INODE_INVALID,
8464           N_("Resize @i not valid.  "),
8465           PROMPT_RECREATE, 0 },
8466
8467         /* Pass 1 errors */
8468
8469         /* Pass 1: Checking inodes, blocks, and sizes */
8470         { PR_1_PASS_HEADER,
8471           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472           PROMPT_NONE, 0 },
8473
8474         /* Root directory is not an inode */
8475         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8476           PROMPT_CLEAR, 0 },
8477
8478         /* Root directory has dtime set */
8479         { PR_1_ROOT_DTIME,
8480           N_("@r has dtime set (probably due to old mke2fs).  "),
8481           PROMPT_FIX, PR_PREEN_OK },
8482
8483         /* Reserved inode has bad mode */
8484         { PR_1_RESERVED_BAD_MODE,
8485           N_("Reserved @i %i (%Q) has @n mode.  "),
8486           PROMPT_CLEAR, PR_PREEN_OK },
8487
8488         /* Deleted inode has zero dtime */
8489         { PR_1_ZERO_DTIME,
8490           N_("@D @i %i has zero dtime.  "),
8491           PROMPT_FIX, PR_PREEN_OK },
8492
8493         /* Inode in use, but dtime set */
8494         { PR_1_SET_DTIME,
8495           N_("@i %i is in use, but has dtime set.  "),
8496           PROMPT_FIX, PR_PREEN_OK },
8497
8498         /* Zero-length directory */
8499         { PR_1_ZERO_LENGTH_DIR,
8500           N_("@i %i is a @z @d.  "),
8501           PROMPT_CLEAR, PR_PREEN_OK },
8502
8503         /* Block bitmap conflicts with some other fs block */
8504         { PR_1_BB_CONFLICT,
8505           N_("@g %g's @b @B at %b @C.\n"),
8506           PROMPT_RELOCATE, 0 },
8507
8508         /* Inode bitmap conflicts with some other fs block */
8509         { PR_1_IB_CONFLICT,
8510           N_("@g %g's @i @B at %b @C.\n"),
8511           PROMPT_RELOCATE, 0 },
8512
8513         /* Inode table conflicts with some other fs block */
8514         { PR_1_ITABLE_CONFLICT,
8515           N_("@g %g's @i table at %b @C.\n"),
8516           PROMPT_RELOCATE, 0 },
8517
8518         /* Block bitmap is on a bad block */
8519         { PR_1_BB_BAD_BLOCK,
8520           N_("@g %g's @b @B (%b) is bad.  "),
8521           PROMPT_RELOCATE, 0 },
8522
8523         /* Inode bitmap is on a bad block */
8524         { PR_1_IB_BAD_BLOCK,
8525           N_("@g %g's @i @B (%b) is bad.  "),
8526           PROMPT_RELOCATE, 0 },
8527
8528         /* Inode has incorrect i_size */
8529         { PR_1_BAD_I_SIZE,
8530           N_("@i %i, i_size is %Is, @s %N.  "),
8531           PROMPT_FIX, PR_PREEN_OK },
8532
8533         /* Inode has incorrect i_blocks */
8534         { PR_1_BAD_I_BLOCKS,
8535           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8536           PROMPT_FIX, PR_PREEN_OK },
8537
8538         /* Illegal blocknumber in inode */
8539         { PR_1_ILLEGAL_BLOCK_NUM,
8540           N_("@I @b #%B (%b) in @i %i.  "),
8541           PROMPT_CLEAR, PR_LATCH_BLOCK },
8542
8543         /* Block number overlaps fs metadata */
8544         { PR_1_BLOCK_OVERLAPS_METADATA,
8545           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8546           PROMPT_CLEAR, PR_LATCH_BLOCK },
8547
8548         /* Inode has illegal blocks (latch question) */
8549         { PR_1_INODE_BLOCK_LATCH,
8550           N_("@i %i has illegal @b(s).  "),
8551           PROMPT_CLEAR, 0 },
8552
8553         /* Too many bad blocks in inode */
8554         { PR_1_TOO_MANY_BAD_BLOCKS,
8555           N_("Too many illegal @bs in @i %i.\n"),
8556           PROMPT_CLEAR_INODE, PR_NO_OK },
8557
8558         /* Illegal block number in bad block inode */
8559         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560           N_("@I @b #%B (%b) in bad @b @i.  "),
8561           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8562
8563         /* Bad block inode has illegal blocks (latch question) */
8564         { PR_1_INODE_BBLOCK_LATCH,
8565           N_("Bad @b @i has illegal @b(s).  "),
8566           PROMPT_CLEAR, 0 },
8567
8568         /* Duplicate or bad blocks in use! */
8569         { PR_1_DUP_BLOCKS_PREENSTOP,
8570           N_("Duplicate or bad @b in use!\n"),
8571           PROMPT_NONE, 0 },
8572
8573         /* Bad block used as bad block indirect block */
8574         { PR_1_BBINODE_BAD_METABLOCK,
8575           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8576           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8577
8578         /* Inconsistency can't be fixed prompt */
8579         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8581              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582              "in the @f.\n"),
8583           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8584
8585         /* Bad primary block */
8586         { PR_1_BAD_PRIMARY_BLOCK,
8587           N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8589
8590         /* Bad primary block prompt */
8591         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592           N_("You can remove this @b from the bad @b list and hope\n"
8593              "that the @b is really OK.  But there are no guarantees.\n\n"),
8594           PROMPT_CLEAR, PR_PREEN_NOMSG },
8595
8596         /* Bad primary superblock */
8597         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598           N_("The primary @S (%b) is on the bad @b list.\n"),
8599           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8600
8601         /* Bad primary block group descriptors */
8602         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603           N_("Block %b in the primary @g descriptors "
8604           "is on the bad @b list\n"),
8605           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8606
8607         /* Bad superblock in group */
8608         { PR_1_BAD_SUPERBLOCK,
8609           N_("Warning: Group %g's @S (%b) is bad.\n"),
8610           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8611
8612         /* Bad block group descriptors in group */
8613         { PR_1_BAD_GROUP_DESCRIPTORS,
8614           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615           "@b (%b).\n"),
8616           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8617
8618         /* Block claimed for no reason */
8619         { PR_1_PROGERR_CLAIMED_BLOCK,
8620           N_("Programming error?  @b #%b claimed for no reason in "
8621           "process_bad_@b.\n"),
8622           PROMPT_NONE, PR_PREEN_OK },
8623
8624         /* Error allocating blocks for relocating metadata */
8625         { PR_1_RELOC_BLOCK_ALLOCATE,
8626           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627           PROMPT_NONE, PR_PREEN_OK },
8628
8629         /* Error allocating block buffer during relocation process */
8630         { PR_1_RELOC_MEMORY_ALLOCATE,
8631           N_("@A @b buffer for relocating %s\n"),
8632           PROMPT_NONE, PR_PREEN_OK },
8633
8634         /* Relocating metadata group information from X to Y */
8635         { PR_1_RELOC_FROM_TO,
8636           N_("Relocating @g %g's %s from %b to %c...\n"),
8637           PROMPT_NONE, PR_PREEN_OK },
8638
8639         /* Relocating metatdata group information to X */
8640         { PR_1_RELOC_TO,
8641           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642           PROMPT_NONE, PR_PREEN_OK },
8643
8644         /* Block read error during relocation process */
8645         { PR_1_RELOC_READ_ERR,
8646           N_("Warning: could not read @b %b of %s: %m\n"),
8647           PROMPT_NONE, PR_PREEN_OK },
8648
8649         /* Block write error during relocation process */
8650         { PR_1_RELOC_WRITE_ERR,
8651           N_("Warning: could not write @b %b for %s: %m\n"),
8652           PROMPT_NONE, PR_PREEN_OK },
8653
8654         /* Error allocating inode bitmap */
8655         { PR_1_ALLOCATE_IBITMAP_ERROR,
8656           N_("@A @i @B (%N): %m\n"),
8657           PROMPT_NONE, PR_FATAL },
8658
8659         /* Error allocating block bitmap */
8660         { PR_1_ALLOCATE_BBITMAP_ERROR,
8661           N_("@A @b @B (%N): %m\n"),
8662           PROMPT_NONE, PR_FATAL },
8663
8664         /* Error allocating icount structure */
8665         { PR_1_ALLOCATE_ICOUNT,
8666           N_("@A icount link information: %m\n"),
8667           PROMPT_NONE, PR_FATAL },
8668
8669         /* Error allocating dbcount */
8670         { PR_1_ALLOCATE_DBCOUNT,
8671           N_("@A @d @b array: %m\n"),
8672           PROMPT_NONE, PR_FATAL },
8673
8674         /* Error while scanning inodes */
8675         { PR_1_ISCAN_ERROR,
8676           N_("Error while scanning @is (%i): %m\n"),
8677           PROMPT_NONE, PR_FATAL },
8678
8679         /* Error while iterating over blocks */
8680         { PR_1_BLOCK_ITERATE,
8681           N_("Error while iterating over @bs in @i %i: %m\n"),
8682           PROMPT_NONE, PR_FATAL },
8683
8684         /* Error while storing inode count information */
8685         { PR_1_ICOUNT_STORE,
8686           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687           PROMPT_NONE, PR_FATAL },
8688
8689         /* Error while storing directory block information */
8690         { PR_1_ADD_DBLOCK,
8691           N_("Error storing @d @b information "
8692           "(@i=%i, @b=%b, num=%N): %m\n"),
8693           PROMPT_NONE, PR_FATAL },
8694
8695         /* Error while reading inode (for clearing) */
8696         { PR_1_READ_INODE,
8697           N_("Error reading @i %i: %m\n"),
8698           PROMPT_NONE, PR_FATAL },
8699
8700         /* Suppress messages prompt */
8701         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8702
8703         /* Imagic flag set on an inode when filesystem doesn't support it */
8704         { PR_1_SET_IMAGIC,
8705           N_("@i %i has imagic flag set.  "),
8706           PROMPT_CLEAR, 0 },
8707
8708         /* Immutable flag set on a device or socket inode */
8709         { PR_1_SET_IMMUTABLE,
8710           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711              "or append-only flag set.  "),
8712           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8713
8714         /* Compression flag set on an inode when filesystem doesn't support it */
8715         { PR_1_COMPR_SET,
8716           N_("@i %i has @cion flag set on @f without @cion support.  "),
8717           PROMPT_CLEAR, 0 },
8718
8719         /* Non-zero size for device, fifo or socket inode */
8720         { PR_1_SET_NONZSIZE,
8721           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8722           PROMPT_FIX, PR_PREEN_OK },
8723
8724         /* Filesystem revision is 0, but feature flags are set */
8725         { PR_1_FS_REV_LEVEL,
8726           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8727           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8728
8729         /* Journal inode is not in use, but contains data */
8730         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731           N_("@j @i is not in use, but contains data.  "),
8732           PROMPT_CLEAR, PR_PREEN_OK },
8733
8734         /* Journal has bad mode */
8735         { PR_1_JOURNAL_BAD_MODE,
8736           N_("@j is not regular file.  "),
8737           PROMPT_FIX, PR_PREEN_OK },
8738
8739         /* Deal with inodes that were part of orphan linked list */
8740         { PR_1_LOW_DTIME,
8741           N_("@i %i was part of the @o @i list.  "),
8742           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8743
8744         /* Deal with inodes that were part of corrupted orphan linked
8745            list (latch question) */
8746         { PR_1_ORPHAN_LIST_REFUGEES,
8747           N_("@is that were part of a corrupted orphan linked list found.  "),
8748           PROMPT_FIX, 0 },
8749
8750         /* Error allocating refcount structure */
8751         { PR_1_ALLOCATE_REFCOUNT,
8752           N_("@A refcount structure (%N): %m\n"),
8753           PROMPT_NONE, PR_FATAL },
8754
8755         /* Error reading extended attribute block */
8756         { PR_1_READ_EA_BLOCK,
8757           N_("Error reading @a @b %b for @i %i.  "),
8758           PROMPT_CLEAR, 0 },
8759
8760         /* Invalid extended attribute block */
8761         { PR_1_BAD_EA_BLOCK,
8762           N_("@i %i has a bad @a @b %b.  "),
8763           PROMPT_CLEAR, 0 },
8764
8765         /* Error reading Extended Attribute block while fixing refcount */
8766         { PR_1_EXTATTR_READ_ABORT,
8767           N_("Error reading @a @b %b (%m).  "),
8768           PROMPT_ABORT, 0 },
8769
8770         /* Extended attribute reference count incorrect */
8771         { PR_1_EXTATTR_REFCOUNT,
8772           N_("@a @b %b has reference count %B, @s %N.  "),
8773           PROMPT_FIX, 0 },
8774
8775         /* Error writing Extended Attribute block while fixing refcount */
8776         { PR_1_EXTATTR_WRITE,
8777           N_("Error writing @a @b %b (%m).  "),
8778           PROMPT_ABORT, 0 },
8779
8780         /* Multiple EA blocks not supported */
8781         { PR_1_EA_MULTI_BLOCK,
8782           N_("@a @b %b has h_@bs > 1.  "),
8783           PROMPT_CLEAR, 0},
8784
8785         /* Error allocating EA region allocation structure */
8786         { PR_1_EA_ALLOC_REGION,
8787           N_("@A @a @b %b.  "),
8788           PROMPT_ABORT, 0},
8789
8790         /* Error EA allocation collision */
8791         { PR_1_EA_ALLOC_COLLISION,
8792           N_("@a @b %b is corrupt (allocation collision).  "),
8793           PROMPT_CLEAR, 0},
8794
8795         /* Bad extended attribute name */
8796         { PR_1_EA_BAD_NAME,
8797           N_("@a @b %b is corrupt (@n name).  "),
8798           PROMPT_CLEAR, 0},
8799
8800         /* Bad extended attribute value */
8801         { PR_1_EA_BAD_VALUE,
8802           N_("@a @b %b is corrupt (@n value).  "),
8803           PROMPT_CLEAR, 0},
8804
8805         /* Inode too big (latch question) */
8806         { PR_1_INODE_TOOBIG,
8807           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8808
8809         /* Directory too big */
8810         { PR_1_TOOBIG_DIR,
8811           N_("@b #%B (%b) causes @d to be too big.  "),
8812           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8813
8814         /* Regular file too big */
8815         { PR_1_TOOBIG_REG,
8816           N_("@b #%B (%b) causes file to be too big.  "),
8817           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8818
8819         /* Symlink too big */
8820         { PR_1_TOOBIG_SYMLINK,
8821           N_("@b #%B (%b) causes symlink to be too big.  "),
8822           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8823
8824         /* INDEX_FL flag set on a non-HTREE filesystem */
8825         { PR_1_HTREE_SET,
8826           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8828
8829         /* INDEX_FL flag set on a non-directory */
8830         { PR_1_HTREE_NODIR,
8831           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8833
8834         /* Invalid root node in HTREE directory */
8835         { PR_1_HTREE_BADROOT,
8836           N_("@h %i has an @n root node.\n"),
8837           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8838
8839         /* Unsupported hash version in HTREE directory */
8840         { PR_1_HTREE_HASHV,
8841           N_("@h %i has an unsupported hash version (%N)\n"),
8842           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8843
8844         /* Incompatible flag in HTREE root node */
8845         { PR_1_HTREE_INCOMPAT,
8846           N_("@h %i uses an incompatible htree root node flag.\n"),
8847           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8848
8849         /* HTREE too deep */
8850         { PR_1_HTREE_DEPTH,
8851           N_("@h %i has a tree depth (%N) which is too big\n"),
8852           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853
8854         /* Bad block has indirect block that conflicts with filesystem block */
8855         { PR_1_BB_FS_BLOCK,
8856           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857              "@f metadata.  "),
8858           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8859
8860         /* Resize inode failed */
8861         { PR_1_RESIZE_INODE_CREATE,
8862           N_("Resize @i (re)creation failed: %m."),
8863           PROMPT_ABORT, 0 },
8864
8865         /* invalid inode->i_extra_isize */
8866         { PR_1_EXTRA_ISIZE,
8867           N_("@i %i has a extra size (%IS) which is @n\n"),
8868           PROMPT_FIX, PR_PREEN_OK },
8869
8870         /* invalid ea entry->e_name_len */
8871         { PR_1_ATTR_NAME_LEN,
8872           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873           PROMPT_CLEAR, PR_PREEN_OK },
8874
8875         /* invalid ea entry->e_value_size */
8876         { PR_1_ATTR_VALUE_SIZE,
8877           N_("@a in @i %i has a value size (%N) which is @n\n"),
8878           PROMPT_CLEAR, PR_PREEN_OK },
8879
8880         /* invalid ea entry->e_value_offs */
8881         { PR_1_ATTR_VALUE_OFFSET,
8882           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883           PROMPT_CLEAR, PR_PREEN_OK },
8884
8885         /* invalid ea entry->e_value_block */
8886         { PR_1_ATTR_VALUE_BLOCK,
8887           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888           PROMPT_CLEAR, PR_PREEN_OK },
8889
8890         /* invalid ea entry->e_hash */
8891         { PR_1_ATTR_HASH,
8892           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893           PROMPT_CLEAR, PR_PREEN_OK },
8894
8895         /* Pass 1b errors */
8896
8897         /* Pass 1B: Rescan for duplicate/bad blocks */
8898         { PR_1B_PASS_HEADER,
8899           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900           "Pass 1B: Rescanning for @m @bs\n"),
8901           PROMPT_NONE, 0 },
8902
8903         /* Duplicate/bad block(s) header */
8904         { PR_1B_DUP_BLOCK_HEADER,
8905           N_("@m @b(s) in @i %i:"),
8906           PROMPT_NONE, 0 },
8907
8908         /* Duplicate/bad block(s) in inode */
8909         { PR_1B_DUP_BLOCK,
8910           " %b",
8911           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8912
8913         /* Duplicate/bad block(s) end */
8914         { PR_1B_DUP_BLOCK_END,
8915           "\n",
8916           PROMPT_NONE, PR_PREEN_NOHDR },
8917
8918         /* Error while scanning inodes */
8919         { PR_1B_ISCAN_ERROR,
8920           N_("Error while scanning inodes (%i): %m\n"),
8921           PROMPT_NONE, PR_FATAL },
8922
8923         /* Error allocating inode bitmap */
8924         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925           N_("@A @i @B (@i_dup_map): %m\n"),
8926           PROMPT_NONE, PR_FATAL },
8927
8928         /* Error while iterating over blocks */
8929         { PR_1B_BLOCK_ITERATE,
8930           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931           PROMPT_NONE, 0 },
8932
8933         /* Error adjusting EA refcount */
8934         { PR_1B_ADJ_EA_REFCOUNT,
8935           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936           PROMPT_NONE, 0 },
8937
8938
8939         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940         { PR_1C_PASS_HEADER,
8941           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942           PROMPT_NONE, 0 },
8943
8944
8945         /* Pass 1D: Reconciling multiply-claimed blocks */
8946         { PR_1D_PASS_HEADER,
8947           N_("Pass 1D: Reconciling @m @bs\n"),
8948           PROMPT_NONE, 0 },
8949
8950         /* File has duplicate blocks */
8951         { PR_1D_DUP_FILE,
8952           N_("File %Q (@i #%i, mod time %IM)\n"
8953           "  has %B @m @b(s), shared with %N file(s):\n"),
8954           PROMPT_NONE, 0 },
8955
8956         /* List of files sharing duplicate blocks */
8957         { PR_1D_DUP_FILE_LIST,
8958           N_("\t%Q (@i #%i, mod time %IM)\n"),
8959           PROMPT_NONE, 0 },
8960
8961         /* File sharing blocks with filesystem metadata  */
8962         { PR_1D_SHARE_METADATA,
8963           N_("\t<@f metadata>\n"),
8964           PROMPT_NONE, 0 },
8965
8966         /* Report of how many duplicate/bad inodes */
8967         { PR_1D_NUM_DUP_INODES,
8968           N_("(There are %N @is containing @m @bs.)\n\n"),
8969           PROMPT_NONE, 0 },
8970
8971         /* Duplicated blocks already reassigned or cloned. */
8972         { PR_1D_DUP_BLOCKS_DEALT,
8973           N_("@m @bs already reassigned or cloned.\n\n"),
8974           PROMPT_NONE, 0 },
8975
8976         /* Clone duplicate/bad blocks? */
8977         { PR_1D_CLONE_QUESTION,
8978           "", PROMPT_CLONE, PR_NO_OK },
8979
8980         /* Delete file? */
8981         { PR_1D_DELETE_QUESTION,
8982           "", PROMPT_DELETE, 0 },
8983
8984         /* Couldn't clone file (error) */
8985         { PR_1D_CLONE_ERROR,
8986           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8987
8988         /* Pass 2 errors */
8989
8990         /* Pass 2: Checking directory structure */
8991         { PR_2_PASS_HEADER,
8992           N_("Pass 2: Checking @d structure\n"),
8993           PROMPT_NONE, 0 },
8994
8995         /* Bad inode number for '.' */
8996         { PR_2_BAD_INODE_DOT,
8997           N_("@n @i number for '.' in @d @i %i.\n"),
8998           PROMPT_FIX, 0 },
8999
9000         /* Directory entry has bad inode number */
9001         { PR_2_BAD_INO,
9002           N_("@E has @n @i #: %Di.\n"),
9003           PROMPT_CLEAR, 0 },
9004
9005         /* Directory entry has deleted or unused inode */
9006         { PR_2_UNUSED_INODE,
9007           N_("@E has @D/unused @i %Di.  "),
9008           PROMPT_CLEAR, PR_PREEN_OK },
9009
9010         /* Directry entry is link to '.' */
9011         { PR_2_LINK_DOT,
9012           N_("@E @L to '.'  "),
9013           PROMPT_CLEAR, 0 },
9014
9015         /* Directory entry points to inode now located in a bad block */
9016         { PR_2_BB_INODE,
9017           N_("@E points to @i (%Di) located in a bad @b.\n"),
9018           PROMPT_CLEAR, 0 },
9019
9020         /* Directory entry contains a link to a directory */
9021         { PR_2_LINK_DIR,
9022           N_("@E @L to @d %P (%Di).\n"),
9023           PROMPT_CLEAR, 0 },
9024
9025         /* Directory entry contains a link to the root directry */
9026         { PR_2_LINK_ROOT,
9027           N_("@E @L to the @r.\n"),
9028           PROMPT_CLEAR, 0 },
9029
9030         /* Directory entry has illegal characters in its name */
9031         { PR_2_BAD_NAME,
9032           N_("@E has illegal characters in its name.\n"),
9033           PROMPT_FIX, 0 },
9034
9035         /* Missing '.' in directory inode */
9036         { PR_2_MISSING_DOT,
9037           N_("Missing '.' in @d @i %i.\n"),
9038           PROMPT_FIX, 0 },
9039
9040         /* Missing '..' in directory inode */
9041         { PR_2_MISSING_DOT_DOT,
9042           N_("Missing '..' in @d @i %i.\n"),
9043           PROMPT_FIX, 0 },
9044
9045         /* First entry in directory inode doesn't contain '.' */
9046         { PR_2_1ST_NOT_DOT,
9047           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048           PROMPT_FIX, 0 },
9049
9050         /* Second entry in directory inode doesn't contain '..' */
9051         { PR_2_2ND_NOT_DOT_DOT,
9052           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053           PROMPT_FIX, 0 },
9054
9055         /* i_faddr should be zero */
9056         { PR_2_FADDR_ZERO,
9057           N_("i_faddr @F %IF, @s zero.\n"),
9058           PROMPT_CLEAR, 0 },
9059
9060         /* i_file_acl should be zero */
9061         { PR_2_FILE_ACL_ZERO,
9062           N_("i_file_acl @F %If, @s zero.\n"),
9063           PROMPT_CLEAR, 0 },
9064
9065         /* i_dir_acl should be zero */
9066         { PR_2_DIR_ACL_ZERO,
9067           N_("i_dir_acl @F %Id, @s zero.\n"),
9068           PROMPT_CLEAR, 0 },
9069
9070         /* i_frag should be zero */
9071         { PR_2_FRAG_ZERO,
9072           N_("i_frag @F %N, @s zero.\n"),
9073           PROMPT_CLEAR, 0 },
9074
9075         /* i_fsize should be zero */
9076         { PR_2_FSIZE_ZERO,
9077           N_("i_fsize @F %N, @s zero.\n"),
9078           PROMPT_CLEAR, 0 },
9079
9080         /* inode has bad mode */
9081         { PR_2_BAD_MODE,
9082           N_("@i %i (%Q) has @n mode (%Im).\n"),
9083           PROMPT_CLEAR, 0 },
9084
9085         /* directory corrupted */
9086         { PR_2_DIR_CORRUPTED,
9087           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088           PROMPT_SALVAGE, 0 },
9089
9090         /* filename too long */
9091         { PR_2_FILENAME_LONG,
9092           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093           PROMPT_TRUNCATE, 0 },
9094
9095         /* Directory inode has a missing block (hole) */
9096         { PR_2_DIRECTORY_HOLE,
9097           N_("@d @i %i has an unallocated @b #%B.  "),
9098           PROMPT_ALLOCATE, 0 },
9099
9100         /* '.' is not NULL terminated */
9101         { PR_2_DOT_NULL_TERM,
9102           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103           PROMPT_FIX, 0 },
9104
9105         /* '..' is not NULL terminated */
9106         { PR_2_DOT_DOT_NULL_TERM,
9107           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108           PROMPT_FIX, 0 },
9109
9110         /* Illegal character device inode */
9111         { PR_2_BAD_CHAR_DEV,
9112           N_("@i %i (%Q) is an @I character @v.\n"),
9113           PROMPT_CLEAR, 0 },
9114
9115         /* Illegal block device inode */
9116         { PR_2_BAD_BLOCK_DEV,
9117           N_("@i %i (%Q) is an @I @b @v.\n"),
9118           PROMPT_CLEAR, 0 },
9119
9120         /* Duplicate '.' entry */
9121         { PR_2_DUP_DOT,
9122           N_("@E is duplicate '.' @e.\n"),
9123           PROMPT_FIX, 0 },
9124
9125         /* Duplicate '..' entry */
9126         { PR_2_DUP_DOT_DOT,
9127           N_("@E is duplicate '..' @e.\n"),
9128           PROMPT_FIX, 0 },
9129
9130         /* Internal error: couldn't find dir_info */
9131         { PR_2_NO_DIRINFO,
9132           N_("Internal error: cannot find dir_info for %i.\n"),
9133           PROMPT_NONE, PR_FATAL },
9134
9135         /* Final rec_len is wrong */
9136         { PR_2_FINAL_RECLEN,
9137           N_("@E has rec_len of %Dr, @s %N.\n"),
9138           PROMPT_FIX, 0 },
9139
9140         /* Error allocating icount structure */
9141         { PR_2_ALLOCATE_ICOUNT,
9142           N_("@A icount structure: %m\n"),
9143           PROMPT_NONE, PR_FATAL },
9144
9145         /* Error iterating over directory blocks */
9146         { PR_2_DBLIST_ITERATE,
9147           N_("Error iterating over @d @bs: %m\n"),
9148           PROMPT_NONE, PR_FATAL },
9149
9150         /* Error reading directory block */
9151         { PR_2_READ_DIRBLOCK,
9152           N_("Error reading @d @b %b (@i %i): %m\n"),
9153           PROMPT_CONTINUE, 0 },
9154
9155         /* Error writing directory block */
9156         { PR_2_WRITE_DIRBLOCK,
9157           N_("Error writing @d @b %b (@i %i): %m\n"),
9158           PROMPT_CONTINUE, 0 },
9159
9160         /* Error allocating new directory block */
9161         { PR_2_ALLOC_DIRBOCK,
9162           N_("@A new @d @b for @i %i (%s): %m\n"),
9163           PROMPT_NONE, 0 },
9164
9165         /* Error deallocating inode */
9166         { PR_2_DEALLOC_INODE,
9167           N_("Error deallocating @i %i: %m\n"),
9168           PROMPT_NONE, PR_FATAL },
9169
9170         /* Directory entry for '.' is big.  Split? */
9171         { PR_2_SPLIT_DOT,
9172           N_("@d @e for '.' is big.  "),
9173           PROMPT_SPLIT, PR_NO_OK },
9174
9175         /* Illegal FIFO inode */
9176         { PR_2_BAD_FIFO,
9177           N_("@i %i (%Q) is an @I FIFO.\n"),
9178           PROMPT_CLEAR, 0 },
9179
9180         /* Illegal socket inode */
9181         { PR_2_BAD_SOCKET,
9182           N_("@i %i (%Q) is an @I socket.\n"),
9183           PROMPT_CLEAR, 0 },
9184
9185         /* Directory filetype not set */
9186         { PR_2_SET_FILETYPE,
9187           N_("Setting filetype for @E to %N.\n"),
9188           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9189
9190         /* Directory filetype incorrect */
9191         { PR_2_BAD_FILETYPE,
9192           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193           PROMPT_FIX, 0 },
9194
9195         /* Directory filetype set on filesystem */
9196         { PR_2_CLEAR_FILETYPE,
9197           N_("@E has filetype set.\n"),
9198           PROMPT_CLEAR, PR_PREEN_OK },
9199
9200         /* Directory filename is null */
9201         { PR_2_NULL_NAME,
9202           N_("@E has a @z name.\n"),
9203           PROMPT_CLEAR, 0 },
9204
9205         /* Invalid symlink */
9206         { PR_2_INVALID_SYMLINK,
9207           N_("Symlink %Q (@i #%i) is @n.\n"),
9208           PROMPT_CLEAR, 0 },
9209
9210         /* i_file_acl (extended attribute block) is bad */
9211         { PR_2_FILE_ACL_BAD,
9212           N_("@a @b @F @n (%If).\n"),
9213           PROMPT_CLEAR, 0 },
9214
9215         /* Filesystem contains large files, but has no such flag in sb */
9216         { PR_2_FEATURE_LARGE_FILES,
9217           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218           PROMPT_FIX, 0 },
9219
9220         /* Node in HTREE directory not referenced */
9221         { PR_2_HTREE_NOTREF,
9222           N_("@p @h %d: node (%B) not referenced\n"),
9223           PROMPT_NONE, 0 },
9224
9225         /* Node in HTREE directory referenced twice */
9226         { PR_2_HTREE_DUPREF,
9227           N_("@p @h %d: node (%B) referenced twice\n"),
9228           PROMPT_NONE, 0 },
9229
9230         /* Node in HTREE directory has bad min hash */
9231         { PR_2_HTREE_MIN_HASH,
9232           N_("@p @h %d: node (%B) has bad min hash\n"),
9233           PROMPT_NONE, 0 },
9234
9235         /* Node in HTREE directory has bad max hash */
9236         { PR_2_HTREE_MAX_HASH,
9237           N_("@p @h %d: node (%B) has bad max hash\n"),
9238           PROMPT_NONE, 0 },
9239
9240         /* Clear invalid HTREE directory */
9241         { PR_2_HTREE_CLEAR,
9242           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9243
9244         /* Bad block in htree interior node */
9245         { PR_2_HTREE_BADBLK,
9246           N_("@p @h %d (%q): bad @b number %b.\n"),
9247           PROMPT_CLEAR_HTREE, 0 },
9248
9249         /* Error adjusting EA refcount */
9250         { PR_2_ADJ_EA_REFCOUNT,
9251           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252           PROMPT_NONE, PR_FATAL },
9253
9254         /* Invalid HTREE root node */
9255         { PR_2_HTREE_BAD_ROOT,
9256           N_("@p @h %d: root node is @n\n"),
9257           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9258
9259         /* Invalid HTREE limit */
9260         { PR_2_HTREE_BAD_LIMIT,
9261           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9263
9264         /* Invalid HTREE count */
9265         { PR_2_HTREE_BAD_COUNT,
9266           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9268
9269         /* HTREE interior node has out-of-order hashes in table */
9270         { PR_2_HTREE_HASH_ORDER,
9271           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9273
9274         /* Node in HTREE directory has invalid depth */
9275         { PR_2_HTREE_BAD_DEPTH,
9276           N_("@p @h %d: node (%B) has @n depth\n"),
9277           PROMPT_NONE, 0 },
9278
9279         /* Duplicate directory entry found */
9280         { PR_2_DUPLICATE_DIRENT,
9281           N_("Duplicate @E found.  "),
9282           PROMPT_CLEAR, 0 },
9283
9284         /* Non-unique filename found */
9285         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286           N_("@E has a non-unique filename.\nRename to %s"),
9287           PROMPT_NULL, 0 },
9288
9289         /* Duplicate directory entry found */
9290         { PR_2_REPORT_DUP_DIRENT,
9291           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292           PROMPT_NONE, 0 },
9293
9294         /* Pass 3 errors */
9295
9296         /* Pass 3: Checking directory connectivity */
9297         { PR_3_PASS_HEADER,
9298           N_("Pass 3: Checking @d connectivity\n"),
9299           PROMPT_NONE, 0 },
9300
9301         /* Root inode not allocated */
9302         { PR_3_NO_ROOT_INODE,
9303           N_("@r not allocated.  "),
9304           PROMPT_ALLOCATE, 0 },
9305
9306         /* No room in lost+found */
9307         { PR_3_EXPAND_LF_DIR,
9308           N_("No room in @l @d.  "),
9309           PROMPT_EXPAND, 0 },
9310
9311         /* Unconnected directory inode */
9312         { PR_3_UNCONNECTED_DIR,
9313           N_("Unconnected @d @i %i (%p)\n"),
9314           PROMPT_CONNECT, 0 },
9315
9316         /* /lost+found not found */
9317         { PR_3_NO_LF_DIR,
9318           N_("/@l not found.  "),
9319           PROMPT_CREATE, PR_PREEN_OK },
9320
9321         /* .. entry is incorrect */
9322         { PR_3_BAD_DOT_DOT,
9323           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324           PROMPT_FIX, 0 },
9325
9326         /* Bad or non-existent /lost+found.  Cannot reconnect */
9327         { PR_3_NO_LPF,
9328           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9329           PROMPT_NONE, 0 },
9330
9331         /* Could not expand /lost+found */
9332         { PR_3_CANT_EXPAND_LPF,
9333           N_("Could not expand /@l: %m\n"),
9334           PROMPT_NONE, 0 },
9335
9336         /* Could not reconnect inode */
9337         { PR_3_CANT_RECONNECT,
9338           N_("Could not reconnect %i: %m\n"),
9339           PROMPT_NONE, 0 },
9340
9341         /* Error while trying to find /lost+found */
9342         { PR_3_ERR_FIND_LPF,
9343           N_("Error while trying to find /@l: %m\n"),
9344           PROMPT_NONE, 0 },
9345
9346         /* Error in ext2fs_new_block while creating /lost+found */
9347         { PR_3_ERR_LPF_NEW_BLOCK,
9348           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349           PROMPT_NONE, 0 },
9350
9351         /* Error in ext2fs_new_inode while creating /lost+found */
9352         { PR_3_ERR_LPF_NEW_INODE,
9353           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354           PROMPT_NONE, 0 },
9355
9356         /* Error in ext2fs_new_dir_block while creating /lost+found */
9357         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359           PROMPT_NONE, 0 },
9360
9361         /* Error while writing directory block for /lost+found */
9362         { PR_3_ERR_LPF_WRITE_BLOCK,
9363           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364           PROMPT_NONE, 0 },
9365
9366         /* Error while adjusting inode count */
9367         { PR_3_ADJUST_INODE,
9368           N_("Error while adjusting @i count on @i %i\n"),
9369           PROMPT_NONE, 0 },
9370
9371         /* Couldn't fix parent directory -- error */
9372         { PR_3_FIX_PARENT_ERR,
9373           N_("Couldn't fix parent of @i %i: %m\n\n"),
9374           PROMPT_NONE, 0 },
9375
9376         /* Couldn't fix parent directory -- couldn't find it */
9377         { PR_3_FIX_PARENT_NOFIND,
9378           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379           PROMPT_NONE, 0 },
9380
9381         /* Error allocating inode bitmap */
9382         { PR_3_ALLOCATE_IBITMAP_ERROR,
9383           N_("@A @i @B (%N): %m\n"),
9384           PROMPT_NONE, PR_FATAL },
9385
9386         /* Error creating root directory */
9387         { PR_3_CREATE_ROOT_ERROR,
9388           N_("Error creating root @d (%s): %m\n"),
9389           PROMPT_NONE, PR_FATAL },
9390
9391         /* Error creating lost and found directory */
9392         { PR_3_CREATE_LPF_ERROR,
9393           N_("Error creating /@l @d (%s): %m\n"),
9394           PROMPT_NONE, PR_FATAL },
9395
9396         /* Root inode is not directory; aborting */
9397         { PR_3_ROOT_NOT_DIR_ABORT,
9398           N_("@r is not a @d; aborting.\n"),
9399           PROMPT_NONE, PR_FATAL },
9400
9401         /* Cannot proceed without a root inode. */
9402         { PR_3_NO_ROOT_INODE_ABORT,
9403           N_("Cannot proceed without a @r.\n"),
9404           PROMPT_NONE, PR_FATAL },
9405
9406         /* Internal error: couldn't find dir_info */
9407         { PR_3_NO_DIRINFO,
9408           N_("Internal error: cannot find dir_info for %i.\n"),
9409           PROMPT_NONE, PR_FATAL },
9410
9411         /* Lost+found not a directory */
9412         { PR_3_LPF_NOTDIR,
9413           N_("/@l is not a @d (ino=%i)\n"),
9414           PROMPT_UNLINK, 0 },
9415
9416         /* Pass 3A Directory Optimization       */
9417
9418         /* Pass 3A: Optimizing directories */
9419         { PR_3A_PASS_HEADER,
9420           N_("Pass 3A: Optimizing directories\n"),
9421           PROMPT_NONE, PR_PREEN_NOMSG },
9422
9423         /* Error iterating over directories */
9424         { PR_3A_OPTIMIZE_ITER,
9425           N_("Failed to create dirs_to_hash iterator: %m"),
9426           PROMPT_NONE, 0 },
9427
9428         /* Error rehash directory */
9429         { PR_3A_OPTIMIZE_DIR_ERR,
9430           N_("Failed to optimize directory %q (%d): %m"),
9431           PROMPT_NONE, 0 },
9432
9433         /* Rehashing dir header */
9434         { PR_3A_OPTIMIZE_DIR_HEADER,
9435           N_("Optimizing directories: "),
9436           PROMPT_NONE, PR_MSG_ONLY },
9437
9438         /* Rehashing directory %d */
9439         { PR_3A_OPTIMIZE_DIR,
9440           " %d",
9441           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9442
9443         /* Rehashing dir end */
9444         { PR_3A_OPTIMIZE_DIR_END,
9445           "\n",
9446           PROMPT_NONE, PR_PREEN_NOHDR },
9447
9448         /* Pass 4 errors */
9449
9450         /* Pass 4: Checking reference counts */
9451         { PR_4_PASS_HEADER,
9452           N_("Pass 4: Checking reference counts\n"),
9453           PROMPT_NONE, 0 },
9454
9455         /* Unattached zero-length inode */
9456         { PR_4_ZERO_LEN_INODE,
9457           N_("@u @z @i %i.  "),
9458           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9459
9460         /* Unattached inode */
9461         { PR_4_UNATTACHED_INODE,
9462           N_("@u @i %i\n"),
9463           PROMPT_CONNECT, 0 },
9464
9465         /* Inode ref count wrong */
9466         { PR_4_BAD_REF_COUNT,
9467           N_("@i %i ref count is %Il, @s %N.  "),
9468           PROMPT_FIX, PR_PREEN_OK },
9469
9470         { PR_4_INCONSISTENT_COUNT,
9471           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9474           "They @s the same!\n"),
9475           PROMPT_NONE, 0 },
9476
9477         /* Pass 5 errors */
9478
9479         /* Pass 5: Checking group summary information */
9480         { PR_5_PASS_HEADER,
9481           N_("Pass 5: Checking @g summary information\n"),
9482           PROMPT_NONE, 0 },
9483
9484         /* Padding at end of inode bitmap is not set. */
9485         { PR_5_INODE_BMAP_PADDING,
9486           N_("Padding at end of @i @B is not set. "),
9487           PROMPT_FIX, PR_PREEN_OK },
9488
9489         /* Padding at end of block bitmap is not set. */
9490         { PR_5_BLOCK_BMAP_PADDING,
9491           N_("Padding at end of @b @B is not set. "),
9492           PROMPT_FIX, PR_PREEN_OK },
9493
9494         /* Block bitmap differences header */
9495         { PR_5_BLOCK_BITMAP_HEADER,
9496           N_("@b @B differences: "),
9497           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9498
9499         /* Block not used, but marked in bitmap */
9500         { PR_5_BLOCK_UNUSED,
9501           " -%b",
9502           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9503
9504         /* Block used, but not marked used in bitmap */
9505         { PR_5_BLOCK_USED,
9506           " +%b",
9507           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9508
9509         /* Block bitmap differences end */
9510         { PR_5_BLOCK_BITMAP_END,
9511           "\n",
9512           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9513
9514         /* Inode bitmap differences header */
9515         { PR_5_INODE_BITMAP_HEADER,
9516           N_("@i @B differences: "),
9517           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9518
9519         /* Inode not used, but marked in bitmap */
9520         { PR_5_INODE_UNUSED,
9521           " -%i",
9522           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9523
9524         /* Inode used, but not marked used in bitmap */
9525         { PR_5_INODE_USED,
9526           " +%i",
9527           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528
9529         /* Inode bitmap differences end */
9530         { PR_5_INODE_BITMAP_END,
9531           "\n",
9532           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9533
9534         /* Free inodes count for group wrong */
9535         { PR_5_FREE_INODE_COUNT_GROUP,
9536           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538
9539         /* Directories count for group wrong */
9540         { PR_5_FREE_DIR_COUNT_GROUP,
9541           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9543
9544         /* Free inodes count wrong */
9545         { PR_5_FREE_INODE_COUNT,
9546           N_("Free @is count wrong (%i, counted=%j).\n"),
9547           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9548
9549         /* Free blocks count for group wrong */
9550         { PR_5_FREE_BLOCK_COUNT_GROUP,
9551           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9553
9554         /* Free blocks count wrong */
9555         { PR_5_FREE_BLOCK_COUNT,
9556           N_("Free @bs count wrong (%b, counted=%c).\n"),
9557           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558
9559         /* Programming error: bitmap endpoints don't match */
9560         { PR_5_BMAP_ENDPOINTS,
9561           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562           "match calculated @B endpoints (%i, %j)\n"),
9563           PROMPT_NONE, PR_FATAL },
9564
9565         /* Internal error: fudging end of bitmap */
9566         { PR_5_FUDGE_BITMAP_ERROR,
9567           N_("Internal error: fudging end of bitmap (%N)\n"),
9568           PROMPT_NONE, PR_FATAL },
9569
9570         /* Error copying in replacement inode bitmap */
9571         { PR_5_COPY_IBITMAP_ERROR,
9572           N_("Error copying in replacement @i @B: %m\n"),
9573           PROMPT_NONE, PR_FATAL },
9574
9575         /* Error copying in replacement block bitmap */
9576         { PR_5_COPY_BBITMAP_ERROR,
9577           N_("Error copying in replacement @b @B: %m\n"),
9578           PROMPT_NONE, PR_FATAL },
9579
9580         /* Block range not used, but marked in bitmap */
9581         { PR_5_BLOCK_RANGE_UNUSED,
9582           " -(%b--%c)",
9583           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9584
9585         /* Block range used, but not marked used in bitmap */
9586         { PR_5_BLOCK_RANGE_USED,
9587           " +(%b--%c)",
9588           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9589
9590         /* Inode range not used, but marked in bitmap */
9591         { PR_5_INODE_RANGE_UNUSED,
9592           " -(%i--%j)",
9593           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9594
9595         /* Inode range used, but not marked used in bitmap */
9596         { PR_5_INODE_RANGE_USED,
9597           " +(%i--%j)",
9598           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9599
9600         { 0 }
9601 };
9602
9603 /*
9604  * This is the latch flags register.  It allows several problems to be
9605  * "latched" together.  This means that the user has to answer but one
9606  * question for the set of problems, and all of the associated
9607  * problems will be either fixed or not fixed.
9608  */
9609 static struct latch_descr pr_latch_info[] = {
9610         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619         { -1, 0, 0 },
9620 };
9621
9622 static const struct e2fsck_problem *find_problem(problem_t code)
9623 {
9624         int     i;
9625
9626         for (i=0; problem_table[i].e2p_code; i++) {
9627                 if (problem_table[i].e2p_code == code)
9628                         return &problem_table[i];
9629         }
9630         return 0;
9631 }
9632
9633 static struct latch_descr *find_latch(int code)
9634 {
9635         int     i;
9636
9637         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638                 if (pr_latch_info[i].latch_code == code)
9639                         return &pr_latch_info[i];
9640         }
9641         return 0;
9642 }
9643
9644 int end_problem_latch(e2fsck_t ctx, int mask)
9645 {
9646         struct latch_descr *ldesc;
9647         struct problem_context pctx;
9648         int answer = -1;
9649
9650         ldesc = find_latch(mask);
9651         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652                 clear_problem_context(&pctx);
9653                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9654         }
9655         ldesc->flags &= ~(PRL_VARIABLE);
9656         return answer;
9657 }
9658
9659 int set_latch_flags(int mask, int setflags, int clearflags)
9660 {
9661         struct latch_descr *ldesc;
9662
9663         ldesc = find_latch(mask);
9664         if (!ldesc)
9665                 return -1;
9666         ldesc->flags |= setflags;
9667         ldesc->flags &= ~clearflags;
9668         return 0;
9669 }
9670
9671 void clear_problem_context(struct problem_context *ctx)
9672 {
9673         memset(ctx, 0, sizeof(struct problem_context));
9674         ctx->blkcount = -1;
9675         ctx->group = -1;
9676 }
9677
9678 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9679 {
9680         ext2_filsys fs = ctx->fs;
9681         const struct e2fsck_problem *ptr;
9682         struct latch_descr *ldesc = 0;
9683         const char *message;
9684         int             def_yn, answer, ans;
9685         int             print_answer = 0;
9686         int             suppress = 0;
9687
9688         ptr = find_problem(code);
9689         if (!ptr) {
9690                 printf(_("Unhandled error code (0x%x)!\n"), code);
9691                 return 0;
9692         }
9693         def_yn = 1;
9694         if ((ptr->flags & PR_NO_DEFAULT) ||
9695             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696             (ctx->options & E2F_OPT_NO))
9697                 def_yn= 0;
9698
9699         /*
9700          * Do special latch processing.  This is where we ask the
9701          * latch question, if it exists
9702          */
9703         if (ptr->flags & PR_LATCH_MASK) {
9704                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706                         ans = fix_problem(ctx, ldesc->question, pctx);
9707                         if (ans == 1)
9708                                 ldesc->flags |= PRL_YES;
9709                         if (ans == 0)
9710                                 ldesc->flags |= PRL_NO;
9711                         ldesc->flags |= PRL_LATCHED;
9712                 }
9713                 if (ldesc->flags & PRL_SUPPRESS)
9714                         suppress++;
9715         }
9716         if ((ptr->flags & PR_PREEN_NOMSG) &&
9717             (ctx->options & E2F_OPT_PREEN))
9718                 suppress++;
9719         if ((ptr->flags & PR_NO_NOMSG) &&
9720             (ctx->options & E2F_OPT_NO))
9721                 suppress++;
9722         if (!suppress) {
9723                 message = ptr->e2p_description;
9724                 if ((ctx->options & E2F_OPT_PREEN) &&
9725                     !(ptr->flags & PR_PREEN_NOHDR)) {
9726                         printf("%s: ", ctx->device_name ?
9727                                ctx->device_name : ctx->filesystem_name);
9728                 }
9729                 if (*message)
9730                         print_e2fsck_message(ctx, _(message), pctx, 1);
9731         }
9732         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733                 preenhalt(ctx);
9734
9735         if (ptr->flags & PR_FATAL)
9736                 bb_error_msg_and_die(0);
9737
9738         if (ptr->prompt == PROMPT_NONE) {
9739                 if (ptr->flags & PR_NOCOLLATE)
9740                         answer = -1;
9741                 else
9742                         answer = def_yn;
9743         } else {
9744                 if (ctx->options & E2F_OPT_PREEN) {
9745                         answer = def_yn;
9746                         if (!(ptr->flags & PR_PREEN_NOMSG))
9747                                 print_answer = 1;
9748                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9749                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9750                         if (!suppress)
9751                                 print_answer = 1;
9752                         if (ldesc->flags & PRL_YES)
9753                                 answer = 1;
9754                         else
9755                                 answer = 0;
9756                 } else
9757                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758                 if (!answer && !(ptr->flags & PR_NO_OK))
9759                         ext2fs_unmark_valid(fs);
9760
9761                 if (print_answer)
9762                         printf("%s.\n", answer ?
9763                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9764
9765         }
9766
9767         if ((ptr->prompt == PROMPT_ABORT) && answer)
9768                 bb_error_msg_and_die(0);
9769
9770         if (ptr->flags & PR_AFTER_CODE)
9771                 answer = fix_problem(ctx, ptr->second_code, pctx);
9772
9773         return answer;
9774 }
9775
9776 /*
9777  * linux/fs/recovery.c
9778  *
9779  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9780  */
9781
9782 /*
9783  * Maintain information about the progress of the recovery job, so that
9784  * the different passes can carry information between them.
9785  */
9786 struct recovery_info
9787 {
9788         tid_t           start_transaction;
9789         tid_t           end_transaction;
9790
9791         int             nr_replays;
9792         int             nr_revokes;
9793         int             nr_revoke_hits;
9794 };
9795
9796 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9797 static int do_one_pass(journal_t *journal,
9798                                 struct recovery_info *info, enum passtype pass);
9799 static int scan_revoke_records(journal_t *, struct buffer_head *,
9800                                 tid_t, struct recovery_info *);
9801
9802 /*
9803  * Read a block from the journal
9804  */
9805
9806 static int jread(struct buffer_head **bhp, journal_t *journal,
9807                  unsigned int offset)
9808 {
9809         int err;
9810         unsigned long blocknr;
9811         struct buffer_head *bh;
9812
9813         *bhp = NULL;
9814
9815         err = journal_bmap(journal, offset, &blocknr);
9816
9817         if (err) {
9818                 printf("JBD: bad block at offset %u\n", offset);
9819                 return err;
9820         }
9821
9822         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9823         if (!bh)
9824                 return -ENOMEM;
9825
9826         if (!buffer_uptodate(bh)) {
9827                 /* If this is a brand new buffer, start readahead.
9828                    Otherwise, we assume we are already reading it.  */
9829                 if (!buffer_req(bh))
9830                         do_readahead(journal, offset);
9831                 wait_on_buffer(bh);
9832         }
9833
9834         if (!buffer_uptodate(bh)) {
9835                 printf("JBD: Failed to read block at offset %u\n", offset);
9836                 brelse(bh);
9837                 return -EIO;
9838         }
9839
9840         *bhp = bh;
9841         return 0;
9842 }
9843
9844
9845 /*
9846  * Count the number of in-use tags in a journal descriptor block.
9847  */
9848
9849 static int count_tags(struct buffer_head *bh, int size)
9850 {
9851         char *                  tagp;
9852         journal_block_tag_t *   tag;
9853         int                     nr = 0;
9854
9855         tagp = &bh->b_data[sizeof(journal_header_t)];
9856
9857         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9858                 tag = (journal_block_tag_t *) tagp;
9859
9860                 nr++;
9861                 tagp += sizeof(journal_block_tag_t);
9862                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9863                         tagp += 16;
9864
9865                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9866                         break;
9867         }
9868
9869         return nr;
9870 }
9871
9872
9873 /* Make sure we wrap around the log correctly! */
9874 #define wrap(journal, var)                                            \
9875 do {                                                                \
9876         if (var >= (journal)->j_last)                                   \
9877                 var -= ((journal)->j_last - (journal)->j_first);        \
9878 } while (0)
9879
9880 /**
9881  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9882  * @journal: the journal to recover
9883  *
9884  * The primary function for recovering the log contents when mounting a
9885  * journaled device.
9886  *
9887  * Recovery is done in three passes.  In the first pass, we look for the
9888  * end of the log.  In the second, we assemble the list of revoke
9889  * blocks.  In the third and final pass, we replay any un-revoked blocks
9890  * in the log.
9891  */
9892 int journal_recover(journal_t *journal)
9893 {
9894         int                     err;
9895         journal_superblock_t *  sb;
9896
9897         struct recovery_info    info;
9898
9899         memset(&info, 0, sizeof(info));
9900         sb = journal->j_superblock;
9901
9902         /*
9903          * The journal superblock's s_start field (the current log head)
9904          * is always zero if, and only if, the journal was cleanly
9905          * unmounted.
9906          */
9907
9908         if (!sb->s_start) {
9909                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9910                 return 0;
9911         }
9912
9913         err = do_one_pass(journal, &info, PASS_SCAN);
9914         if (!err)
9915                 err = do_one_pass(journal, &info, PASS_REVOKE);
9916         if (!err)
9917                 err = do_one_pass(journal, &info, PASS_REPLAY);
9918
9919         /* Restart the log at the next transaction ID, thus invalidating
9920          * any existing commit records in the log. */
9921         journal->j_transaction_sequence = ++info.end_transaction;
9922
9923         journal_clear_revoke(journal);
9924         sync_blockdev(journal->j_fs_dev);
9925         return err;
9926 }
9927
9928 static int do_one_pass(journal_t *journal,
9929                         struct recovery_info *info, enum passtype pass)
9930 {
9931         unsigned int            first_commit_ID, next_commit_ID;
9932         unsigned long           next_log_block;
9933         int                     err, success = 0;
9934         journal_superblock_t *  sb;
9935         journal_header_t *      tmp;
9936         struct buffer_head *    bh;
9937         unsigned int            sequence;
9938         int                     blocktype;
9939
9940         /* Precompute the maximum metadata descriptors in a descriptor block */
9941         int                     MAX_BLOCKS_PER_DESC;
9942         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9943                                / sizeof(journal_block_tag_t));
9944
9945         /*
9946          * First thing is to establish what we expect to find in the log
9947          * (in terms of transaction IDs), and where (in terms of log
9948          * block offsets): query the superblock.
9949          */
9950
9951         sb = journal->j_superblock;
9952         next_commit_ID = ntohl(sb->s_sequence);
9953         next_log_block = ntohl(sb->s_start);
9954
9955         first_commit_ID = next_commit_ID;
9956         if (pass == PASS_SCAN)
9957                 info->start_transaction = first_commit_ID;
9958
9959         /*
9960          * Now we walk through the log, transaction by transaction,
9961          * making sure that each transaction has a commit block in the
9962          * expected place.  Each complete transaction gets replayed back
9963          * into the main filesystem.
9964          */
9965
9966         while (1) {
9967                 int                     flags;
9968                 char *                  tagp;
9969                 journal_block_tag_t *   tag;
9970                 struct buffer_head *    obh;
9971                 struct buffer_head *    nbh;
9972
9973                 /* If we already know where to stop the log traversal,
9974                  * check right now that we haven't gone past the end of
9975                  * the log. */
9976
9977                 if (pass != PASS_SCAN)
9978                         if (tid_geq(next_commit_ID, info->end_transaction))
9979                                 break;
9980
9981                 /* Skip over each chunk of the transaction looking
9982                  * either the next descriptor block or the final commit
9983                  * record. */
9984
9985                 err = jread(&bh, journal, next_log_block);
9986                 if (err)
9987                         goto failed;
9988
9989                 next_log_block++;
9990                 wrap(journal, next_log_block);
9991
9992                 /* What kind of buffer is it?
9993                  *
9994                  * If it is a descriptor block, check that it has the
9995                  * expected sequence number.  Otherwise, we're all done
9996                  * here. */
9997
9998                 tmp = (journal_header_t *)bh->b_data;
9999
10000                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10001                         brelse(bh);
10002                         break;
10003                 }
10004
10005                 blocktype = ntohl(tmp->h_blocktype);
10006                 sequence = ntohl(tmp->h_sequence);
10007
10008                 if (sequence != next_commit_ID) {
10009                         brelse(bh);
10010                         break;
10011                 }
10012
10013                 /* OK, we have a valid descriptor block which matches
10014                  * all of the sequence number checks.  What are we going
10015                  * to do with it?  That depends on the pass... */
10016
10017                 switch(blocktype) {
10018                 case JFS_DESCRIPTOR_BLOCK:
10019                         /* If it is a valid descriptor block, replay it
10020                          * in pass REPLAY; otherwise, just skip over the
10021                          * blocks it describes. */
10022                         if (pass != PASS_REPLAY) {
10023                                 next_log_block +=
10024                                         count_tags(bh, journal->j_blocksize);
10025                                 wrap(journal, next_log_block);
10026                                 brelse(bh);
10027                                 continue;
10028                         }
10029
10030                         /* A descriptor block: we can now write all of
10031                          * the data blocks.  Yay, useful work is finally
10032                          * getting done here! */
10033
10034                         tagp = &bh->b_data[sizeof(journal_header_t)];
10035                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10036                                <= journal->j_blocksize) {
10037                                 unsigned long io_block;
10038
10039                                 tag = (journal_block_tag_t *) tagp;
10040                                 flags = ntohl(tag->t_flags);
10041
10042                                 io_block = next_log_block++;
10043                                 wrap(journal, next_log_block);
10044                                 err = jread(&obh, journal, io_block);
10045                                 if (err) {
10046                                         /* Recover what we can, but
10047                                          * report failure at the end. */
10048                                         success = err;
10049                                         printf("JBD: IO error %d recovering "
10050                                                 "block %ld in log\n",
10051                                                 err, io_block);
10052                                 } else {
10053                                         unsigned long blocknr;
10054
10055                                         blocknr = ntohl(tag->t_blocknr);
10056
10057                                         /* If the block has been
10058                                          * revoked, then we're all done
10059                                          * here. */
10060                                         if (journal_test_revoke
10061                                             (journal, blocknr,
10062                                              next_commit_ID)) {
10063                                                 brelse(obh);
10064                                                 ++info->nr_revoke_hits;
10065                                                 goto skip_write;
10066                                         }
10067
10068                                         /* Find a buffer for the new
10069                                          * data being restored */
10070                                         nbh = getblk(journal->j_fs_dev,
10071                                                        blocknr,
10072                                                      journal->j_blocksize);
10073                                         if (nbh == NULL) {
10074                                                 printf("JBD: Out of memory "
10075                                                        "during recovery.\n");
10076                                                 err = -ENOMEM;
10077                                                 brelse(bh);
10078                                                 brelse(obh);
10079                                                 goto failed;
10080                                         }
10081
10082                                         lock_buffer(nbh);
10083                                         memcpy(nbh->b_data, obh->b_data,
10084                                                         journal->j_blocksize);
10085                                         if (flags & JFS_FLAG_ESCAPE) {
10086                                                 *((unsigned int *)bh->b_data) =
10087                                                         htonl(JFS_MAGIC_NUMBER);
10088                                         }
10089
10090                                         mark_buffer_uptodate(nbh, 1);
10091                                         mark_buffer_dirty(nbh);
10092                                         ++info->nr_replays;
10093                                         /* ll_rw_block(WRITE, 1, &nbh); */
10094                                         unlock_buffer(nbh);
10095                                         brelse(obh);
10096                                         brelse(nbh);
10097                                 }
10098
10099                         skip_write:
10100                                 tagp += sizeof(journal_block_tag_t);
10101                                 if (!(flags & JFS_FLAG_SAME_UUID))
10102                                         tagp += 16;
10103
10104                                 if (flags & JFS_FLAG_LAST_TAG)
10105                                         break;
10106                         }
10107
10108                         brelse(bh);
10109                         continue;
10110
10111                 case JFS_COMMIT_BLOCK:
10112                         /* Found an expected commit block: not much to
10113                          * do other than move on to the next sequence
10114                          * number. */
10115                         brelse(bh);
10116                         next_commit_ID++;
10117                         continue;
10118
10119                 case JFS_REVOKE_BLOCK:
10120                         /* If we aren't in the REVOKE pass, then we can
10121                          * just skip over this block. */
10122                         if (pass != PASS_REVOKE) {
10123                                 brelse(bh);
10124                                 continue;
10125                         }
10126
10127                         err = scan_revoke_records(journal, bh,
10128                                                   next_commit_ID, info);
10129                         brelse(bh);
10130                         if (err)
10131                                 goto failed;
10132                         continue;
10133
10134                 default:
10135                         goto done;
10136                 }
10137         }
10138
10139  done:
10140         /*
10141          * We broke out of the log scan loop: either we came to the
10142          * known end of the log or we found an unexpected block in the
10143          * log.  If the latter happened, then we know that the "current"
10144          * transaction marks the end of the valid log.
10145          */
10146
10147         if (pass == PASS_SCAN)
10148                 info->end_transaction = next_commit_ID;
10149         else {
10150                 /* It's really bad news if different passes end up at
10151                  * different places (but possible due to IO errors). */
10152                 if (info->end_transaction != next_commit_ID) {
10153                         printf("JBD: recovery pass %d ended at "
10154                                 "transaction %u, expected %u\n",
10155                                 pass, next_commit_ID, info->end_transaction);
10156                         if (!success)
10157                                 success = -EIO;
10158                 }
10159         }
10160
10161         return success;
10162
10163  failed:
10164         return err;
10165 }
10166
10167
10168 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10169
10170 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10171                                tid_t sequence, struct recovery_info *info)
10172 {
10173         journal_revoke_header_t *header;
10174         int offset, max;
10175
10176         header = (journal_revoke_header_t *) bh->b_data;
10177         offset = sizeof(journal_revoke_header_t);
10178         max = ntohl(header->r_count);
10179
10180         while (offset < max) {
10181                 unsigned long blocknr;
10182                 int err;
10183
10184                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10185                 offset += 4;
10186                 err = journal_set_revoke(journal, blocknr, sequence);
10187                 if (err)
10188                         return err;
10189                 ++info->nr_revokes;
10190         }
10191         return 0;
10192 }
10193
10194
10195 /*
10196  * rehash.c --- rebuild hash tree directories
10197  *
10198  * This algorithm is designed for simplicity of implementation and to
10199  * pack the directory as much as possible.  It however requires twice
10200  * as much memory as the size of the directory.  The maximum size
10201  * directory supported using a 4k blocksize is roughly a gigabyte, and
10202  * so there may very well be problems with machines that don't have
10203  * virtual memory, and obscenely large directories.
10204  *
10205  * An alternate algorithm which is much more disk intensive could be
10206  * written, and probably will need to be written in the future.  The
10207  * design goals of such an algorithm are: (a) use (roughly) constant
10208  * amounts of memory, no matter how large the directory, (b) the
10209  * directory must be safe at all times, even if e2fsck is interrupted
10210  * in the middle, (c) we must use minimal amounts of extra disk
10211  * blocks.  This pretty much requires an incremental approach, where
10212  * we are reading from one part of the directory, and inserting into
10213  * the front half.  So the algorithm will have to keep track of a
10214  * moving block boundary between the new tree and the old tree, and
10215  * files will need to be moved from the old directory and inserted
10216  * into the new tree.  If the new directory requires space which isn't
10217  * yet available, blocks from the beginning part of the old directory
10218  * may need to be moved to the end of the directory to make room for
10219  * the new tree:
10220  *
10221  *    --------------------------------------------------------
10222  *    |  new tree   |        | old tree                      |
10223  *    --------------------------------------------------------
10224  *                  ^ ptr    ^ptr
10225  *                tail new   head old
10226  *
10227  * This is going to be a pain in the tuckus to implement, and will
10228  * require a lot more disk accesses.  So I'm going to skip it for now;
10229  * it's only really going to be an issue for really, really big
10230  * filesystems (when we reach the level of tens of millions of files
10231  * in a single directory).  It will probably be easier to simply
10232  * require that e2fsck use VM first.
10233  */
10234
10235 struct fill_dir_struct {
10236         char *buf;
10237         struct ext2_inode *inode;
10238         int err;
10239         e2fsck_t ctx;
10240         struct hash_entry *harray;
10241         int max_array, num_array;
10242         int dir_size;
10243         int compress;
10244         ino_t parent;
10245 };
10246
10247 struct hash_entry {
10248         ext2_dirhash_t  hash;
10249         ext2_dirhash_t  minor_hash;
10250         struct ext2_dir_entry   *dir;
10251 };
10252
10253 struct out_dir {
10254         int             num;
10255         int             max;
10256         char            *buf;
10257         ext2_dirhash_t  *hashes;
10258 };
10259
10260 static int fill_dir_block(ext2_filsys fs,
10261                           blk_t *block_nr,
10262                           e2_blkcnt_t blockcnt,
10263                           blk_t ref_block FSCK_ATTR((unused)),
10264                           int ref_offset FSCK_ATTR((unused)),
10265                           void *priv_data)
10266 {
10267         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10268         struct hash_entry       *new_array, *ent;
10269         struct ext2_dir_entry   *dirent;
10270         char                    *dir;
10271         unsigned int            offset, dir_offset;
10272
10273         if (blockcnt < 0)
10274                 return 0;
10275
10276         offset = blockcnt * fs->blocksize;
10277         if (offset + fs->blocksize > fd->inode->i_size) {
10278                 fd->err = EXT2_ET_DIR_CORRUPTED;
10279                 return BLOCK_ABORT;
10280         }
10281         dir = (fd->buf+offset);
10282         if (HOLE_BLKADDR(*block_nr)) {
10283                 memset(dir, 0, fs->blocksize);
10284                 dirent = (struct ext2_dir_entry *) dir;
10285                 dirent->rec_len = fs->blocksize;
10286         } else {
10287                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10288                 if (fd->err)
10289                         return BLOCK_ABORT;
10290         }
10291         /* While the directory block is "hot", index it. */
10292         dir_offset = 0;
10293         while (dir_offset < fs->blocksize) {
10294                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10295                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10296                     (dirent->rec_len < 8) ||
10297                     ((dirent->rec_len % 4) != 0) ||
10298                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10299                         fd->err = EXT2_ET_DIR_CORRUPTED;
10300                         return BLOCK_ABORT;
10301                 }
10302                 dir_offset += dirent->rec_len;
10303                 if (dirent->inode == 0)
10304                         continue;
10305                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10306                     (dirent->name[0] == '.'))
10307                         continue;
10308                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10309                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10310                         fd->parent = dirent->inode;
10311                         continue;
10312                 }
10313                 if (fd->num_array >= fd->max_array) {
10314                         new_array = realloc(fd->harray,
10315                             sizeof(struct hash_entry) * (fd->max_array+500));
10316                         if (!new_array) {
10317                                 fd->err = ENOMEM;
10318                                 return BLOCK_ABORT;
10319                         }
10320                         fd->harray = new_array;
10321                         fd->max_array += 500;
10322                 }
10323                 ent = fd->harray + fd->num_array++;
10324                 ent->dir = dirent;
10325                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10326                 if (fd->compress)
10327                         ent->hash = ent->minor_hash = 0;
10328                 else {
10329                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10330                                                  dirent->name,
10331                                                  dirent->name_len & 0xFF,
10332                                                  fs->super->s_hash_seed,
10333                                                  &ent->hash, &ent->minor_hash);
10334                         if (fd->err)
10335                                 return BLOCK_ABORT;
10336                 }
10337         }
10338
10339         return 0;
10340 }
10341
10342 /* Used for sorting the hash entry */
10343 static int name_cmp(const void *a, const void *b)
10344 {
10345         const struct hash_entry *he_a = (const struct hash_entry *) a;
10346         const struct hash_entry *he_b = (const struct hash_entry *) b;
10347         int     ret;
10348         int     min_len;
10349
10350         min_len = he_a->dir->name_len;
10351         if (min_len > he_b->dir->name_len)
10352                 min_len = he_b->dir->name_len;
10353
10354         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10355         if (ret == 0) {
10356                 if (he_a->dir->name_len > he_b->dir->name_len)
10357                         ret = 1;
10358                 else if (he_a->dir->name_len < he_b->dir->name_len)
10359                         ret = -1;
10360                 else
10361                         ret = he_b->dir->inode - he_a->dir->inode;
10362         }
10363         return ret;
10364 }
10365
10366 /* Used for sorting the hash entry */
10367 static int hash_cmp(const void *a, const void *b)
10368 {
10369         const struct hash_entry *he_a = (const struct hash_entry *) a;
10370         const struct hash_entry *he_b = (const struct hash_entry *) b;
10371         int     ret;
10372
10373         if (he_a->hash > he_b->hash)
10374                 ret = 1;
10375         else if (he_a->hash < he_b->hash)
10376                 ret = -1;
10377         else {
10378                 if (he_a->minor_hash > he_b->minor_hash)
10379                         ret = 1;
10380                 else if (he_a->minor_hash < he_b->minor_hash)
10381                         ret = -1;
10382                 else
10383                         ret = name_cmp(a, b);
10384         }
10385         return ret;
10386 }
10387
10388 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10389                                 int blocks)
10390 {
10391         void                    *new_mem;
10392
10393         if (outdir->max) {
10394                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
10395                 if (!new_mem)
10396                         return ENOMEM;
10397                 outdir->buf = new_mem;
10398                 new_mem = realloc(outdir->hashes,
10399                                   blocks * sizeof(ext2_dirhash_t));
10400                 if (!new_mem)
10401                         return ENOMEM;
10402                 outdir->hashes = new_mem;
10403         } else {
10404                 outdir->buf = malloc(blocks * fs->blocksize);
10405                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
10406                 outdir->num = 0;
10407         }
10408         outdir->max = blocks;
10409         return 0;
10410 }
10411
10412 static void free_out_dir(struct out_dir *outdir)
10413 {
10414         free(outdir->buf);
10415         free(outdir->hashes);
10416         outdir->max = 0;
10417         outdir->num =0;
10418 }
10419
10420 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10421                          char ** ret)
10422 {
10423         errcode_t       retval;
10424
10425         if (outdir->num >= outdir->max) {
10426                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10427                 if (retval)
10428                         return retval;
10429         }
10430         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10431         memset(*ret, 0, fs->blocksize);
10432         return 0;
10433 }
10434
10435 /*
10436  * This function is used to make a unique filename.  We do this by
10437  * appending ~0, and then incrementing the number.  However, we cannot
10438  * expand the length of the filename beyond the padding available in
10439  * the directory entry.
10440  */
10441 static void mutate_name(char *str, __u16 *len)
10442 {
10443         int     i;
10444         __u16   l = *len & 0xFF, h = *len & 0xff00;
10445
10446         /*
10447          * First check to see if it looks the name has been mutated
10448          * already
10449          */
10450         for (i = l-1; i > 0; i--) {
10451                 if (!isdigit(str[i]))
10452                         break;
10453         }
10454         if ((i == l-1) || (str[i] != '~')) {
10455                 if (((l-1) & 3) < 2)
10456                         l += 2;
10457                 else
10458                         l = (l+3) & ~3;
10459                 str[l-2] = '~';
10460                 str[l-1] = '0';
10461                 *len = l | h;
10462                 return;
10463         }
10464         for (i = l-1; i >= 0; i--) {
10465                 if (isdigit(str[i])) {
10466                         if (str[i] == '9')
10467                                 str[i] = '0';
10468                         else {
10469                                 str[i]++;
10470                                 return;
10471                         }
10472                         continue;
10473                 }
10474                 if (i == 1) {
10475                         if (str[0] == 'z')
10476                                 str[0] = 'A';
10477                         else if (str[0] == 'Z') {
10478                                 str[0] = '~';
10479                                 str[1] = '0';
10480                         } else
10481                                 str[0]++;
10482                 } else if (i > 0) {
10483                         str[i] = '1';
10484                         str[i-1] = '~';
10485                 } else {
10486                         if (str[0] == '~')
10487                                 str[0] = 'a';
10488                         else
10489                                 str[0]++;
10490                 }
10491                 break;
10492         }
10493 }
10494
10495 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10496                                     ext2_ino_t ino,
10497                                     struct fill_dir_struct *fd)
10498 {
10499         struct problem_context  pctx;
10500         struct hash_entry       *ent, *prev;
10501         int                     i, j;
10502         int                     fixed = 0;
10503         char                    new_name[256];
10504         __u16                   new_len;
10505
10506         clear_problem_context(&pctx);
10507         pctx.ino = ino;
10508
10509         for (i=1; i < fd->num_array; i++) {
10510                 ent = fd->harray + i;
10511                 prev = ent - 1;
10512                 if (!ent->dir->inode ||
10513                     ((ent->dir->name_len & 0xFF) !=
10514                      (prev->dir->name_len & 0xFF)) ||
10515                     (strncmp(ent->dir->name, prev->dir->name,
10516                              ent->dir->name_len & 0xFF)))
10517                         continue;
10518                 pctx.dirent = ent->dir;
10519                 if ((ent->dir->inode == prev->dir->inode) &&
10520                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10521                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10522                         ent->dir->inode = 0;
10523                         fixed++;
10524                         continue;
10525                 }
10526                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10527                 new_len = ent->dir->name_len;
10528                 mutate_name(new_name, &new_len);
10529                 for (j=0; j < fd->num_array; j++) {
10530                         if ((i==j) ||
10531                             ((ent->dir->name_len & 0xFF) !=
10532                              (fd->harray[j].dir->name_len & 0xFF)) ||
10533                             (strncmp(new_name, fd->harray[j].dir->name,
10534                                      new_len & 0xFF)))
10535                                 continue;
10536                         mutate_name(new_name, &new_len);
10537
10538                         j = -1;
10539                 }
10540                 new_name[new_len & 0xFF] = 0;
10541                 pctx.str = new_name;
10542                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10543                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10544                         ent->dir->name_len = new_len;
10545                         ext2fs_dirhash(fs->super->s_def_hash_version,
10546                                        ent->dir->name,
10547                                        ent->dir->name_len & 0xFF,
10548                                        fs->super->s_hash_seed,
10549                                        &ent->hash, &ent->minor_hash);
10550                         fixed++;
10551                 }
10552         }
10553         return fixed;
10554 }
10555
10556
10557 static errcode_t copy_dir_entries(ext2_filsys fs,
10558                                   struct fill_dir_struct *fd,
10559                                   struct out_dir *outdir)
10560 {
10561         errcode_t               retval;
10562         char                    *block_start;
10563         struct hash_entry       *ent;
10564         struct ext2_dir_entry   *dirent;
10565         int                     i, rec_len, left;
10566         ext2_dirhash_t          prev_hash;
10567         int                     offset;
10568
10569         outdir->max = 0;
10570         retval = alloc_size_dir(fs, outdir,
10571                                 (fd->dir_size / fs->blocksize) + 2);
10572         if (retval)
10573                 return retval;
10574         outdir->num = fd->compress ? 0 : 1;
10575         offset = 0;
10576         outdir->hashes[0] = 0;
10577         prev_hash = 1;
10578         if ((retval = get_next_block(fs, outdir, &block_start)))
10579                 return retval;
10580         dirent = (struct ext2_dir_entry *) block_start;
10581         left = fs->blocksize;
10582         for (i=0; i < fd->num_array; i++) {
10583                 ent = fd->harray + i;
10584                 if (ent->dir->inode == 0)
10585                         continue;
10586                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10587                 if (rec_len > left) {
10588                         if (left)
10589                                 dirent->rec_len += left;
10590                         if ((retval = get_next_block(fs, outdir,
10591                                                       &block_start)))
10592                                 return retval;
10593                         offset = 0;
10594                 }
10595                 left = fs->blocksize - offset;
10596                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10597                 if (offset == 0) {
10598                         if (ent->hash == prev_hash)
10599                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10600                         else
10601                                 outdir->hashes[outdir->num-1] = ent->hash;
10602                 }
10603                 dirent->inode = ent->dir->inode;
10604                 dirent->name_len = ent->dir->name_len;
10605                 dirent->rec_len = rec_len;
10606                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10607                 offset += rec_len;
10608                 left -= rec_len;
10609                 if (left < 12) {
10610                         dirent->rec_len += left;
10611                         offset += left;
10612                         left = 0;
10613                 }
10614                 prev_hash = ent->hash;
10615         }
10616         if (left)
10617                 dirent->rec_len += left;
10618
10619         return 0;
10620 }
10621
10622
10623 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10624                                     ext2_ino_t ino, ext2_ino_t parent)
10625 {
10626         struct ext2_dir_entry           *dir;
10627         struct ext2_dx_root_info        *root;
10628         struct ext2_dx_countlimit       *limits;
10629         int                             filetype = 0;
10630
10631         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10632                 filetype = EXT2_FT_DIR << 8;
10633
10634         memset(buf, 0, fs->blocksize);
10635         dir = (struct ext2_dir_entry *) buf;
10636         dir->inode = ino;
10637         dir->name[0] = '.';
10638         dir->name_len = 1 | filetype;
10639         dir->rec_len = 12;
10640         dir = (struct ext2_dir_entry *) (buf + 12);
10641         dir->inode = parent;
10642         dir->name[0] = '.';
10643         dir->name[1] = '.';
10644         dir->name_len = 2 | filetype;
10645         dir->rec_len = fs->blocksize - 12;
10646
10647         root = (struct ext2_dx_root_info *) (buf+24);
10648         root->reserved_zero = 0;
10649         root->hash_version = fs->super->s_def_hash_version;
10650         root->info_length = 8;
10651         root->indirect_levels = 0;
10652         root->unused_flags = 0;
10653
10654         limits = (struct ext2_dx_countlimit *) (buf+32);
10655         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10656         limits->count = 0;
10657
10658         return root;
10659 }
10660
10661
10662 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10663 {
10664         struct ext2_dir_entry           *dir;
10665         struct ext2_dx_countlimit       *limits;
10666
10667         memset(buf, 0, fs->blocksize);
10668         dir = (struct ext2_dir_entry *) buf;
10669         dir->inode = 0;
10670         dir->rec_len = fs->blocksize;
10671
10672         limits = (struct ext2_dx_countlimit *) (buf+8);
10673         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10674         limits->count = 0;
10675
10676         return (struct ext2_dx_entry *) limits;
10677 }
10678
10679 /*
10680  * This function takes the leaf nodes which have been written in
10681  * outdir, and populates the root node and any necessary interior nodes.
10682  */
10683 static errcode_t calculate_tree(ext2_filsys fs,
10684                                 struct out_dir *outdir,
10685                                 ext2_ino_t ino,
10686                                 ext2_ino_t parent)
10687 {
10688         struct ext2_dx_root_info        *root_info;
10689         struct ext2_dx_entry            *root, *dx_ent = 0;
10690         struct ext2_dx_countlimit       *root_limit, *limit;
10691         errcode_t                       retval;
10692         char                            * block_start;
10693         int                             i, c1, c2, nblks;
10694         int                             limit_offset, root_offset;
10695
10696         root_info = set_root_node(fs, outdir->buf, ino, parent);
10697         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10698                 root_info->info_length;
10699         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10700         c1 = root_limit->limit;
10701         nblks = outdir->num;
10702
10703         /* Write out the pointer blocks */
10704         if (nblks-1 <= c1) {
10705                 /* Just write out the root block, and we're done */
10706                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10707                 for (i=1; i < nblks; i++) {
10708                         root->block = ext2fs_cpu_to_le32(i);
10709                         if (i != 1)
10710                                 root->hash =
10711                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10712                         root++;
10713                         c1--;
10714                 }
10715         } else {
10716                 c2 = 0;
10717                 limit = 0;
10718                 root_info->indirect_levels = 1;
10719                 for (i=1; i < nblks; i++) {
10720                         if (c1 == 0)
10721                                 return ENOSPC;
10722                         if (c2 == 0) {
10723                                 if (limit)
10724                                         limit->limit = limit->count =
10725                 ext2fs_cpu_to_le16(limit->limit);
10726                                 root = (struct ext2_dx_entry *)
10727                                         (outdir->buf + root_offset);
10728                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10729                                 if (i != 1)
10730                                         root->hash =
10731                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10732                                 if ((retval =  get_next_block(fs, outdir,
10733                                                               &block_start)))
10734                                         return retval;
10735                                 dx_ent = set_int_node(fs, block_start);
10736                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10737                                 c2 = limit->limit;
10738                                 root_offset += sizeof(struct ext2_dx_entry);
10739                                 c1--;
10740                         }
10741                         dx_ent->block = ext2fs_cpu_to_le32(i);
10742                         if (c2 != limit->limit)
10743                                 dx_ent->hash =
10744                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10745                         dx_ent++;
10746                         c2--;
10747                 }
10748                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10749                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10750         }
10751         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10752         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10753         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10754
10755         return 0;
10756 }
10757
10758 struct write_dir_struct {
10759         struct out_dir *outdir;
10760         errcode_t       err;
10761         e2fsck_t        ctx;
10762         int             cleared;
10763 };
10764
10765 /*
10766  * Helper function which writes out a directory block.
10767  */
10768 static int write_dir_block(ext2_filsys fs,
10769                            blk_t        *block_nr,
10770                            e2_blkcnt_t blockcnt,
10771                            blk_t ref_block FSCK_ATTR((unused)),
10772                            int ref_offset FSCK_ATTR((unused)),
10773                            void *priv_data)
10774 {
10775         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10776         blk_t   blk;
10777         char    *dir;
10778
10779         if (*block_nr == 0)
10780                 return 0;
10781         if (blockcnt >= wd->outdir->num) {
10782                 e2fsck_read_bitmaps(wd->ctx);
10783                 blk = *block_nr;
10784                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10785                 ext2fs_block_alloc_stats(fs, blk, -1);
10786                 *block_nr = 0;
10787                 wd->cleared++;
10788                 return BLOCK_CHANGED;
10789         }
10790         if (blockcnt < 0)
10791                 return 0;
10792
10793         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10794         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10795         if (wd->err)
10796                 return BLOCK_ABORT;
10797         return 0;
10798 }
10799
10800 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10801                                  struct out_dir *outdir,
10802                                  ext2_ino_t ino, int compress)
10803 {
10804         struct write_dir_struct wd;
10805         errcode_t       retval;
10806         struct ext2_inode       inode;
10807
10808         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10809         if (retval)
10810                 return retval;
10811
10812         wd.outdir = outdir;
10813         wd.err = 0;
10814         wd.ctx = ctx;
10815         wd.cleared = 0;
10816
10817         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10818                                        write_dir_block, &wd);
10819         if (retval)
10820                 return retval;
10821         if (wd.err)
10822                 return wd.err;
10823
10824         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10825         if (compress)
10826                 inode.i_flags &= ~EXT2_INDEX_FL;
10827         else
10828                 inode.i_flags |= EXT2_INDEX_FL;
10829         inode.i_size = outdir->num * fs->blocksize;
10830         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10831         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10832
10833         return 0;
10834 }
10835
10836 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10837 {
10838         ext2_filsys             fs = ctx->fs;
10839         errcode_t               retval;
10840         struct ext2_inode       inode;
10841         char                    *dir_buf = 0;
10842         struct fill_dir_struct  fd;
10843         struct out_dir          outdir;
10844
10845         outdir.max = outdir.num = 0;
10846         outdir.buf = 0;
10847         outdir.hashes = 0;
10848         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10849
10850         retval = ENOMEM;
10851         fd.harray = 0;
10852         dir_buf = malloc(inode.i_size);
10853         if (!dir_buf)
10854                 goto errout;
10855
10856         fd.max_array = inode.i_size / 32;
10857         fd.num_array = 0;
10858         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
10859         if (!fd.harray)
10860                 goto errout;
10861
10862         fd.ctx = ctx;
10863         fd.buf = dir_buf;
10864         fd.inode = &inode;
10865         fd.err = 0;
10866         fd.dir_size = 0;
10867         fd.compress = 0;
10868         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10869             (inode.i_size / fs->blocksize) < 2)
10870                 fd.compress = 1;
10871         fd.parent = 0;
10872
10873         /* Read in the entire directory into memory */
10874         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10875                                        fill_dir_block, &fd);
10876         if (fd.err) {
10877                 retval = fd.err;
10878                 goto errout;
10879         }
10880
10881         /* Sort the list */
10882 resort:
10883         if (fd.compress)
10884                 qsort(fd.harray+2, fd.num_array-2,
10885                       sizeof(struct hash_entry), name_cmp);
10886         else
10887                 qsort(fd.harray, fd.num_array,
10888                       sizeof(struct hash_entry), hash_cmp);
10889
10890         /*
10891          * Look for duplicates
10892          */
10893         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10894                 goto resort;
10895
10896         if (ctx->options & E2F_OPT_NO) {
10897                 retval = 0;
10898                 goto errout;
10899         }
10900
10901         /*
10902          * Copy the directory entries.  In a htree directory these
10903          * will become the leaf nodes.
10904          */
10905         retval = copy_dir_entries(fs, &fd, &outdir);
10906         if (retval)
10907                 goto errout;
10908
10909         free(dir_buf); dir_buf = 0;
10910
10911         if (!fd.compress) {
10912                 /* Calculate the interior nodes */
10913                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10914                 if (retval)
10915                         goto errout;
10916         }
10917
10918         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10919
10920 errout:
10921         free(dir_buf);
10922         free(fd.harray);
10923
10924         free_out_dir(&outdir);
10925         return retval;
10926 }
10927
10928 void e2fsck_rehash_directories(e2fsck_t ctx)
10929 {
10930         struct problem_context  pctx;
10931         struct dir_info         *dir;
10932         ext2_u32_iterate        iter;
10933         ext2_ino_t              ino;
10934         errcode_t               retval;
10935         int                     i, cur, max, all_dirs, dir_index, first = 1;
10936
10937         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10938
10939         if (!ctx->dirs_to_hash && !all_dirs)
10940                 return;
10941
10942         e2fsck_get_lost_and_found(ctx, 0);
10943
10944         clear_problem_context(&pctx);
10945
10946         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10947         cur = 0;
10948         if (all_dirs) {
10949                 i = 0;
10950                 max = e2fsck_get_num_dirinfo(ctx);
10951         } else {
10952                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10953                                                        &iter);
10954                 if (retval) {
10955                         pctx.errcode = retval;
10956                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10957                         return;
10958                 }
10959                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10960         }
10961         while (1) {
10962                 if (all_dirs) {
10963                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10964                                 break;
10965                         ino = dir->ino;
10966                 } else {
10967                         if (!ext2fs_u32_list_iterate(iter, &ino))
10968                                 break;
10969                 }
10970                 if (ino == ctx->lost_and_found)
10971                         continue;
10972                 pctx.dir = ino;
10973                 if (first) {
10974                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10975                         first = 0;
10976                 }
10977                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10978                 if (pctx.errcode) {
10979                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10980                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10981                 }
10982                 if (ctx->progress && !ctx->progress_fd)
10983                         e2fsck_simple_progress(ctx, "Rebuilding directory",
10984                                100.0 * (float) (++cur) / (float) max, ino);
10985         }
10986         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10987         if (!all_dirs)
10988                 ext2fs_u32_list_iterate_end(iter);
10989
10990         ext2fs_u32_list_free(ctx->dirs_to_hash);
10991         ctx->dirs_to_hash = 0;
10992 }
10993
10994 /*
10995  * linux/fs/revoke.c
10996  *
10997  * Journal revoke routines for the generic filesystem journaling code;
10998  * part of the ext2fs journaling system.
10999  *
11000  * Revoke is the mechanism used to prevent old log records for deleted
11001  * metadata from being replayed on top of newer data using the same
11002  * blocks.  The revoke mechanism is used in two separate places:
11003  *
11004  * + Commit: during commit we write the entire list of the current
11005  *   transaction's revoked blocks to the journal
11006  *
11007  * + Recovery: during recovery we record the transaction ID of all
11008  *   revoked blocks.  If there are multiple revoke records in the log
11009  *   for a single block, only the last one counts, and if there is a log
11010  *   entry for a block beyond the last revoke, then that log entry still
11011  *   gets replayed.
11012  *
11013  * We can get interactions between revokes and new log data within a
11014  * single transaction:
11015  *
11016  * Block is revoked and then journaled:
11017  *   The desired end result is the journaling of the new block, so we
11018  *   cancel the revoke before the transaction commits.
11019  *
11020  * Block is journaled and then revoked:
11021  *   The revoke must take precedence over the write of the block, so we
11022  *   need either to cancel the journal entry or to write the revoke
11023  *   later in the log than the log block.  In this case, we choose the
11024  *   latter: journaling a block cancels any revoke record for that block
11025  *   in the current transaction, so any revoke for that block in the
11026  *   transaction must have happened after the block was journaled and so
11027  *   the revoke must take precedence.
11028  *
11029  * Block is revoked and then written as data:
11030  *   The data write is allowed to succeed, but the revoke is _not_
11031  *   cancelled.  We still need to prevent old log records from
11032  *   overwriting the new data.  We don't even need to clear the revoke
11033  *   bit here.
11034  *
11035  * Revoke information on buffers is a tri-state value:
11036  *
11037  * RevokeValid clear:   no cached revoke status, need to look it up
11038  * RevokeValid set, Revoked clear:
11039  *                      buffer has not been revoked, and cancel_revoke
11040  *                      need do nothing.
11041  * RevokeValid set, Revoked set:
11042  *                      buffer has been revoked.
11043  */
11044
11045 static kmem_cache_t *revoke_record_cache;
11046 static kmem_cache_t *revoke_table_cache;
11047
11048 /* Each revoke record represents one single revoked block.  During
11049    journal replay, this involves recording the transaction ID of the
11050    last transaction to revoke this block. */
11051
11052 struct jbd_revoke_record_s
11053 {
11054         struct list_head  hash;
11055         tid_t             sequence;     /* Used for recovery only */
11056         unsigned long     blocknr;
11057 };
11058
11059
11060 /* The revoke table is just a simple hash table of revoke records. */
11061 struct jbd_revoke_table_s
11062 {
11063         /* It is conceivable that we might want a larger hash table
11064          * for recovery.  Must be a power of two. */
11065         int               hash_size;
11066         int               hash_shift;
11067         struct list_head *hash_table;
11068 };
11069
11070
11071 /* Utility functions to maintain the revoke table */
11072
11073 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11074 static int hash(journal_t *journal, unsigned long block)
11075 {
11076         struct jbd_revoke_table_s *table = journal->j_revoke;
11077         int hash_shift = table->hash_shift;
11078
11079         return ((block << (hash_shift - 6)) ^
11080                 (block >> 13) ^
11081                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11082 }
11083
11084 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11085                               tid_t seq)
11086 {
11087         struct list_head *hash_list;
11088         struct jbd_revoke_record_s *record;
11089
11090         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11091         if (!record)
11092                 goto oom;
11093
11094         record->sequence = seq;
11095         record->blocknr = blocknr;
11096         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11097         list_add(&record->hash, hash_list);
11098         return 0;
11099
11100 oom:
11101         return -ENOMEM;
11102 }
11103
11104 /* Find a revoke record in the journal's hash table. */
11105
11106 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11107                                                       unsigned long blocknr)
11108 {
11109         struct list_head *hash_list;
11110         struct jbd_revoke_record_s *record;
11111
11112         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11113
11114         record = (struct jbd_revoke_record_s *) hash_list->next;
11115         while (&(record->hash) != hash_list) {
11116                 if (record->blocknr == blocknr)
11117                         return record;
11118                 record = (struct jbd_revoke_record_s *) record->hash.next;
11119         }
11120         return NULL;
11121 }
11122
11123 int journal_init_revoke_caches(void)
11124 {
11125         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11126         if (revoke_record_cache == 0)
11127                 return -ENOMEM;
11128
11129         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11130         if (revoke_table_cache == 0) {
11131                 do_cache_destroy(revoke_record_cache);
11132                 revoke_record_cache = NULL;
11133                 return -ENOMEM;
11134         }
11135         return 0;
11136 }
11137
11138 void journal_destroy_revoke_caches(void)
11139 {
11140         do_cache_destroy(revoke_record_cache);
11141         revoke_record_cache = 0;
11142         do_cache_destroy(revoke_table_cache);
11143         revoke_table_cache = 0;
11144 }
11145
11146 /* Initialise the revoke table for a given journal to a given size. */
11147
11148 int journal_init_revoke(journal_t *journal, int hash_size)
11149 {
11150         int shift, tmp;
11151
11152         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11153         if (!journal->j_revoke)
11154                 return -ENOMEM;
11155
11156         /* Check that the hash_size is a power of two */
11157         journal->j_revoke->hash_size = hash_size;
11158
11159         shift = 0;
11160         tmp = hash_size;
11161         while((tmp >>= 1UL) != 0UL)
11162                 shift++;
11163         journal->j_revoke->hash_shift = shift;
11164
11165         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
11166         if (!journal->j_revoke->hash_table) {
11167                 free(journal->j_revoke);
11168                 journal->j_revoke = NULL;
11169                 return -ENOMEM;
11170         }
11171
11172         for (tmp = 0; tmp < hash_size; tmp++)
11173                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11174
11175         return 0;
11176 }
11177
11178 /* Destoy a journal's revoke table.  The table must already be empty! */
11179
11180 void journal_destroy_revoke(journal_t *journal)
11181 {
11182         struct jbd_revoke_table_s *table;
11183         struct list_head *hash_list;
11184         int i;
11185
11186         table = journal->j_revoke;
11187         if (!table)
11188                 return;
11189
11190         for (i=0; i<table->hash_size; i++) {
11191                 hash_list = &table->hash_table[i];
11192         }
11193
11194         free(table->hash_table);
11195         free(table);
11196         journal->j_revoke = NULL;
11197 }
11198
11199 /*
11200  * Revoke support for recovery.
11201  *
11202  * Recovery needs to be able to:
11203  *
11204  *  record all revoke records, including the tid of the latest instance
11205  *  of each revoke in the journal
11206  *
11207  *  check whether a given block in a given transaction should be replayed
11208  *  (ie. has not been revoked by a revoke record in that or a subsequent
11209  *  transaction)
11210  *
11211  *  empty the revoke table after recovery.
11212  */
11213
11214 /*
11215  * First, setting revoke records.  We create a new revoke record for
11216  * every block ever revoked in the log as we scan it for recovery, and
11217  * we update the existing records if we find multiple revokes for a
11218  * single block.
11219  */
11220
11221 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11222                        tid_t sequence)
11223 {
11224         struct jbd_revoke_record_s *record;
11225
11226         record = find_revoke_record(journal, blocknr);
11227         if (record) {
11228                 /* If we have multiple occurences, only record the
11229                  * latest sequence number in the hashed record */
11230                 if (tid_gt(sequence, record->sequence))
11231                         record->sequence = sequence;
11232                 return 0;
11233         }
11234         return insert_revoke_hash(journal, blocknr, sequence);
11235 }
11236
11237 /*
11238  * Test revoke records.  For a given block referenced in the log, has
11239  * that block been revoked?  A revoke record with a given transaction
11240  * sequence number revokes all blocks in that transaction and earlier
11241  * ones, but later transactions still need replayed.
11242  */
11243
11244 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11245                         tid_t sequence)
11246 {
11247         struct jbd_revoke_record_s *record;
11248
11249         record = find_revoke_record(journal, blocknr);
11250         if (!record)
11251                 return 0;
11252         if (tid_gt(sequence, record->sequence))
11253                 return 0;
11254         return 1;
11255 }
11256
11257 /*
11258  * Finally, once recovery is over, we need to clear the revoke table so
11259  * that it can be reused by the running filesystem.
11260  */
11261
11262 void journal_clear_revoke(journal_t *journal)
11263 {
11264         int i;
11265         struct list_head *hash_list;
11266         struct jbd_revoke_record_s *record;
11267         struct jbd_revoke_table_s *revoke_var;
11268
11269         revoke_var = journal->j_revoke;
11270
11271         for (i = 0; i < revoke_var->hash_size; i++) {
11272                 hash_list = &revoke_var->hash_table[i];
11273                 while (!list_empty(hash_list)) {
11274                         record = (struct jbd_revoke_record_s*) hash_list->next;
11275                         list_del(&record->hash);
11276                         free(record);
11277                 }
11278         }
11279 }
11280
11281 /*
11282  * e2fsck.c - superblock checks
11283  */
11284
11285 #define MIN_CHECK 1
11286 #define MAX_CHECK 2
11287
11288 static void check_super_value(e2fsck_t ctx, const char *descr,
11289                               unsigned long value, int flags,
11290                               unsigned long min_val, unsigned long max_val)
11291 {
11292         struct          problem_context pctx;
11293
11294         if (((flags & MIN_CHECK) && (value < min_val)) ||
11295             ((flags & MAX_CHECK) && (value > max_val))) {
11296                 clear_problem_context(&pctx);
11297                 pctx.num = value;
11298                 pctx.str = descr;
11299                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11300                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11301         }
11302 }
11303
11304 /*
11305  * This routine may get stubbed out in special compilations of the
11306  * e2fsck code..
11307  */
11308 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11309 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11310 {
11311         return (ext2fs_get_device_size(ctx->filesystem_name,
11312                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11313                                        &ctx->num_blocks));
11314 }
11315 #endif
11316
11317 /*
11318  * helper function to release an inode
11319  */
11320 struct process_block_struct {
11321         e2fsck_t        ctx;
11322         char            *buf;
11323         struct problem_context *pctx;
11324         int             truncating;
11325         int             truncate_offset;
11326         e2_blkcnt_t     truncate_block;
11327         int             truncated_blocks;
11328         int             abort;
11329         errcode_t       errcode;
11330 };
11331
11332 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11333                                e2_blkcnt_t blockcnt,
11334                                blk_t    ref_blk FSCK_ATTR((unused)),
11335                                int      ref_offset FSCK_ATTR((unused)),
11336                                void *priv_data)
11337 {
11338         struct process_block_struct *pb;
11339         e2fsck_t                ctx;
11340         struct problem_context  *pctx;
11341         blk_t                   blk = *block_nr;
11342         int                     retval = 0;
11343
11344         pb = (struct process_block_struct *) priv_data;
11345         ctx = pb->ctx;
11346         pctx = pb->pctx;
11347
11348         pctx->blk = blk;
11349         pctx->blkcount = blockcnt;
11350
11351         if (HOLE_BLKADDR(blk))
11352                 return 0;
11353
11354         if ((blk < fs->super->s_first_data_block) ||
11355             (blk >= fs->super->s_blocks_count)) {
11356                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11357         return_abort:
11358                 pb->abort = 1;
11359                 return BLOCK_ABORT;
11360         }
11361
11362         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11363                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11364                 goto return_abort;
11365         }
11366
11367         /*
11368          * If we are deleting an orphan, then we leave the fields alone.
11369          * If we are truncating an orphan, then update the inode fields
11370          * and clean up any partial block data.
11371          */
11372         if (pb->truncating) {
11373                 /*
11374                  * We only remove indirect blocks if they are
11375                  * completely empty.
11376                  */
11377                 if (blockcnt < 0) {
11378                         int     i, limit;
11379                         blk_t   *bp;
11380
11381                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11382                                                         pb->buf);
11383                         if (pb->errcode)
11384                                 goto return_abort;
11385
11386                         limit = fs->blocksize >> 2;
11387                         for (i = 0, bp = (blk_t *) pb->buf;
11388                              i < limit;  i++, bp++)
11389                                 if (*bp)
11390                                         return 0;
11391                 }
11392                 /*
11393                  * We don't remove direct blocks until we've reached
11394                  * the truncation block.
11395                  */
11396                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11397                         return 0;
11398                 /*
11399                  * If part of the last block needs truncating, we do
11400                  * it here.
11401                  */
11402                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11403                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11404                                                         pb->buf);
11405                         if (pb->errcode)
11406                                 goto return_abort;
11407                         memset(pb->buf + pb->truncate_offset, 0,
11408                                fs->blocksize - pb->truncate_offset);
11409                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11410                                                          pb->buf);
11411                         if (pb->errcode)
11412                                 goto return_abort;
11413                 }
11414                 pb->truncated_blocks++;
11415                 *block_nr = 0;
11416                 retval |= BLOCK_CHANGED;
11417         }
11418
11419         ext2fs_block_alloc_stats(fs, blk, -1);
11420         return retval;
11421 }
11422
11423 /*
11424  * This function releases an inode.  Returns 1 if an inconsistency was
11425  * found.  If the inode has a link count, then it is being truncated and
11426  * not deleted.
11427  */
11428 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11429                                 struct ext2_inode *inode, char *block_buf,
11430                                 struct problem_context *pctx)
11431 {
11432         struct process_block_struct     pb;
11433         ext2_filsys                     fs = ctx->fs;
11434         errcode_t                       retval;
11435         __u32                           count;
11436
11437         if (!ext2fs_inode_has_valid_blocks(inode))
11438                 return 0;
11439
11440         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11441         pb.ctx = ctx;
11442         pb.abort = 0;
11443         pb.errcode = 0;
11444         pb.pctx = pctx;
11445         if (inode->i_links_count) {
11446                 pb.truncating = 1;
11447                 pb.truncate_block = (e2_blkcnt_t)
11448                         ((((long long)inode->i_size_high << 32) +
11449                           inode->i_size + fs->blocksize - 1) /
11450                          fs->blocksize);
11451                 pb.truncate_offset = inode->i_size % fs->blocksize;
11452         } else {
11453                 pb.truncating = 0;
11454                 pb.truncate_block = 0;
11455                 pb.truncate_offset = 0;
11456         }
11457         pb.truncated_blocks = 0;
11458         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11459                                       block_buf, release_inode_block, &pb);
11460         if (retval) {
11461                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11462                         ino);
11463                 return 1;
11464         }
11465         if (pb.abort)
11466                 return 1;
11467
11468         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11469         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11470
11471         if (pb.truncated_blocks)
11472                 inode->i_blocks -= pb.truncated_blocks *
11473                         (fs->blocksize / 512);
11474
11475         if (inode->i_file_acl) {
11476                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11477                                                    block_buf, -1, &count);
11478                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11479                         retval = 0;
11480                         count = 1;
11481                 }
11482                 if (retval) {
11483                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11484                                 ino);
11485                         return 1;
11486                 }
11487                 if (count == 0)
11488                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11489                 inode->i_file_acl = 0;
11490         }
11491         return 0;
11492 }
11493
11494 /*
11495  * This function releases all of the orphan inodes.  It returns 1 if
11496  * it hit some error, and 0 on success.
11497  */
11498 static int release_orphan_inodes(e2fsck_t ctx)
11499 {
11500         ext2_filsys fs = ctx->fs;
11501         ext2_ino_t      ino, next_ino;
11502         struct ext2_inode inode;
11503         struct problem_context pctx;
11504         char *block_buf;
11505
11506         if ((ino = fs->super->s_last_orphan) == 0)
11507                 return 0;
11508
11509         /*
11510          * Win or lose, we won't be using the head of the orphan inode
11511          * list again.
11512          */
11513         fs->super->s_last_orphan = 0;
11514         ext2fs_mark_super_dirty(fs);
11515
11516         /*
11517          * If the filesystem contains errors, don't run the orphan
11518          * list, since the orphan list can't be trusted; and we're
11519          * going to be running a full e2fsck run anyway...
11520          */
11521         if (fs->super->s_state & EXT2_ERROR_FS)
11522                 return 0;
11523
11524         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11525             (ino > fs->super->s_inodes_count)) {
11526                 clear_problem_context(&pctx);
11527                 pctx.ino = ino;
11528                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11529                 return 1;
11530         }
11531
11532         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11533                                                     "block iterate buffer");
11534         e2fsck_read_bitmaps(ctx);
11535
11536         while (ino) {
11537                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11538                 clear_problem_context(&pctx);
11539                 pctx.ino = ino;
11540                 pctx.inode = &inode;
11541                 pctx.str = inode.i_links_count ? _("Truncating") :
11542                         _("Clearing");
11543
11544                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11545
11546                 next_ino = inode.i_dtime;
11547                 if (next_ino &&
11548                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11549                      (next_ino > fs->super->s_inodes_count))) {
11550                         pctx.ino = next_ino;
11551                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11552                         goto return_abort;
11553                 }
11554
11555                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11556                         goto return_abort;
11557
11558                 if (!inode.i_links_count) {
11559                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11560                                                   LINUX_S_ISDIR(inode.i_mode));
11561                         inode.i_dtime = time(0);
11562                 } else {
11563                         inode.i_dtime = 0;
11564                 }
11565                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11566                 ino = next_ino;
11567         }
11568         ext2fs_free_mem(&block_buf);
11569         return 0;
11570 return_abort:
11571         ext2fs_free_mem(&block_buf);
11572         return 1;
11573 }
11574
11575 /*
11576  * Check the resize inode to make sure it is sane.  We check both for
11577  * the case where on-line resizing is not enabled (in which case the
11578  * resize inode should be cleared) as well as the case where on-line
11579  * resizing is enabled.
11580  */
11581 static void check_resize_inode(e2fsck_t ctx)
11582 {
11583         ext2_filsys fs = ctx->fs;
11584         struct ext2_inode inode;
11585         struct problem_context  pctx;
11586         int             i, j, gdt_off, ind_off;
11587         blk_t           blk, pblk, expect;
11588         __u32           *dind_buf = 0, *ind_buf;
11589         errcode_t       retval;
11590
11591         clear_problem_context(&pctx);
11592
11593         /*
11594          * If the resize inode feature isn't set, then
11595          * s_reserved_gdt_blocks must be zero.
11596          */
11597         if (!(fs->super->s_feature_compat &
11598               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11599                 if (fs->super->s_reserved_gdt_blocks) {
11600                         pctx.num = fs->super->s_reserved_gdt_blocks;
11601                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11602                                         &pctx)) {
11603                                 fs->super->s_reserved_gdt_blocks = 0;
11604                                 ext2fs_mark_super_dirty(fs);
11605                         }
11606                 }
11607         }
11608
11609         /* Read the resize inode */
11610         pctx.ino = EXT2_RESIZE_INO;
11611         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11612         if (retval) {
11613                 if (fs->super->s_feature_compat &
11614                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11615                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11616                 return;
11617         }
11618
11619         /*
11620          * If the resize inode feature isn't set, check to make sure
11621          * the resize inode is cleared; then we're done.
11622          */
11623         if (!(fs->super->s_feature_compat &
11624               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11625                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11626                         if (inode.i_block[i])
11627                                 break;
11628                 }
11629                 if ((i < EXT2_N_BLOCKS) &&
11630                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11631                         memset(&inode, 0, sizeof(inode));
11632                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11633                                            "clear_resize");
11634                 }
11635                 return;
11636         }
11637
11638         /*
11639          * The resize inode feature is enabled; check to make sure the
11640          * only block in use is the double indirect block
11641          */
11642         blk = inode.i_block[EXT2_DIND_BLOCK];
11643         for (i=0; i < EXT2_N_BLOCKS; i++) {
11644                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11645                         break;
11646         }
11647         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11648             !(inode.i_mode & LINUX_S_IFREG) ||
11649             (blk < fs->super->s_first_data_block ||
11650              blk >= fs->super->s_blocks_count)) {
11651         resize_inode_invalid:
11652                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11653                         memset(&inode, 0, sizeof(inode));
11654                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11655                                            "clear_resize");
11656                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11657                 }
11658                 if (!(ctx->options & E2F_OPT_READONLY)) {
11659                         fs->super->s_state &= ~EXT2_VALID_FS;
11660                         ext2fs_mark_super_dirty(fs);
11661                 }
11662                 goto cleanup;
11663         }
11664         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11665                                                     "resize dind buffer");
11666         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11667
11668         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11669         if (retval)
11670                 goto resize_inode_invalid;
11671
11672         gdt_off = fs->desc_blocks;
11673         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11674         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11675              i++, gdt_off++, pblk++) {
11676                 gdt_off %= fs->blocksize/4;
11677                 if (dind_buf[gdt_off] != pblk)
11678                         goto resize_inode_invalid;
11679                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11680                 if (retval)
11681                         goto resize_inode_invalid;
11682                 ind_off = 0;
11683                 for (j = 1; j < fs->group_desc_count; j++) {
11684                         if (!ext2fs_bg_has_super(fs, j))
11685                                 continue;
11686                         expect = pblk + (j * fs->super->s_blocks_per_group);
11687                         if (ind_buf[ind_off] != expect)
11688                                 goto resize_inode_invalid;
11689                         ind_off++;
11690                 }
11691         }
11692
11693 cleanup:
11694         ext2fs_free_mem(&dind_buf);
11695
11696  }
11697
11698 static void check_super_block(e2fsck_t ctx)
11699 {
11700         ext2_filsys fs = ctx->fs;
11701         blk_t   first_block, last_block;
11702         struct ext2_super_block *sb = fs->super;
11703         struct ext2_group_desc *gd;
11704         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11705         blk_t   bpg_max;
11706         int     inodes_per_block;
11707         int     ipg_max;
11708         int     inode_size;
11709         dgrp_t  i;
11710         blk_t   should_be;
11711         struct problem_context  pctx;
11712         __u32   free_blocks = 0, free_inodes = 0;
11713
11714         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11715         ipg_max = inodes_per_block * (blocks_per_group - 4);
11716         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11717                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11718         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11719         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11720                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11721
11722         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11723                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11724         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11725                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11726         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11727                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11728
11729         clear_problem_context(&pctx);
11730
11731         /*
11732          * Verify the super block constants...
11733          */
11734         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11735                           MIN_CHECK, 1, 0);
11736         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11737                           MIN_CHECK, 1, 0);
11738         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11739                           MAX_CHECK, 0, sb->s_blocks_count);
11740         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11741                           MIN_CHECK | MAX_CHECK, 0,
11742                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11743         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11744                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11745         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11746                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11747                           bpg_max);
11748         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11749                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11750         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11751                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11752         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11753                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11754         check_super_value(ctx, "reserved_gdt_blocks",
11755                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11756                           fs->blocksize/4);
11757         inode_size = EXT2_INODE_SIZE(sb);
11758         check_super_value(ctx, "inode_size",
11759                           inode_size, MIN_CHECK | MAX_CHECK,
11760                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11761         if (inode_size & (inode_size - 1)) {
11762                 pctx.num = inode_size;
11763                 pctx.str = "inode_size";
11764                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11765                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11766                 return;
11767         }
11768
11769         if (!ctx->num_blocks) {
11770                 pctx.errcode = e2fsck_get_device_size(ctx);
11771                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11772                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11773                         ctx->flags |= E2F_FLAG_ABORT;
11774                         return;
11775                 }
11776                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11777                     (ctx->num_blocks < sb->s_blocks_count)) {
11778                         pctx.blk = sb->s_blocks_count;
11779                         pctx.blk2 = ctx->num_blocks;
11780                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11781                                 ctx->flags |= E2F_FLAG_ABORT;
11782                                 return;
11783                         }
11784                 }
11785         }
11786
11787         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11788                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11789                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11790                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11791                 ctx->flags |= E2F_FLAG_ABORT;
11792                 return;
11793         }
11794
11795         should_be = sb->s_frags_per_group >>
11796                 (sb->s_log_block_size - sb->s_log_frag_size);
11797         if (sb->s_blocks_per_group != should_be) {
11798                 pctx.blk = sb->s_blocks_per_group;
11799                 pctx.blk2 = should_be;
11800                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11801                 ctx->flags |= E2F_FLAG_ABORT;
11802                 return;
11803         }
11804
11805         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11806         if (sb->s_first_data_block != should_be) {
11807                 pctx.blk = sb->s_first_data_block;
11808                 pctx.blk2 = should_be;
11809                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11810                 ctx->flags |= E2F_FLAG_ABORT;
11811                 return;
11812         }
11813
11814         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11815         if (sb->s_inodes_count != should_be) {
11816                 pctx.ino = sb->s_inodes_count;
11817                 pctx.ino2 = should_be;
11818                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11819                         sb->s_inodes_count = should_be;
11820                         ext2fs_mark_super_dirty(fs);
11821                 }
11822         }
11823
11824         /*
11825          * Verify the group descriptors....
11826          */
11827         first_block =  sb->s_first_data_block;
11828         last_block = first_block + blocks_per_group;
11829
11830         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11831                 pctx.group = i;
11832
11833                 if (i == fs->group_desc_count - 1)
11834                         last_block = sb->s_blocks_count;
11835                 if ((gd->bg_block_bitmap < first_block) ||
11836                     (gd->bg_block_bitmap >= last_block)) {
11837                         pctx.blk = gd->bg_block_bitmap;
11838                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11839                                 gd->bg_block_bitmap = 0;
11840                 }
11841                 if (gd->bg_block_bitmap == 0) {
11842                         ctx->invalid_block_bitmap_flag[i]++;
11843                         ctx->invalid_bitmaps++;
11844                 }
11845                 if ((gd->bg_inode_bitmap < first_block) ||
11846                     (gd->bg_inode_bitmap >= last_block)) {
11847                         pctx.blk = gd->bg_inode_bitmap;
11848                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11849                                 gd->bg_inode_bitmap = 0;
11850                 }
11851                 if (gd->bg_inode_bitmap == 0) {
11852                         ctx->invalid_inode_bitmap_flag[i]++;
11853                         ctx->invalid_bitmaps++;
11854                 }
11855                 if ((gd->bg_inode_table < first_block) ||
11856                     ((gd->bg_inode_table +
11857                       fs->inode_blocks_per_group - 1) >= last_block)) {
11858                         pctx.blk = gd->bg_inode_table;
11859                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11860                                 gd->bg_inode_table = 0;
11861                 }
11862                 if (gd->bg_inode_table == 0) {
11863                         ctx->invalid_inode_table_flag[i]++;
11864                         ctx->invalid_bitmaps++;
11865                 }
11866                 free_blocks += gd->bg_free_blocks_count;
11867                 free_inodes += gd->bg_free_inodes_count;
11868                 first_block += sb->s_blocks_per_group;
11869                 last_block += sb->s_blocks_per_group;
11870
11871                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11872                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11873                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11874                         ext2fs_unmark_valid(fs);
11875
11876         }
11877
11878         /*
11879          * Update the global counts from the block group counts.  This
11880          * is needed for an experimental patch which eliminates
11881          * locking the entire filesystem when allocating blocks or
11882          * inodes; if the filesystem is not unmounted cleanly, the
11883          * global counts may not be accurate.
11884          */
11885         if ((free_blocks != sb->s_free_blocks_count) ||
11886             (free_inodes != sb->s_free_inodes_count)) {
11887                 if (ctx->options & E2F_OPT_READONLY)
11888                         ext2fs_unmark_valid(fs);
11889                 else {
11890                         sb->s_free_blocks_count = free_blocks;
11891                         sb->s_free_inodes_count = free_inodes;
11892                         ext2fs_mark_super_dirty(fs);
11893                 }
11894         }
11895
11896         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11897             (sb->s_free_inodes_count > sb->s_inodes_count))
11898                 ext2fs_unmark_valid(fs);
11899
11900
11901         /*
11902          * If we have invalid bitmaps, set the error state of the
11903          * filesystem.
11904          */
11905         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11906                 sb->s_state &= ~EXT2_VALID_FS;
11907                 ext2fs_mark_super_dirty(fs);
11908         }
11909
11910         clear_problem_context(&pctx);
11911
11912         /*
11913          * If the UUID field isn't assigned, assign it.
11914          */
11915         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11916                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11917                         uuid_generate(sb->s_uuid);
11918                         ext2fs_mark_super_dirty(fs);
11919                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11920                 }
11921         }
11922
11923         /* FIXME - HURD support?
11924          * For the Hurd, check to see if the filetype option is set,
11925          * since it doesn't support it.
11926          */
11927         if (!(ctx->options & E2F_OPT_READONLY) &&
11928             fs->super->s_creator_os == EXT2_OS_HURD &&
11929             (fs->super->s_feature_incompat &
11930              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11931                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11932                         fs->super->s_feature_incompat &=
11933                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11934                         ext2fs_mark_super_dirty(fs);
11935
11936                 }
11937         }
11938
11939         /*
11940          * If we have any of the compatibility flags set, we need to have a
11941          * revision 1 filesystem.  Most kernels will not check the flags on
11942          * a rev 0 filesystem and we may have corruption issues because of
11943          * the incompatible changes to the filesystem.
11944          */
11945         if (!(ctx->options & E2F_OPT_READONLY) &&
11946             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11947             (fs->super->s_feature_compat ||
11948              fs->super->s_feature_ro_compat ||
11949              fs->super->s_feature_incompat) &&
11950             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11951                 ext2fs_update_dynamic_rev(fs);
11952                 ext2fs_mark_super_dirty(fs);
11953         }
11954
11955         check_resize_inode(ctx);
11956
11957         /*
11958          * Clean up any orphan inodes, if present.
11959          */
11960         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11961                 fs->super->s_state &= ~EXT2_VALID_FS;
11962                 ext2fs_mark_super_dirty(fs);
11963         }
11964
11965         /*
11966          * Move the ext3 journal file, if necessary.
11967          */
11968         e2fsck_move_ext3_journal(ctx);
11969 }
11970
11971 /*
11972  * swapfs.c --- byte-swap an ext2 filesystem
11973  */
11974
11975 #ifdef ENABLE_SWAPFS
11976
11977 struct swap_block_struct {
11978         ext2_ino_t      ino;
11979         int             isdir;
11980         errcode_t       errcode;
11981         char            *dir_buf;
11982         struct ext2_inode *inode;
11983 };
11984
11985 /*
11986  * This is a helper function for block_iterate.  We mark all of the
11987  * indirect and direct blocks as changed, so that block_iterate will
11988  * write them out.
11989  */
11990 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11991                       void *priv_data)
11992 {
11993         errcode_t       retval;
11994
11995         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11996
11997         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11998                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11999                 if (retval) {
12000                         sb->errcode = retval;
12001                         return BLOCK_ABORT;
12002                 }
12003                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
12004                 if (retval) {
12005                         sb->errcode = retval;
12006                         return BLOCK_ABORT;
12007                 }
12008         }
12009         if (blockcnt >= 0) {
12010                 if (blockcnt < EXT2_NDIR_BLOCKS)
12011                         return 0;
12012                 return BLOCK_CHANGED;
12013         }
12014         if (blockcnt == BLOCK_COUNT_IND) {
12015                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
12016                         return 0;
12017                 return BLOCK_CHANGED;
12018         }
12019         if (blockcnt == BLOCK_COUNT_DIND) {
12020                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12021                         return 0;
12022                 return BLOCK_CHANGED;
12023         }
12024         if (blockcnt == BLOCK_COUNT_TIND) {
12025                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12026                         return 0;
12027                 return BLOCK_CHANGED;
12028         }
12029         return BLOCK_CHANGED;
12030 }
12031
12032 /*
12033  * This function is responsible for byte-swapping all of the indirect,
12034  * block pointers.  It is also responsible for byte-swapping directories.
12035  */
12036 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12037                               struct ext2_inode *inode)
12038 {
12039         errcode_t                       retval;
12040         struct swap_block_struct        sb;
12041
12042         sb.ino = ino;
12043         sb.inode = inode;
12044         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12045         sb.errcode = 0;
12046         sb.isdir = 0;
12047         if (LINUX_S_ISDIR(inode->i_mode))
12048                 sb.isdir = 1;
12049
12050         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12051                                       swap_block, &sb);
12052         if (retval) {
12053                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12054                 ctx->flags |= E2F_FLAG_ABORT;
12055                 return;
12056         }
12057         if (sb.errcode) {
12058                 bb_error_msg(_("while calling iterator function"));
12059                 ctx->flags |= E2F_FLAG_ABORT;
12060                 return;
12061         }
12062 }
12063
12064 static void swap_inodes(e2fsck_t ctx)
12065 {
12066         ext2_filsys fs = ctx->fs;
12067         dgrp_t                  group;
12068         unsigned int            i;
12069         ext2_ino_t              ino = 1;
12070         char                    *buf, *block_buf;
12071         errcode_t               retval;
12072         struct ext2_inode *     inode;
12073
12074         e2fsck_use_inode_shortcuts(ctx, 1);
12075
12076         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12077                                 &buf);
12078         if (retval) {
12079                 bb_error_msg(_("while allocating inode buffer"));
12080                 ctx->flags |= E2F_FLAG_ABORT;
12081                 return;
12082         }
12083         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12084                                                     "block interate buffer");
12085         for (group = 0; group < fs->group_desc_count; group++) {
12086                 retval = io_channel_read_blk(fs->io,
12087                       fs->group_desc[group].bg_inode_table,
12088                       fs->inode_blocks_per_group, buf);
12089                 if (retval) {
12090                         bb_error_msg(_("while reading inode table (group %d)"),
12091                                 group);
12092                         ctx->flags |= E2F_FLAG_ABORT;
12093                         return;
12094                 }
12095                 inode = (struct ext2_inode *) buf;
12096                 for (i=0; i < fs->super->s_inodes_per_group;
12097                      i++, ino++, inode++) {
12098                         ctx->stashed_ino = ino;
12099                         ctx->stashed_inode = inode;
12100
12101                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12102                                 ext2fs_swap_inode(fs, inode, inode, 0);
12103
12104                         /*
12105                          * Skip deleted files.
12106                          */
12107                         if (inode->i_links_count == 0)
12108                                 continue;
12109
12110                         if (LINUX_S_ISDIR(inode->i_mode) ||
12111                             ((inode->i_block[EXT2_IND_BLOCK] ||
12112                               inode->i_block[EXT2_DIND_BLOCK] ||
12113                               inode->i_block[EXT2_TIND_BLOCK]) &&
12114                              ext2fs_inode_has_valid_blocks(inode)))
12115                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12116
12117                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12118                                 return;
12119
12120                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12121                                 ext2fs_swap_inode(fs, inode, inode, 1);
12122                 }
12123                 retval = io_channel_write_blk(fs->io,
12124                       fs->group_desc[group].bg_inode_table,
12125                       fs->inode_blocks_per_group, buf);
12126                 if (retval) {
12127                         bb_error_msg(_("while writing inode table (group %d)"),
12128                                 group);
12129                         ctx->flags |= E2F_FLAG_ABORT;
12130                         return;
12131                 }
12132         }
12133         ext2fs_free_mem(&buf);
12134         ext2fs_free_mem(&block_buf);
12135         e2fsck_use_inode_shortcuts(ctx, 0);
12136         ext2fs_flush_icache(fs);
12137 }
12138
12139 #if defined(__powerpc__) && BB_BIG_ENDIAN
12140 /*
12141  * On the PowerPC, the big-endian variant of the ext2 filesystem
12142  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12143  * of each word.  Thus a bitmap with only bit 0 set would be, as
12144  * a string of bytes, 00 00 00 01 00 ...
12145  * To cope with this, we byte-reverse each word of a bitmap if
12146  * we have a big-endian filesystem, that is, if we are *not*
12147  * byte-swapping other word-sized numbers.
12148  */
12149 #define EXT2_BIG_ENDIAN_BITMAPS
12150 #endif
12151
12152 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12153 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12154 {
12155         __u32 *p = (__u32 *) bmap->bitmap;
12156         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12157
12158         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12159                 *p = ext2fs_swab32(*p);
12160 }
12161 #endif
12162
12163
12164 #ifdef ENABLE_SWAPFS
12165 static void swap_filesys(e2fsck_t ctx)
12166 {
12167         ext2_filsys fs = ctx->fs;
12168         if (!(ctx->options & E2F_OPT_PREEN))
12169                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12170
12171         /* Byte swap */
12172
12173         if (fs->super->s_mnt_count) {
12174                 fprintf(stderr, _("%s: the filesystem must be freshly "
12175                         "checked using fsck\n"
12176                         "and not mounted before trying to "
12177                         "byte-swap it.\n"), ctx->device_name);
12178                 ctx->flags |= E2F_FLAG_ABORT;
12179                 return;
12180         }
12181         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12182                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12183                                EXT2_FLAG_SWAP_BYTES_WRITE);
12184                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12185         } else {
12186                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12187                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12188         }
12189         swap_inodes(ctx);
12190         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12191                 return;
12192         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12193                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12194         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12195                        EXT2_FLAG_SWAP_BYTES_WRITE);
12196
12197 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12198         e2fsck_read_bitmaps(ctx);
12199         ext2fs_swap_bitmap(fs->inode_map);
12200         ext2fs_swap_bitmap(fs->block_map);
12201         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12202 #endif
12203         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12204         ext2fs_flush(fs);
12205         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12206 }
12207 #endif  /* ENABLE_SWAPFS */
12208
12209 #endif
12210
12211 /*
12212  * util.c --- miscellaneous utilities
12213  */
12214
12215
12216 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12217                              const char *description)
12218 {
12219         void *ret;
12220         char buf[256];
12221
12222         ret = malloc(size);
12223         if (!ret) {
12224                 sprintf(buf, "Can't allocate %s\n", description);
12225                 bb_error_msg_and_die(buf);
12226         }
12227         memset(ret, 0, size);
12228         return ret;
12229 }
12230
12231 static char *string_copy(const char *str, int len)
12232 {
12233         char    *ret;
12234
12235         if (!str)
12236                 return NULL;
12237         if (!len)
12238                 len = strlen(str);
12239         ret = malloc(len+1);
12240         if (ret) {
12241                 strncpy(ret, str, len);
12242                 ret[len] = 0;
12243         }
12244         return ret;
12245 }
12246
12247 #ifndef HAVE_CONIO_H
12248 static int read_a_char(void)
12249 {
12250         char    c;
12251         int     r;
12252         int     fail = 0;
12253
12254         while(1) {
12255                 if (e2fsck_global_ctx &&
12256                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12257                         return 3;
12258                 }
12259                 r = read(0, &c, 1);
12260                 if (r == 1)
12261                         return c;
12262                 if (fail++ > 100)
12263                         break;
12264         }
12265         return EOF;
12266 }
12267 #endif
12268
12269 static int ask_yn(const char * string, int def)
12270 {
12271         int             c;
12272         const char      *defstr;
12273         static const char short_yes[] = "yY";
12274         static const char short_no[] = "nN";
12275
12276 #ifdef HAVE_TERMIOS_H
12277         struct termios  termios, tmp;
12278
12279         tcgetattr (0, &termios);
12280         tmp = termios;
12281         tmp.c_lflag &= ~(ICANON | ECHO);
12282         tmp.c_cc[VMIN] = 1;
12283         tmp.c_cc[VTIME] = 0;
12284         tcsetattr (0, TCSANOW, &tmp);
12285 #endif
12286
12287         if (def == 1)
12288                 defstr = "<y>";
12289         else if (def == 0)
12290                 defstr = "<n>";
12291         else
12292                 defstr = " (y/n)";
12293         printf("%s%s? ", string, defstr);
12294         while (1) {
12295                 fflush (stdout);
12296                 if ((c = read_a_char()) == EOF)
12297                         break;
12298                 if (c == 3) {
12299 #ifdef HAVE_TERMIOS_H
12300                         tcsetattr (0, TCSANOW, &termios);
12301 #endif
12302                         if (e2fsck_global_ctx &&
12303                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12304                                 puts("\n");
12305                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12306                         }
12307                         puts(_("cancelled!\n"));
12308                         return 0;
12309                 }
12310                 if (strchr(short_yes, (char) c)) {
12311                         def = 1;
12312                         break;
12313                 }
12314                 else if (strchr(short_no, (char) c)) {
12315                         def = 0;
12316                         break;
12317                 }
12318                 else if ((c == ' ' || c == '\n') && (def != -1))
12319                         break;
12320         }
12321         if (def)
12322                 puts("yes\n");
12323         else
12324                 puts ("no\n");
12325 #ifdef HAVE_TERMIOS_H
12326         tcsetattr (0, TCSANOW, &termios);
12327 #endif
12328         return def;
12329 }
12330
12331 int ask (e2fsck_t ctx, const char * string, int def)
12332 {
12333         if (ctx->options & E2F_OPT_NO) {
12334                 printf(_("%s? no\n\n"), string);
12335                 return 0;
12336         }
12337         if (ctx->options & E2F_OPT_YES) {
12338                 printf(_("%s? yes\n\n"), string);
12339                 return 1;
12340         }
12341         if (ctx->options & E2F_OPT_PREEN) {
12342                 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12343                 return def;
12344         }
12345         return ask_yn(string, def);
12346 }
12347
12348 void e2fsck_read_bitmaps(e2fsck_t ctx)
12349 {
12350         ext2_filsys fs = ctx->fs;
12351         errcode_t       retval;
12352
12353         if (ctx->invalid_bitmaps) {
12354                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12355                         ctx->device_name);
12356                 bb_error_msg_and_die(0);
12357         }
12358
12359         ehandler_operation(_("reading inode and block bitmaps"));
12360         retval = ext2fs_read_bitmaps(fs);
12361         ehandler_operation(0);
12362         if (retval) {
12363                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12364                         ctx->device_name);
12365                 bb_error_msg_and_die(0);
12366         }
12367 }
12368
12369 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12370 {
12371         ext2_filsys fs = ctx->fs;
12372         errcode_t       retval;
12373
12374         if (ext2fs_test_bb_dirty(fs)) {
12375                 ehandler_operation(_("writing block bitmaps"));
12376                 retval = ext2fs_write_block_bitmap(fs);
12377                 ehandler_operation(0);
12378                 if (retval) {
12379                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12380                                 ctx->device_name);
12381                         bb_error_msg_and_die(0);
12382                 }
12383         }
12384
12385         if (ext2fs_test_ib_dirty(fs)) {
12386                 ehandler_operation(_("writing inode bitmaps"));
12387                 retval = ext2fs_write_inode_bitmap(fs);
12388                 ehandler_operation(0);
12389                 if (retval) {
12390                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12391                                 ctx->device_name);
12392                         bb_error_msg_and_die(0);
12393                 }
12394         }
12395 }
12396
12397 void preenhalt(e2fsck_t ctx)
12398 {
12399         ext2_filsys fs = ctx->fs;
12400
12401         if (!(ctx->options & E2F_OPT_PREEN))
12402                 return;
12403         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12404                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12405                ctx->device_name);
12406         if (fs != NULL) {
12407                 fs->super->s_state |= EXT2_ERROR_FS;
12408                 ext2fs_mark_super_dirty(fs);
12409                 ext2fs_close(fs);
12410         }
12411         exit(EXIT_UNCORRECTED);
12412 }
12413
12414 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12415                               struct ext2_inode * inode, const char *proc)
12416 {
12417         int retval;
12418
12419         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12420         if (retval) {
12421                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12422                 bb_error_msg_and_die(0);
12423         }
12424 }
12425
12426 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12427                                struct ext2_inode * inode, int bufsize,
12428                                const char *proc)
12429 {
12430         int retval;
12431
12432         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12433         if (retval) {
12434                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12435                 bb_error_msg_and_die(0);
12436         }
12437 }
12438
12439 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12440                                struct ext2_inode * inode, const char *proc)
12441 {
12442         int retval;
12443
12444         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12445         if (retval) {
12446                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12447                 bb_error_msg_and_die(0);
12448         }
12449 }
12450
12451 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12452                    io_manager manager)
12453 {
12454         struct ext2_super_block *sb;
12455         io_channel              io = NULL;
12456         void                    *buf = NULL;
12457         int                     blocksize;
12458         blk_t                   superblock, ret_sb = 8193;
12459
12460         if (fs && fs->super) {
12461                 ret_sb = (fs->super->s_blocks_per_group +
12462                           fs->super->s_first_data_block);
12463                 if (ctx) {
12464                         ctx->superblock = ret_sb;
12465                         ctx->blocksize = fs->blocksize;
12466                 }
12467                 return ret_sb;
12468         }
12469
12470         if (ctx) {
12471                 if (ctx->blocksize) {
12472                         ret_sb = ctx->blocksize * 8;
12473                         if (ctx->blocksize == 1024)
12474                                 ret_sb++;
12475                         ctx->superblock = ret_sb;
12476                         return ret_sb;
12477                 }
12478                 ctx->superblock = ret_sb;
12479                 ctx->blocksize = 1024;
12480         }
12481
12482         if (!name || !manager)
12483                 goto cleanup;
12484
12485         if (manager->open(name, 0, &io) != 0)
12486                 goto cleanup;
12487
12488         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12489                 goto cleanup;
12490         sb = (struct ext2_super_block *) buf;
12491
12492         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12493              blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12494                 superblock = blocksize*8;
12495                 if (blocksize == 1024)
12496                         superblock++;
12497                 io_channel_set_blksize(io, blocksize);
12498                 if (io_channel_read_blk(io, superblock,
12499                                         -SUPERBLOCK_SIZE, buf))
12500                         continue;
12501 #if BB_BIG_ENDIAN
12502                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12503                         ext2fs_swap_super(sb);
12504 #endif
12505                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12506                         ret_sb = superblock;
12507                         if (ctx) {
12508                                 ctx->superblock = superblock;
12509                                 ctx->blocksize = blocksize;
12510                         }
12511                         break;
12512                 }
12513         }
12514
12515 cleanup:
12516         if (io)
12517                 io_channel_close(io);
12518         ext2fs_free_mem(&buf);
12519         return ret_sb;
12520 }
12521
12522
12523 /*
12524  * This function runs through the e2fsck passes and calls them all,
12525  * returning restart, abort, or cancel as necessary...
12526  */
12527 typedef void (*pass_t)(e2fsck_t ctx);
12528
12529 static const pass_t e2fsck_passes[] = {
12530         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12531         e2fsck_pass5, 0 };
12532
12533 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12534
12535 static int e2fsck_run(e2fsck_t ctx)
12536 {
12537         int     i;
12538         pass_t  e2fsck_pass;
12539
12540         if (setjmp(ctx->abort_loc)) {
12541                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12542                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12543         }
12544         ctx->flags |= E2F_FLAG_SETJMP_OK;
12545
12546         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12547                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12548                         break;
12549                 e2fsck_pass(ctx);
12550                 if (ctx->progress)
12551                         (void) (ctx->progress)(ctx, 0, 0, 0);
12552         }
12553         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12554
12555         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12556                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12557         return 0;
12558 }
12559
12560
12561 /*
12562  * unix.c - The unix-specific code for e2fsck
12563  */
12564
12565
12566 /* Command line options */
12567 static int swapfs;
12568 #ifdef ENABLE_SWAPFS
12569 static int normalize_swapfs;
12570 #endif
12571 static int cflag;               /* check disk */
12572 static int show_version_only;
12573 static int verbose;
12574
12575 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12576
12577 static void show_stats(e2fsck_t ctx)
12578 {
12579         ext2_filsys fs = ctx->fs;
12580         int inodes, inodes_used, blocks, blocks_used;
12581         int dir_links;
12582         int num_files, num_links;
12583         int frag_percent;
12584
12585         dir_links = 2 * ctx->fs_directory_count - 1;
12586         num_files = ctx->fs_total_count - dir_links;
12587         num_links = ctx->fs_links_count - dir_links;
12588         inodes = fs->super->s_inodes_count;
12589         inodes_used = (fs->super->s_inodes_count -
12590                        fs->super->s_free_inodes_count);
12591         blocks = fs->super->s_blocks_count;
12592         blocks_used = (fs->super->s_blocks_count -
12593                        fs->super->s_free_blocks_count);
12594
12595         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12596         frag_percent = (frag_percent + 5) / 10;
12597
12598         if (!verbose) {
12599                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12600                        ctx->device_name, inodes_used, inodes,
12601                        frag_percent / 10, frag_percent % 10,
12602                        blocks_used, blocks);
12603                 return;
12604         }
12605         printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12606                 100 * inodes_used / inodes);
12607         printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12608                 P_E2("", "s", ctx->fs_fragmented),
12609                 frag_percent / 10, frag_percent % 10);
12610         printf(_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12611                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12612         printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12613                 (int) ((long long) 100 * blocks_used / blocks));
12614         printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12615         printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12616         printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12617         printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12618         printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12619         printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12620         printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12621         printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12622         printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12623         printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12624         printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12625 }
12626
12627 static void check_mount(e2fsck_t ctx)
12628 {
12629         errcode_t       retval;
12630         int             cont;
12631
12632         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12633                                          &ctx->mount_flags);
12634         if (retval) {
12635                 bb_error_msg(_("while determining whether %s is mounted."),
12636                         ctx->filesystem_name);
12637                 return;
12638         }
12639
12640         /*
12641          * If the filesystem isn't mounted, or it's the root filesystem
12642          * and it's mounted read-only, then everything's fine.
12643          */
12644         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12645             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12646              (ctx->mount_flags & EXT2_MF_READONLY)))
12647                 return;
12648
12649         if (ctx->options & E2F_OPT_READONLY) {
12650                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12651                 return;
12652         }
12653
12654         printf(_("%s is mounted.  "), ctx->filesystem_name);
12655         if (!ctx->interactive)
12656                 bb_error_msg_and_die(_("Cannot continue, aborting."));
12657         printf(_("\n\n\007\007\007\007WARNING!!!  "
12658                "Running e2fsck on a mounted filesystem may cause\n"
12659                "SEVERE filesystem damage.\007\007\007\n\n"));
12660         cont = ask_yn(_("Do you really want to continue"), -1);
12661         if (!cont) {
12662                 printf(_("check aborted.\n"));
12663                 exit(0);
12664         }
12665 }
12666
12667 static int is_on_batt(void)
12668 {
12669         FILE    *f;
12670         DIR     *d;
12671         char    tmp[80], tmp2[80], fname[80];
12672         unsigned int    acflag;
12673         struct dirent*  de;
12674
12675         f = fopen("/proc/apm", "r");
12676         if (f) {
12677                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12678                         acflag = 1;
12679                 fclose(f);
12680                 return (acflag != 1);
12681         }
12682         d = opendir("/proc/acpi/ac_adapter");
12683         if (d) {
12684                 while ((de=readdir(d)) != NULL) {
12685                         if (!strncmp(".", de->d_name, 1))
12686                                 continue;
12687                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12688                                  de->d_name);
12689                         f = fopen(fname, "r");
12690                         if (!f)
12691                                 continue;
12692                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12693                                 tmp[0] = 0;
12694                         fclose(f);
12695                         if (strncmp(tmp, "off-line", 8) == 0) {
12696                                 closedir(d);
12697                                 return 1;
12698                         }
12699                 }
12700                 closedir(d);
12701         }
12702         return 0;
12703 }
12704
12705 /*
12706  * This routine checks to see if a filesystem can be skipped; if so,
12707  * it will exit with EXIT_OK.  Under some conditions it will print a
12708  * message explaining why a check is being forced.
12709  */
12710 static void check_if_skip(e2fsck_t ctx)
12711 {
12712         ext2_filsys fs = ctx->fs;
12713         const char *reason = NULL;
12714         unsigned int reason_arg = 0;
12715         long next_check;
12716         int batt = is_on_batt();
12717         time_t now = time(0);
12718
12719         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12720                 return;
12721
12722         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12723             !ext2fs_test_valid(fs))
12724                 reason = _(" contains a file system with errors");
12725         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12726                 reason = _(" was not cleanly unmounted");
12727         else if ((fs->super->s_max_mnt_count > 0) &&
12728                  (fs->super->s_mnt_count >=
12729                   (unsigned) fs->super->s_max_mnt_count)) {
12730                 reason = _(" has been mounted %u times without being checked");
12731                 reason_arg = fs->super->s_mnt_count;
12732                 if (batt && (fs->super->s_mnt_count <
12733                              (unsigned) fs->super->s_max_mnt_count*2))
12734                         reason = 0;
12735         } else if (fs->super->s_checkinterval &&
12736                    ((now - fs->super->s_lastcheck) >=
12737                     fs->super->s_checkinterval)) {
12738                 reason = _(" has gone %u days without being checked");
12739                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12740                 if (batt && ((now - fs->super->s_lastcheck) <
12741                              fs->super->s_checkinterval*2))
12742                         reason = 0;
12743         }
12744         if (reason) {
12745                 fputs(ctx->device_name, stdout);
12746                 printf(reason, reason_arg);
12747                 fputs(_(", check forced.\n"), stdout);
12748                 return;
12749         }
12750         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12751                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12752                fs->super->s_inodes_count,
12753                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12754                fs->super->s_blocks_count);
12755         next_check = 100000;
12756         if (fs->super->s_max_mnt_count > 0) {
12757                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12758                 if (next_check <= 0)
12759                         next_check = 1;
12760         }
12761         if (fs->super->s_checkinterval &&
12762             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12763                 next_check = 1;
12764         if (next_check <= 5) {
12765                 if (next_check == 1)
12766                         fputs(_(" (check after next mount)"), stdout);
12767                 else
12768                         printf(_(" (check in %ld mounts)"), next_check);
12769         }
12770         bb_putchar('\n');
12771         ext2fs_close(fs);
12772         ctx->fs = NULL;
12773         e2fsck_free_context(ctx);
12774         exit(EXIT_OK);
12775 }
12776
12777 /*
12778  * For completion notice
12779  */
12780 struct percent_tbl {
12781         int     max_pass;
12782         int     table[32];
12783 };
12784 static const struct percent_tbl e2fsck_tbl = {
12785         5, { 0, 70, 90, 92,  95, 100 }
12786 };
12787
12788 static char bar[128], spaces[128];
12789
12790 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12791                           int max)
12792 {
12793         float   percent;
12794
12795         if (pass <= 0)
12796                 return 0.0;
12797         if (pass > tbl->max_pass || max == 0)
12798                 return 100.0;
12799         percent = ((float) curr) / ((float) max);
12800         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12801                 + tbl->table[pass-1]);
12802 }
12803
12804 void e2fsck_clear_progbar(e2fsck_t ctx)
12805 {
12806         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12807                 return;
12808
12809         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12810                ctx->stop_meta);
12811         fflush(stdout);
12812         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12813 }
12814
12815 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12816                            unsigned int dpynum)
12817 {
12818         static const char spinner[] = "\\|/-";
12819         int     i;
12820         unsigned int    tick;
12821         struct timeval  tv;
12822         int dpywidth;
12823         int fixed_percent;
12824
12825         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12826                 return 0;
12827
12828         /*
12829          * Calculate the new progress position.  If the
12830          * percentage hasn't changed, then we skip out right
12831          * away.
12832          */
12833         fixed_percent = (int) ((10 * percent) + 0.5);
12834         if (ctx->progress_last_percent == fixed_percent)
12835                 return 0;
12836         ctx->progress_last_percent = fixed_percent;
12837
12838         /*
12839          * If we've already updated the spinner once within
12840          * the last 1/8th of a second, no point doing it
12841          * again.
12842          */
12843         gettimeofday(&tv, NULL);
12844         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12845         if ((tick == ctx->progress_last_time) &&
12846             (fixed_percent != 0) && (fixed_percent != 1000))
12847                 return 0;
12848         ctx->progress_last_time = tick;
12849
12850         /*
12851          * Advance the spinner, and note that the progress bar
12852          * will be on the screen
12853          */
12854         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12855         ctx->flags |= E2F_FLAG_PROG_BAR;
12856
12857         dpywidth = 66 - strlen(label);
12858         dpywidth = 8 * (dpywidth / 8);
12859         if (dpynum)
12860                 dpywidth -= 8;
12861
12862         i = ((percent * dpywidth) + 50) / 100;
12863         printf("%s%s: |%s%s", ctx->start_meta, label,
12864                bar + (sizeof(bar) - (i+1)),
12865                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12866         if (fixed_percent == 1000)
12867                 bb_putchar('|');
12868         else
12869                 bb_putchar(spinner[ctx->progress_pos & 3]);
12870         printf(" %4.1f%%  ", percent);
12871         if (dpynum)
12872                 printf("%u\r", dpynum);
12873         else
12874                 fputs(" \r", stdout);
12875         fputs(ctx->stop_meta, stdout);
12876
12877         if (fixed_percent == 1000)
12878                 e2fsck_clear_progbar(ctx);
12879         fflush(stdout);
12880
12881         return 0;
12882 }
12883
12884 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12885                                   unsigned long cur, unsigned long max)
12886 {
12887         char buf[80];
12888         float percent;
12889
12890         if (pass == 0)
12891                 return 0;
12892
12893         if (ctx->progress_fd) {
12894                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12895                 write(ctx->progress_fd, buf, strlen(buf));
12896         } else {
12897                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12898                 e2fsck_simple_progress(ctx, ctx->device_name,
12899                                        percent, 0);
12900         }
12901         return 0;
12902 }
12903
12904 static void reserve_stdio_fds(void)
12905 {
12906         int     fd;
12907
12908         while (1) {
12909                 fd = open(bb_dev_null, O_RDWR);
12910                 if (fd > 2)
12911                         break;
12912                 if (fd < 0) {
12913                         fprintf(stderr, _("ERROR: Cannot open "
12914                                 "/dev/null (%s)\n"),
12915                                 strerror(errno));
12916                         break;
12917                 }
12918         }
12919         close(fd);
12920 }
12921
12922 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12923 {
12924         e2fsck_t ctx = e2fsck_global_ctx;
12925
12926         if (!ctx)
12927                 return;
12928
12929         ctx->progress = e2fsck_update_progress;
12930         ctx->progress_fd = 0;
12931 }
12932
12933 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12934 {
12935         e2fsck_t ctx = e2fsck_global_ctx;
12936
12937         if (!ctx)
12938                 return;
12939
12940         e2fsck_clear_progbar(ctx);
12941         ctx->progress = 0;
12942 }
12943
12944 static void signal_cancel(int sig FSCK_ATTR((unused)))
12945 {
12946         e2fsck_t ctx = e2fsck_global_ctx;
12947
12948         if (!ctx)
12949                 exit(FSCK_CANCELED);
12950
12951         ctx->flags |= E2F_FLAG_CANCEL;
12952 }
12953
12954 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12955 {
12956         char    *buf, *token, *next, *p, *arg;
12957         int     ea_ver;
12958         int     extended_usage = 0;
12959
12960         buf = string_copy(opts, 0);
12961         for (token = buf; token && *token; token = next) {
12962                 p = strchr(token, ',');
12963                 next = 0;
12964                 if (p) {
12965                         *p = 0;
12966                         next = p+1;
12967                 }
12968                 arg = strchr(token, '=');
12969                 if (arg) {
12970                         *arg = 0;
12971                         arg++;
12972                 }
12973                 if (strcmp(token, "ea_ver") == 0) {
12974                         if (!arg) {
12975                                 extended_usage++;
12976                                 continue;
12977                         }
12978                         ea_ver = strtoul(arg, &p, 0);
12979                         if (*p ||
12980                             ((ea_ver != 1) && (ea_ver != 2))) {
12981                                 fprintf(stderr,
12982                                         _("Invalid EA version.\n"));
12983                                 extended_usage++;
12984                                 continue;
12985                         }
12986                         ctx->ext_attr_ver = ea_ver;
12987                 } else {
12988                         fprintf(stderr, _("Unknown extended option: %s\n"),
12989                                 token);
12990                         extended_usage++;
12991                 }
12992         }
12993         if (extended_usage) {
12994                 bb_error_msg_and_die(
12995                         "Extended options are separated by commas, "
12996                         "and may take an argument which\n"
12997                         "is set off by an equals ('=') sign.  "
12998                         "Valid extended options are:\n"
12999                         "\tea_ver=<ea_version (1 or 2)>\n\n");
13000         }
13001 }
13002
13003
13004 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
13005 {
13006         int             flush = 0;
13007         int             c, fd;
13008         e2fsck_t        ctx;
13009         errcode_t       retval;
13010         struct sigaction        sa;
13011         char            *extended_opts = 0;
13012
13013         retval = e2fsck_allocate_context(&ctx);
13014         if (retval)
13015                 return retval;
13016
13017         *ret_ctx = ctx;
13018
13019         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
13020         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
13021         if (isatty(0) && isatty(1)) {
13022                 ctx->interactive = 1;
13023         } else {
13024                 ctx->start_meta[0] = '\001';
13025                 ctx->stop_meta[0] = '\002';
13026         }
13027         memset(bar, '=', sizeof(bar)-1);
13028         memset(spaces, ' ', sizeof(spaces)-1);
13029         blkid_get_cache(&ctx->blkid, NULL);
13030
13031         if (argc && *argv)
13032                 ctx->program_name = *argv;
13033         else
13034                 ctx->program_name = "e2fsck";
13035         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13036                 switch (c) {
13037                 case 'C':
13038                         ctx->progress = e2fsck_update_progress;
13039                         ctx->progress_fd = atoi(optarg);
13040                         if (!ctx->progress_fd)
13041                                 break;
13042                         /* Validate the file descriptor to avoid disasters */
13043                         fd = dup(ctx->progress_fd);
13044                         if (fd < 0) {
13045                                 fprintf(stderr,
13046                                 _("Error validating file descriptor %d: %s\n"),
13047                                         ctx->progress_fd,
13048                                         error_message(errno));
13049                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13050                         } else
13051                                 close(fd);
13052                         break;
13053                 case 'D':
13054                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13055                         break;
13056                 case 'E':
13057                         extended_opts = optarg;
13058                         break;
13059                 case 'p':
13060                 case 'a':
13061                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13062                         conflict_opt:
13063                                 bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
13064                         }
13065                         ctx->options |= E2F_OPT_PREEN;
13066                         break;
13067                 case 'n':
13068                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13069                                 goto conflict_opt;
13070                         ctx->options |= E2F_OPT_NO;
13071                         break;
13072                 case 'y':
13073                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13074                                 goto conflict_opt;
13075                         ctx->options |= E2F_OPT_YES;
13076                         break;
13077                 case 't':
13078                         /* FIXME - This needs to go away in a future path - will change binary */
13079                         fprintf(stderr, _("The -t option is not "
13080                                 "supported on this version of e2fsck.\n"));
13081                         break;
13082                 case 'c':
13083                         if (cflag++)
13084                                 ctx->options |= E2F_OPT_WRITECHECK;
13085                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13086                         break;
13087                 case 'r':
13088                         /* What we do by default, anyway! */
13089                         break;
13090                 case 'b':
13091                         ctx->use_superblock = atoi(optarg);
13092                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13093                         break;
13094                 case 'B':
13095                         ctx->blocksize = atoi(optarg);
13096                         break;
13097                 case 'I':
13098                         ctx->inode_buffer_blocks = atoi(optarg);
13099                         break;
13100                 case 'j':
13101                         ctx->journal_name = string_copy(optarg, 0);
13102                         break;
13103                 case 'P':
13104                         ctx->process_inode_size = atoi(optarg);
13105                         break;
13106                 case 'd':
13107                         ctx->options |= E2F_OPT_DEBUG;
13108                         break;
13109                 case 'f':
13110                         ctx->options |= E2F_OPT_FORCE;
13111                         break;
13112                 case 'F':
13113                         flush = 1;
13114                         break;
13115                 case 'v':
13116                         verbose = 1;
13117                         break;
13118                 case 'V':
13119                         show_version_only = 1;
13120                         break;
13121                 case 'N':
13122                         ctx->device_name = optarg;
13123                         break;
13124 #ifdef ENABLE_SWAPFS
13125                 case 's':
13126                         normalize_swapfs = 1;
13127                 case 'S':
13128                         swapfs = 1;
13129                         break;
13130 #else
13131                 case 's':
13132                 case 'S':
13133                         fprintf(stderr, _("Byte-swapping filesystems "
13134                                           "not compiled in this version "
13135                                           "of e2fsck\n"));
13136                         exit(1);
13137 #endif
13138                 default:
13139                         bb_show_usage();
13140                 }
13141         if (show_version_only)
13142                 return 0;
13143         if (optind != argc - 1)
13144                 bb_show_usage();
13145         if ((ctx->options & E2F_OPT_NO) &&
13146             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13147                 ctx->options |= E2F_OPT_READONLY;
13148         ctx->io_options = strchr(argv[optind], '?');
13149         if (ctx->io_options)
13150                 *ctx->io_options++ = 0;
13151         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13152         if (!ctx->filesystem_name) {
13153                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13154                 bb_error_msg_and_die(0);
13155         }
13156         if (extended_opts)
13157                 parse_extended_opts(ctx, extended_opts);
13158
13159         if (flush) {
13160                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13161                 if (fd < 0) {
13162                         bb_error_msg(_("while opening %s for flushing"),
13163                                 ctx->filesystem_name);
13164                         bb_error_msg_and_die(0);
13165                 }
13166                 if ((retval = ext2fs_sync_device(fd, 1))) {
13167                         bb_error_msg(_("while trying to flush %s"),
13168                                 ctx->filesystem_name);
13169                         bb_error_msg_and_die(0);
13170                 }
13171                 close(fd);
13172         }
13173 #ifdef ENABLE_SWAPFS
13174         if (swapfs && cflag) {
13175                         fprintf(stderr, _("Incompatible options not "
13176                                           "allowed when byte-swapping.\n"));
13177                         exit(EXIT_USAGE);
13178         }
13179 #endif
13180         /*
13181          * Set up signal action
13182          */
13183         memset(&sa, 0, sizeof(struct sigaction));
13184         sa.sa_handler = signal_cancel;
13185         sigaction(SIGINT, &sa, 0);
13186         sigaction(SIGTERM, &sa, 0);
13187 #ifdef SA_RESTART
13188         sa.sa_flags = SA_RESTART;
13189 #endif
13190         e2fsck_global_ctx = ctx;
13191         sa.sa_handler = signal_progress_on;
13192         sigaction(SIGUSR1, &sa, 0);
13193         sa.sa_handler = signal_progress_off;
13194         sigaction(SIGUSR2, &sa, 0);
13195
13196         /* Update our PATH to include /sbin if we need to run badblocks  */
13197         if (cflag)
13198                 e2fs_set_sbin_path();
13199         return 0;
13200 }
13201
13202 static const char my_ver_string[] = E2FSPROGS_VERSION;
13203 static const char my_ver_date[] = E2FSPROGS_DATE;
13204
13205 int e2fsck_main (int argc, char **argv);
13206 int e2fsck_main (int argc, char **argv)
13207 {
13208         errcode_t       retval;
13209         int             exit_value = EXIT_OK;
13210         ext2_filsys     fs = 0;
13211         io_manager      io_ptr;
13212         struct ext2_super_block *sb;
13213         const char      *lib_ver_date;
13214         int             my_ver, lib_ver;
13215         e2fsck_t        ctx;
13216         struct problem_context pctx;
13217         int flags, run_result;
13218
13219         clear_problem_context(&pctx);
13220
13221         my_ver = ext2fs_parse_version_string(my_ver_string);
13222         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13223         if (my_ver > lib_ver) {
13224                 fprintf( stderr, _("Error: ext2fs library version "
13225                         "out of date!\n"));
13226                 show_version_only++;
13227         }
13228
13229         retval = PRS(argc, argv, &ctx);
13230         if (retval) {
13231                 bb_error_msg(_("while trying to initialize program"));
13232                 exit(EXIT_ERROR);
13233         }
13234         reserve_stdio_fds();
13235
13236         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13237                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13238                          my_ver_date);
13239
13240         if (show_version_only) {
13241                 fprintf(stderr, _("\tUsing %s, %s\n"),
13242                         error_message(EXT2_ET_BASE), lib_ver_date);
13243                 exit(EXIT_OK);
13244         }
13245
13246         check_mount(ctx);
13247
13248         if (!(ctx->options & E2F_OPT_PREEN) &&
13249             !(ctx->options & E2F_OPT_NO) &&
13250             !(ctx->options & E2F_OPT_YES)) {
13251                 if (!ctx->interactive)
13252                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13253         }
13254         ctx->superblock = ctx->use_superblock;
13255 restart:
13256 #ifdef CONFIG_TESTIO_DEBUG
13257         io_ptr = test_io_manager;
13258         test_io_backing_manager = unix_io_manager;
13259 #else
13260         io_ptr = unix_io_manager;
13261 #endif
13262         flags = 0;
13263         if ((ctx->options & E2F_OPT_READONLY) == 0)
13264                 flags |= EXT2_FLAG_RW;
13265
13266         if (ctx->superblock && ctx->blocksize) {
13267                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13268                                       flags, ctx->superblock, ctx->blocksize,
13269                                       io_ptr, &fs);
13270         } else if (ctx->superblock) {
13271                 int blocksize;
13272                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13273                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13274                         retval = ext2fs_open2(ctx->filesystem_name,
13275                                               ctx->io_options, flags,
13276                                               ctx->superblock, blocksize,
13277                                               io_ptr, &fs);
13278                         if (!retval)
13279                                 break;
13280                 }
13281         } else
13282                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13283                                       flags, 0, 0, io_ptr, &fs);
13284         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13285             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13286             ((retval == EXT2_ET_BAD_MAGIC) ||
13287              ((retval == 0) && ext2fs_check_desc(fs)))) {
13288                 if (!fs || (fs->group_desc_count > 1)) {
13289                         printf(_("%s trying backup blocks...\n"),
13290                                retval ? _("Couldn't find ext2 superblock,") :
13291                                _("Group descriptors look bad..."));
13292                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13293                         if (fs)
13294                                 ext2fs_close(fs);
13295                         goto restart;
13296                 }
13297         }
13298         if (retval) {
13299                 bb_error_msg(_("while trying to open %s"),
13300                         ctx->filesystem_name);
13301                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13302                         printf(_("The filesystem revision is apparently "
13303                                "too high for this version of e2fsck.\n"
13304                                "(Or the filesystem superblock "
13305                                "is corrupt)\n\n"));
13306                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13307                 } else if (retval == EXT2_ET_SHORT_READ)
13308                         printf(_("Could this be a zero-length partition?\n"));
13309                 else if ((retval == EPERM) || (retval == EACCES))
13310                         printf(_("You must have %s access to the "
13311                                "filesystem or be root\n"),
13312                                (ctx->options & E2F_OPT_READONLY) ?
13313                                "r/o" : "r/w");
13314                 else if (retval == ENXIO)
13315                         printf(_("Possibly non-existent or swap device?\n"));
13316 #ifdef EROFS
13317                 else if (retval == EROFS)
13318                         printf(_("Disk write-protected; use the -n option "
13319                                "to do a read-only\n"
13320                                "check of the device.\n"));
13321 #endif
13322                 else
13323                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13324                 bb_error_msg_and_die(0);
13325         }
13326         ctx->fs = fs;
13327         fs->priv_data = ctx;
13328         sb = fs->super;
13329         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13330                 bb_error_msg(_("while trying to open %s"),
13331                         ctx->filesystem_name);
13332         get_newer:
13333                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13334         }
13335
13336         /*
13337          * Set the device name, which is used whenever we print error
13338          * or informational messages to the user.
13339          */
13340         if (ctx->device_name == 0 &&
13341             (sb->s_volume_name[0] != 0)) {
13342                 ctx->device_name = string_copy(sb->s_volume_name,
13343                                                sizeof(sb->s_volume_name));
13344         }
13345         if (ctx->device_name == 0)
13346                 ctx->device_name = ctx->filesystem_name;
13347
13348         /*
13349          * Make sure the ext3 superblock fields are consistent.
13350          */
13351         retval = e2fsck_check_ext3_journal(ctx);
13352         if (retval) {
13353                 bb_error_msg(_("while checking ext3 journal for %s"),
13354                         ctx->device_name);
13355                 bb_error_msg_and_die(0);
13356         }
13357
13358         /*
13359          * Check to see if we need to do ext3-style recovery.  If so,
13360          * do it, and then restart the fsck.
13361          */
13362         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13363                 if (ctx->options & E2F_OPT_READONLY) {
13364                         printf(_("Warning: skipping journal recovery "
13365                                  "because doing a read-only filesystem "
13366                                  "check.\n"));
13367                         io_channel_flush(ctx->fs->io);
13368                 } else {
13369                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13370                                 /*
13371                                  * Whoops, we attempted to run the
13372                                  * journal twice.  This should never
13373                                  * happen, unless the hardware or
13374                                  * device driver is being bogus.
13375                                  */
13376                                 bb_error_msg(_("cannot set superblock flags on %s"), ctx->device_name);
13377                                 bb_error_msg_and_die(0);
13378                         }
13379                         retval = e2fsck_run_ext3_journal(ctx);
13380                         if (retval) {
13381                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13382                                         ctx->device_name);
13383                                 bb_error_msg_and_die(0);
13384                         }
13385                         ext2fs_close(ctx->fs);
13386                         ctx->fs = 0;
13387                         ctx->flags |= E2F_FLAG_RESTARTED;
13388                         goto restart;
13389                 }
13390         }
13391
13392         /*
13393          * Check for compatibility with the feature sets.  We need to
13394          * be more stringent than ext2fs_open().
13395          */
13396         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13397             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13398                 bb_error_msg("(%s)", ctx->device_name);
13399                 goto get_newer;
13400         }
13401         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13402                 bb_error_msg("(%s)", ctx->device_name);
13403                 goto get_newer;
13404         }
13405 #ifdef ENABLE_COMPRESSION
13406         /* FIXME - do we support this at all? */
13407         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13408                 bb_error_msg(_("Warning: compression support is experimental."));
13409 #endif
13410 #ifndef ENABLE_HTREE
13411         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13412                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13413                           "but filesystem %s has HTREE directories."),
13414                         ctx->device_name);
13415                 goto get_newer;
13416         }
13417 #endif
13418
13419         /*
13420          * If the user specified a specific superblock, presumably the
13421          * master superblock has been trashed.  So we mark the
13422          * superblock as dirty, so it can be written out.
13423          */
13424         if (ctx->superblock &&
13425             !(ctx->options & E2F_OPT_READONLY))
13426                 ext2fs_mark_super_dirty(fs);
13427
13428         /*
13429          * We only update the master superblock because (a) paranoia;
13430          * we don't want to corrupt the backup superblocks, and (b) we
13431          * don't need to update the mount count and last checked
13432          * fields in the backup superblock (the kernel doesn't
13433          * update the backup superblocks anyway).
13434          */
13435         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13436
13437         ehandler_init(fs->io);
13438
13439         if (ctx->superblock)
13440                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13441         ext2fs_mark_valid(fs);
13442         check_super_block(ctx);
13443         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13444                 bb_error_msg_and_die(0);
13445         check_if_skip(ctx);
13446         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13447                 bb_error_msg_and_die(0);
13448 #ifdef ENABLE_SWAPFS
13449
13450 #ifdef WORDS_BIGENDIAN
13451 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13452 #else
13453 #define NATIVE_FLAG 0
13454 #endif
13455
13456
13457         if (normalize_swapfs) {
13458                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13459                         fprintf(stderr, _("%s: Filesystem byte order "
13460                                 "already normalized.\n"), ctx->device_name);
13461                         bb_error_msg_and_die(0);
13462                 }
13463         }
13464         if (swapfs) {
13465                 swap_filesys(ctx);
13466                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13467                         bb_error_msg_and_die(0);
13468         }
13469 #endif
13470
13471         /*
13472          * Mark the system as valid, 'til proven otherwise
13473          */
13474         ext2fs_mark_valid(fs);
13475
13476         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13477         if (retval) {
13478                 bb_error_msg(_("while reading bad blocks inode"));
13479                 preenhalt(ctx);
13480                 printf(_("This doesn't bode well,"
13481                          " but we'll try to go on...\n"));
13482         }
13483
13484         run_result = e2fsck_run(ctx);
13485         e2fsck_clear_progbar(ctx);
13486         if (run_result == E2F_FLAG_RESTART) {
13487                 printf(_("Restarting e2fsck from the beginning...\n"));
13488                 retval = e2fsck_reset_context(ctx);
13489                 if (retval) {
13490                         bb_error_msg(_("while resetting context"));
13491                         bb_error_msg_and_die(0);
13492                 }
13493                 ext2fs_close(fs);
13494                 goto restart;
13495         }
13496         if (run_result & E2F_FLAG_CANCEL) {
13497                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13498                        ctx->device_name : ctx->filesystem_name);
13499                 exit_value |= FSCK_CANCELED;
13500         }
13501         if (run_result & E2F_FLAG_ABORT)
13502                 bb_error_msg_and_die(_("aborted"));
13503
13504         /* Cleanup */
13505         if (ext2fs_test_changed(fs)) {
13506                 exit_value |= EXIT_NONDESTRUCT;
13507                 if (!(ctx->options & E2F_OPT_PREEN))
13508                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13509                                ctx->device_name);
13510                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13511                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13512                                ctx->device_name);
13513                         exit_value |= EXIT_DESTRUCT;
13514                 }
13515         }
13516         if (!ext2fs_test_valid(fs)) {
13517                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13518                          "errors **********\n\n"), ctx->device_name);
13519                 exit_value |= EXIT_UNCORRECTED;
13520                 exit_value &= ~EXIT_NONDESTRUCT;
13521         }
13522         if (exit_value & FSCK_CANCELED)
13523                 exit_value &= ~EXIT_NONDESTRUCT;
13524         else {
13525                 show_stats(ctx);
13526                 if (!(ctx->options & E2F_OPT_READONLY)) {
13527                         if (ext2fs_test_valid(fs)) {
13528                                 if (!(sb->s_state & EXT2_VALID_FS))
13529                                         exit_value |= EXIT_NONDESTRUCT;
13530                                 sb->s_state = EXT2_VALID_FS;
13531                         } else
13532                                 sb->s_state &= ~EXT2_VALID_FS;
13533                         sb->s_mnt_count = 0;
13534                         sb->s_lastcheck = time(NULL);
13535                         ext2fs_mark_super_dirty(fs);
13536                 }
13537         }
13538
13539         e2fsck_write_bitmaps(ctx);
13540
13541         ext2fs_close(fs);
13542         ctx->fs = NULL;
13543         free(ctx->filesystem_name);
13544         free(ctx->journal_name);
13545         e2fsck_free_context(ctx);
13546
13547         return exit_value;
13548 }