upload tizen1.0 source
[external/busybox.git] / util-linux / e2fsprogs / old_e2fsprogs / e2fsck.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * e2fsck
4  *
5  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6  * Copyright (C) 2006 Garrett Kajmowicz
7  *
8  * Dictionary Abstract Data Type
9  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10  * Free Software License:
11  * All rights are reserved by the author, with the following exceptions:
12  * Permission is granted to freely reproduce and distribute this software,
13  * possibly in exchange for a fee, provided that this copyright notice appears
14  * intact. Permission is also granted to adapt this software to produce
15  * derivative works, as long as the modified versions carry this copyright
16  * notice and additional notices stating that the work has been modified.
17  * This source code may be translated into executable form and incorporated
18  * into proprietary software; there is no requirement for such software to
19  * contain a copyright notice related to this source.
20  *
21  * linux/fs/recovery  and linux/fs/revoke
22  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23  *
24  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25  *
26  * Journal recovery routines for the generic filesystem journaling code;
27  * part of the ext2fs journaling system.
28  *
29  * Licensed under GPLv2 or later, see file License in this tarball for details.
30  */
31
32 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
33
34 #define _(x) x
35 #define N_(x) x
36
37 /*
38  * Procedure declarations
39  */
40
41 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
42
43 /* pass1.c */
44 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
45
46 /* pass2.c */
47 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
48                                     ext2_ino_t ino, char *buf);
49
50 /* pass3.c */
51 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
52 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
53                                          int num, int gauranteed_size);
54 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
55 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
56                                            int adj);
57
58 /* rehash.c */
59 static void e2fsck_rehash_directories(e2fsck_t ctx);
60
61 /* util.c */
62 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
63                                     const char *description);
64 static int ask(e2fsck_t ctx, const char * string, int def);
65 static void e2fsck_read_bitmaps(e2fsck_t ctx);
66 static void preenhalt(e2fsck_t ctx);
67 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
68                               struct ext2_inode * inode, const char * proc);
69 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
70                                struct ext2_inode * inode, const char * proc);
71 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
72                            const char *name, io_manager manager);
73
74 /* unix.c */
75 static void e2fsck_clear_progbar(e2fsck_t ctx);
76 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
77                                   float percent, unsigned int dpynum);
78
79
80 /*
81  * problem.h --- e2fsck problem error codes
82  */
83
84 typedef __u32 problem_t;
85
86 struct problem_context {
87         errcode_t       errcode;
88         ext2_ino_t      ino, ino2, dir;
89         struct ext2_inode *inode;
90         struct ext2_dir_entry *dirent;
91         blk_t           blk, blk2;
92         e2_blkcnt_t     blkcount;
93         int             group;
94         __u64           num;
95         const char      *str;
96 };
97
98
99 /*
100  * Function declarations
101  */
102 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
103 static int end_problem_latch(e2fsck_t ctx, int mask);
104 static int set_latch_flags(int mask, int setflags, int clearflags);
105 static void clear_problem_context(struct problem_context *ctx);
106
107 /*
108  * Dictionary Abstract Data Type
109  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
110  *
111  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
112  * kazlib_1_20
113  */
114
115 #ifndef DICT_H
116 #define DICT_H
117
118 /*
119  * Blurb for inclusion into C++ translation units
120  */
121
122 typedef unsigned long dictcount_t;
123 #define DICTCOUNT_T_MAX ULONG_MAX
124
125 /*
126  * The dictionary is implemented as a red-black tree
127  */
128
129 typedef enum { dnode_red, dnode_black } dnode_color_t;
130
131 typedef struct dnode_t {
132         struct dnode_t *dict_left;
133         struct dnode_t *dict_right;
134         struct dnode_t *dict_parent;
135         dnode_color_t dict_color;
136         const void *dict_key;
137         void *dict_data;
138 } dnode_t;
139
140 typedef int (*dict_comp_t)(const void *, const void *);
141 typedef void (*dnode_free_t)(dnode_t *);
142
143 typedef struct dict_t {
144         dnode_t dict_nilnode;
145         dictcount_t dict_nodecount;
146         dictcount_t dict_maxcount;
147         dict_comp_t dict_compare;
148         dnode_free_t dict_freenode;
149         int dict_dupes;
150 } dict_t;
151
152 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
153
154 typedef struct dict_load_t {
155         dict_t *dict_dictptr;
156         dnode_t dict_nilnode;
157 } dict_load_t;
158
159 #define dict_count(D) ((D)->dict_nodecount)
160 #define dnode_get(N) ((N)->dict_data)
161 #define dnode_getkey(N) ((N)->dict_key)
162
163 #endif
164
165 /*
166  * Compatibility header file for e2fsck which should be included
167  * instead of linux/jfs.h
168  *
169  * Copyright (C) 2000 Stephen C. Tweedie
170  */
171
172 /*
173  * Pull in the definition of the e2fsck context structure
174  */
175
176 struct buffer_head {
177         char            b_data[8192];
178         e2fsck_t        b_ctx;
179         io_channel      b_io;
180         int             b_size;
181         blk_t           b_blocknr;
182         int             b_dirty;
183         int             b_uptodate;
184         int             b_err;
185 };
186
187
188 #define K_DEV_FS        1
189 #define K_DEV_JOURNAL   2
190
191 #define lock_buffer(bh) do {} while (0)
192 #define unlock_buffer(bh) do {} while (0)
193 #define buffer_req(bh) 1
194 #define do_readahead(journal, start) do {} while (0)
195
196 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
197
198 typedef struct {
199         int     object_length;
200 } kmem_cache_t;
201
202 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
203
204 /*
205  * We use the standard libext2fs portability tricks for inline
206  * functions.
207  */
208
209 static kmem_cache_t * do_cache_create(int len)
210 {
211         kmem_cache_t *new_cache;
212
213         new_cache = xmalloc(sizeof(*new_cache));
214         new_cache->object_length = len;
215         return new_cache;
216 }
217
218 static void do_cache_destroy(kmem_cache_t *cache)
219 {
220         free(cache);
221 }
222
223
224 /*
225  * Dictionary Abstract Data Type
226  */
227
228
229 /*
230  * These macros provide short convenient names for structure members,
231  * which are embellished with dict_ prefixes so that they are
232  * properly confined to the documented namespace. It's legal for a
233  * program which uses dict to define, for instance, a macro called ``parent''.
234  * Such a macro would interfere with the dnode_t struct definition.
235  * In general, highly portable and reusable C modules which expose their
236  * structures need to confine structure member names to well-defined spaces.
237  * The resulting identifiers aren't necessarily convenient to use, nor
238  * readable, in the implementation, however!
239  */
240
241 #define left dict_left
242 #define right dict_right
243 #define parent dict_parent
244 #define color dict_color
245 #define key dict_key
246 #define data dict_data
247
248 #define nilnode dict_nilnode
249 #define maxcount dict_maxcount
250 #define compare dict_compare
251 #define dupes dict_dupes
252
253 #define dict_root(D) ((D)->nilnode.left)
254 #define dict_nil(D) (&(D)->nilnode)
255
256 static void dnode_free(dnode_t *node);
257
258 /*
259  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
260  * its right child C are rearranged so that the P instead becomes the left
261  * child of C.   The left subtree of C is inherited as the new right subtree
262  * for P.  The ordering of the keys within the tree is thus preserved.
263  */
264
265 static void rotate_left(dnode_t *upper)
266 {
267         dnode_t *lower, *lowleft, *upparent;
268
269         lower = upper->right;
270         upper->right = lowleft = lower->left;
271         lowleft->parent = upper;
272
273         lower->parent = upparent = upper->parent;
274
275         /* don't need to check for root node here because root->parent is
276            the sentinel nil node, and root->parent->left points back to root */
277
278         if (upper == upparent->left) {
279                 upparent->left = lower;
280         } else {
281                 assert (upper == upparent->right);
282                 upparent->right = lower;
283         }
284
285         lower->left = upper;
286         upper->parent = lower;
287 }
288
289 /*
290  * This operation is the ``mirror'' image of rotate_left. It is
291  * the same procedure, but with left and right interchanged.
292  */
293
294 static void rotate_right(dnode_t *upper)
295 {
296         dnode_t *lower, *lowright, *upparent;
297
298         lower = upper->left;
299         upper->left = lowright = lower->right;
300         lowright->parent = upper;
301
302         lower->parent = upparent = upper->parent;
303
304         if (upper == upparent->right) {
305                 upparent->right = lower;
306         } else {
307                 assert (upper == upparent->left);
308                 upparent->left = lower;
309         }
310
311         lower->right = upper;
312         upper->parent = lower;
313 }
314
315 /*
316  * Do a postorder traversal of the tree rooted at the specified
317  * node and free everything under it.  Used by dict_free().
318  */
319
320 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
321 {
322         if (node == nil)
323                 return;
324         free_nodes(dict, node->left, nil);
325         free_nodes(dict, node->right, nil);
326         dict->dict_freenode(node);
327 }
328
329 /*
330  * Verify that the tree contains the given node. This is done by
331  * traversing all of the nodes and comparing their pointers to the
332  * given pointer. Returns 1 if the node is found, otherwise
333  * returns zero. It is intended for debugging purposes.
334  */
335
336 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
337 {
338         if (root != nil) {
339                 return root == node
340                         || verify_dict_has_node(nil, root->left, node)
341                         || verify_dict_has_node(nil, root->right, node);
342         }
343         return 0;
344 }
345
346
347 /*
348  * Select a different set of node allocator routines.
349  */
350
351 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
352 {
353         assert(dict_count(dict) == 0);
354         dict->dict_freenode = fr;
355 }
356
357 /*
358  * Free all the nodes in the dictionary by using the dictionary's
359  * installed free routine. The dictionary is emptied.
360  */
361
362 static void dict_free_nodes(dict_t *dict)
363 {
364         dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
365         free_nodes(dict, root, nil);
366         dict->dict_nodecount = 0;
367         dict->nilnode.left = &dict->nilnode;
368         dict->nilnode.right = &dict->nilnode;
369 }
370
371 /*
372  * Initialize a user-supplied dictionary object.
373  */
374
375 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
376 {
377         dict->compare = comp;
378         dict->dict_freenode = dnode_free;
379         dict->dict_nodecount = 0;
380         dict->maxcount = maxcount;
381         dict->nilnode.left = &dict->nilnode;
382         dict->nilnode.right = &dict->nilnode;
383         dict->nilnode.parent = &dict->nilnode;
384         dict->nilnode.color = dnode_black;
385         dict->dupes = 0;
386         return dict;
387 }
388
389 /*
390  * Locate a node in the dictionary having the given key.
391  * If the node is not found, a null a pointer is returned (rather than
392  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
393  * located node is returned.
394  */
395
396 static dnode_t *dict_lookup(dict_t *dict, const void *key)
397 {
398         dnode_t *root = dict_root(dict);
399         dnode_t *nil = dict_nil(dict);
400         dnode_t *saved;
401         int result;
402
403         /* simple binary search adapted for trees that contain duplicate keys */
404
405         while (root != nil) {
406                 result = dict->compare(key, root->key);
407                 if (result < 0)
408                         root = root->left;
409                 else if (result > 0)
410                         root = root->right;
411                 else {
412                         if (!dict->dupes) { /* no duplicates, return match          */
413                                 return root;
414                         } else {            /* could be dupes, find leftmost one    */
415                                 do {
416                                         saved = root;
417                                         root = root->left;
418                                         while (root != nil && dict->compare(key, root->key))
419                                                 root = root->right;
420                                 } while (root != nil);
421                                 return saved;
422                         }
423                 }
424         }
425
426         return NULL;
427 }
428
429 /*
430  * Insert a node into the dictionary. The node should have been
431  * initialized with a data field. All other fields are ignored.
432  * The behavior is undefined if the user attempts to insert into
433  * a dictionary that is already full (for which the dict_isfull()
434  * function returns true).
435  */
436
437 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
438 {
439         dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
440         dnode_t *parent = nil, *uncle, *grandpa;
441         int result = -1;
442
443         node->key = key;
444
445         /* basic binary tree insert */
446
447         while (where != nil) {
448                 parent = where;
449                 result = dict->compare(key, where->key);
450                 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
451                 assert(dict->dupes || result != 0);
452                 if (result < 0)
453                         where = where->left;
454                 else
455                         where = where->right;
456         }
457
458         assert(where == nil);
459
460         if (result < 0)
461                 parent->left = node;
462         else
463                 parent->right = node;
464
465         node->parent = parent;
466         node->left = nil;
467         node->right = nil;
468
469         dict->dict_nodecount++;
470
471         /* red black adjustments */
472
473         node->color = dnode_red;
474
475         while (parent->color == dnode_red) {
476                 grandpa = parent->parent;
477                 if (parent == grandpa->left) {
478                         uncle = grandpa->right;
479                         if (uncle->color == dnode_red) {    /* red parent, red uncle */
480                                 parent->color = dnode_black;
481                                 uncle->color = dnode_black;
482                                 grandpa->color = dnode_red;
483                                 node = grandpa;
484                                 parent = grandpa->parent;
485                         } else {                            /* red parent, black uncle */
486                                 if (node == parent->right) {
487                                         rotate_left(parent);
488                                         parent = node;
489                                         assert (grandpa == parent->parent);
490                                         /* rotation between parent and child preserves grandpa */
491                                 }
492                                 parent->color = dnode_black;
493                                 grandpa->color = dnode_red;
494                                 rotate_right(grandpa);
495                                 break;
496                         }
497                 } else {        /* symmetric cases: parent == parent->parent->right */
498                         uncle = grandpa->left;
499                         if (uncle->color == dnode_red) {
500                                 parent->color = dnode_black;
501                                 uncle->color = dnode_black;
502                                 grandpa->color = dnode_red;
503                                 node = grandpa;
504                                 parent = grandpa->parent;
505                         } else {
506                                 if (node == parent->left) {
507                                         rotate_right(parent);
508                                         parent = node;
509                                         assert (grandpa == parent->parent);
510                                 }
511                                 parent->color = dnode_black;
512                                 grandpa->color = dnode_red;
513                                 rotate_left(grandpa);
514                                 break;
515                         }
516                 }
517         }
518
519         dict_root(dict)->color = dnode_black;
520
521 }
522
523 /*
524  * Allocate a node using the dictionary's allocator routine, give it
525  * the data item.
526  */
527
528 static dnode_t *dnode_init(dnode_t *dnode, void *data)
529 {
530         dnode->data = data;
531         dnode->parent = NULL;
532         dnode->left = NULL;
533         dnode->right = NULL;
534         return dnode;
535 }
536
537 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
538 {
539         dnode_t *node = xmalloc(sizeof(dnode_t));
540
541         dnode_init(node, data);
542         dict_insert(dict, node, key);
543         return 1;
544 }
545
546 /*
547  * Return the node with the lowest (leftmost) key. If the dictionary is empty
548  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
549  */
550
551 static dnode_t *dict_first(dict_t *dict)
552 {
553         dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
554
555         if (root != nil)
556                 while ((left = root->left) != nil)
557                         root = left;
558
559         return (root == nil) ? NULL : root;
560 }
561
562 /*
563  * Return the given node's successor node---the node which has the
564  * next key in the the left to right ordering. If the node has
565  * no successor, a null pointer is returned rather than a pointer to
566  * the nil node.
567  */
568
569 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
570 {
571         dnode_t *nil = dict_nil(dict), *parent, *left;
572
573         if (curr->right != nil) {
574                 curr = curr->right;
575                 while ((left = curr->left) != nil)
576                         curr = left;
577                 return curr;
578         }
579
580         parent = curr->parent;
581
582         while (parent != nil && curr == parent->right) {
583                 curr = parent;
584                 parent = curr->parent;
585         }
586
587         return (parent == nil) ? NULL : parent;
588 }
589
590
591 static void dnode_free(dnode_t *node)
592 {
593         free(node);
594 }
595
596
597 #undef left
598 #undef right
599 #undef parent
600 #undef color
601 #undef key
602 #undef data
603
604 #undef nilnode
605 #undef maxcount
606 #undef compare
607 #undef dupes
608
609
610 /*
611  * dirinfo.c --- maintains the directory information table for e2fsck.
612  */
613
614 /*
615  * This subroutine is called during pass1 to create a directory info
616  * entry.  During pass1, the passed-in parent is 0; it will get filled
617  * in during pass2.
618  */
619 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
620 {
621         struct dir_info *dir;
622         int             i, j;
623         ext2_ino_t      num_dirs;
624         errcode_t       retval;
625         unsigned long   old_size;
626
627         if (!ctx->dir_info) {
628                 ctx->dir_info_count = 0;
629                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
630                 if (retval)
631                         num_dirs = 1024;        /* Guess */
632                 ctx->dir_info_size = num_dirs + 10;
633                 ctx->dir_info  = (struct dir_info *)
634                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
635                                                * sizeof (struct dir_info),
636                                                "directory map");
637         }
638
639         if (ctx->dir_info_count >= ctx->dir_info_size) {
640                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
641                 ctx->dir_info_size += 10;
642                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
643                                            sizeof(struct dir_info),
644                                            &ctx->dir_info);
645                 if (retval) {
646                         ctx->dir_info_size -= 10;
647                         return;
648                 }
649         }
650
651         /*
652          * Normally, add_dir_info is called with each inode in
653          * sequential order; but once in a while (like when pass 3
654          * needs to recreate the root directory or lost+found
655          * directory) it is called out of order.  In those cases, we
656          * need to move the dir_info entries down to make room, since
657          * the dir_info array needs to be sorted by inode number for
658          * get_dir_info()'s sake.
659          */
660         if (ctx->dir_info_count &&
661             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
662                 for (i = ctx->dir_info_count-1; i > 0; i--)
663                         if (ctx->dir_info[i-1].ino < ino)
664                                 break;
665                 dir = &ctx->dir_info[i];
666                 if (dir->ino != ino)
667                         for (j = ctx->dir_info_count++; j > i; j--)
668                                 ctx->dir_info[j] = ctx->dir_info[j-1];
669         } else
670                 dir = &ctx->dir_info[ctx->dir_info_count++];
671
672         dir->ino = ino;
673         dir->dotdot = parent;
674         dir->parent = parent;
675 }
676
677 /*
678  * get_dir_info() --- given an inode number, try to find the directory
679  * information entry for it.
680  */
681 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
682 {
683         int     low, high, mid;
684
685         low = 0;
686         high = ctx->dir_info_count-1;
687         if (!ctx->dir_info)
688                 return 0;
689         if (ino == ctx->dir_info[low].ino)
690                 return &ctx->dir_info[low];
691         if  (ino == ctx->dir_info[high].ino)
692                 return &ctx->dir_info[high];
693
694         while (low < high) {
695                 mid = (low+high)/2;
696                 if (mid == low || mid == high)
697                         break;
698                 if (ino == ctx->dir_info[mid].ino)
699                         return &ctx->dir_info[mid];
700                 if (ino < ctx->dir_info[mid].ino)
701                         high = mid;
702                 else
703                         low = mid;
704         }
705         return 0;
706 }
707
708 /*
709  * Free the dir_info structure when it isn't needed any more.
710  */
711 static void e2fsck_free_dir_info(e2fsck_t ctx)
712 {
713         ext2fs_free_mem(&ctx->dir_info);
714         ctx->dir_info_size = 0;
715         ctx->dir_info_count = 0;
716 }
717
718 /*
719  * Return the count of number of directories in the dir_info structure
720  */
721 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
722 {
723         return ctx->dir_info_count;
724 }
725
726 /*
727  * A simple interator function
728  */
729 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
730 {
731         if (*control >= ctx->dir_info_count)
732                 return 0;
733
734         return ctx->dir_info + (*control)++;
735 }
736
737 /*
738  * dirinfo.c --- maintains the directory information table for e2fsck.
739  *
740  */
741
742 #ifdef ENABLE_HTREE
743
744 /*
745  * This subroutine is called during pass1 to create a directory info
746  * entry.  During pass1, the passed-in parent is 0; it will get filled
747  * in during pass2.
748  */
749 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
750 {
751         struct dx_dir_info *dir;
752         int             i, j;
753         errcode_t       retval;
754         unsigned long   old_size;
755
756         if (!ctx->dx_dir_info) {
757                 ctx->dx_dir_info_count = 0;
758                 ctx->dx_dir_info_size = 100; /* Guess */
759                 ctx->dx_dir_info  = (struct dx_dir_info *)
760                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
761                                                * sizeof (struct dx_dir_info),
762                                                "directory map");
763         }
764
765         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
766                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
767                 ctx->dx_dir_info_size += 10;
768                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
769                                            sizeof(struct dx_dir_info),
770                                            &ctx->dx_dir_info);
771                 if (retval) {
772                         ctx->dx_dir_info_size -= 10;
773                         return;
774                 }
775         }
776
777         /*
778          * Normally, add_dx_dir_info is called with each inode in
779          * sequential order; but once in a while (like when pass 3
780          * needs to recreate the root directory or lost+found
781          * directory) it is called out of order.  In those cases, we
782          * need to move the dx_dir_info entries down to make room, since
783          * the dx_dir_info array needs to be sorted by inode number for
784          * get_dx_dir_info()'s sake.
785          */
786         if (ctx->dx_dir_info_count &&
787             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
788                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
789                         if (ctx->dx_dir_info[i-1].ino < ino)
790                                 break;
791                 dir = &ctx->dx_dir_info[i];
792                 if (dir->ino != ino)
793                         for (j = ctx->dx_dir_info_count++; j > i; j--)
794                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
795         } else
796                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
797
798         dir->ino = ino;
799         dir->numblocks = num_blocks;
800         dir->hashversion = 0;
801         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
802                                        * sizeof (struct dx_dirblock_info),
803                                        "dx_block info array");
804
805 }
806
807 /*
808  * get_dx_dir_info() --- given an inode number, try to find the directory
809  * information entry for it.
810  */
811 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
812 {
813         int     low, high, mid;
814
815         low = 0;
816         high = ctx->dx_dir_info_count-1;
817         if (!ctx->dx_dir_info)
818                 return 0;
819         if (ino == ctx->dx_dir_info[low].ino)
820                 return &ctx->dx_dir_info[low];
821         if  (ino == ctx->dx_dir_info[high].ino)
822                 return &ctx->dx_dir_info[high];
823
824         while (low < high) {
825                 mid = (low+high)/2;
826                 if (mid == low || mid == high)
827                         break;
828                 if (ino == ctx->dx_dir_info[mid].ino)
829                         return &ctx->dx_dir_info[mid];
830                 if (ino < ctx->dx_dir_info[mid].ino)
831                         high = mid;
832                 else
833                         low = mid;
834         }
835         return 0;
836 }
837
838 /*
839  * Free the dx_dir_info structure when it isn't needed any more.
840  */
841 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
842 {
843         int     i;
844         struct dx_dir_info *dir;
845
846         if (ctx->dx_dir_info) {
847                 dir = ctx->dx_dir_info;
848                 for (i=0; i < ctx->dx_dir_info_count; i++) {
849                         ext2fs_free_mem(&dir->dx_block);
850                 }
851                 ext2fs_free_mem(&ctx->dx_dir_info);
852         }
853         ctx->dx_dir_info_size = 0;
854         ctx->dx_dir_info_count = 0;
855 }
856
857 /*
858  * A simple interator function
859  */
860 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
861 {
862         if (*control >= ctx->dx_dir_info_count)
863                 return 0;
864
865         return ctx->dx_dir_info + (*control)++;
866 }
867
868 #endif /* ENABLE_HTREE */
869 /*
870  * e2fsck.c - a consistency checker for the new extended file system.
871  *
872  */
873
874 /*
875  * This function allocates an e2fsck context
876  */
877 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
878 {
879         e2fsck_t        context;
880         errcode_t       retval;
881
882         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
883         if (retval)
884                 return retval;
885
886         memset(context, 0, sizeof(struct e2fsck_struct));
887
888         context->process_inode_size = 256;
889         context->ext_attr_ver = 2;
890
891         *ret = context;
892         return 0;
893 }
894
895 struct ea_refcount_el {
896         blk_t   ea_blk;
897         int     ea_count;
898 };
899
900 struct ea_refcount {
901         blk_t           count;
902         blk_t           size;
903         blk_t           cursor;
904         struct ea_refcount_el   *list;
905 };
906
907 static void ea_refcount_free(ext2_refcount_t refcount)
908 {
909         if (!refcount)
910                 return;
911
912         ext2fs_free_mem(&refcount->list);
913         ext2fs_free_mem(&refcount);
914 }
915
916 /*
917  * This function resets an e2fsck context; it is called when e2fsck
918  * needs to be restarted.
919  */
920 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
921 {
922         ctx->flags = 0;
923         ctx->lost_and_found = 0;
924         ctx->bad_lost_and_found = 0;
925         ext2fs_free_inode_bitmap(ctx->inode_used_map);
926         ctx->inode_used_map = 0;
927         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
928         ctx->inode_dir_map = 0;
929         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
930         ctx->inode_reg_map = 0;
931         ext2fs_free_block_bitmap(ctx->block_found_map);
932         ctx->block_found_map = 0;
933         ext2fs_free_icount(ctx->inode_link_info);
934         ctx->inode_link_info = 0;
935         if (ctx->journal_io) {
936                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
937                         io_channel_close(ctx->journal_io);
938                 ctx->journal_io = 0;
939         }
940         if (ctx->fs) {
941                 ext2fs_free_dblist(ctx->fs->dblist);
942                 ctx->fs->dblist = 0;
943         }
944         e2fsck_free_dir_info(ctx);
945 #ifdef ENABLE_HTREE
946         e2fsck_free_dx_dir_info(ctx);
947 #endif
948         ea_refcount_free(ctx->refcount);
949         ctx->refcount = 0;
950         ea_refcount_free(ctx->refcount_extra);
951         ctx->refcount_extra = 0;
952         ext2fs_free_block_bitmap(ctx->block_dup_map);
953         ctx->block_dup_map = 0;
954         ext2fs_free_block_bitmap(ctx->block_ea_map);
955         ctx->block_ea_map = 0;
956         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
957         ctx->inode_bad_map = 0;
958         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
959         ctx->inode_imagic_map = 0;
960         ext2fs_u32_list_free(ctx->dirs_to_hash);
961         ctx->dirs_to_hash = 0;
962
963         /*
964          * Clear the array of invalid meta-data flags
965          */
966         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
967         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
968         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
969
970         /* Clear statistic counters */
971         ctx->fs_directory_count = 0;
972         ctx->fs_regular_count = 0;
973         ctx->fs_blockdev_count = 0;
974         ctx->fs_chardev_count = 0;
975         ctx->fs_links_count = 0;
976         ctx->fs_symlinks_count = 0;
977         ctx->fs_fast_symlinks_count = 0;
978         ctx->fs_fifo_count = 0;
979         ctx->fs_total_count = 0;
980         ctx->fs_sockets_count = 0;
981         ctx->fs_ind_count = 0;
982         ctx->fs_dind_count = 0;
983         ctx->fs_tind_count = 0;
984         ctx->fs_fragmented = 0;
985         ctx->large_files = 0;
986
987         /* Reset the superblock to the user's requested value */
988         ctx->superblock = ctx->use_superblock;
989
990         return 0;
991 }
992
993 static void e2fsck_free_context(e2fsck_t ctx)
994 {
995         if (!ctx)
996                 return;
997
998         e2fsck_reset_context(ctx);
999         if (ctx->blkid)
1000                 blkid_put_cache(ctx->blkid);
1001
1002         ext2fs_free_mem(&ctx);
1003 }
1004
1005 /*
1006  * ea_refcount.c
1007  */
1008
1009 /*
1010  * The strategy we use for keeping track of EA refcounts is as
1011  * follows.  We keep a sorted array of first EA blocks and its
1012  * reference counts.  Once the refcount has dropped to zero, it is
1013  * removed from the array to save memory space.  Once the EA block is
1014  * checked, its bit is set in the block_ea_map bitmap.
1015  */
1016
1017
1018 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1019 {
1020         ext2_refcount_t refcount;
1021         errcode_t       retval;
1022         size_t          bytes;
1023
1024         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1025         if (retval)
1026                 return retval;
1027         memset(refcount, 0, sizeof(struct ea_refcount));
1028
1029         if (!size)
1030                 size = 500;
1031         refcount->size = size;
1032         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1033 #ifdef DEBUG
1034         printf("Refcount allocated %d entries, %d bytes.\n",
1035                refcount->size, bytes);
1036 #endif
1037         retval = ext2fs_get_mem(bytes, &refcount->list);
1038         if (retval)
1039                 goto errout;
1040         memset(refcount->list, 0, bytes);
1041
1042         refcount->count = 0;
1043         refcount->cursor = 0;
1044
1045         *ret = refcount;
1046         return 0;
1047
1048 errout:
1049         ea_refcount_free(refcount);
1050         return retval;
1051 }
1052
1053 /*
1054  * collapse_refcount() --- go through the refcount array, and get rid
1055  * of any count == zero entries
1056  */
1057 static void refcount_collapse(ext2_refcount_t refcount)
1058 {
1059         unsigned int    i, j;
1060         struct ea_refcount_el   *list;
1061
1062         list = refcount->list;
1063         for (i = 0, j = 0; i < refcount->count; i++) {
1064                 if (list[i].ea_count) {
1065                         if (i != j)
1066                                 list[j] = list[i];
1067                         j++;
1068                 }
1069         }
1070 #if defined(DEBUG) || defined(TEST_PROGRAM)
1071         printf("Refcount_collapse: size was %d, now %d\n",
1072                refcount->count, j);
1073 #endif
1074         refcount->count = j;
1075 }
1076
1077
1078 /*
1079  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1080  *      specified position.
1081  */
1082 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1083                                                  blk_t blk, int pos)
1084 {
1085         struct ea_refcount_el   *el;
1086         errcode_t               retval;
1087         blk_t                   new_size = 0;
1088         int                     num;
1089
1090         if (refcount->count >= refcount->size) {
1091                 new_size = refcount->size + 100;
1092 #ifdef DEBUG
1093                 printf("Reallocating refcount %d entries...\n", new_size);
1094 #endif
1095                 retval = ext2fs_resize_mem((size_t) refcount->size *
1096                                            sizeof(struct ea_refcount_el),
1097                                            (size_t) new_size *
1098                                            sizeof(struct ea_refcount_el),
1099                                            &refcount->list);
1100                 if (retval)
1101                         return 0;
1102                 refcount->size = new_size;
1103         }
1104         num = (int) refcount->count - pos;
1105         if (num < 0)
1106                 return 0;       /* should never happen */
1107         if (num) {
1108                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1109                         sizeof(struct ea_refcount_el) * num);
1110         }
1111         refcount->count++;
1112         el = &refcount->list[pos];
1113         el->ea_count = 0;
1114         el->ea_blk = blk;
1115         return el;
1116 }
1117
1118
1119 /*
1120  * get_refcount_el() --- given an block number, try to find refcount
1121  *      information in the sorted list.  If the create flag is set,
1122  *      and we can't find an entry, create one in the sorted list.
1123  */
1124 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1125                                               blk_t blk, int create)
1126 {
1127         float   range;
1128         int     low, high, mid;
1129         blk_t   lowval, highval;
1130
1131         if (!refcount || !refcount->list)
1132                 return 0;
1133 retry:
1134         low = 0;
1135         high = (int) refcount->count-1;
1136         if (create && ((refcount->count == 0) ||
1137                        (blk > refcount->list[high].ea_blk))) {
1138                 if (refcount->count >= refcount->size)
1139                         refcount_collapse(refcount);
1140
1141                 return insert_refcount_el(refcount, blk,
1142                                           (unsigned) refcount->count);
1143         }
1144         if (refcount->count == 0)
1145                 return 0;
1146
1147         if (refcount->cursor >= refcount->count)
1148                 refcount->cursor = 0;
1149         if (blk == refcount->list[refcount->cursor].ea_blk)
1150                 return &refcount->list[refcount->cursor++];
1151 #ifdef DEBUG
1152         printf("Non-cursor get_refcount_el: %u\n", blk);
1153 #endif
1154         while (low <= high) {
1155                 if (low == high)
1156                         mid = low;
1157                 else {
1158                         /* Interpolate for efficiency */
1159                         lowval = refcount->list[low].ea_blk;
1160                         highval = refcount->list[high].ea_blk;
1161
1162                         if (blk < lowval)
1163                                 range = 0;
1164                         else if (blk > highval)
1165                                 range = 1;
1166                         else
1167                                 range = ((float) (blk - lowval)) /
1168                                         (highval - lowval);
1169                         mid = low + ((int) (range * (high-low)));
1170                 }
1171
1172                 if (blk == refcount->list[mid].ea_blk) {
1173                         refcount->cursor = mid+1;
1174                         return &refcount->list[mid];
1175                 }
1176                 if (blk < refcount->list[mid].ea_blk)
1177                         high = mid-1;
1178                 else
1179                         low = mid+1;
1180         }
1181         /*
1182          * If we need to create a new entry, it should be right at
1183          * low (where high will be left at low-1).
1184          */
1185         if (create) {
1186                 if (refcount->count >= refcount->size) {
1187                         refcount_collapse(refcount);
1188                         if (refcount->count < refcount->size)
1189                                 goto retry;
1190                 }
1191                 return insert_refcount_el(refcount, blk, low);
1192         }
1193         return 0;
1194 }
1195
1196 static errcode_t
1197 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1198 {
1199         struct ea_refcount_el   *el;
1200
1201         el = get_refcount_el(refcount, blk, 1);
1202         if (!el)
1203                 return EXT2_ET_NO_MEMORY;
1204         el->ea_count++;
1205
1206         if (ret)
1207                 *ret = el->ea_count;
1208         return 0;
1209 }
1210
1211 static errcode_t
1212 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1213 {
1214         struct ea_refcount_el   *el;
1215
1216         el = get_refcount_el(refcount, blk, 0);
1217         if (!el || el->ea_count == 0)
1218                 return EXT2_ET_INVALID_ARGUMENT;
1219
1220         el->ea_count--;
1221
1222         if (ret)
1223                 *ret = el->ea_count;
1224         return 0;
1225 }
1226
1227 static errcode_t
1228 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1229 {
1230         struct ea_refcount_el   *el;
1231
1232         /*
1233          * Get the refcount element
1234          */
1235         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1236         if (!el)
1237                 return count ? EXT2_ET_NO_MEMORY : 0;
1238         el->ea_count = count;
1239         return 0;
1240 }
1241
1242 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1243 {
1244         refcount->cursor = 0;
1245 }
1246
1247
1248 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1249 {
1250         struct ea_refcount_el   *list;
1251
1252         while (1) {
1253                 if (refcount->cursor >= refcount->count)
1254                         return 0;
1255                 list = refcount->list;
1256                 if (list[refcount->cursor].ea_count) {
1257                         if (ret)
1258                                 *ret = list[refcount->cursor].ea_count;
1259                         return list[refcount->cursor++].ea_blk;
1260                 }
1261                 refcount->cursor++;
1262         }
1263 }
1264
1265
1266 /*
1267  * ehandler.c --- handle bad block errors which come up during the
1268  *      course of an e2fsck session.
1269  */
1270
1271
1272 static const char *operation;
1273
1274 static errcode_t
1275 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1276                          void *data, size_t size FSCK_ATTR((unused)),
1277                          int actual FSCK_ATTR((unused)), errcode_t error)
1278 {
1279         int     i;
1280         char    *p;
1281         ext2_filsys fs = (ext2_filsys) channel->app_data;
1282         e2fsck_t ctx;
1283
1284         ctx = (e2fsck_t) fs->priv_data;
1285
1286         /*
1287          * If more than one block was read, try reading each block
1288          * separately.  We could use the actual bytes read to figure
1289          * out where to start, but we don't bother.
1290          */
1291         if (count > 1) {
1292                 p = (char *) data;
1293                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1294                         error = io_channel_read_blk(channel, block,
1295                                                     1, p);
1296                         if (error)
1297                                 return error;
1298                 }
1299                 return 0;
1300         }
1301         if (operation)
1302                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1303                        error_message(error), operation);
1304         else
1305                 printf(_("Error reading block %lu (%s).  "), block,
1306                        error_message(error));
1307         preenhalt(ctx);
1308         if (ask(ctx, _("Ignore error"), 1)) {
1309                 if (ask(ctx, _("Force rewrite"), 1))
1310                         io_channel_write_blk(channel, block, 1, data);
1311                 return 0;
1312         }
1313
1314         return error;
1315 }
1316
1317 static errcode_t
1318 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1319                         const void *data, size_t size FSCK_ATTR((unused)),
1320                         int actual FSCK_ATTR((unused)), errcode_t error)
1321 {
1322         int             i;
1323         const char      *p;
1324         ext2_filsys fs = (ext2_filsys) channel->app_data;
1325         e2fsck_t ctx;
1326
1327         ctx = (e2fsck_t) fs->priv_data;
1328
1329         /*
1330          * If more than one block was written, try writing each block
1331          * separately.  We could use the actual bytes read to figure
1332          * out where to start, but we don't bother.
1333          */
1334         if (count > 1) {
1335                 p = (const char *) data;
1336                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1337                         error = io_channel_write_blk(channel, block,
1338                                                      1, p);
1339                         if (error)
1340                                 return error;
1341                 }
1342                 return 0;
1343         }
1344
1345         if (operation)
1346                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1347                        error_message(error), operation);
1348         else
1349                 printf(_("Error writing block %lu (%s).  "), block,
1350                        error_message(error));
1351         preenhalt(ctx);
1352         if (ask(ctx, _("Ignore error"), 1))
1353                 return 0;
1354
1355         return error;
1356 }
1357
1358 static const char *ehandler_operation(const char *op)
1359 {
1360         const char *ret = operation;
1361
1362         operation = op;
1363         return ret;
1364 }
1365
1366 static void ehandler_init(io_channel channel)
1367 {
1368         channel->read_error = e2fsck_handle_read_error;
1369         channel->write_error = e2fsck_handle_write_error;
1370 }
1371
1372 /*
1373  * journal.c --- code for handling the "ext3" journal
1374  *
1375  * Copyright (C) 2000 Andreas Dilger
1376  * Copyright (C) 2000 Theodore Ts'o
1377  *
1378  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1379  * Copyright (C) 1999 Red Hat Software
1380  *
1381  * This file may be redistributed under the terms of the
1382  * GNU General Public License version 2 or at your discretion
1383  * any later version.
1384  */
1385
1386 /*
1387  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1388  * This creates a larger static binary, and a smaller binary using
1389  * shared libraries.  It's also probably slightly less CPU-efficient,
1390  * which is why it's not on by default.  But, it's a good way of
1391  * testing the functions in inode_io.c and fileio.c.
1392  */
1393 #undef USE_INODE_IO
1394
1395 /* Kernel compatibility functions for handling the journal.  These allow us
1396  * to use the recovery.c file virtually unchanged from the kernel, so we
1397  * don't have to do much to keep kernel and user recovery in sync.
1398  */
1399 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1400 {
1401 #ifdef USE_INODE_IO
1402         *phys = block;
1403         return 0;
1404 #else
1405         struct inode    *inode = journal->j_inode;
1406         errcode_t       retval;
1407         blk_t           pblk;
1408
1409         if (!inode) {
1410                 *phys = block;
1411                 return 0;
1412         }
1413
1414         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1415                             &inode->i_ext2, NULL, 0, block, &pblk);
1416         *phys = pblk;
1417         return retval;
1418 #endif
1419 }
1420
1421 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1422 {
1423         struct buffer_head *bh;
1424
1425         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1426         if (!bh)
1427                 return NULL;
1428
1429         bh->b_ctx = kdev->k_ctx;
1430         if (kdev->k_dev == K_DEV_FS)
1431                 bh->b_io = kdev->k_ctx->fs->io;
1432         else
1433                 bh->b_io = kdev->k_ctx->journal_io;
1434         bh->b_size = blocksize;
1435         bh->b_blocknr = blocknr;
1436
1437         return bh;
1438 }
1439
1440 static void sync_blockdev(kdev_t kdev)
1441 {
1442         io_channel      io;
1443
1444         if (kdev->k_dev == K_DEV_FS)
1445                 io = kdev->k_ctx->fs->io;
1446         else
1447                 io = kdev->k_ctx->journal_io;
1448
1449         io_channel_flush(io);
1450 }
1451
1452 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1453 {
1454         int retval;
1455         struct buffer_head *bh;
1456
1457         for (; nr > 0; --nr) {
1458                 bh = *bhp++;
1459                 if (rw == READ && !bh->b_uptodate) {
1460                         retval = io_channel_read_blk(bh->b_io,
1461                                                      bh->b_blocknr,
1462                                                      1, bh->b_data);
1463                         if (retval) {
1464                                 bb_error_msg("while reading block %lu",
1465                                         (unsigned long) bh->b_blocknr);
1466                                 bh->b_err = retval;
1467                                 continue;
1468                         }
1469                         bh->b_uptodate = 1;
1470                 } else if (rw == WRITE && bh->b_dirty) {
1471                         retval = io_channel_write_blk(bh->b_io,
1472                                                       bh->b_blocknr,
1473                                                       1, bh->b_data);
1474                         if (retval) {
1475                                 bb_error_msg("while writing block %lu",
1476                                         (unsigned long) bh->b_blocknr);
1477                                 bh->b_err = retval;
1478                                 continue;
1479                         }
1480                         bh->b_dirty = 0;
1481                         bh->b_uptodate = 1;
1482                 }
1483         }
1484 }
1485
1486 static void mark_buffer_dirty(struct buffer_head *bh)
1487 {
1488         bh->b_dirty = 1;
1489 }
1490
1491 static inline void mark_buffer_clean(struct buffer_head * bh)
1492 {
1493         bh->b_dirty = 0;
1494 }
1495
1496 static void brelse(struct buffer_head *bh)
1497 {
1498         if (bh->b_dirty)
1499                 ll_rw_block(WRITE, 1, &bh);
1500         ext2fs_free_mem(&bh);
1501 }
1502
1503 static int buffer_uptodate(struct buffer_head *bh)
1504 {
1505         return bh->b_uptodate;
1506 }
1507
1508 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1509 {
1510         bh->b_uptodate = val;
1511 }
1512
1513 static void wait_on_buffer(struct buffer_head *bh)
1514 {
1515         if (!bh->b_uptodate)
1516                 ll_rw_block(READ, 1, &bh);
1517 }
1518
1519
1520 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1521 {
1522         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1523
1524         /* if we had an error doing journal recovery, we need a full fsck */
1525         if (error)
1526                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1527         ext2fs_mark_super_dirty(ctx->fs);
1528 }
1529
1530 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1531 {
1532         struct ext2_super_block *sb = ctx->fs->super;
1533         struct ext2_super_block jsuper;
1534         struct problem_context  pctx;
1535         struct buffer_head      *bh;
1536         struct inode            *j_inode = NULL;
1537         struct kdev_s           *dev_fs = NULL, *dev_journal;
1538         const char              *journal_name = NULL;
1539         journal_t               *journal = NULL;
1540         errcode_t               retval = 0;
1541         io_manager              io_ptr = 0;
1542         unsigned long           start = 0;
1543         blk_t                   blk;
1544         int                     ext_journal = 0;
1545         int                     tried_backup_jnl = 0;
1546         int                     i;
1547
1548         clear_problem_context(&pctx);
1549
1550         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1551         if (!journal) {
1552                 return EXT2_ET_NO_MEMORY;
1553         }
1554
1555         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1556         if (!dev_fs) {
1557                 retval = EXT2_ET_NO_MEMORY;
1558                 goto errout;
1559         }
1560         dev_journal = dev_fs+1;
1561
1562         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1563         dev_fs->k_dev = K_DEV_FS;
1564         dev_journal->k_dev = K_DEV_JOURNAL;
1565
1566         journal->j_dev = dev_journal;
1567         journal->j_fs_dev = dev_fs;
1568         journal->j_inode = NULL;
1569         journal->j_blocksize = ctx->fs->blocksize;
1570
1571         if (uuid_is_null(sb->s_journal_uuid)) {
1572                 if (!sb->s_journal_inum)
1573                         return EXT2_ET_BAD_INODE_NUM;
1574                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1575                                                  "journal inode");
1576                 if (!j_inode) {
1577                         retval = EXT2_ET_NO_MEMORY;
1578                         goto errout;
1579                 }
1580
1581                 j_inode->i_ctx = ctx;
1582                 j_inode->i_ino = sb->s_journal_inum;
1583
1584                 if ((retval = ext2fs_read_inode(ctx->fs,
1585                                                 sb->s_journal_inum,
1586                                                 &j_inode->i_ext2))) {
1587                 try_backup_journal:
1588                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1589                             tried_backup_jnl)
1590                                 goto errout;
1591                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1592                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1593                                EXT2_N_BLOCKS*4);
1594                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1595                         j_inode->i_ext2.i_links_count = 1;
1596                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1597                         tried_backup_jnl++;
1598                 }
1599                 if (!j_inode->i_ext2.i_links_count ||
1600                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1601                         retval = EXT2_ET_NO_JOURNAL;
1602                         goto try_backup_journal;
1603                 }
1604                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1605                     JFS_MIN_JOURNAL_BLOCKS) {
1606                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1607                         goto try_backup_journal;
1608                 }
1609                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1610                         blk = j_inode->i_ext2.i_block[i];
1611                         if (!blk) {
1612                                 if (i < EXT2_NDIR_BLOCKS) {
1613                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1614                                         goto try_backup_journal;
1615                                 }
1616                                 continue;
1617                         }
1618                         if (blk < sb->s_first_data_block ||
1619                             blk >= sb->s_blocks_count) {
1620                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1621                                 goto try_backup_journal;
1622                         }
1623                 }
1624                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1625
1626 #ifdef USE_INODE_IO
1627                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1628                                                  &j_inode->i_ext2,
1629                                                  &journal_name);
1630                 if (retval)
1631                         goto errout;
1632
1633                 io_ptr = inode_io_manager;
1634 #else
1635                 journal->j_inode = j_inode;
1636                 ctx->journal_io = ctx->fs->io;
1637                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1638                         goto errout;
1639 #endif
1640         } else {
1641                 ext_journal = 1;
1642                 if (!ctx->journal_name) {
1643                         char uuid[37];
1644
1645                         uuid_unparse(sb->s_journal_uuid, uuid);
1646                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1647                                                               "UUID", uuid);
1648                         if (!ctx->journal_name)
1649                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1650                 }
1651                 journal_name = ctx->journal_name;
1652
1653                 if (!journal_name) {
1654                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1655                         return EXT2_ET_LOAD_EXT_JOURNAL;
1656                 }
1657
1658                 io_ptr = unix_io_manager;
1659         }
1660
1661 #ifndef USE_INODE_IO
1662         if (ext_journal)
1663 #endif
1664                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1665                                       &ctx->journal_io);
1666         if (retval)
1667                 goto errout;
1668
1669         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1670
1671         if (ext_journal) {
1672                 if (ctx->fs->blocksize == 1024)
1673                         start = 1;
1674                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1675                 if (!bh) {
1676                         retval = EXT2_ET_NO_MEMORY;
1677                         goto errout;
1678                 }
1679                 ll_rw_block(READ, 1, &bh);
1680                 if ((retval = bh->b_err) != 0)
1681                         goto errout;
1682                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1683                        sizeof(jsuper));
1684                 brelse(bh);
1685 #if BB_BIG_ENDIAN
1686                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1687                         ext2fs_swap_super(&jsuper);
1688 #endif
1689                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1690                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1691                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1692                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1693                         goto errout;
1694                 }
1695                 /* Make sure the journal UUID is correct */
1696                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1697                            sizeof(jsuper.s_uuid))) {
1698                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1699                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1700                         goto errout;
1701                 }
1702
1703                 journal->j_maxlen = jsuper.s_blocks_count;
1704                 start++;
1705         }
1706
1707         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1708                 retval = EXT2_ET_NO_MEMORY;
1709                 goto errout;
1710         }
1711
1712         journal->j_sb_buffer = bh;
1713         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1714
1715 #ifdef USE_INODE_IO
1716         ext2fs_free_mem(&j_inode);
1717 #endif
1718
1719         *ret_journal = journal;
1720         return 0;
1721
1722 errout:
1723         ext2fs_free_mem(&dev_fs);
1724         ext2fs_free_mem(&j_inode);
1725         ext2fs_free_mem(&journal);
1726         return retval;
1727
1728 }
1729
1730 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1731                                               struct problem_context *pctx)
1732 {
1733         struct ext2_super_block *sb = ctx->fs->super;
1734         int recover = ctx->fs->super->s_feature_incompat &
1735                 EXT3_FEATURE_INCOMPAT_RECOVER;
1736         int has_journal = ctx->fs->super->s_feature_compat &
1737                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1738
1739         if (has_journal || sb->s_journal_inum) {
1740                 /* The journal inode is bogus, remove and force full fsck */
1741                 pctx->ino = sb->s_journal_inum;
1742                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1743                         if (has_journal && sb->s_journal_inum)
1744                                 printf("*** ext3 journal has been deleted - "
1745                                        "filesystem is now ext2 only ***\n\n");
1746                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1747                         sb->s_journal_inum = 0;
1748                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1749                         e2fsck_clear_recover(ctx, 1);
1750                         return 0;
1751                 }
1752                 return EXT2_ET_BAD_INODE_NUM;
1753         } else if (recover) {
1754                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1755                         e2fsck_clear_recover(ctx, 1);
1756                         return 0;
1757                 }
1758                 return EXT2_ET_UNSUPP_FEATURE;
1759         }
1760         return 0;
1761 }
1762
1763 #define V1_SB_SIZE      0x0024
1764 static void clear_v2_journal_fields(journal_t *journal)
1765 {
1766         e2fsck_t ctx = journal->j_dev->k_ctx;
1767         struct problem_context pctx;
1768
1769         clear_problem_context(&pctx);
1770
1771         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1772                 return;
1773
1774         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1775                ctx->fs->blocksize-V1_SB_SIZE);
1776         mark_buffer_dirty(journal->j_sb_buffer);
1777 }
1778
1779
1780 static errcode_t e2fsck_journal_load(journal_t *journal)
1781 {
1782         e2fsck_t ctx = journal->j_dev->k_ctx;
1783         journal_superblock_t *jsb;
1784         struct buffer_head *jbh = journal->j_sb_buffer;
1785         struct problem_context pctx;
1786
1787         clear_problem_context(&pctx);
1788
1789         ll_rw_block(READ, 1, &jbh);
1790         if (jbh->b_err) {
1791                 bb_error_msg(_("reading journal superblock"));
1792                 return jbh->b_err;
1793         }
1794
1795         jsb = journal->j_superblock;
1796         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1797         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1798                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1799
1800         switch (ntohl(jsb->s_header.h_blocktype)) {
1801         case JFS_SUPERBLOCK_V1:
1802                 journal->j_format_version = 1;
1803                 if (jsb->s_feature_compat ||
1804                     jsb->s_feature_incompat ||
1805                     jsb->s_feature_ro_compat ||
1806                     jsb->s_nr_users)
1807                         clear_v2_journal_fields(journal);
1808                 break;
1809
1810         case JFS_SUPERBLOCK_V2:
1811                 journal->j_format_version = 2;
1812                 if (ntohl(jsb->s_nr_users) > 1 &&
1813                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1814                         clear_v2_journal_fields(journal);
1815                 if (ntohl(jsb->s_nr_users) > 1) {
1816                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1817                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1818                 }
1819                 break;
1820
1821         /*
1822          * These should never appear in a journal super block, so if
1823          * they do, the journal is badly corrupted.
1824          */
1825         case JFS_DESCRIPTOR_BLOCK:
1826         case JFS_COMMIT_BLOCK:
1827         case JFS_REVOKE_BLOCK:
1828                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1829
1830         /* If we don't understand the superblock major type, but there
1831          * is a magic number, then it is likely to be a new format we
1832          * just don't understand, so leave it alone. */
1833         default:
1834                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1835         }
1836
1837         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1838                 return EXT2_ET_UNSUPP_FEATURE;
1839
1840         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1841                 return EXT2_ET_RO_UNSUPP_FEATURE;
1842
1843         /* We have now checked whether we know enough about the journal
1844          * format to be able to proceed safely, so any other checks that
1845          * fail we should attempt to recover from. */
1846         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1847                 bb_error_msg(_("%s: no valid journal superblock found"),
1848                         ctx->device_name);
1849                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1850         }
1851
1852         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1853                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1854         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1855                 bb_error_msg(_("%s: journal too short"),
1856                         ctx->device_name);
1857                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1858         }
1859
1860         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1861         journal->j_transaction_sequence = journal->j_tail_sequence;
1862         journal->j_tail = ntohl(jsb->s_start);
1863         journal->j_first = ntohl(jsb->s_first);
1864         journal->j_last = ntohl(jsb->s_maxlen);
1865
1866         return 0;
1867 }
1868
1869 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1870                                        journal_t *journal)
1871 {
1872         char *p;
1873         union {
1874                 uuid_t uuid;
1875                 __u32 val[4];
1876         } u;
1877         __u32 new_seq = 0;
1878         int i;
1879
1880         /* Leave a valid existing V1 superblock signature alone.
1881          * Anything unrecognizable we overwrite with a new V2
1882          * signature. */
1883
1884         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1885             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1886                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1887                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1888         }
1889
1890         /* Zero out everything else beyond the superblock header */
1891
1892         p = ((char *) jsb) + sizeof(journal_header_t);
1893         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1894
1895         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1896         jsb->s_maxlen = htonl(journal->j_maxlen);
1897         jsb->s_first = htonl(1);
1898
1899         /* Initialize the journal sequence number so that there is "no"
1900          * chance we will find old "valid" transactions in the journal.
1901          * This avoids the need to zero the whole journal (slow to do,
1902          * and risky when we are just recovering the filesystem).
1903          */
1904         uuid_generate(u.uuid);
1905         for (i = 0; i < 4; i ++)
1906                 new_seq ^= u.val[i];
1907         jsb->s_sequence = htonl(new_seq);
1908
1909         mark_buffer_dirty(journal->j_sb_buffer);
1910         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1911 }
1912
1913 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1914                                                   journal_t *journal,
1915                                                   struct problem_context *pctx)
1916 {
1917         struct ext2_super_block *sb = ctx->fs->super;
1918         int recover = ctx->fs->super->s_feature_incompat &
1919                 EXT3_FEATURE_INCOMPAT_RECOVER;
1920
1921         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1922                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1923                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1924                                                    journal);
1925                         journal->j_transaction_sequence = 1;
1926                         e2fsck_clear_recover(ctx, recover);
1927                         return 0;
1928                 }
1929                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1930         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1931                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1932
1933         return 0;
1934 }
1935
1936 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1937                                    int reset, int drop)
1938 {
1939         journal_superblock_t *jsb;
1940
1941         if (drop)
1942                 mark_buffer_clean(journal->j_sb_buffer);
1943         else if (!(ctx->options & E2F_OPT_READONLY)) {
1944                 jsb = journal->j_superblock;
1945                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1946                 if (reset)
1947                         jsb->s_start = 0; /* this marks the journal as empty */
1948                 mark_buffer_dirty(journal->j_sb_buffer);
1949         }
1950         brelse(journal->j_sb_buffer);
1951
1952         if (ctx->journal_io) {
1953                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1954                         io_channel_close(ctx->journal_io);
1955                 ctx->journal_io = 0;
1956         }
1957
1958 #ifndef USE_INODE_IO
1959         ext2fs_free_mem(&journal->j_inode);
1960 #endif
1961         ext2fs_free_mem(&journal->j_fs_dev);
1962         ext2fs_free_mem(&journal);
1963 }
1964
1965 /*
1966  * This function makes sure that the superblock fields regarding the
1967  * journal are consistent.
1968  */
1969 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1970 {
1971         struct ext2_super_block *sb = ctx->fs->super;
1972         journal_t *journal;
1973         int recover = ctx->fs->super->s_feature_incompat &
1974                 EXT3_FEATURE_INCOMPAT_RECOVER;
1975         struct problem_context pctx;
1976         problem_t problem;
1977         int reset = 0, force_fsck = 0;
1978         int retval;
1979
1980         /* If we don't have any journal features, don't do anything more */
1981         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1982             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1983             uuid_is_null(sb->s_journal_uuid))
1984                 return 0;
1985
1986         clear_problem_context(&pctx);
1987         pctx.num = sb->s_journal_inum;
1988
1989         retval = e2fsck_get_journal(ctx, &journal);
1990         if (retval) {
1991                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1992                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1993                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1994                     (retval == EXT2_ET_NO_JOURNAL))
1995                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1996                 return retval;
1997         }
1998
1999         retval = e2fsck_journal_load(journal);
2000         if (retval) {
2001                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2002                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2003                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2004                                   &pctx))) ||
2005                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2006                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2007                                   &pctx))) ||
2008                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2009                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2010                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2011                                                                   &pctx);
2012                 e2fsck_journal_release(ctx, journal, 0, 1);
2013                 return retval;
2014         }
2015
2016         /*
2017          * We want to make the flags consistent here.  We will not leave with
2018          * needs_recovery set but has_journal clear.  We can't get in a loop
2019          * with -y, -n, or -p, only if a user isn't making up their mind.
2020          */
2021 no_has_journal:
2022         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2023                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2024                 pctx.str = "inode";
2025                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2026                         if (recover &&
2027                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2028                                 goto no_has_journal;
2029                         /*
2030                          * Need a full fsck if we are releasing a
2031                          * journal stored on a reserved inode.
2032                          */
2033                         force_fsck = recover ||
2034                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2035                         /* Clear all of the journal fields */
2036                         sb->s_journal_inum = 0;
2037                         sb->s_journal_dev = 0;
2038                         memset(sb->s_journal_uuid, 0,
2039                                sizeof(sb->s_journal_uuid));
2040                         e2fsck_clear_recover(ctx, force_fsck);
2041                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2042                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2043                         ext2fs_mark_super_dirty(ctx->fs);
2044                 }
2045         }
2046
2047         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2048             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2049             journal->j_superblock->s_start != 0) {
2050                 /* Print status information */
2051                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2052                 if (ctx->superblock)
2053                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2054                 else
2055                         problem = PR_0_JOURNAL_RUN;
2056                 if (fix_problem(ctx, problem, &pctx)) {
2057                         ctx->options |= E2F_OPT_FORCE;
2058                         sb->s_feature_incompat |=
2059                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2060                         ext2fs_mark_super_dirty(ctx->fs);
2061                 } else if (fix_problem(ctx,
2062                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2063                         reset = 1;
2064                         sb->s_state &= ~EXT2_VALID_FS;
2065                         ext2fs_mark_super_dirty(ctx->fs);
2066                 }
2067                 /*
2068                  * If the user answers no to the above question, we
2069                  * ignore the fact that journal apparently has data;
2070                  * accidentally replaying over valid data would be far
2071                  * worse than skipping a questionable recovery.
2072                  *
2073                  * XXX should we abort with a fatal error here?  What
2074                  * will the ext3 kernel code do if a filesystem with
2075                  * !NEEDS_RECOVERY but with a non-zero
2076                  * journal->j_superblock->s_start is mounted?
2077                  */
2078         }
2079
2080         e2fsck_journal_release(ctx, journal, reset, 0);
2081         return retval;
2082 }
2083
2084 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2085 {
2086         journal_t *journal;
2087         int retval;
2088
2089         journal_init_revoke_caches();
2090         retval = e2fsck_get_journal(ctx, &journal);
2091         if (retval)
2092                 return retval;
2093
2094         retval = e2fsck_journal_load(journal);
2095         if (retval)
2096                 goto errout;
2097
2098         retval = journal_init_revoke(journal, 1024);
2099         if (retval)
2100                 goto errout;
2101
2102         retval = -journal_recover(journal);
2103         if (retval)
2104                 goto errout;
2105
2106         if (journal->j_superblock->s_errno) {
2107                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2108                 ext2fs_mark_super_dirty(ctx->fs);
2109                 journal->j_superblock->s_errno = 0;
2110                 mark_buffer_dirty(journal->j_sb_buffer);
2111         }
2112
2113 errout:
2114         journal_destroy_revoke(journal);
2115         journal_destroy_revoke_caches();
2116         e2fsck_journal_release(ctx, journal, 1, 0);
2117         return retval;
2118 }
2119
2120 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2121 {
2122         io_manager io_ptr = ctx->fs->io->manager;
2123         int blocksize = ctx->fs->blocksize;
2124         errcode_t       retval, recover_retval;
2125
2126         printf(_("%s: recovering journal\n"), ctx->device_name);
2127         if (ctx->options & E2F_OPT_READONLY) {
2128                 printf(_("%s: won't do journal recovery while read-only\n"),
2129                        ctx->device_name);
2130                 return EXT2_ET_FILE_RO;
2131         }
2132
2133         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2134                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2135
2136         recover_retval = recover_ext3_journal(ctx);
2137
2138         /*
2139          * Reload the filesystem context to get up-to-date data from disk
2140          * because journal recovery will change the filesystem under us.
2141          */
2142         ext2fs_close(ctx->fs);
2143         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2144                              ctx->superblock, blocksize, io_ptr,
2145                              &ctx->fs);
2146
2147         if (retval) {
2148                 bb_error_msg(_("while trying to re-open %s"),
2149                         ctx->device_name);
2150                 bb_error_msg_and_die(0);
2151         }
2152         ctx->fs->priv_data = ctx;
2153
2154         /* Set the superblock flags */
2155         e2fsck_clear_recover(ctx, recover_retval);
2156         return recover_retval;
2157 }
2158
2159 /*
2160  * This function will move the journal inode from a visible file in
2161  * the filesystem directory hierarchy to the reserved inode if necessary.
2162  */
2163 static const char *const journal_names[] = {
2164         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2165
2166 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2167 {
2168         struct ext2_super_block *sb = ctx->fs->super;
2169         struct problem_context  pctx;
2170         struct ext2_inode       inode;
2171         ext2_filsys             fs = ctx->fs;
2172         ext2_ino_t              ino;
2173         errcode_t               retval;
2174         const char *const *    cpp;
2175         int                     group, mount_flags;
2176
2177         clear_problem_context(&pctx);
2178
2179         /*
2180          * If the filesystem is opened read-only, or there is no
2181          * journal, then do nothing.
2182          */
2183         if ((ctx->options & E2F_OPT_READONLY) ||
2184             (sb->s_journal_inum == 0) ||
2185             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2186                 return;
2187
2188         /*
2189          * Read in the journal inode
2190          */
2191         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2192                 return;
2193
2194         /*
2195          * If it's necessary to backup the journal inode, do so.
2196          */
2197         if ((sb->s_jnl_backup_type == 0) ||
2198             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2199              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2200                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2201                         memcpy(sb->s_jnl_blocks, inode.i_block,
2202                                EXT2_N_BLOCKS*4);
2203                         sb->s_jnl_blocks[16] = inode.i_size;
2204                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2205                         ext2fs_mark_super_dirty(fs);
2206                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2207                 }
2208         }
2209
2210         /*
2211          * If the journal is already the hidden inode, then do nothing
2212          */
2213         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2214                 return;
2215
2216         /*
2217          * The journal inode had better have only one link and not be readable.
2218          */
2219         if (inode.i_links_count != 1)
2220                 return;
2221
2222         /*
2223          * If the filesystem is mounted, or we can't tell whether
2224          * or not it's mounted, do nothing.
2225          */
2226         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2227         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2228                 return;
2229
2230         /*
2231          * If we can't find the name of the journal inode, then do
2232          * nothing.
2233          */
2234         for (cpp = journal_names; *cpp; cpp++) {
2235                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2236                                        strlen(*cpp), 0, &ino);
2237                 if ((retval == 0) && (ino == sb->s_journal_inum))
2238                         break;
2239         }
2240         if (*cpp == 0)
2241                 return;
2242
2243         /* We need the inode bitmap to be loaded */
2244         retval = ext2fs_read_bitmaps(fs);
2245         if (retval)
2246                 return;
2247
2248         pctx.str = *cpp;
2249         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2250                 return;
2251
2252         /*
2253          * OK, we've done all the checks, let's actually move the
2254          * journal inode.  Errors at this point mean we need to force
2255          * an ext2 filesystem check.
2256          */
2257         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2258                 goto err_out;
2259         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2260                 goto err_out;
2261         sb->s_journal_inum = EXT2_JOURNAL_INO;
2262         ext2fs_mark_super_dirty(fs);
2263         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2264         inode.i_links_count = 0;
2265         inode.i_dtime = time(NULL);
2266         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2267                 goto err_out;
2268
2269         group = ext2fs_group_of_ino(fs, ino);
2270         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2271         ext2fs_mark_ib_dirty(fs);
2272         fs->group_desc[group].bg_free_inodes_count++;
2273         fs->super->s_free_inodes_count++;
2274         return;
2275
2276 err_out:
2277         pctx.errcode = retval;
2278         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2279         fs->super->s_state &= ~EXT2_VALID_FS;
2280         ext2fs_mark_super_dirty(fs);
2281 }
2282
2283 /*
2284  * message.c --- print e2fsck messages (with compression)
2285  *
2286  * print_e2fsck_message() prints a message to the user, using
2287  * compression techniques and expansions of abbreviations.
2288  *
2289  * The following % expansions are supported:
2290  *
2291  *      %b      <blk>                   block number
2292  *      %B      <blkcount>              integer
2293  *      %c      <blk2>                  block number
2294  *      %Di     <dirent>->ino           inode number
2295  *      %Dn     <dirent>->name          string
2296  *      %Dr     <dirent>->rec_len
2297  *      %Dl     <dirent>->name_len
2298  *      %Dt     <dirent>->filetype
2299  *      %d      <dir>                   inode number
2300  *      %g      <group>                 integer
2301  *      %i      <ino>                   inode number
2302  *      %Is     <inode> -> i_size
2303  *      %IS     <inode> -> i_extra_isize
2304  *      %Ib     <inode> -> i_blocks
2305  *      %Il     <inode> -> i_links_count
2306  *      %Im     <inode> -> i_mode
2307  *      %IM     <inode> -> i_mtime
2308  *      %IF     <inode> -> i_faddr
2309  *      %If     <inode> -> i_file_acl
2310  *      %Id     <inode> -> i_dir_acl
2311  *      %Iu     <inode> -> i_uid
2312  *      %Ig     <inode> -> i_gid
2313  *      %j      <ino2>                  inode number
2314  *      %m      <com_err error message>
2315  *      %N      <num>
2316  *      %p      ext2fs_get_pathname of directory <ino>
2317  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2318  *                      the containing directory.  (If dirent is NULL
2319  *                      then return the pathname of directory <ino2>)
2320  *      %q      ext2fs_get_pathname of directory <dir>
2321  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2322  *                      the containing directory.
2323  *      %s      <str>                   miscellaneous string
2324  *      %S      backup superblock
2325  *      %X      <num> hexadecimal format
2326  *
2327  * The following '@' expansions are supported:
2328  *
2329  *      @a      extended attribute
2330  *      @A      error allocating
2331  *      @b      block
2332  *      @B      bitmap
2333  *      @c      compress
2334  *      @C      conflicts with some other fs block
2335  *      @D      deleted
2336  *      @d      directory
2337  *      @e      entry
2338  *      @E      Entry '%Dn' in %p (%i)
2339  *      @f      filesystem
2340  *      @F      for @i %i (%Q) is
2341  *      @g      group
2342  *      @h      HTREE directory inode
2343  *      @i      inode
2344  *      @I      illegal
2345  *      @j      journal
2346  *      @l      lost+found
2347  *      @L      is a link
2348  *      @m      multiply-claimed
2349  *      @n      invalid
2350  *      @o      orphaned
2351  *      @p      problem in
2352  *      @r      root inode
2353  *      @s      should be
2354  *      @S      superblock
2355  *      @u      unattached
2356  *      @v      device
2357  *      @z      zero-length
2358  */
2359
2360
2361 /*
2362  * This structure defines the abbreviations used by the text strings
2363  * below.  The first character in the string is the index letter.  An
2364  * abbreviation of the form '@<i>' is expanded by looking up the index
2365  * letter <i> in the table below.
2366  */
2367 static const char *const abbrevs[] = {
2368         N_("aextended attribute"),
2369         N_("Aerror allocating"),
2370         N_("bblock"),
2371         N_("Bbitmap"),
2372         N_("ccompress"),
2373         N_("Cconflicts with some other fs @b"),
2374         N_("iinode"),
2375         N_("Iillegal"),
2376         N_("jjournal"),
2377         N_("Ddeleted"),
2378         N_("ddirectory"),
2379         N_("eentry"),
2380         N_("E@e '%Dn' in %p (%i)"),
2381         N_("ffilesystem"),
2382         N_("Ffor @i %i (%Q) is"),
2383         N_("ggroup"),
2384         N_("hHTREE @d @i"),
2385         N_("llost+found"),
2386         N_("Lis a link"),
2387         N_("mmultiply-claimed"),
2388         N_("ninvalid"),
2389         N_("oorphaned"),
2390         N_("pproblem in"),
2391         N_("rroot @i"),
2392         N_("sshould be"),
2393         N_("Ssuper@b"),
2394         N_("uunattached"),
2395         N_("vdevice"),
2396         N_("zzero-length"),
2397         "@@",
2398         0
2399         };
2400
2401 /*
2402  * Give more user friendly names to the "special" inodes.
2403  */
2404 #define num_special_inodes      11
2405 static const char *const special_inode_name[] =
2406 {
2407         N_("<The NULL inode>"),                 /* 0 */
2408         N_("<The bad blocks inode>"),           /* 1 */
2409         "/",                                    /* 2 */
2410         N_("<The ACL index inode>"),            /* 3 */
2411         N_("<The ACL data inode>"),             /* 4 */
2412         N_("<The boot loader inode>"),          /* 5 */
2413         N_("<The undelete directory inode>"),   /* 6 */
2414         N_("<The group descriptor inode>"),     /* 7 */
2415         N_("<The journal inode>"),              /* 8 */
2416         N_("<Reserved inode 9>"),               /* 9 */
2417         N_("<Reserved inode 10>"),              /* 10 */
2418 };
2419
2420 /*
2421  * This function does "safe" printing.  It will convert non-printable
2422  * ASCII characters using '^' and M- notation.
2423  */
2424 static void safe_print(const char *cp, int len)
2425 {
2426         unsigned char   ch;
2427
2428         if (len < 0)
2429                 len = strlen(cp);
2430
2431         while (len--) {
2432                 ch = *cp++;
2433                 if (ch > 128) {
2434                         fputs("M-", stdout);
2435                         ch -= 128;
2436                 }
2437                 if ((ch < 32) || (ch == 0x7f)) {
2438                         bb_putchar('^');
2439                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2440                 }
2441                 bb_putchar(ch);
2442         }
2443 }
2444
2445
2446 /*
2447  * This function prints a pathname, using the ext2fs_get_pathname
2448  * function
2449  */
2450 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2451 {
2452         errcode_t       retval;
2453         char            *path;
2454
2455         if (!dir && (ino < num_special_inodes)) {
2456                 fputs(_(special_inode_name[ino]), stdout);
2457                 return;
2458         }
2459
2460         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2461         if (retval)
2462                 fputs("???", stdout);
2463         else {
2464                 safe_print(path, -1);
2465                 ext2fs_free_mem(&path);
2466         }
2467 }
2468
2469 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2470                           struct problem_context *pctx, int first);
2471 /*
2472  * This function handles the '@' expansion.  We allow recursive
2473  * expansion; an @ expression can contain further '@' and '%'
2474  * expressions.
2475  */
2476 static void expand_at_expression(e2fsck_t ctx, char ch,
2477                                           struct problem_context *pctx,
2478                                           int *first)
2479 {
2480         const char *const *cpp;
2481         const char *str;
2482
2483         /* Search for the abbreviation */
2484         for (cpp = abbrevs; *cpp; cpp++) {
2485                 if (ch == *cpp[0])
2486                         break;
2487         }
2488         if (*cpp) {
2489                 str = _(*cpp) + 1;
2490                 if (*first && islower(*str)) {
2491                         *first = 0;
2492                         bb_putchar(toupper(*str++));
2493                 }
2494                 print_e2fsck_message(ctx, str, pctx, *first);
2495         } else
2496                 printf("@%c", ch);
2497 }
2498
2499 /*
2500  * This function expands '%IX' expressions
2501  */
2502 static void expand_inode_expression(char ch,
2503                                              struct problem_context *ctx)
2504 {
2505         struct ext2_inode       *inode;
2506         struct ext2_inode_large *large_inode;
2507         char *                  time_str;
2508         time_t                  t;
2509         int                     do_gmt = -1;
2510
2511         if (!ctx || !ctx->inode)
2512                 goto no_inode;
2513
2514         inode = ctx->inode;
2515         large_inode = (struct ext2_inode_large *) inode;
2516
2517         switch (ch) {
2518         case 's':
2519                 if (LINUX_S_ISDIR(inode->i_mode))
2520                         printf("%u", inode->i_size);
2521                 else {
2522                         printf("%"PRIu64, (inode->i_size |
2523                                         ((uint64_t) inode->i_size_high << 32)));
2524                 }
2525                 break;
2526         case 'S':
2527                 printf("%u", large_inode->i_extra_isize);
2528                 break;
2529         case 'b':
2530                 printf("%u", inode->i_blocks);
2531                 break;
2532         case 'l':
2533                 printf("%d", inode->i_links_count);
2534                 break;
2535         case 'm':
2536                 printf("0%o", inode->i_mode);
2537                 break;
2538         case 'M':
2539                 /* The diet libc doesn't respect the TZ environemnt variable */
2540                 if (do_gmt == -1) {
2541                         time_str = getenv("TZ");
2542                         if (!time_str)
2543                                 time_str = "";
2544                         do_gmt = !strcmp(time_str, "GMT");
2545                 }
2546                 t = inode->i_mtime;
2547                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2548                 printf("%.24s", time_str);
2549                 break;
2550         case 'F':
2551                 printf("%u", inode->i_faddr);
2552                 break;
2553         case 'f':
2554                 printf("%u", inode->i_file_acl);
2555                 break;
2556         case 'd':
2557                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2558                               inode->i_dir_acl : 0));
2559                 break;
2560         case 'u':
2561                 printf("%d", (inode->i_uid |
2562                               (inode->osd2.linux2.l_i_uid_high << 16)));
2563                 break;
2564         case 'g':
2565                 printf("%d", (inode->i_gid |
2566                               (inode->osd2.linux2.l_i_gid_high << 16)));
2567                 break;
2568         default:
2569         no_inode:
2570                 printf("%%I%c", ch);
2571                 break;
2572         }
2573 }
2574
2575 /*
2576  * This function expands '%dX' expressions
2577  */
2578 static void expand_dirent_expression(char ch,
2579                                               struct problem_context *ctx)
2580 {
2581         struct ext2_dir_entry   *dirent;
2582         int     len;
2583
2584         if (!ctx || !ctx->dirent)
2585                 goto no_dirent;
2586
2587         dirent = ctx->dirent;
2588
2589         switch (ch) {
2590         case 'i':
2591                 printf("%u", dirent->inode);
2592                 break;
2593         case 'n':
2594                 len = dirent->name_len & 0xFF;
2595                 if (len > EXT2_NAME_LEN)
2596                         len = EXT2_NAME_LEN;
2597                 if (len > dirent->rec_len)
2598                         len = dirent->rec_len;
2599                 safe_print(dirent->name, len);
2600                 break;
2601         case 'r':
2602                 printf("%u", dirent->rec_len);
2603                 break;
2604         case 'l':
2605                 printf("%u", dirent->name_len & 0xFF);
2606                 break;
2607         case 't':
2608                 printf("%u", dirent->name_len >> 8);
2609                 break;
2610         default:
2611         no_dirent:
2612                 printf("%%D%c", ch);
2613                 break;
2614         }
2615 }
2616
2617 static void expand_percent_expression(ext2_filsys fs, char ch,
2618                                                struct problem_context *ctx)
2619 {
2620         if (!ctx)
2621                 goto no_context;
2622
2623         switch (ch) {
2624         case '%':
2625                 bb_putchar('%');
2626                 break;
2627         case 'b':
2628                 printf("%u", ctx->blk);
2629                 break;
2630         case 'B':
2631                 printf("%"PRIi64, ctx->blkcount);
2632                 break;
2633         case 'c':
2634                 printf("%u", ctx->blk2);
2635                 break;
2636         case 'd':
2637                 printf("%u", ctx->dir);
2638                 break;
2639         case 'g':
2640                 printf("%d", ctx->group);
2641                 break;
2642         case 'i':
2643                 printf("%u", ctx->ino);
2644                 break;
2645         case 'j':
2646                 printf("%u", ctx->ino2);
2647                 break;
2648         case 'm':
2649                 fputs(error_message(ctx->errcode), stdout);
2650                 break;
2651         case 'N':
2652                 printf("%"PRIi64, ctx->num);
2653                 break;
2654         case 'p':
2655                 print_pathname(fs, ctx->ino, 0);
2656                 break;
2657         case 'P':
2658                 print_pathname(fs, ctx->ino2,
2659                                ctx->dirent ? ctx->dirent->inode : 0);
2660                 break;
2661         case 'q':
2662                 print_pathname(fs, ctx->dir, 0);
2663                 break;
2664         case 'Q':
2665                 print_pathname(fs, ctx->dir, ctx->ino);
2666                 break;
2667         case 'S':
2668                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2669                 break;
2670         case 's':
2671                 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2672                 break;
2673         case 'X':
2674                 printf("0x%"PRIi64, ctx->num);
2675                 break;
2676         default:
2677         no_context:
2678                 printf("%%%c", ch);
2679                 break;
2680         }
2681 }
2682
2683
2684 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2685                           struct problem_context *pctx, int first)
2686 {
2687         ext2_filsys fs = ctx->fs;
2688         const char *    cp;
2689         int             i;
2690
2691         e2fsck_clear_progbar(ctx);
2692         for (cp = msg; *cp; cp++) {
2693                 if (cp[0] == '@') {
2694                         cp++;
2695                         expand_at_expression(ctx, *cp, pctx, &first);
2696                 } else if (cp[0] == '%' && cp[1] == 'I') {
2697                         cp += 2;
2698                         expand_inode_expression(*cp, pctx);
2699                 } else if (cp[0] == '%' && cp[1] == 'D') {
2700                         cp += 2;
2701                         expand_dirent_expression(*cp, pctx);
2702                 } else if ((cp[0] == '%')) {
2703                         cp++;
2704                         expand_percent_expression(fs, *cp, pctx);
2705                 } else {
2706                         for (i=0; cp[i]; i++)
2707                                 if ((cp[i] == '@') || cp[i] == '%')
2708                                         break;
2709                         printf("%.*s", i, cp);
2710                         cp += i-1;
2711                 }
2712                 first = 0;
2713         }
2714 }
2715
2716
2717 /*
2718  * region.c --- code which manages allocations within a region.
2719  */
2720
2721 struct region_el {
2722         region_addr_t   start;
2723         region_addr_t   end;
2724         struct region_el *next;
2725 };
2726
2727 struct region_struct {
2728         region_addr_t   min;
2729         region_addr_t   max;
2730         struct region_el *allocated;
2731 };
2732
2733 static region_t region_create(region_addr_t min, region_addr_t max)
2734 {
2735         region_t        region;
2736
2737         region = xzalloc(sizeof(struct region_struct));
2738         region->min = min;
2739         region->max = max;
2740         return region;
2741 }
2742
2743 static void region_free(region_t region)
2744 {
2745         struct region_el        *r, *next;
2746
2747         for (r = region->allocated; r; r = next) {
2748                 next = r->next;
2749                 free(r);
2750         }
2751         memset(region, 0, sizeof(struct region_struct));
2752         free(region);
2753 }
2754
2755 static int region_allocate(region_t region, region_addr_t start, int n)
2756 {
2757         struct region_el        *r, *new_region, *prev, *next;
2758         region_addr_t end;
2759
2760         end = start+n;
2761         if ((start < region->min) || (end > region->max))
2762                 return -1;
2763         if (n == 0)
2764                 return 1;
2765
2766         /*
2767          * Search through the linked list.  If we find that it
2768          * conflicts witih something that's already allocated, return
2769          * 1; if we can find an existing region which we can grow, do
2770          * so.  Otherwise, stop when we find the appropriate place
2771          * insert a new region element into the linked list.
2772          */
2773         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2774                 if (((start >= r->start) && (start < r->end)) ||
2775                     ((end > r->start) && (end <= r->end)) ||
2776                     ((start <= r->start) && (end >= r->end)))
2777                         return 1;
2778                 if (end == r->start) {
2779                         r->start = start;
2780                         return 0;
2781                 }
2782                 if (start == r->end) {
2783                         if ((next = r->next)) {
2784                                 if (end > next->start)
2785                                         return 1;
2786                                 if (end == next->start) {
2787                                         r->end = next->end;
2788                                         r->next = next->next;
2789                                         free(next);
2790                                         return 0;
2791                                 }
2792                         }
2793                         r->end = end;
2794                         return 0;
2795                 }
2796                 if (start < r->start)
2797                         break;
2798         }
2799         /*
2800          * Insert a new region element structure into the linked list
2801          */
2802         new_region = xmalloc(sizeof(struct region_el));
2803         new_region->start = start;
2804         new_region->end = start + n;
2805         new_region->next = r;
2806         if (prev)
2807                 prev->next = new_region;
2808         else
2809                 region->allocated = new_region;
2810         return 0;
2811 }
2812
2813 /*
2814  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2815  *
2816  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2817  * and applies the following tests to each inode:
2818  *
2819  *      - The mode field of the inode must be legal.
2820  *      - The size and block count fields of the inode are correct.
2821  *      - A data block must not be used by another inode
2822  *
2823  * Pass 1 also gathers the collects the following information:
2824  *
2825  *      - A bitmap of which inodes are in use.          (inode_used_map)
2826  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2827  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2828  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2829  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2830  *      - A bitmap of which blocks are in use.          (block_found_map)
2831  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2832  *      - The data blocks of the directory inodes.      (dir_map)
2833  *
2834  * Pass 1 is designed to stash away enough information so that the
2835  * other passes should not need to read in the inode information
2836  * during the normal course of a filesystem check.  (Althogh if an
2837  * inconsistency is detected, other passes may need to read in an
2838  * inode to fix it.)
2839  *
2840  * Note that pass 1B will be invoked if there are any duplicate blocks
2841  * found.
2842  */
2843
2844
2845 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2846                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2847                          int ref_offset, void *priv_data);
2848 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2849                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2850                              int ref_offset, void *priv_data);
2851 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2852                          char *block_buf);
2853 static void mark_table_blocks(e2fsck_t ctx);
2854 static void alloc_imagic_map(e2fsck_t ctx);
2855 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2856 static void handle_fs_bad_blocks(e2fsck_t ctx);
2857 static void process_inodes(e2fsck_t ctx, char *block_buf);
2858 static int process_inode_cmp(const void *a, const void *b);
2859 static errcode_t scan_callback(ext2_filsys fs,
2860                                   dgrp_t group, void * priv_data);
2861 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2862                                     char *block_buf, int adjust_sign);
2863 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2864
2865 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2866                                struct ext2_inode * inode, int bufsize,
2867                                const char *proc);
2868
2869 struct process_block_struct_1 {
2870         ext2_ino_t      ino;
2871         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2872                                 fragmented:1, compressed:1, bbcheck:1;
2873         blk_t           num_blocks;
2874         blk_t           max_blocks;
2875         e2_blkcnt_t     last_block;
2876         int             num_illegal_blocks;
2877         blk_t           previous_block;
2878         struct ext2_inode *inode;
2879         struct problem_context *pctx;
2880         ext2fs_block_bitmap fs_meta_blocks;
2881         e2fsck_t        ctx;
2882 };
2883
2884 struct process_inode_block {
2885         ext2_ino_t ino;
2886         struct ext2_inode inode;
2887 };
2888
2889 struct scan_callback_struct {
2890         e2fsck_t        ctx;
2891         char            *block_buf;
2892 };
2893
2894 /*
2895  * For the inodes to process list.
2896  */
2897 static struct process_inode_block *inodes_to_process;
2898 static int process_inode_count;
2899
2900 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2901                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2902
2903 /*
2904  * Free all memory allocated by pass1 in preparation for restarting
2905  * things.
2906  */
2907 static void unwind_pass1(void)
2908 {
2909         ext2fs_free_mem(&inodes_to_process);
2910 }
2911
2912 /*
2913  * Check to make sure a device inode is real.  Returns 1 if the device
2914  * checks out, 0 if not.
2915  *
2916  * Note: this routine is now also used to check FIFO's and Sockets,
2917  * since they have the same requirement; the i_block fields should be
2918  * zero.
2919  */
2920 static int
2921 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2922 {
2923         int     i;
2924
2925         /*
2926          * If i_blocks is non-zero, or the index flag is set, then
2927          * this is a bogus device/fifo/socket
2928          */
2929         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2930             (inode->i_flags & EXT2_INDEX_FL))
2931                 return 0;
2932
2933         /*
2934          * We should be able to do the test below all the time, but
2935          * because the kernel doesn't forcibly clear the device
2936          * inode's additional i_block fields, there are some rare
2937          * occasions when a legitimate device inode will have non-zero
2938          * additional i_block fields.  So for now, we only complain
2939          * when the immutable flag is set, which should never happen
2940          * for devices.  (And that's when the problem is caused, since
2941          * you can't set or clear immutable flags for devices.)  Once
2942          * the kernel has been fixed we can change this...
2943          */
2944         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2945                 for (i=4; i < EXT2_N_BLOCKS; i++)
2946                         if (inode->i_block[i])
2947                                 return 0;
2948         }
2949         return 1;
2950 }
2951
2952 /*
2953  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2954  * checks out, 0 if not.
2955  */
2956 static int
2957 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2958 {
2959         unsigned int len;
2960         int i;
2961         blk_t   blocks;
2962
2963         if ((inode->i_size_high || inode->i_size == 0) ||
2964             (inode->i_flags & EXT2_INDEX_FL))
2965                 return 0;
2966
2967         blocks = ext2fs_inode_data_blocks(fs, inode);
2968         if (blocks) {
2969                 if ((inode->i_size >= fs->blocksize) ||
2970                     (blocks != fs->blocksize >> 9) ||
2971                     (inode->i_block[0] < fs->super->s_first_data_block) ||
2972                     (inode->i_block[0] >= fs->super->s_blocks_count))
2973                         return 0;
2974
2975                 for (i = 1; i < EXT2_N_BLOCKS; i++)
2976                         if (inode->i_block[i])
2977                                 return 0;
2978
2979                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2980                         return 0;
2981
2982                 len = strnlen(buf, fs->blocksize);
2983                 if (len == fs->blocksize)
2984                         return 0;
2985         } else {
2986                 if (inode->i_size >= sizeof(inode->i_block))
2987                         return 0;
2988
2989                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2990                 if (len == sizeof(inode->i_block))
2991                         return 0;
2992         }
2993         if (len != inode->i_size)
2994                 return 0;
2995         return 1;
2996 }
2997
2998 /*
2999  * If the immutable (or append-only) flag is set on the inode, offer
3000  * to clear it.
3001  */
3002 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3003 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3004 {
3005         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3006                 return;
3007
3008         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3009                 return;
3010
3011         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3012         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3013 }
3014
3015 /*
3016  * If device, fifo or socket, check size is zero -- if not offer to
3017  * clear it
3018  */
3019 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3020 {
3021         struct ext2_inode *inode = pctx->inode;
3022
3023         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3024                 return;
3025
3026         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3027                 return;
3028
3029         inode->i_size = 0;
3030         inode->i_size_high = 0;
3031         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3032 }
3033
3034 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3035 {
3036         struct ext2_super_block *sb = ctx->fs->super;
3037         struct ext2_inode_large *inode;
3038         struct ext2_ext_attr_entry *entry;
3039         char *start, *end;
3040         int storage_size, remain, offs;
3041         int problem = 0;
3042
3043         inode = (struct ext2_inode_large *) pctx->inode;
3044         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3045                 inode->i_extra_isize;
3046         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3047                 inode->i_extra_isize + sizeof(__u32);
3048         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3049         entry = (struct ext2_ext_attr_entry *) start;
3050
3051         /* scan all entry's headers first */
3052
3053         /* take finish entry 0UL into account */
3054         remain = storage_size - sizeof(__u32);
3055         offs = end - start;
3056
3057         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3058
3059                 /* header eats this space */
3060                 remain -= sizeof(struct ext2_ext_attr_entry);
3061
3062                 /* is attribute name valid? */
3063                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3064                         pctx->num = entry->e_name_len;
3065                         problem = PR_1_ATTR_NAME_LEN;
3066                         goto fix;
3067                 }
3068
3069                 /* attribute len eats this space */
3070                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3071
3072                 /* check value size */
3073                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3074                         pctx->num = entry->e_value_size;
3075                         problem = PR_1_ATTR_VALUE_SIZE;
3076                         goto fix;
3077                 }
3078
3079                 /* check value placement */
3080                 if (entry->e_value_offs +
3081                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3082                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3083                         pctx->num = entry->e_value_offs;
3084                         problem = PR_1_ATTR_VALUE_OFFSET;
3085                         goto fix;
3086                 }
3087
3088                 /* e_value_block must be 0 in inode's ea */
3089                 if (entry->e_value_block != 0) {
3090                         pctx->num = entry->e_value_block;
3091                         problem = PR_1_ATTR_VALUE_BLOCK;
3092                         goto fix;
3093                 }
3094
3095                 /* e_hash must be 0 in inode's ea */
3096                 if (entry->e_hash != 0) {
3097                         pctx->num = entry->e_hash;
3098                         problem = PR_1_ATTR_HASH;
3099                         goto fix;
3100                 }
3101
3102                 remain -= entry->e_value_size;
3103                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3104
3105                 entry = EXT2_EXT_ATTR_NEXT(entry);
3106         }
3107 fix:
3108         /*
3109          * it seems like a corruption. it's very unlikely we could repair
3110          * EA(s) in automatic fashion -bzzz
3111          */
3112         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3113                 return;
3114
3115         /* simple remove all possible EA(s) */
3116         *((__u32 *)start) = 0UL;
3117         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3118                                 EXT2_INODE_SIZE(sb), "pass1");
3119 }
3120
3121 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3122 {
3123         struct ext2_super_block *sb = ctx->fs->super;
3124         struct ext2_inode_large *inode;
3125         __u32 *eamagic;
3126         int min, max;
3127
3128         inode = (struct ext2_inode_large *) pctx->inode;
3129         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3130                 /* this isn't large inode. so, nothing to check */
3131                 return;
3132         }
3133
3134         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3135         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3136         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3137         /*
3138          * For now we will allow i_extra_isize to be 0, but really
3139          * implementations should never allow i_extra_isize to be 0
3140          */
3141         if (inode->i_extra_isize &&
3142             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3143                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3144                         return;
3145                 inode->i_extra_isize = min;
3146                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3147                                         EXT2_INODE_SIZE(sb), "pass1");
3148                 return;
3149         }
3150
3151         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3152                         inode->i_extra_isize);
3153         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3154                 /* it seems inode has an extended attribute(s) in body */
3155                 check_ea_in_inode(ctx, pctx);
3156         }
3157 }
3158
3159 static void e2fsck_pass1(e2fsck_t ctx)
3160 {
3161         int     i;
3162         __u64   max_sizes;
3163         ext2_filsys fs = ctx->fs;
3164         ext2_ino_t      ino;
3165         struct ext2_inode *inode;
3166         ext2_inode_scan scan;
3167         char            *block_buf;
3168         unsigned char   frag, fsize;
3169         struct          problem_context pctx;
3170         struct          scan_callback_struct scan_struct;
3171         struct ext2_super_block *sb = ctx->fs->super;
3172         int             imagic_fs;
3173         int             busted_fs_time = 0;
3174         int             inode_size;
3175
3176         clear_problem_context(&pctx);
3177
3178         if (!(ctx->options & E2F_OPT_PREEN))
3179                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3180
3181         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3182             !(ctx->options & E2F_OPT_NO)) {
3183                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3184                         ctx->dirs_to_hash = 0;
3185         }
3186
3187         /* Pass 1 */
3188
3189 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3190
3191         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3192                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3193                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3194                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3195                 max_sizes = (max_sizes * (1UL << i)) - 1;
3196                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3197         }
3198 #undef EXT2_BPP
3199
3200         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3201
3202         /*
3203          * Allocate bitmaps structures
3204          */
3205         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3206                                               &ctx->inode_used_map);
3207         if (pctx.errcode) {
3208                 pctx.num = 1;
3209                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3210                 ctx->flags |= E2F_FLAG_ABORT;
3211                 return;
3212         }
3213         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3214                                 _("directory inode map"), &ctx->inode_dir_map);
3215         if (pctx.errcode) {
3216                 pctx.num = 2;
3217                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3218                 ctx->flags |= E2F_FLAG_ABORT;
3219                 return;
3220         }
3221         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3222                         _("regular file inode map"), &ctx->inode_reg_map);
3223         if (pctx.errcode) {
3224                 pctx.num = 6;
3225                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3226                 ctx->flags |= E2F_FLAG_ABORT;
3227                 return;
3228         }
3229         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3230                                               &ctx->block_found_map);
3231         if (pctx.errcode) {
3232                 pctx.num = 1;
3233                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3234                 ctx->flags |= E2F_FLAG_ABORT;
3235                 return;
3236         }
3237         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3238                                              &ctx->inode_link_info);
3239         if (pctx.errcode) {
3240                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3241                 ctx->flags |= E2F_FLAG_ABORT;
3242                 return;
3243         }
3244         inode_size = EXT2_INODE_SIZE(fs->super);
3245         inode = (struct ext2_inode *)
3246                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3247
3248         inodes_to_process = (struct process_inode_block *)
3249                 e2fsck_allocate_memory(ctx,
3250                                        (ctx->process_inode_size *
3251                                         sizeof(struct process_inode_block)),
3252                                        "array of inodes to process");
3253         process_inode_count = 0;
3254
3255         pctx.errcode = ext2fs_init_dblist(fs, 0);
3256         if (pctx.errcode) {
3257                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3258                 ctx->flags |= E2F_FLAG_ABORT;
3259                 return;
3260         }
3261
3262         /*
3263          * If the last orphan field is set, clear it, since the pass1
3264          * processing will automatically find and clear the orphans.
3265          * In the future, we may want to try using the last_orphan
3266          * linked list ourselves, but for now, we clear it so that the
3267          * ext3 mount code won't get confused.
3268          */
3269         if (!(ctx->options & E2F_OPT_READONLY)) {
3270                 if (fs->super->s_last_orphan) {
3271                         fs->super->s_last_orphan = 0;
3272                         ext2fs_mark_super_dirty(fs);
3273                 }
3274         }
3275
3276         mark_table_blocks(ctx);
3277         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3278                                                     "block interate buffer");
3279         e2fsck_use_inode_shortcuts(ctx, 1);
3280         ehandler_operation(_("doing inode scan"));
3281         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3282                                               &scan);
3283         if (pctx.errcode) {
3284                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3285                 ctx->flags |= E2F_FLAG_ABORT;
3286                 return;
3287         }
3288         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3289         ctx->stashed_inode = inode;
3290         scan_struct.ctx = ctx;
3291         scan_struct.block_buf = block_buf;
3292         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3293         if (ctx->progress)
3294                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3295                         return;
3296         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3297             (fs->super->s_mtime < fs->super->s_inodes_count))
3298                 busted_fs_time = 1;
3299
3300         while (1) {
3301                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3302                                                           inode, inode_size);
3303                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3304                         return;
3305                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3306                         continue;
3307                 }
3308                 if (pctx.errcode) {
3309                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3310                         ctx->flags |= E2F_FLAG_ABORT;
3311                         return;
3312                 }
3313                 if (!ino)
3314                         break;
3315                 pctx.ino = ino;
3316                 pctx.inode = inode;
3317                 ctx->stashed_ino = ino;
3318                 if (inode->i_links_count) {
3319                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3320                                            ino, inode->i_links_count);
3321                         if (pctx.errcode) {
3322                                 pctx.num = inode->i_links_count;
3323                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3324                                 ctx->flags |= E2F_FLAG_ABORT;
3325                                 return;
3326                         }
3327                 }
3328                 if (ino == EXT2_BAD_INO) {
3329                         struct process_block_struct_1 pb;
3330
3331                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3332                                                           &pb.fs_meta_blocks);
3333                         if (pctx.errcode) {
3334                                 pctx.num = 4;
3335                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3336                                 ctx->flags |= E2F_FLAG_ABORT;
3337                                 return;
3338                         }
3339                         pb.ino = EXT2_BAD_INO;
3340                         pb.num_blocks = pb.last_block = 0;
3341                         pb.num_illegal_blocks = 0;
3342                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3343                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3344                         pb.inode = inode;
3345                         pb.pctx = &pctx;
3346                         pb.ctx = ctx;
3347                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3348                                      block_buf, process_bad_block, &pb);
3349                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3350                         if (pctx.errcode) {
3351                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3352                                 ctx->flags |= E2F_FLAG_ABORT;
3353                                 return;
3354                         }
3355                         if (pb.bbcheck)
3356                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3357                                 ctx->flags |= E2F_FLAG_ABORT;
3358                                 return;
3359                         }
3360                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3361                         clear_problem_context(&pctx);
3362                         continue;
3363                 } else if (ino == EXT2_ROOT_INO) {
3364                         /*
3365                          * Make sure the root inode is a directory; if
3366                          * not, offer to clear it.  It will be
3367                          * regnerated in pass #3.
3368                          */
3369                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3370                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3371                                         inode->i_dtime = time(NULL);
3372                                         inode->i_links_count = 0;
3373                                         ext2fs_icount_store(ctx->inode_link_info,
3374                                                             ino, 0);
3375                                         e2fsck_write_inode(ctx, ino, inode,
3376                                                            "pass1");
3377                                 }
3378
3379                         }
3380                         /*
3381                          * If dtime is set, offer to clear it.  mke2fs
3382                          * version 0.2b created filesystems with the
3383                          * dtime field set for the root and lost+found
3384                          * directories.  We won't worry about
3385                          * /lost+found, since that can be regenerated
3386                          * easily.  But we will fix the root directory
3387                          * as a special case.
3388                          */
3389                         if (inode->i_dtime && inode->i_links_count) {
3390                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3391                                         inode->i_dtime = 0;
3392                                         e2fsck_write_inode(ctx, ino, inode,
3393                                                            "pass1");
3394                                 }
3395                         }
3396                 } else if (ino == EXT2_JOURNAL_INO) {
3397                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3398                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3399                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3400                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3401                                                 &pctx)) {
3402                                         inode->i_mode = LINUX_S_IFREG;
3403                                         e2fsck_write_inode(ctx, ino, inode,
3404                                                            "pass1");
3405                                 }
3406                                 check_blocks(ctx, &pctx, block_buf);
3407                                 continue;
3408                         }
3409                         if ((inode->i_links_count || inode->i_blocks ||
3410                              inode->i_blocks || inode->i_block[0]) &&
3411                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3412                                         &pctx)) {
3413                                 memset(inode, 0, inode_size);
3414                                 ext2fs_icount_store(ctx->inode_link_info,
3415                                                     ino, 0);
3416                                 e2fsck_write_inode_full(ctx, ino, inode,
3417                                                         inode_size, "pass1");
3418                         }
3419                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3420                         int     problem = 0;
3421
3422                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3423                         if (ino == EXT2_BOOT_LOADER_INO) {
3424                                 if (LINUX_S_ISDIR(inode->i_mode))
3425                                         problem = PR_1_RESERVED_BAD_MODE;
3426                         } else if (ino == EXT2_RESIZE_INO) {
3427                                 if (inode->i_mode &&
3428                                     !LINUX_S_ISREG(inode->i_mode))
3429                                         problem = PR_1_RESERVED_BAD_MODE;
3430                         } else {
3431                                 if (inode->i_mode != 0)
3432                                         problem = PR_1_RESERVED_BAD_MODE;
3433                         }
3434                         if (problem) {
3435                                 if (fix_problem(ctx, problem, &pctx)) {
3436                                         inode->i_mode = 0;
3437                                         e2fsck_write_inode(ctx, ino, inode,
3438                                                            "pass1");
3439                                 }
3440                         }
3441                         check_blocks(ctx, &pctx, block_buf);
3442                         continue;
3443                 }
3444                 /*
3445                  * Check for inodes who might have been part of the
3446                  * orphaned list linked list.  They should have gotten
3447                  * dealt with by now, unless the list had somehow been
3448                  * corrupted.
3449                  *
3450                  * FIXME: In the future, inodes which are still in use
3451                  * (and which are therefore) pending truncation should
3452                  * be handled specially.  Right now we just clear the
3453                  * dtime field, and the normal e2fsck handling of
3454                  * inodes where i_size and the inode blocks are
3455                  * inconsistent is to fix i_size, instead of releasing
3456                  * the extra blocks.  This won't catch the inodes that
3457                  * was at the end of the orphan list, but it's better
3458                  * than nothing.  The right answer is that there
3459                  * shouldn't be any bugs in the orphan list handling.  :-)
3460                  */
3461                 if (inode->i_dtime && !busted_fs_time &&
3462                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3463                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3464                                 inode->i_dtime = inode->i_links_count ?
3465                                         0 : time(NULL);
3466                                 e2fsck_write_inode(ctx, ino, inode,
3467                                                    "pass1");
3468                         }
3469                 }
3470
3471                 /*
3472                  * This code assumes that deleted inodes have
3473                  * i_links_count set to 0.
3474                  */
3475                 if (!inode->i_links_count) {
3476                         if (!inode->i_dtime && inode->i_mode) {
3477                                 if (fix_problem(ctx,
3478                                             PR_1_ZERO_DTIME, &pctx)) {
3479                                         inode->i_dtime = time(NULL);
3480                                         e2fsck_write_inode(ctx, ino, inode,
3481                                                            "pass1");
3482                                 }
3483                         }
3484                         continue;
3485                 }
3486                 /*
3487                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3488                  * deleted files.  Oops.
3489                  *
3490                  * Since all new ext2 implementations get this right,
3491                  * we now assume that the case of non-zero
3492                  * i_links_count and non-zero dtime means that we
3493                  * should keep the file, not delete it.
3494                  *
3495                  */
3496                 if (inode->i_dtime) {
3497                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3498                                 inode->i_dtime = 0;
3499                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3500                         }
3501                 }
3502
3503                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3504                 switch (fs->super->s_creator_os) {
3505                     case EXT2_OS_LINUX:
3506                         frag = inode->osd2.linux2.l_i_frag;
3507                         fsize = inode->osd2.linux2.l_i_fsize;
3508                         break;
3509                     case EXT2_OS_HURD:
3510                         frag = inode->osd2.hurd2.h_i_frag;
3511                         fsize = inode->osd2.hurd2.h_i_fsize;
3512                         break;
3513                     case EXT2_OS_MASIX:
3514                         frag = inode->osd2.masix2.m_i_frag;
3515                         fsize = inode->osd2.masix2.m_i_fsize;
3516                         break;
3517                     default:
3518                         frag = fsize = 0;
3519                 }
3520
3521                 if (inode->i_faddr || frag || fsize ||
3522                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3523                         mark_inode_bad(ctx, ino);
3524                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3525                         if (imagic_fs) {
3526                                 if (!ctx->inode_imagic_map)
3527                                         alloc_imagic_map(ctx);
3528                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3529                                                          ino);
3530                         } else {
3531                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3532                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3533                                         e2fsck_write_inode(ctx, ino,
3534                                                            inode, "pass1");
3535                                 }
3536                         }
3537                 }
3538
3539                 check_inode_extra_space(ctx, &pctx);
3540
3541                 if (LINUX_S_ISDIR(inode->i_mode)) {
3542                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3543                         e2fsck_add_dir_info(ctx, ino, 0);
3544                         ctx->fs_directory_count++;
3545                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3546                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3547                         ctx->fs_regular_count++;
3548                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3549                            e2fsck_pass1_check_device_inode(fs, inode)) {
3550                         check_immutable(ctx, &pctx);
3551                         check_size(ctx, &pctx);
3552                         ctx->fs_chardev_count++;
3553                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3554                            e2fsck_pass1_check_device_inode(fs, inode)) {
3555                         check_immutable(ctx, &pctx);
3556                         check_size(ctx, &pctx);
3557                         ctx->fs_blockdev_count++;
3558                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3559                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3560                         check_immutable(ctx, &pctx);
3561                         ctx->fs_symlinks_count++;
3562                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3563                                 ctx->fs_fast_symlinks_count++;
3564                                 check_blocks(ctx, &pctx, block_buf);
3565                                 continue;
3566                         }
3567                 }
3568                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3569                          e2fsck_pass1_check_device_inode(fs, inode)) {
3570                         check_immutable(ctx, &pctx);
3571                         check_size(ctx, &pctx);
3572                         ctx->fs_fifo_count++;
3573                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3574                            e2fsck_pass1_check_device_inode(fs, inode)) {
3575                         check_immutable(ctx, &pctx);
3576                         check_size(ctx, &pctx);
3577                         ctx->fs_sockets_count++;
3578                 } else
3579                         mark_inode_bad(ctx, ino);
3580                 if (inode->i_block[EXT2_IND_BLOCK])
3581                         ctx->fs_ind_count++;
3582                 if (inode->i_block[EXT2_DIND_BLOCK])
3583                         ctx->fs_dind_count++;
3584                 if (inode->i_block[EXT2_TIND_BLOCK])
3585                         ctx->fs_tind_count++;
3586                 if (inode->i_block[EXT2_IND_BLOCK] ||
3587                     inode->i_block[EXT2_DIND_BLOCK] ||
3588                     inode->i_block[EXT2_TIND_BLOCK] ||
3589                     inode->i_file_acl) {
3590                         inodes_to_process[process_inode_count].ino = ino;
3591                         inodes_to_process[process_inode_count].inode = *inode;
3592                         process_inode_count++;
3593                 } else
3594                         check_blocks(ctx, &pctx, block_buf);
3595
3596                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3597                         return;
3598
3599                 if (process_inode_count >= ctx->process_inode_size) {
3600                         process_inodes(ctx, block_buf);
3601
3602                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3603                                 return;
3604                 }
3605         }
3606         process_inodes(ctx, block_buf);
3607         ext2fs_close_inode_scan(scan);
3608         ehandler_operation(0);
3609
3610         /*
3611          * If any extended attribute blocks' reference counts need to
3612          * be adjusted, either up (ctx->refcount_extra), or down
3613          * (ctx->refcount), then fix them.
3614          */
3615         if (ctx->refcount) {
3616                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3617                 ea_refcount_free(ctx->refcount);
3618                 ctx->refcount = 0;
3619         }
3620         if (ctx->refcount_extra) {
3621                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3622                                         block_buf, +1);
3623                 ea_refcount_free(ctx->refcount_extra);
3624                 ctx->refcount_extra = 0;
3625         }
3626
3627         if (ctx->invalid_bitmaps)
3628                 handle_fs_bad_blocks(ctx);
3629
3630         /* We don't need the block_ea_map any more */
3631         ext2fs_free_block_bitmap(ctx->block_ea_map);
3632         ctx->block_ea_map = 0;
3633
3634         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3635                 ext2fs_block_bitmap save_bmap;
3636
3637                 save_bmap = fs->block_map;
3638                 fs->block_map = ctx->block_found_map;
3639                 clear_problem_context(&pctx);
3640                 pctx.errcode = ext2fs_create_resize_inode(fs);
3641                 if (pctx.errcode) {
3642                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3643                         /* Should never get here */
3644                         ctx->flags |= E2F_FLAG_ABORT;
3645                         return;
3646                 }
3647                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3648                                   "recreate inode");
3649                 inode->i_mtime = time(NULL);
3650                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3651                                   "recreate inode");
3652                 fs->block_map = save_bmap;
3653                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3654         }
3655
3656         if (ctx->flags & E2F_FLAG_RESTART) {
3657                 /*
3658                  * Only the master copy of the superblock and block
3659                  * group descriptors are going to be written during a
3660                  * restart, so set the superblock to be used to be the
3661                  * master superblock.
3662                  */
3663                 ctx->use_superblock = 0;
3664                 unwind_pass1();
3665                 goto endit;
3666         }
3667
3668         if (ctx->block_dup_map) {
3669                 if (ctx->options & E2F_OPT_PREEN) {
3670                         clear_problem_context(&pctx);
3671                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3672                 }
3673                 e2fsck_pass1_dupblocks(ctx, block_buf);
3674         }
3675         ext2fs_free_mem(&inodes_to_process);
3676 endit:
3677         e2fsck_use_inode_shortcuts(ctx, 0);
3678
3679         ext2fs_free_mem(&block_buf);
3680         ext2fs_free_mem(&inode);
3681
3682 }
3683
3684 /*
3685  * When the inode_scan routines call this callback at the end of the
3686  * glock group, call process_inodes.
3687  */
3688 static errcode_t scan_callback(ext2_filsys fs,
3689                                dgrp_t group, void * priv_data)
3690 {
3691         struct scan_callback_struct *scan_struct;
3692         e2fsck_t ctx;
3693
3694         scan_struct = (struct scan_callback_struct *) priv_data;
3695         ctx = scan_struct->ctx;
3696
3697         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3698
3699         if (ctx->progress)
3700                 if ((ctx->progress)(ctx, 1, group+1,
3701                                     ctx->fs->group_desc_count))
3702                         return EXT2_ET_CANCEL_REQUESTED;
3703
3704         return 0;
3705 }
3706
3707 /*
3708  * Process the inodes in the "inodes to process" list.
3709  */
3710 static void process_inodes(e2fsck_t ctx, char *block_buf)
3711 {
3712         int                     i;
3713         struct ext2_inode       *old_stashed_inode;
3714         ext2_ino_t              old_stashed_ino;
3715         const char              *old_operation;
3716         char                    buf[80];
3717         struct problem_context  pctx;
3718
3719         /* begin process_inodes */
3720         if (process_inode_count == 0)
3721                 return;
3722         old_operation = ehandler_operation(0);
3723         old_stashed_inode = ctx->stashed_inode;
3724         old_stashed_ino = ctx->stashed_ino;
3725         qsort(inodes_to_process, process_inode_count,
3726                       sizeof(struct process_inode_block), process_inode_cmp);
3727         clear_problem_context(&pctx);
3728         for (i=0; i < process_inode_count; i++) {
3729                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3730                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3731                 sprintf(buf, _("reading indirect blocks of inode %u"),
3732                         pctx.ino);
3733                 ehandler_operation(buf);
3734                 check_blocks(ctx, &pctx, block_buf);
3735                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3736                         break;
3737         }
3738         ctx->stashed_inode = old_stashed_inode;
3739         ctx->stashed_ino = old_stashed_ino;
3740         process_inode_count = 0;
3741         /* end process inodes */
3742
3743         ehandler_operation(old_operation);
3744 }
3745
3746 static int process_inode_cmp(const void *a, const void *b)
3747 {
3748         const struct process_inode_block *ib_a =
3749                 (const struct process_inode_block *) a;
3750         const struct process_inode_block *ib_b =
3751                 (const struct process_inode_block *) b;
3752         int     ret;
3753
3754         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3755                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3756         if (ret == 0)
3757                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3758         return ret;
3759 }
3760
3761 /*
3762  * Mark an inode as being bad in some what
3763  */
3764 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3765 {
3766         struct          problem_context pctx;
3767
3768         if (!ctx->inode_bad_map) {
3769                 clear_problem_context(&pctx);
3770
3771                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3772                             _("bad inode map"), &ctx->inode_bad_map);
3773                 if (pctx.errcode) {
3774                         pctx.num = 3;
3775                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3776                         /* Should never get here */
3777                         ctx->flags |= E2F_FLAG_ABORT;
3778                         return;
3779                 }
3780         }
3781         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3782 }
3783
3784
3785 /*
3786  * This procedure will allocate the inode imagic table
3787  */
3788 static void alloc_imagic_map(e2fsck_t ctx)
3789 {
3790         struct          problem_context pctx;
3791
3792         clear_problem_context(&pctx);
3793         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3794                                               _("imagic inode map"),
3795                                               &ctx->inode_imagic_map);
3796         if (pctx.errcode) {
3797                 pctx.num = 5;
3798                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3799                 /* Should never get here */
3800                 ctx->flags |= E2F_FLAG_ABORT;
3801                 return;
3802         }
3803 }
3804
3805 /*
3806  * Marks a block as in use, setting the dup_map if it's been set
3807  * already.  Called by process_block and process_bad_block.
3808  *
3809  * WARNING: Assumes checks have already been done to make sure block
3810  * is valid.  This is true in both process_block and process_bad_block.
3811  */
3812 static void mark_block_used(e2fsck_t ctx, blk_t block)
3813 {
3814         struct          problem_context pctx;
3815
3816         clear_problem_context(&pctx);
3817
3818         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3819                 if (!ctx->block_dup_map) {
3820                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3821                               _("multiply claimed block map"),
3822                               &ctx->block_dup_map);
3823                         if (pctx.errcode) {
3824                                 pctx.num = 3;
3825                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3826                                             &pctx);
3827                                 /* Should never get here */
3828                                 ctx->flags |= E2F_FLAG_ABORT;
3829                                 return;
3830                         }
3831                 }
3832                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3833         } else {
3834                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3835         }
3836 }
3837
3838 /*
3839  * Adjust the extended attribute block's reference counts at the end
3840  * of pass 1, either by subtracting out references for EA blocks that
3841  * are still referenced in ctx->refcount, or by adding references for
3842  * EA blocks that had extra references as accounted for in
3843  * ctx->refcount_extra.
3844  */
3845 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3846                                     char *block_buf, int adjust_sign)
3847 {
3848         struct ext2_ext_attr_header     *header;
3849         struct problem_context          pctx;
3850         ext2_filsys                     fs = ctx->fs;
3851         blk_t                           blk;
3852         __u32                           should_be;
3853         int                             count;
3854
3855         clear_problem_context(&pctx);
3856
3857         ea_refcount_intr_begin(refcount);
3858         while (1) {
3859                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3860                         break;
3861                 pctx.blk = blk;
3862                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3863                 if (pctx.errcode) {
3864                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3865                         return;
3866                 }
3867                 header = (struct ext2_ext_attr_header *) block_buf;
3868                 pctx.blkcount = header->h_refcount;
3869                 should_be = header->h_refcount + adjust_sign * count;
3870                 pctx.num = should_be;
3871                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3872                         header->h_refcount = should_be;
3873                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3874                                                              block_buf);
3875                         if (pctx.errcode) {
3876                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3877                                 continue;
3878                         }
3879                 }
3880         }
3881 }
3882
3883 /*
3884  * Handle processing the extended attribute blocks
3885  */
3886 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3887                            char *block_buf)
3888 {
3889         ext2_filsys fs = ctx->fs;
3890         ext2_ino_t      ino = pctx->ino;
3891         struct ext2_inode *inode = pctx->inode;
3892         blk_t           blk;
3893         char *          end;
3894         struct ext2_ext_attr_header *header;
3895         struct ext2_ext_attr_entry *entry;
3896         int             count;
3897         region_t        region;
3898
3899         blk = inode->i_file_acl;
3900         if (blk == 0)
3901                 return 0;
3902
3903         /*
3904          * If the Extended attribute flag isn't set, then a non-zero
3905          * file acl means that the inode is corrupted.
3906          *
3907          * Or if the extended attribute block is an invalid block,
3908          * then the inode is also corrupted.
3909          */
3910         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3911             (blk < fs->super->s_first_data_block) ||
3912             (blk >= fs->super->s_blocks_count)) {
3913                 mark_inode_bad(ctx, ino);
3914                 return 0;
3915         }
3916
3917         /* If ea bitmap hasn't been allocated, create it */
3918         if (!ctx->block_ea_map) {
3919                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3920                                                       _("ext attr block map"),
3921                                                       &ctx->block_ea_map);
3922                 if (pctx->errcode) {
3923                         pctx->num = 2;
3924                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3925                         ctx->flags |= E2F_FLAG_ABORT;
3926                         return 0;
3927                 }
3928         }
3929
3930         /* Create the EA refcount structure if necessary */
3931         if (!ctx->refcount) {
3932                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3933                 if (pctx->errcode) {
3934                         pctx->num = 1;
3935                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3936                         ctx->flags |= E2F_FLAG_ABORT;
3937                         return 0;
3938                 }
3939         }
3940
3941         /* Have we seen this EA block before? */
3942         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3943                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3944                         return 1;
3945                 /* Ooops, this EA was referenced more than it stated */
3946                 if (!ctx->refcount_extra) {
3947                         pctx->errcode = ea_refcount_create(0,
3948                                            &ctx->refcount_extra);
3949                         if (pctx->errcode) {
3950                                 pctx->num = 2;
3951                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3952                                 ctx->flags |= E2F_FLAG_ABORT;
3953                                 return 0;
3954                         }
3955                 }
3956                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3957                 return 1;
3958         }
3959
3960         /*
3961          * OK, we haven't seen this EA block yet.  So we need to
3962          * validate it
3963          */
3964         pctx->blk = blk;
3965         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3966         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3967                 goto clear_extattr;
3968         header = (struct ext2_ext_attr_header *) block_buf;
3969         pctx->blk = inode->i_file_acl;
3970         if (((ctx->ext_attr_ver == 1) &&
3971              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3972             ((ctx->ext_attr_ver == 2) &&
3973              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3974                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3975                         goto clear_extattr;
3976         }
3977
3978         if (header->h_blocks != 1) {
3979                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3980                         goto clear_extattr;
3981         }
3982
3983         region = region_create(0, fs->blocksize);
3984         if (!region) {
3985                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3986                 ctx->flags |= E2F_FLAG_ABORT;
3987                 return 0;
3988         }
3989         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3990                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3991                         goto clear_extattr;
3992         }
3993
3994         entry = (struct ext2_ext_attr_entry *)(header+1);
3995         end = block_buf + fs->blocksize;
3996         while ((char *)entry < end && *(__u32 *)entry) {
3997                 if (region_allocate(region, (char *)entry - (char *)header,
3998                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
3999                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4000                                 goto clear_extattr;
4001                 }
4002                 if ((ctx->ext_attr_ver == 1 &&
4003                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4004                     (ctx->ext_attr_ver == 2 &&
4005                      entry->e_name_index == 0)) {
4006                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4007                                 goto clear_extattr;
4008                 }
4009                 if (entry->e_value_block != 0) {
4010                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4011                                 goto clear_extattr;
4012                 }
4013                 if (entry->e_value_size &&
4014                     region_allocate(region, entry->e_value_offs,
4015                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4016                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4017                                 goto clear_extattr;
4018                 }
4019                 entry = EXT2_EXT_ATTR_NEXT(entry);
4020         }
4021         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4022                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4023                         goto clear_extattr;
4024         }
4025         region_free(region);
4026
4027         count = header->h_refcount - 1;
4028         if (count)
4029                 ea_refcount_store(ctx->refcount, blk, count);
4030         mark_block_used(ctx, blk);
4031         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4032
4033         return 1;
4034
4035 clear_extattr:
4036         inode->i_file_acl = 0;
4037         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4038         return 0;
4039 }
4040
4041 /* Returns 1 if bad htree, 0 if OK */
4042 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4043                         ext2_ino_t ino FSCK_ATTR((unused)),
4044                         struct ext2_inode *inode,
4045                         char *block_buf)
4046 {
4047         struct ext2_dx_root_info        *root;
4048         ext2_filsys                     fs = ctx->fs;
4049         errcode_t                       retval;
4050         blk_t                           blk;
4051
4052         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4053              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4054             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4055              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4056                 return 1;
4057
4058         blk = inode->i_block[0];
4059         if (((blk == 0) ||
4060              (blk < fs->super->s_first_data_block) ||
4061              (blk >= fs->super->s_blocks_count)) &&
4062             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4063                 return 1;
4064
4065         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4066         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4067                 return 1;
4068
4069         /* XXX should check that beginning matches a directory */
4070         root = (struct ext2_dx_root_info *) (block_buf + 24);
4071
4072         if ((root->reserved_zero || root->info_length < 8) &&
4073             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4074                 return 1;
4075
4076         pctx->num = root->hash_version;
4077         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4078             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4079             (root->hash_version != EXT2_HASH_TEA) &&
4080             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4081                 return 1;
4082
4083         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4084             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4085                 return 1;
4086
4087         pctx->num = root->indirect_levels;
4088         if ((root->indirect_levels > 1) &&
4089             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4090                 return 1;
4091
4092         return 0;
4093 }
4094
4095 /*
4096  * This subroutine is called on each inode to account for all of the
4097  * blocks used by that inode.
4098  */
4099 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4100                          char *block_buf)
4101 {
4102         ext2_filsys fs = ctx->fs;
4103         struct process_block_struct_1 pb;
4104         ext2_ino_t      ino = pctx->ino;
4105         struct ext2_inode *inode = pctx->inode;
4106         int             bad_size = 0;
4107         int             dirty_inode = 0;
4108         __u64           size;
4109
4110         pb.ino = ino;
4111         pb.num_blocks = 0;
4112         pb.last_block = -1;
4113         pb.num_illegal_blocks = 0;
4114         pb.suppress = 0; pb.clear = 0;
4115         pb.fragmented = 0;
4116         pb.compressed = 0;
4117         pb.previous_block = 0;
4118         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4119         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4120         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4121         pb.inode = inode;
4122         pb.pctx = pctx;
4123         pb.ctx = ctx;
4124         pctx->ino = ino;
4125         pctx->errcode = 0;
4126
4127         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4128                 if (fs->super->s_feature_incompat &
4129                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4130                         pb.compressed = 1;
4131                 else {
4132                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4133                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4134                                 dirty_inode++;
4135                         }
4136                 }
4137         }
4138
4139         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4140                 pb.num_blocks++;
4141
4142         if (ext2fs_inode_has_valid_blocks(inode))
4143                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4144                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4145                                        block_buf, process_block, &pb);
4146         end_problem_latch(ctx, PR_LATCH_BLOCK);
4147         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4148         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4149                 goto out;
4150         if (pctx->errcode)
4151                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4152
4153         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4154                 ctx->fs_fragmented++;
4155
4156         if (pb.clear) {
4157                 inode->i_links_count = 0;
4158                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4159                 inode->i_dtime = time(NULL);
4160                 dirty_inode++;
4161                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4162                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4163                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4164                 /*
4165                  * The inode was probably partially accounted for
4166                  * before processing was aborted, so we need to
4167                  * restart the pass 1 scan.
4168                  */
4169                 ctx->flags |= E2F_FLAG_RESTART;
4170                 goto out;
4171         }
4172
4173         if (inode->i_flags & EXT2_INDEX_FL) {
4174                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4175                         inode->i_flags &= ~EXT2_INDEX_FL;
4176                         dirty_inode++;
4177                 } else {
4178 #ifdef ENABLE_HTREE
4179                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4180 #endif
4181                 }
4182         }
4183         if (ctx->dirs_to_hash && pb.is_dir &&
4184             !(inode->i_flags & EXT2_INDEX_FL) &&
4185             ((inode->i_size / fs->blocksize) >= 3))
4186                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4187
4188         if (!pb.num_blocks && pb.is_dir) {
4189                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4190                         inode->i_links_count = 0;
4191                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4192                         inode->i_dtime = time(NULL);
4193                         dirty_inode++;
4194                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4195                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4196                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4197                         ctx->fs_directory_count--;
4198                         goto out;
4199                 }
4200         }
4201
4202         pb.num_blocks *= (fs->blocksize / 512);
4203
4204         if (pb.is_dir) {
4205                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4206                 if (nblock > (pb.last_block + 1))
4207                         bad_size = 1;
4208                 else if (nblock < (pb.last_block + 1)) {
4209                         if (((pb.last_block + 1) - nblock) >
4210                             fs->super->s_prealloc_dir_blocks)
4211                                 bad_size = 2;
4212                 }
4213         } else {
4214                 size = EXT2_I_SIZE(inode);
4215                 if ((pb.last_block >= 0) &&
4216                     (size < (__u64) pb.last_block * fs->blocksize))
4217                         bad_size = 3;
4218                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4219                         bad_size = 4;
4220         }
4221         /* i_size for symlinks is checked elsewhere */
4222         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4223                 pctx->num = (pb.last_block+1) * fs->blocksize;
4224                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4225                         inode->i_size = pctx->num;
4226                         if (!LINUX_S_ISDIR(inode->i_mode))
4227                                 inode->i_size_high = pctx->num >> 32;
4228                         dirty_inode++;
4229                 }
4230                 pctx->num = 0;
4231         }
4232         if (LINUX_S_ISREG(inode->i_mode) &&
4233             (inode->i_size_high || inode->i_size & 0x80000000UL))
4234                 ctx->large_files++;
4235         if (pb.num_blocks != inode->i_blocks) {
4236                 pctx->num = pb.num_blocks;
4237                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4238                         inode->i_blocks = pb.num_blocks;
4239                         dirty_inode++;
4240                 }
4241                 pctx->num = 0;
4242         }
4243 out:
4244         if (dirty_inode)
4245                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4246 }
4247
4248
4249 /*
4250  * This is a helper function for check_blocks().
4251  */
4252 static int process_block(ext2_filsys fs,
4253                   blk_t *block_nr,
4254                   e2_blkcnt_t blockcnt,
4255                   blk_t ref_block FSCK_ATTR((unused)),
4256                   int ref_offset FSCK_ATTR((unused)),
4257                   void *priv_data)
4258 {
4259         struct process_block_struct_1 *p;
4260         struct problem_context *pctx;
4261         blk_t   blk = *block_nr;
4262         int     ret_code = 0;
4263         int     problem = 0;
4264         e2fsck_t        ctx;
4265
4266         p = (struct process_block_struct_1 *) priv_data;
4267         pctx = p->pctx;
4268         ctx = p->ctx;
4269
4270         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4271                 /* todo: Check that the comprblk_fl is high, that the
4272                    blkaddr pattern looks right (all non-holes up to
4273                    first EXT2FS_COMPRESSED_BLKADDR, then all
4274                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4275                    that the feature_incompat bit is high, and that the
4276                    inode is a regular file.  If we're doing a "full
4277                    check" (a concept introduced to e2fsck by e2compr,
4278                    meaning that we look at data blocks as well as
4279                    metadata) then call some library routine that
4280                    checks the compressed data.  I'll have to think
4281                    about this, because one particularly important
4282                    problem to be able to fix is to recalculate the
4283                    cluster size if necessary.  I think that perhaps
4284                    we'd better do most/all e2compr-specific checks
4285                    separately, after the non-e2compr checks.  If not
4286                    doing a full check, it may be useful to test that
4287                    the personality is linux; e.g. if it isn't then
4288                    perhaps this really is just an illegal block. */
4289                 return 0;
4290         }
4291
4292         if (blk == 0) {
4293                 if (p->is_dir == 0) {
4294                         /*
4295                          * Should never happen, since only directories
4296                          * get called with BLOCK_FLAG_HOLE
4297                          */
4298 #ifdef DEBUG_E2FSCK
4299                         printf("process_block() called with blk == 0, "
4300                                "blockcnt=%d, inode %lu???\n",
4301                                blockcnt, p->ino);
4302 #endif
4303                         return 0;
4304                 }
4305                 if (blockcnt < 0)
4306                         return 0;
4307                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4308                         goto mark_dir;
4309                 }
4310                 return 0;
4311         }
4312
4313         /*
4314          * Simplistic fragmentation check.  We merely require that the
4315          * file be contiguous.  (Which can never be true for really
4316          * big files that are greater than a block group.)
4317          */
4318         if (!HOLE_BLKADDR(p->previous_block)) {
4319                 if (p->previous_block+1 != blk)
4320                         p->fragmented = 1;
4321         }
4322         p->previous_block = blk;
4323
4324         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4325                 problem = PR_1_TOOBIG_DIR;
4326         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4327                 problem = PR_1_TOOBIG_REG;
4328         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4329                 problem = PR_1_TOOBIG_SYMLINK;
4330
4331         if (blk < fs->super->s_first_data_block ||
4332             blk >= fs->super->s_blocks_count)
4333                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4334
4335         if (problem) {
4336                 p->num_illegal_blocks++;
4337                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4338                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4339                                 p->clear = 1;
4340                                 return BLOCK_ABORT;
4341                         }
4342                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4343                                 p->suppress = 1;
4344                                 set_latch_flags(PR_LATCH_BLOCK,
4345                                                 PRL_SUPPRESS, 0);
4346                         }
4347                 }
4348                 pctx->blk = blk;
4349                 pctx->blkcount = blockcnt;
4350                 if (fix_problem(ctx, problem, pctx)) {
4351                         blk = *block_nr = 0;
4352                         ret_code = BLOCK_CHANGED;
4353                         goto mark_dir;
4354                 } else
4355                         return 0;
4356         }
4357
4358         if (p->ino == EXT2_RESIZE_INO) {
4359                 /*
4360                  * The resize inode has already be sanity checked
4361                  * during pass #0 (the superblock checks).  All we
4362                  * have to do is mark the double indirect block as
4363                  * being in use; all of the other blocks are handled
4364                  * by mark_table_blocks()).
4365                  */
4366                 if (blockcnt == BLOCK_COUNT_DIND)
4367                         mark_block_used(ctx, blk);
4368         } else
4369                 mark_block_used(ctx, blk);
4370         p->num_blocks++;
4371         if (blockcnt >= 0)
4372                 p->last_block = blockcnt;
4373 mark_dir:
4374         if (p->is_dir && (blockcnt >= 0)) {
4375                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4376                                                     blk, blockcnt);
4377                 if (pctx->errcode) {
4378                         pctx->blk = blk;
4379                         pctx->num = blockcnt;
4380                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4381                         /* Should never get here */
4382                         ctx->flags |= E2F_FLAG_ABORT;
4383                         return BLOCK_ABORT;
4384                 }
4385         }
4386         return ret_code;
4387 }
4388
4389 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4390                       blk_t *block_nr,
4391                       e2_blkcnt_t blockcnt,
4392                       blk_t ref_block FSCK_ATTR((unused)),
4393                       int ref_offset FSCK_ATTR((unused)),
4394                       void *priv_data EXT2FS_ATTR((unused)))
4395 {
4396         /*
4397          * Note: This function processes blocks for the bad blocks
4398          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4399          */
4400
4401         printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4402         return BLOCK_ERROR;
4403 }
4404
4405 /*
4406  * This routine gets called at the end of pass 1 if bad blocks are
4407  * detected in the superblock, group descriptors, inode_bitmaps, or
4408  * block bitmaps.  At this point, all of the blocks have been mapped
4409  * out, so we can try to allocate new block(s) to replace the bad
4410  * blocks.
4411  */
4412 static void handle_fs_bad_blocks(e2fsck_t ctx)
4413 {
4414         printf("Bad blocks detected on your filesystem\n"
4415                 "You should get your data off as the device will soon die\n");
4416 }
4417
4418 /*
4419  * This routine marks all blocks which are used by the superblock,
4420  * group descriptors, inode bitmaps, and block bitmaps.
4421  */
4422 static void mark_table_blocks(e2fsck_t ctx)
4423 {
4424         ext2_filsys fs = ctx->fs;
4425         blk_t   block, b;
4426         dgrp_t  i;
4427         int     j;
4428         struct problem_context pctx;
4429
4430         clear_problem_context(&pctx);
4431
4432         block = fs->super->s_first_data_block;
4433         for (i = 0; i < fs->group_desc_count; i++) {
4434                 pctx.group = i;
4435
4436                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4437
4438                 /*
4439                  * Mark the blocks used for the inode table
4440                  */
4441                 if (fs->group_desc[i].bg_inode_table) {
4442                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4443                              j < fs->inode_blocks_per_group;
4444                              j++, b++) {
4445                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4446                                                              b)) {
4447                                         pctx.blk = b;
4448                                         if (fix_problem(ctx,
4449                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4450                                                 ctx->invalid_inode_table_flag[i]++;
4451                                                 ctx->invalid_bitmaps++;
4452                                         }
4453                                 } else {
4454                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
4455                                                              b);
4456                                 }
4457                         }
4458                 }
4459
4460                 /*
4461                  * Mark block used for the block bitmap
4462                  */
4463                 if (fs->group_desc[i].bg_block_bitmap) {
4464                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4465                                      fs->group_desc[i].bg_block_bitmap)) {
4466                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4467                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4468                                         ctx->invalid_block_bitmap_flag[i]++;
4469                                         ctx->invalid_bitmaps++;
4470                                 }
4471                         } else {
4472                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4473                                      fs->group_desc[i].bg_block_bitmap);
4474                     }
4475
4476                 }
4477                 /*
4478                  * Mark block used for the inode bitmap
4479                  */
4480                 if (fs->group_desc[i].bg_inode_bitmap) {
4481                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4482                                      fs->group_desc[i].bg_inode_bitmap)) {
4483                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4484                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4485                                         ctx->invalid_inode_bitmap_flag[i]++;
4486                                         ctx->invalid_bitmaps++;
4487                                 }
4488                         } else {
4489                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4490                                      fs->group_desc[i].bg_inode_bitmap);
4491                         }
4492                 }
4493                 block += fs->super->s_blocks_per_group;
4494         }
4495 }
4496
4497 /*
4498  * Thes subroutines short circuits ext2fs_get_blocks and
4499  * ext2fs_check_directory; we use them since we already have the inode
4500  * structure, so there's no point in letting the ext2fs library read
4501  * the inode again.
4502  */
4503 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4504                                   blk_t *blocks)
4505 {
4506         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4507         int     i;
4508
4509         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4510                 return EXT2_ET_CALLBACK_NOTHANDLED;
4511
4512         for (i=0; i < EXT2_N_BLOCKS; i++)
4513                 blocks[i] = ctx->stashed_inode->i_block[i];
4514         return 0;
4515 }
4516
4517 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4518                                   struct ext2_inode *inode)
4519 {
4520         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521
4522         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4523                 return EXT2_ET_CALLBACK_NOTHANDLED;
4524         *inode = *ctx->stashed_inode;
4525         return 0;
4526 }
4527
4528 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4529                             struct ext2_inode *inode)
4530 {
4531         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4532
4533         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4534                 *ctx->stashed_inode = *inode;
4535         return EXT2_ET_CALLBACK_NOTHANDLED;
4536 }
4537
4538 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4539 {
4540         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4541
4542         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4543                 return EXT2_ET_CALLBACK_NOTHANDLED;
4544
4545         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4546                 return EXT2_ET_NO_DIRECTORY;
4547         return 0;
4548 }
4549
4550 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4551 {
4552         ext2_filsys fs = ctx->fs;
4553
4554         if (bool) {
4555                 fs->get_blocks = pass1_get_blocks;
4556                 fs->check_directory = pass1_check_directory;
4557                 fs->read_inode = pass1_read_inode;
4558                 fs->write_inode = pass1_write_inode;
4559                 ctx->stashed_ino = 0;
4560         } else {
4561                 fs->get_blocks = 0;
4562                 fs->check_directory = 0;
4563                 fs->read_inode = 0;
4564                 fs->write_inode = 0;
4565         }
4566 }
4567
4568 /*
4569  * pass1b.c --- Pass #1b of e2fsck
4570  *
4571  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4572  * only invoked if pass 1 discovered blocks which are in use by more
4573  * than one inode.
4574  *
4575  * Pass1B scans the data blocks of all the inodes again, generating a
4576  * complete list of duplicate blocks and which inodes have claimed
4577  * them.
4578  *
4579  * Pass1C does a tree-traversal of the filesystem, to determine the
4580  * parent directories of these inodes.  This step is necessary so that
4581  * e2fsck can print out the pathnames of affected inodes.
4582  *
4583  * Pass1D is a reconciliation pass.  For each inode with duplicate
4584  * blocks, the user is prompted if s/he would like to clone the file
4585  * (so that the file gets a fresh copy of the duplicated blocks) or
4586  * simply to delete the file.
4587  *
4588  */
4589
4590
4591 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4592 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4593 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4594
4595 /* Define an extension to the ext2 library's block count information */
4596 #define BLOCK_COUNT_EXTATTR     (-5)
4597
4598 struct block_el {
4599         blk_t   block;
4600         struct block_el *next;
4601 };
4602
4603 struct inode_el {
4604         ext2_ino_t      inode;
4605         struct inode_el *next;
4606 };
4607
4608 struct dup_block {
4609         int             num_bad;
4610         struct inode_el *inode_list;
4611 };
4612
4613 /*
4614  * This structure stores information about a particular inode which
4615  * is sharing blocks with other inodes.  This information is collected
4616  * to display to the user, so that the user knows what files he or she
4617  * is dealing with, when trying to decide how to resolve the conflict
4618  * of multiply-claimed blocks.
4619  */
4620 struct dup_inode {
4621         ext2_ino_t              dir;
4622         int                     num_dupblocks;
4623         struct ext2_inode       inode;
4624         struct block_el         *block_list;
4625 };
4626
4627 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4628                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4629                                 int ref_offset, void *priv_data);
4630 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4631                         struct dup_inode *dp, char *block_buf);
4632 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4633                       struct dup_inode *dp, char* block_buf);
4634 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4635
4636 static void pass1b(e2fsck_t ctx, char *block_buf);
4637 static void pass1c(e2fsck_t ctx, char *block_buf);
4638 static void pass1d(e2fsck_t ctx, char *block_buf);
4639
4640 static int dup_inode_count = 0;
4641
4642 static dict_t blk_dict, ino_dict;
4643
4644 static ext2fs_inode_bitmap inode_dup_map;
4645
4646 static int dict_int_cmp(const void *a, const void *b)
4647 {
4648         intptr_t        ia, ib;
4649
4650         ia = (intptr_t)a;
4651         ib = (intptr_t)b;
4652
4653         return (ia-ib);
4654 }
4655
4656 /*
4657  * Add a duplicate block record
4658  */
4659 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4660                      struct ext2_inode *inode)
4661 {
4662         dnode_t *n;
4663         struct dup_block        *db;
4664         struct dup_inode        *di;
4665         struct block_el         *blk_el;
4666         struct inode_el         *ino_el;
4667
4668         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4669         if (n)
4670                 db = (struct dup_block *) dnode_get(n);
4671         else {
4672                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4673                          sizeof(struct dup_block), "duplicate block header");
4674                 db->num_bad = 0;
4675                 db->inode_list = 0;
4676                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4677         }
4678         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4679                          sizeof(struct inode_el), "inode element");
4680         ino_el->inode = ino;
4681         ino_el->next = db->inode_list;
4682         db->inode_list = ino_el;
4683         db->num_bad++;
4684
4685         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4686         if (n)
4687                 di = (struct dup_inode *) dnode_get(n);
4688         else {
4689                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4690                          sizeof(struct dup_inode), "duplicate inode header");
4691                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4692                 di->num_dupblocks = 0;
4693                 di->block_list = 0;
4694                 di->inode = *inode;
4695                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4696         }
4697         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4698                          sizeof(struct block_el), "block element");
4699         blk_el->block = blk;
4700         blk_el->next = di->block_list;
4701         di->block_list = blk_el;
4702         di->num_dupblocks++;
4703 }
4704
4705 /*
4706  * Free a duplicate inode record
4707  */
4708 static void inode_dnode_free(dnode_t *node)
4709 {
4710         struct dup_inode        *di;
4711         struct block_el         *p, *next;
4712
4713         di = (struct dup_inode *) dnode_get(node);
4714         for (p = di->block_list; p; p = next) {
4715                 next = p->next;
4716                 free(p);
4717         }
4718         free(node);
4719 }
4720
4721 /*
4722  * Free a duplicate block record
4723  */
4724 static void block_dnode_free(dnode_t *node)
4725 {
4726         struct dup_block        *db;
4727         struct inode_el         *p, *next;
4728
4729         db = (struct dup_block *) dnode_get(node);
4730         for (p = db->inode_list; p; p = next) {
4731                 next = p->next;
4732                 free(p);
4733         }
4734         free(node);
4735 }
4736
4737
4738 /*
4739  * Main procedure for handling duplicate blocks
4740  */
4741 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4742 {
4743         ext2_filsys             fs = ctx->fs;
4744         struct problem_context  pctx;
4745
4746         clear_problem_context(&pctx);
4747
4748         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4749                       _("multiply claimed inode map"), &inode_dup_map);
4750         if (pctx.errcode) {
4751                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4752                 ctx->flags |= E2F_FLAG_ABORT;
4753                 return;
4754         }
4755
4756         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4757         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4758         dict_set_allocator(&ino_dict, inode_dnode_free);
4759         dict_set_allocator(&blk_dict, block_dnode_free);
4760
4761         pass1b(ctx, block_buf);
4762         pass1c(ctx, block_buf);
4763         pass1d(ctx, block_buf);
4764
4765         /*
4766          * Time to free all of the accumulated data structures that we
4767          * don't need anymore.
4768          */
4769         dict_free_nodes(&ino_dict);
4770         dict_free_nodes(&blk_dict);
4771 }
4772
4773 /*
4774  * Scan the inodes looking for inodes that contain duplicate blocks.
4775  */
4776 struct process_block_struct_1b {
4777         e2fsck_t        ctx;
4778         ext2_ino_t      ino;
4779         int             dup_blocks;
4780         struct ext2_inode *inode;
4781         struct problem_context *pctx;
4782 };
4783
4784 static void pass1b(e2fsck_t ctx, char *block_buf)
4785 {
4786         ext2_filsys fs = ctx->fs;
4787         ext2_ino_t ino;
4788         struct ext2_inode inode;
4789         ext2_inode_scan scan;
4790         struct process_block_struct_1b pb;
4791         struct problem_context pctx;
4792
4793         clear_problem_context(&pctx);
4794
4795         if (!(ctx->options & E2F_OPT_PREEN))
4796                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4797         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4798                                               &scan);
4799         if (pctx.errcode) {
4800                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4801                 ctx->flags |= E2F_FLAG_ABORT;
4802                 return;
4803         }
4804         ctx->stashed_inode = &inode;
4805         pb.ctx = ctx;
4806         pb.pctx = &pctx;
4807         pctx.str = "pass1b";
4808         while (1) {
4809                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4810                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4811                         continue;
4812                 if (pctx.errcode) {
4813                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4814                         ctx->flags |= E2F_FLAG_ABORT;
4815                         return;
4816                 }
4817                 if (!ino)
4818                         break;
4819                 pctx.ino = ctx->stashed_ino = ino;
4820                 if ((ino != EXT2_BAD_INO) &&
4821                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4822                         continue;
4823
4824                 pb.ino = ino;
4825                 pb.dup_blocks = 0;
4826                 pb.inode = &inode;
4827
4828                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4829                     (ino == EXT2_BAD_INO))
4830                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4831                                      0, block_buf, process_pass1b_block, &pb);
4832                 if (inode.i_file_acl)
4833                         process_pass1b_block(fs, &inode.i_file_acl,
4834                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4835                 if (pb.dup_blocks) {
4836                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4837                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4838                             ino == EXT2_ROOT_INO)
4839                                 dup_inode_count++;
4840                 }
4841                 if (pctx.errcode)
4842                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4843         }
4844         ext2fs_close_inode_scan(scan);
4845         e2fsck_use_inode_shortcuts(ctx, 0);
4846 }
4847
4848 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4849                                 blk_t   *block_nr,
4850                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4851                                 blk_t ref_blk FSCK_ATTR((unused)),
4852                                 int ref_offset FSCK_ATTR((unused)),
4853                                 void *priv_data)
4854 {
4855         struct process_block_struct_1b *p;
4856         e2fsck_t ctx;
4857
4858         if (HOLE_BLKADDR(*block_nr))
4859                 return 0;
4860         p = (struct process_block_struct_1b *) priv_data;
4861         ctx = p->ctx;
4862
4863         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4864                 return 0;
4865
4866         /* OK, this is a duplicate block */
4867         if (p->ino != EXT2_BAD_INO) {
4868                 p->pctx->blk = *block_nr;
4869                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4870         }
4871         p->dup_blocks++;
4872         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4873
4874         add_dupe(ctx, p->ino, *block_nr, p->inode);
4875
4876         return 0;
4877 }
4878
4879 /*
4880  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4881  * is used so that we can print pathnames when prompting the user for
4882  * what to do.
4883  */
4884 struct search_dir_struct {
4885         int             count;
4886         ext2_ino_t      first_inode;
4887         ext2_ino_t      max_inode;
4888 };
4889
4890 static int search_dirent_proc(ext2_ino_t dir, int entry,
4891                               struct ext2_dir_entry *dirent,
4892                               int offset FSCK_ATTR((unused)),
4893                               int blocksize FSCK_ATTR((unused)),
4894                               char *buf FSCK_ATTR((unused)),
4895                               void *priv_data)
4896 {
4897         struct search_dir_struct *sd;
4898         struct dup_inode        *p;
4899         dnode_t                 *n;
4900
4901         sd = (struct search_dir_struct *) priv_data;
4902
4903         if (dirent->inode > sd->max_inode)
4904                 /* Should abort this inode, but not everything */
4905                 return 0;
4906
4907         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4908             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4909                 return 0;
4910
4911         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4912         if (!n)
4913                 return 0;
4914         p = (struct dup_inode *) dnode_get(n);
4915         p->dir = dir;
4916         sd->count--;
4917
4918         return sd->count ? 0 : DIRENT_ABORT;
4919 }
4920
4921
4922 static void pass1c(e2fsck_t ctx, char *block_buf)
4923 {
4924         ext2_filsys fs = ctx->fs;
4925         struct search_dir_struct sd;
4926         struct problem_context pctx;
4927
4928         clear_problem_context(&pctx);
4929
4930         if (!(ctx->options & E2F_OPT_PREEN))
4931                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4932
4933         /*
4934          * Search through all directories to translate inodes to names
4935          * (by searching for the containing directory for that inode.)
4936          */
4937         sd.count = dup_inode_count;
4938         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4939         sd.max_inode = fs->super->s_inodes_count;
4940         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4941                                   search_dirent_proc, &sd);
4942 }
4943
4944 static void pass1d(e2fsck_t ctx, char *block_buf)
4945 {
4946         ext2_filsys fs = ctx->fs;
4947         struct dup_inode        *p, *t;
4948         struct dup_block        *q;
4949         ext2_ino_t              *shared, ino;
4950         int     shared_len;
4951         int     i;
4952         int     file_ok;
4953         int     meta_data = 0;
4954         struct problem_context pctx;
4955         dnode_t *n, *m;
4956         struct block_el *s;
4957         struct inode_el *r;
4958
4959         clear_problem_context(&pctx);
4960
4961         if (!(ctx->options & E2F_OPT_PREEN))
4962                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4963         e2fsck_read_bitmaps(ctx);
4964
4965         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4966         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4967         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4968                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4969                                 "Shared inode list");
4970         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4971                 p = (struct dup_inode *) dnode_get(n);
4972                 shared_len = 0;
4973                 file_ok = 1;
4974                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4975                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4976                         continue;
4977
4978                 /*
4979                  * Find all of the inodes which share blocks with this
4980                  * one.  First we find all of the duplicate blocks
4981                  * belonging to this inode, and then search each block
4982                  * get the list of inodes, and merge them together.
4983                  */
4984                 for (s = p->block_list; s; s = s->next) {
4985                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4986                         if (!m)
4987                                 continue; /* Should never happen... */
4988                         q = (struct dup_block *) dnode_get(m);
4989                         if (q->num_bad > 1)
4990                                 file_ok = 0;
4991                         if (check_if_fs_block(ctx, s->block)) {
4992                                 file_ok = 0;
4993                                 meta_data = 1;
4994                         }
4995
4996                         /*
4997                          * Add all inodes used by this block to the
4998                          * shared[] --- which is a unique list, so
4999                          * if an inode is already in shared[], don't
5000                          * add it again.
5001                          */
5002                         for (r = q->inode_list; r; r = r->next) {
5003                                 if (r->inode == ino)
5004                                         continue;
5005                                 for (i = 0; i < shared_len; i++)
5006                                         if (shared[i] == r->inode)
5007                                                 break;
5008                                 if (i == shared_len) {
5009                                         shared[shared_len++] = r->inode;
5010                                 }
5011                         }
5012                 }
5013
5014                 /*
5015                  * Report the inode that we are working on
5016                  */
5017                 pctx.inode = &p->inode;
5018                 pctx.ino = ino;
5019                 pctx.dir = p->dir;
5020                 pctx.blkcount = p->num_dupblocks;
5021                 pctx.num = meta_data ? shared_len+1 : shared_len;
5022                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5023                 pctx.blkcount = 0;
5024                 pctx.num = 0;
5025
5026                 if (meta_data)
5027                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5028
5029                 for (i = 0; i < shared_len; i++) {
5030                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5031                         if (!m)
5032                                 continue; /* should never happen */
5033                         t = (struct dup_inode *) dnode_get(m);
5034                         /*
5035                          * Report the inode that we are sharing with
5036                          */
5037                         pctx.inode = &t->inode;
5038                         pctx.ino = shared[i];
5039                         pctx.dir = t->dir;
5040                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5041                 }
5042                 if (file_ok) {
5043                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5044                         continue;
5045                 }
5046                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5047                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5048                         if (pctx.errcode)
5049                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5050                         else
5051                                 continue;
5052                 }
5053                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5054                         delete_file(ctx, ino, p, block_buf);
5055                 else
5056                         ext2fs_unmark_valid(fs);
5057         }
5058         ext2fs_free_mem(&shared);
5059 }
5060
5061 /*
5062  * Drop the refcount on the dup_block structure, and clear the entry
5063  * in the block_dup_map if appropriate.
5064  */
5065 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5066 {
5067         p->num_bad--;
5068         if (p->num_bad <= 0 ||
5069             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5070                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5071 }
5072
5073 static int delete_file_block(ext2_filsys fs,
5074                              blk_t      *block_nr,
5075                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5076                              blk_t ref_block FSCK_ATTR((unused)),
5077                              int ref_offset FSCK_ATTR((unused)),
5078                              void *priv_data)
5079 {
5080         struct process_block_struct_1b *pb;
5081         struct dup_block *p;
5082         dnode_t *n;
5083         e2fsck_t ctx;
5084
5085         pb = (struct process_block_struct_1b *) priv_data;
5086         ctx = pb->ctx;
5087
5088         if (HOLE_BLKADDR(*block_nr))
5089                 return 0;
5090
5091         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5092                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5093                 if (n) {
5094                         p = (struct dup_block *) dnode_get(n);
5095                         decrement_badcount(ctx, *block_nr, p);
5096                 } else
5097                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5098                                 *block_nr);
5099         } else {
5100                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5101                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5102         }
5103
5104         return 0;
5105 }
5106
5107 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5108                         struct dup_inode *dp, char* block_buf)
5109 {
5110         ext2_filsys fs = ctx->fs;
5111         struct process_block_struct_1b pb;
5112         struct ext2_inode       inode;
5113         struct problem_context  pctx;
5114         unsigned int            count;
5115
5116         clear_problem_context(&pctx);
5117         pctx.ino = pb.ino = ino;
5118         pb.dup_blocks = dp->num_dupblocks;
5119         pb.ctx = ctx;
5120         pctx.str = "delete_file";
5121
5122         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5123         if (ext2fs_inode_has_valid_blocks(&inode))
5124                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5125                                                      delete_file_block, &pb);
5126         if (pctx.errcode)
5127                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5128         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5129         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5130         if (ctx->inode_bad_map)
5131                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5132         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5133
5134         /* Inode may have changed by block_iterate, so reread it */
5135         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5136         inode.i_links_count = 0;
5137         inode.i_dtime = time(NULL);
5138         if (inode.i_file_acl &&
5139             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5140                 count = 1;
5141                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5142                                                    block_buf, -1, &count);
5143                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5144                         pctx.errcode = 0;
5145                         count = 1;
5146                 }
5147                 if (pctx.errcode) {
5148                         pctx.blk = inode.i_file_acl;
5149                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5150                 }
5151                 /*
5152                  * If the count is zero, then arrange to have the
5153                  * block deleted.  If the block is in the block_dup_map,
5154                  * also call delete_file_block since it will take care
5155                  * of keeping the accounting straight.
5156                  */
5157                 if ((count == 0) ||
5158                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5159                                              inode.i_file_acl))
5160                         delete_file_block(fs, &inode.i_file_acl,
5161                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5162         }
5163         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5164 }
5165
5166 struct clone_struct {
5167         errcode_t       errcode;
5168         ext2_ino_t      dir;
5169         char    *buf;
5170         e2fsck_t ctx;
5171 };
5172
5173 static int clone_file_block(ext2_filsys fs,
5174                             blk_t       *block_nr,
5175                             e2_blkcnt_t blockcnt,
5176                             blk_t ref_block FSCK_ATTR((unused)),
5177                             int ref_offset FSCK_ATTR((unused)),
5178                             void *priv_data)
5179 {
5180         struct dup_block *p;
5181         blk_t   new_block;
5182         errcode_t       retval;
5183         struct clone_struct *cs = (struct clone_struct *) priv_data;
5184         dnode_t *n;
5185         e2fsck_t ctx;
5186
5187         ctx = cs->ctx;
5188
5189         if (HOLE_BLKADDR(*block_nr))
5190                 return 0;
5191
5192         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5193                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5194                 if (n) {
5195                         p = (struct dup_block *) dnode_get(n);
5196                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5197                                                   &new_block);
5198                         if (retval) {
5199                                 cs->errcode = retval;
5200                                 return BLOCK_ABORT;
5201                         }
5202                         if (cs->dir && (blockcnt >= 0)) {
5203                                 retval = ext2fs_set_dir_block(fs->dblist,
5204                                       cs->dir, new_block, blockcnt);
5205                                 if (retval) {
5206                                         cs->errcode = retval;
5207                                         return BLOCK_ABORT;
5208                                 }
5209                         }
5210
5211                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5212                                                      cs->buf);
5213                         if (retval) {
5214                                 cs->errcode = retval;
5215                                 return BLOCK_ABORT;
5216                         }
5217                         retval = io_channel_write_blk(fs->io, new_block, 1,
5218                                                       cs->buf);
5219                         if (retval) {
5220                                 cs->errcode = retval;
5221                                 return BLOCK_ABORT;
5222                         }
5223                         decrement_badcount(ctx, *block_nr, p);
5224                         *block_nr = new_block;
5225                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5226                                                  new_block);
5227                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5228                         return BLOCK_CHANGED;
5229                 } else
5230                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5231                                 *block_nr);
5232         }
5233         return 0;
5234 }
5235
5236 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5237                       struct dup_inode *dp, char* block_buf)
5238 {
5239         ext2_filsys fs = ctx->fs;
5240         errcode_t       retval;
5241         struct clone_struct cs;
5242         struct problem_context  pctx;
5243         blk_t           blk;
5244         dnode_t         *n;
5245         struct inode_el *ino_el;
5246         struct dup_block        *db;
5247         struct dup_inode        *di;
5248
5249         clear_problem_context(&pctx);
5250         cs.errcode = 0;
5251         cs.dir = 0;
5252         cs.ctx = ctx;
5253         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5254         if (retval)
5255                 return retval;
5256
5257         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5258                 cs.dir = ino;
5259
5260         pctx.ino = ino;
5261         pctx.str = "clone_file";
5262         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5263                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5264                                                      clone_file_block, &cs);
5265         ext2fs_mark_bb_dirty(fs);
5266         if (pctx.errcode) {
5267                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5268                 retval = pctx.errcode;
5269                 goto errout;
5270         }
5271         if (cs.errcode) {
5272                 bb_error_msg(_("returned from clone_file_block"));
5273                 retval = cs.errcode;
5274                 goto errout;
5275         }
5276         /* The inode may have changed on disk, so we have to re-read it */
5277         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5278         blk = dp->inode.i_file_acl;
5279         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5280                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5281                     BLOCK_CHANGED)) {
5282                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5283                 /*
5284                  * If we cloned the EA block, find all other inodes
5285                  * which refered to that EA block, and modify
5286                  * them to point to the new EA block.
5287                  */
5288                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5289                 db = (struct dup_block *) dnode_get(n);
5290                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5291                         if (ino_el->inode == ino)
5292                                 continue;
5293                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5294                         di = (struct dup_inode *) dnode_get(n);
5295                         if (di->inode.i_file_acl == blk) {
5296                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5297                                 e2fsck_write_inode(ctx, ino_el->inode,
5298                                            &di->inode, "clone file EA");
5299                                 decrement_badcount(ctx, blk, db);
5300                         }
5301                 }
5302         }
5303         retval = 0;
5304 errout:
5305         ext2fs_free_mem(&cs.buf);
5306         return retval;
5307 }
5308
5309 /*
5310  * This routine returns 1 if a block overlaps with one of the superblocks,
5311  * group descriptors, inode bitmaps, or block bitmaps.
5312  */
5313 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5314 {
5315         ext2_filsys fs = ctx->fs;
5316         blk_t   block;
5317         dgrp_t  i;
5318
5319         block = fs->super->s_first_data_block;
5320         for (i = 0; i < fs->group_desc_count; i++) {
5321
5322                 /* Check superblocks/block group descriptros */
5323                 if (ext2fs_bg_has_super(fs, i)) {
5324                         if (test_block >= block &&
5325                             (test_block <= block + fs->desc_blocks))
5326                                 return 1;
5327                 }
5328
5329                 /* Check the inode table */
5330                 if ((fs->group_desc[i].bg_inode_table) &&
5331                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5332                     (test_block < (fs->group_desc[i].bg_inode_table +
5333                                    fs->inode_blocks_per_group)))
5334                         return 1;
5335
5336                 /* Check the bitmap blocks */
5337                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5338                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5339                         return 1;
5340
5341                 block += fs->super->s_blocks_per_group;
5342         }
5343         return 0;
5344 }
5345 /*
5346  * pass2.c --- check directory structure
5347  *
5348  * Pass 2 of e2fsck iterates through all active directory inodes, and
5349  * applies to following tests to each directory entry in the directory
5350  * blocks in the inodes:
5351  *
5352  *      - The length of the directory entry (rec_len) should be at
5353  *              least 8 bytes, and no more than the remaining space
5354  *              left in the directory block.
5355  *      - The length of the name in the directory entry (name_len)
5356  *              should be less than (rec_len - 8).
5357  *      - The inode number in the directory entry should be within
5358  *              legal bounds.
5359  *      - The inode number should refer to a in-use inode.
5360  *      - The first entry should be '.', and its inode should be
5361  *              the inode of the directory.
5362  *      - The second entry should be '..'.
5363  *
5364  * To minimize disk seek time, the directory blocks are processed in
5365  * sorted order of block numbers.
5366  *
5367  * Pass 2 also collects the following information:
5368  *      - The inode numbers of the subdirectories for each directory.
5369  *
5370  * Pass 2 relies on the following information from previous passes:
5371  *      - The directory information collected in pass 1.
5372  *      - The inode_used_map bitmap
5373  *      - The inode_bad_map bitmap
5374  *      - The inode_dir_map bitmap
5375  *
5376  * Pass 2 frees the following data structures
5377  *      - The inode_bad_map bitmap
5378  *      - The inode_reg_map bitmap
5379  */
5380
5381 /*
5382  * Keeps track of how many times an inode is referenced.
5383  */
5384 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5385 static int check_dir_block(ext2_filsys fs,
5386                            struct ext2_db_entry *dir_blocks_info,
5387                            void *priv_data);
5388 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5389                               struct problem_context *pctx);
5390 static int update_dir_block(ext2_filsys fs,
5391                             blk_t       *block_nr,
5392                             e2_blkcnt_t blockcnt,
5393                             blk_t       ref_block,
5394                             int         ref_offset,
5395                             void        *priv_data);
5396 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5397 static int htree_depth(struct dx_dir_info *dx_dir,
5398                        struct dx_dirblock_info *dx_db);
5399 static int special_dir_block_cmp(const void *a, const void *b);
5400
5401 struct check_dir_struct {
5402         char *buf;
5403         struct problem_context  pctx;
5404         int     count, max;
5405         e2fsck_t ctx;
5406 };
5407
5408 static void e2fsck_pass2(e2fsck_t ctx)
5409 {
5410         struct ext2_super_block *sb = ctx->fs->super;
5411         struct problem_context  pctx;
5412         ext2_filsys             fs = ctx->fs;
5413         char                    *buf;
5414         struct dir_info         *dir;
5415         struct check_dir_struct cd;
5416         struct dx_dir_info      *dx_dir;
5417         struct dx_dirblock_info *dx_db, *dx_parent;
5418         int                     b;
5419         int                     i, depth;
5420         problem_t               code;
5421         int                     bad_dir;
5422
5423         clear_problem_context(&cd.pctx);
5424
5425         /* Pass 2 */
5426
5427         if (!(ctx->options & E2F_OPT_PREEN))
5428                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5429
5430         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5431                                                 0, ctx->inode_link_info,
5432                                                 &ctx->inode_count);
5433         if (cd.pctx.errcode) {
5434                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5435                 ctx->flags |= E2F_FLAG_ABORT;
5436                 return;
5437         }
5438         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5439                                               "directory scan buffer");
5440
5441         /*
5442          * Set up the parent pointer for the root directory, if
5443          * present.  (If the root directory is not present, we will
5444          * create it in pass 3.)
5445          */
5446         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5447         if (dir)
5448                 dir->parent = EXT2_ROOT_INO;
5449
5450         cd.buf = buf;
5451         cd.ctx = ctx;
5452         cd.count = 1;
5453         cd.max = ext2fs_dblist_count(fs->dblist);
5454
5455         if (ctx->progress)
5456                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5457
5458         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5459                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5460
5461         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5462                                                 &cd);
5463         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5464                 return;
5465         if (cd.pctx.errcode) {
5466                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5467                 ctx->flags |= E2F_FLAG_ABORT;
5468                 return;
5469         }
5470
5471 #ifdef ENABLE_HTREE
5472         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5473                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5474                         return;
5475                 if (dx_dir->numblocks == 0)
5476                         continue;
5477                 clear_problem_context(&pctx);
5478                 bad_dir = 0;
5479                 pctx.dir = dx_dir->ino;
5480                 dx_db = dx_dir->dx_block;
5481                 if (dx_db->flags & DX_FLAG_REFERENCED)
5482                         dx_db->flags |= DX_FLAG_DUP_REF;
5483                 else
5484                         dx_db->flags |= DX_FLAG_REFERENCED;
5485                 /*
5486                  * Find all of the first and last leaf blocks, and
5487                  * update their parent's min and max hash values
5488                  */
5489                 for (b=0, dx_db = dx_dir->dx_block;
5490                      b < dx_dir->numblocks;
5491                      b++, dx_db++) {
5492                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5493                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5494                                 continue;
5495                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5496                         /*
5497                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5498                          */
5499                         if (dx_db->flags & DX_FLAG_FIRST)
5500                                 dx_parent->min_hash = dx_db->min_hash;
5501                         /*
5502                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5503                          */
5504                         if (dx_db->flags & DX_FLAG_LAST)
5505                                 dx_parent->max_hash = dx_db->max_hash;
5506                 }
5507
5508                 for (b=0, dx_db = dx_dir->dx_block;
5509                      b < dx_dir->numblocks;
5510                      b++, dx_db++) {
5511                         pctx.blkcount = b;
5512                         pctx.group = dx_db->parent;
5513                         code = 0;
5514                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5515                             (dx_db->min_hash < dx_db->node_min_hash)) {
5516                                 pctx.blk = dx_db->min_hash;
5517                                 pctx.blk2 = dx_db->node_min_hash;
5518                                 code = PR_2_HTREE_MIN_HASH;
5519                                 fix_problem(ctx, code, &pctx);
5520                                 bad_dir++;
5521                         }
5522                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5523                                 depth = htree_depth(dx_dir, dx_db);
5524                                 if (depth != dx_dir->depth) {
5525                                         code = PR_2_HTREE_BAD_DEPTH;
5526                                         fix_problem(ctx, code, &pctx);
5527                                         bad_dir++;
5528                                 }
5529                         }
5530                         /*
5531                          * This test doesn't apply for the root block
5532                          * at block #0
5533                          */
5534                         if (b &&
5535                             (dx_db->max_hash > dx_db->node_max_hash)) {
5536                                 pctx.blk = dx_db->max_hash;
5537                                 pctx.blk2 = dx_db->node_max_hash;
5538                                 code = PR_2_HTREE_MAX_HASH;
5539                                 fix_problem(ctx, code, &pctx);
5540                                 bad_dir++;
5541                         }
5542                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5543                                 code = PR_2_HTREE_NOTREF;
5544                                 fix_problem(ctx, code, &pctx);
5545                                 bad_dir++;
5546                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5547                                 code = PR_2_HTREE_DUPREF;
5548                                 fix_problem(ctx, code, &pctx);
5549                                 bad_dir++;
5550                         }
5551                         if (code == 0)
5552                                 continue;
5553                 }
5554                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5555                         clear_htree(ctx, dx_dir->ino);
5556                         dx_dir->numblocks = 0;
5557                 }
5558         }
5559 #endif
5560         ext2fs_free_mem(&buf);
5561         ext2fs_free_dblist(fs->dblist);
5562
5563         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5564         ctx->inode_bad_map = 0;
5565         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5566         ctx->inode_reg_map = 0;
5567
5568         clear_problem_context(&pctx);
5569         if (ctx->large_files) {
5570                 if (!(sb->s_feature_ro_compat &
5571                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5572                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5573                         sb->s_feature_ro_compat |=
5574                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5575                         ext2fs_mark_super_dirty(fs);
5576                 }
5577                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5578                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5579                         ext2fs_update_dynamic_rev(fs);
5580                         ext2fs_mark_super_dirty(fs);
5581                 }
5582         } else if (!ctx->large_files &&
5583             (sb->s_feature_ro_compat &
5584               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5585                 if (fs->flags & EXT2_FLAG_RW) {
5586                         sb->s_feature_ro_compat &=
5587                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5588                         ext2fs_mark_super_dirty(fs);
5589                 }
5590         }
5591
5592 }
5593
5594 #define MAX_DEPTH 32000
5595 static int htree_depth(struct dx_dir_info *dx_dir,
5596                        struct dx_dirblock_info *dx_db)
5597 {
5598         int     depth = 0;
5599
5600         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5601                 dx_db = &dx_dir->dx_block[dx_db->parent];
5602                 depth++;
5603         }
5604         return depth;
5605 }
5606
5607 static int dict_de_cmp(const void *a, const void *b)
5608 {
5609         const struct ext2_dir_entry *de_a, *de_b;
5610         int     a_len, b_len;
5611
5612         de_a = (const struct ext2_dir_entry *) a;
5613         a_len = de_a->name_len & 0xFF;
5614         de_b = (const struct ext2_dir_entry *) b;
5615         b_len = de_b->name_len & 0xFF;
5616
5617         if (a_len != b_len)
5618                 return (a_len - b_len);
5619
5620         return strncmp(de_a->name, de_b->name, a_len);
5621 }
5622
5623 /*
5624  * This is special sort function that makes sure that directory blocks
5625  * with a dirblock of zero are sorted to the beginning of the list.
5626  * This guarantees that the root node of the htree directories are
5627  * processed first, so we know what hash version to use.
5628  */
5629 static int special_dir_block_cmp(const void *a, const void *b)
5630 {
5631         const struct ext2_db_entry *db_a =
5632                 (const struct ext2_db_entry *) a;
5633         const struct ext2_db_entry *db_b =
5634                 (const struct ext2_db_entry *) b;
5635
5636         if (db_a->blockcnt && !db_b->blockcnt)
5637                 return 1;
5638
5639         if (!db_a->blockcnt && db_b->blockcnt)
5640                 return -1;
5641
5642         if (db_a->blk != db_b->blk)
5643                 return (int) (db_a->blk - db_b->blk);
5644
5645         if (db_a->ino != db_b->ino)
5646                 return (int) (db_a->ino - db_b->ino);
5647
5648         return (int) (db_a->blockcnt - db_b->blockcnt);
5649 }
5650
5651
5652 /*
5653  * Make sure the first entry in the directory is '.', and that the
5654  * directory entry is sane.
5655  */
5656 static int check_dot(e2fsck_t ctx,
5657                      struct ext2_dir_entry *dirent,
5658                      ext2_ino_t ino, struct problem_context *pctx)
5659 {
5660         struct ext2_dir_entry *nextdir;
5661         int     status = 0;
5662         int     created = 0;
5663         int     new_len;
5664         int     problem = 0;
5665
5666         if (!dirent->inode)
5667                 problem = PR_2_MISSING_DOT;
5668         else if (((dirent->name_len & 0xFF) != 1) ||
5669                  (dirent->name[0] != '.'))
5670                 problem = PR_2_1ST_NOT_DOT;
5671         else if (dirent->name[1] != '\0')
5672                 problem = PR_2_DOT_NULL_TERM;
5673
5674         if (problem) {
5675                 if (fix_problem(ctx, problem, pctx)) {
5676                         if (dirent->rec_len < 12)
5677                                 dirent->rec_len = 12;
5678                         dirent->inode = ino;
5679                         dirent->name_len = 1;
5680                         dirent->name[0] = '.';
5681                         dirent->name[1] = '\0';
5682                         status = 1;
5683                         created = 1;
5684                 }
5685         }
5686         if (dirent->inode != ino) {
5687                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5688                         dirent->inode = ino;
5689                         status = 1;
5690                 }
5691         }
5692         if (dirent->rec_len > 12) {
5693                 new_len = dirent->rec_len - 12;
5694                 if (new_len > 12) {
5695                         if (created ||
5696                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5697                                 nextdir = (struct ext2_dir_entry *)
5698                                         ((char *) dirent + 12);
5699                                 dirent->rec_len = 12;
5700                                 nextdir->rec_len = new_len;
5701                                 nextdir->inode = 0;
5702                                 nextdir->name_len = 0;
5703                                 status = 1;
5704                         }
5705                 }
5706         }
5707         return status;
5708 }
5709
5710 /*
5711  * Make sure the second entry in the directory is '..', and that the
5712  * directory entry is sane.  We do not check the inode number of '..'
5713  * here; this gets done in pass 3.
5714  */
5715 static int check_dotdot(e2fsck_t ctx,
5716                         struct ext2_dir_entry *dirent,
5717                         struct dir_info *dir, struct problem_context *pctx)
5718 {
5719         int             problem = 0;
5720
5721         if (!dirent->inode)
5722                 problem = PR_2_MISSING_DOT_DOT;
5723         else if (((dirent->name_len & 0xFF) != 2) ||
5724                  (dirent->name[0] != '.') ||
5725                  (dirent->name[1] != '.'))
5726                 problem = PR_2_2ND_NOT_DOT_DOT;
5727         else if (dirent->name[2] != '\0')
5728                 problem = PR_2_DOT_DOT_NULL_TERM;
5729
5730         if (problem) {
5731                 if (fix_problem(ctx, problem, pctx)) {
5732                         if (dirent->rec_len < 12)
5733                                 dirent->rec_len = 12;
5734                         /*
5735                          * Note: we don't have the parent inode just
5736                          * yet, so we will fill it in with the root
5737                          * inode.  This will get fixed in pass 3.
5738                          */
5739                         dirent->inode = EXT2_ROOT_INO;
5740                         dirent->name_len = 2;
5741                         dirent->name[0] = '.';
5742                         dirent->name[1] = '.';
5743                         dirent->name[2] = '\0';
5744                         return 1;
5745                 }
5746                 return 0;
5747         }
5748         dir->dotdot = dirent->inode;
5749         return 0;
5750 }
5751
5752 /*
5753  * Check to make sure a directory entry doesn't contain any illegal
5754  * characters.
5755  */
5756 static int check_name(e2fsck_t ctx,
5757                       struct ext2_dir_entry *dirent,
5758                       struct problem_context *pctx)
5759 {
5760         int     i;
5761         int     fixup = -1;
5762         int     ret = 0;
5763
5764         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5765                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5766                         if (fixup < 0) {
5767                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5768                         }
5769                         if (fixup) {
5770                                 dirent->name[i] = '.';
5771                                 ret = 1;
5772                         }
5773                 }
5774         }
5775         return ret;
5776 }
5777
5778 /*
5779  * Check the directory filetype (if present)
5780  */
5781
5782 /*
5783  * Given a mode, return the ext2 file type
5784  */
5785 static int ext2_file_type(unsigned int mode)
5786 {
5787         if (LINUX_S_ISREG(mode))
5788                 return EXT2_FT_REG_FILE;
5789
5790         if (LINUX_S_ISDIR(mode))
5791                 return EXT2_FT_DIR;
5792
5793         if (LINUX_S_ISCHR(mode))
5794                 return EXT2_FT_CHRDEV;
5795
5796         if (LINUX_S_ISBLK(mode))
5797                 return EXT2_FT_BLKDEV;
5798
5799         if (LINUX_S_ISLNK(mode))
5800                 return EXT2_FT_SYMLINK;
5801
5802         if (LINUX_S_ISFIFO(mode))
5803                 return EXT2_FT_FIFO;
5804
5805         if (LINUX_S_ISSOCK(mode))
5806                 return EXT2_FT_SOCK;
5807
5808         return 0;
5809 }
5810
5811 static int check_filetype(e2fsck_t ctx,
5812                                    struct ext2_dir_entry *dirent,
5813                                    struct problem_context *pctx)
5814 {
5815         int     filetype = dirent->name_len >> 8;
5816         int     should_be = EXT2_FT_UNKNOWN;
5817         struct ext2_inode       inode;
5818
5819         if (!(ctx->fs->super->s_feature_incompat &
5820               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5821                 if (filetype == 0 ||
5822                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5823                         return 0;
5824                 dirent->name_len = dirent->name_len & 0xFF;
5825                 return 1;
5826         }
5827
5828         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5829                 should_be = EXT2_FT_DIR;
5830         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5831                                             dirent->inode)) {
5832                 should_be = EXT2_FT_REG_FILE;
5833         } else if (ctx->inode_bad_map &&
5834                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5835                                             dirent->inode))
5836                 should_be = 0;
5837         else {
5838                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5839                                   "check_filetype");
5840                 should_be = ext2_file_type(inode.i_mode);
5841         }
5842         if (filetype == should_be)
5843                 return 0;
5844         pctx->num = should_be;
5845
5846         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5847                         pctx) == 0)
5848                 return 0;
5849
5850         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5851         return 1;
5852 }
5853
5854 #ifdef ENABLE_HTREE
5855 static void parse_int_node(ext2_filsys fs,
5856                            struct ext2_db_entry *db,
5857                            struct check_dir_struct *cd,
5858                            struct dx_dir_info   *dx_dir,
5859                            char *block_buf)
5860 {
5861         struct          ext2_dx_root_info  *root;
5862         struct          ext2_dx_entry *ent;
5863         struct          ext2_dx_countlimit *limit;
5864         struct dx_dirblock_info *dx_db;
5865         int             i, expect_limit, count;
5866         blk_t           blk;
5867         ext2_dirhash_t  min_hash = 0xffffffff;
5868         ext2_dirhash_t  max_hash = 0;
5869         ext2_dirhash_t  hash = 0, prev_hash;
5870
5871         if (db->blockcnt == 0) {
5872                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5873                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5874         } else {
5875                 ent = (struct ext2_dx_entry *) (block_buf+8);
5876         }
5877         limit = (struct ext2_dx_countlimit *) ent;
5878
5879         count = ext2fs_le16_to_cpu(limit->count);
5880         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5881                 sizeof(struct ext2_dx_entry);
5882         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5883                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5884                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5885                         goto clear_and_exit;
5886         }
5887         if (count > expect_limit) {
5888                 cd->pctx.num = count;
5889                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5890                         goto clear_and_exit;
5891                 count = expect_limit;
5892         }
5893
5894         for (i=0; i < count; i++) {
5895                 prev_hash = hash;
5896                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5897                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5898                 /* Check to make sure the block is valid */
5899                 if (blk > (blk_t) dx_dir->numblocks) {
5900                         cd->pctx.blk = blk;
5901                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5902                                         &cd->pctx))
5903                                 goto clear_and_exit;
5904                 }
5905                 if (hash < prev_hash &&
5906                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5907                         goto clear_and_exit;
5908                 dx_db = &dx_dir->dx_block[blk];
5909                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5910                         dx_db->flags |= DX_FLAG_DUP_REF;
5911                 } else {
5912                         dx_db->flags |= DX_FLAG_REFERENCED;
5913                         dx_db->parent = db->blockcnt;
5914                 }
5915                 if (hash < min_hash)
5916                         min_hash = hash;
5917                 if (hash > max_hash)
5918                         max_hash = hash;
5919                 dx_db->node_min_hash = hash;
5920                 if ((i+1) < count)
5921                         dx_db->node_max_hash =
5922                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5923                 else {
5924                         dx_db->node_max_hash = 0xfffffffe;
5925                         dx_db->flags |= DX_FLAG_LAST;
5926                 }
5927                 if (i == 0)
5928                         dx_db->flags |= DX_FLAG_FIRST;
5929         }
5930         dx_db = &dx_dir->dx_block[db->blockcnt];
5931         dx_db->min_hash = min_hash;
5932         dx_db->max_hash = max_hash;
5933         return;
5934
5935 clear_and_exit:
5936         clear_htree(cd->ctx, cd->pctx.ino);
5937         dx_dir->numblocks = 0;
5938 }
5939 #endif /* ENABLE_HTREE */
5940
5941 /*
5942  * Given a busted directory, try to salvage it somehow.
5943  *
5944  */
5945 static void salvage_directory(ext2_filsys fs,
5946                               struct ext2_dir_entry *dirent,
5947                               struct ext2_dir_entry *prev,
5948                               unsigned int *offset)
5949 {
5950         char    *cp = (char *) dirent;
5951         int left = fs->blocksize - *offset - dirent->rec_len;
5952         int name_len = dirent->name_len & 0xFF;
5953
5954         /*
5955          * Special case of directory entry of size 8: copy what's left
5956          * of the directory block up to cover up the invalid hole.
5957          */
5958         if ((left >= 12) && (dirent->rec_len == 8)) {
5959                 memmove(cp, cp+8, left);
5960                 memset(cp + left, 0, 8);
5961                 return;
5962         }
5963         /*
5964          * If the directory entry overruns the end of the directory
5965          * block, and the name is small enough to fit, then adjust the
5966          * record length.
5967          */
5968         if ((left < 0) &&
5969             (name_len + 8 <= dirent->rec_len + left) &&
5970             dirent->inode <= fs->super->s_inodes_count &&
5971             strnlen(dirent->name, name_len) == name_len) {
5972                 dirent->rec_len += left;
5973                 return;
5974         }
5975         /*
5976          * If the directory entry is a multiple of four, so it is
5977          * valid, let the previous directory entry absorb the invalid
5978          * one.
5979          */
5980         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5981                 prev->rec_len += dirent->rec_len;
5982                 *offset += dirent->rec_len;
5983                 return;
5984         }
5985         /*
5986          * Default salvage method --- kill all of the directory
5987          * entries for the rest of the block.  We will either try to
5988          * absorb it into the previous directory entry, or create a
5989          * new empty directory entry the rest of the directory block.
5990          */
5991         if (prev) {
5992                 prev->rec_len += fs->blocksize - *offset;
5993                 *offset = fs->blocksize;
5994         } else {
5995                 dirent->rec_len = fs->blocksize - *offset;
5996                 dirent->name_len = 0;
5997                 dirent->inode = 0;
5998         }
5999 }
6000
6001 static int check_dir_block(ext2_filsys fs,
6002                            struct ext2_db_entry *db,
6003                            void *priv_data)
6004 {
6005         struct dir_info         *subdir, *dir;
6006         struct dx_dir_info      *dx_dir;
6007 #ifdef ENABLE_HTREE
6008         struct dx_dirblock_info *dx_db = NULL;
6009 #endif /* ENABLE_HTREE */
6010         struct ext2_dir_entry   *dirent, *prev;
6011         ext2_dirhash_t          hash;
6012         unsigned int            offset = 0;
6013         int                     dir_modified = 0;
6014         int                     dot_state;
6015         blk_t                   block_nr = db->blk;
6016         ext2_ino_t              ino = db->ino;
6017         __u16                   links;
6018         struct check_dir_struct *cd;
6019         char                    *buf;
6020         e2fsck_t                ctx;
6021         int                     problem;
6022         struct ext2_dx_root_info *root;
6023         struct ext2_dx_countlimit *limit;
6024         static dict_t de_dict;
6025         struct problem_context  pctx;
6026         int     dups_found = 0;
6027
6028         cd = (struct check_dir_struct *) priv_data;
6029         buf = cd->buf;
6030         ctx = cd->ctx;
6031
6032         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6033                 return DIRENT_ABORT;
6034
6035         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6036                 return DIRENT_ABORT;
6037
6038         /*
6039          * Make sure the inode is still in use (could have been
6040          * deleted in the duplicate/bad blocks pass.
6041          */
6042         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6043                 return 0;
6044
6045         cd->pctx.ino = ino;
6046         cd->pctx.blk = block_nr;
6047         cd->pctx.blkcount = db->blockcnt;
6048         cd->pctx.ino2 = 0;
6049         cd->pctx.dirent = 0;
6050         cd->pctx.num = 0;
6051
6052         if (db->blk == 0) {
6053                 if (allocate_dir_block(ctx, db, &cd->pctx))
6054                         return 0;
6055                 block_nr = db->blk;
6056         }
6057
6058         if (db->blockcnt)
6059                 dot_state = 2;
6060         else
6061                 dot_state = 0;
6062
6063         if (ctx->dirs_to_hash &&
6064             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6065                 dups_found++;
6066
6067         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6068         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6069                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6070         if (cd->pctx.errcode) {
6071                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6072                         ctx->flags |= E2F_FLAG_ABORT;
6073                         return DIRENT_ABORT;
6074                 }
6075                 memset(buf, 0, fs->blocksize);
6076         }
6077 #ifdef ENABLE_HTREE
6078         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6079         if (dx_dir && dx_dir->numblocks) {
6080                 if (db->blockcnt >= dx_dir->numblocks) {
6081                         printf("XXX should never happen!!!\n");
6082                         abort();
6083                 }
6084                 dx_db = &dx_dir->dx_block[db->blockcnt];
6085                 dx_db->type = DX_DIRBLOCK_LEAF;
6086                 dx_db->phys = block_nr;
6087                 dx_db->min_hash = ~0;
6088                 dx_db->max_hash = 0;
6089
6090                 dirent = (struct ext2_dir_entry *) buf;
6091                 limit = (struct ext2_dx_countlimit *) (buf+8);
6092                 if (db->blockcnt == 0) {
6093                         root = (struct ext2_dx_root_info *) (buf + 24);
6094                         dx_db->type = DX_DIRBLOCK_ROOT;
6095                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6096                         if ((root->reserved_zero ||
6097                              root->info_length < 8 ||
6098                              root->indirect_levels > 1) &&
6099                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6100                                 clear_htree(ctx, ino);
6101                                 dx_dir->numblocks = 0;
6102                                 dx_db = 0;
6103                         }
6104                         dx_dir->hashversion = root->hash_version;
6105                         dx_dir->depth = root->indirect_levels + 1;
6106                 } else if ((dirent->inode == 0) &&
6107                            (dirent->rec_len == fs->blocksize) &&
6108                            (dirent->name_len == 0) &&
6109                            (ext2fs_le16_to_cpu(limit->limit) ==
6110                             ((fs->blocksize-8) /
6111                              sizeof(struct ext2_dx_entry))))
6112                         dx_db->type = DX_DIRBLOCK_NODE;
6113         }
6114 #endif /* ENABLE_HTREE */
6115
6116         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6117         prev = 0;
6118         do {
6119                 problem = 0;
6120                 dirent = (struct ext2_dir_entry *) (buf + offset);
6121                 cd->pctx.dirent = dirent;
6122                 cd->pctx.num = offset;
6123                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6124                     (dirent->rec_len < 12) ||
6125                     ((dirent->rec_len % 4) != 0) ||
6126                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6127                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6128                                 salvage_directory(fs, dirent, prev, &offset);
6129                                 dir_modified++;
6130                                 continue;
6131                         } else
6132                                 goto abort_free_dict;
6133                 }
6134                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6135                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6136                                 dirent->name_len = EXT2_NAME_LEN;
6137                                 dir_modified++;
6138                         }
6139                 }
6140
6141                 if (dot_state == 0) {
6142                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6143                                 dir_modified++;
6144                 } else if (dot_state == 1) {
6145                         dir = e2fsck_get_dir_info(ctx, ino);
6146                         if (!dir) {
6147                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6148                                 goto abort_free_dict;
6149                         }
6150                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6151                                 dir_modified++;
6152                 } else if (dirent->inode == ino) {
6153                         problem = PR_2_LINK_DOT;
6154                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6155                                 dirent->inode = 0;
6156                                 dir_modified++;
6157                                 goto next;
6158                         }
6159                 }
6160                 if (!dirent->inode)
6161                         goto next;
6162
6163                 /*
6164                  * Make sure the inode listed is a legal one.
6165                  */
6166                 if (((dirent->inode != EXT2_ROOT_INO) &&
6167                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6168                     (dirent->inode > fs->super->s_inodes_count)) {
6169                         problem = PR_2_BAD_INO;
6170                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6171                                                dirent->inode))) {
6172                         /*
6173                          * If the inode is unused, offer to clear it.
6174                          */
6175                         problem = PR_2_UNUSED_INODE;
6176                 } else if ((dot_state > 1) &&
6177                            ((dirent->name_len & 0xFF) == 1) &&
6178                            (dirent->name[0] == '.')) {
6179                         /*
6180                          * If there's a '.' entry in anything other
6181                          * than the first directory entry, it's a
6182                          * duplicate entry that should be removed.
6183                          */
6184                         problem = PR_2_DUP_DOT;
6185                 } else if ((dot_state > 1) &&
6186                            ((dirent->name_len & 0xFF) == 2) &&
6187                            (dirent->name[0] == '.') &&
6188                            (dirent->name[1] == '.')) {
6189                         /*
6190                          * If there's a '..' entry in anything other
6191                          * than the second directory entry, it's a
6192                          * duplicate entry that should be removed.
6193                          */
6194                         problem = PR_2_DUP_DOT_DOT;
6195                 } else if ((dot_state > 1) &&
6196                            (dirent->inode == EXT2_ROOT_INO)) {
6197                         /*
6198                          * Don't allow links to the root directory.
6199                          * We check this specially to make sure we
6200                          * catch this error case even if the root
6201                          * directory hasn't been created yet.
6202                          */
6203                         problem = PR_2_LINK_ROOT;
6204                 } else if ((dot_state > 1) &&
6205                            (dirent->name_len & 0xFF) == 0) {
6206                         /*
6207                          * Don't allow zero-length directory names.
6208                          */
6209                         problem = PR_2_NULL_NAME;
6210                 }
6211
6212                 if (problem) {
6213                         if (fix_problem(ctx, problem, &cd->pctx)) {
6214                                 dirent->inode = 0;
6215                                 dir_modified++;
6216                                 goto next;
6217                         } else {
6218                                 ext2fs_unmark_valid(fs);
6219                                 if (problem == PR_2_BAD_INO)
6220                                         goto next;
6221                         }
6222                 }
6223
6224                 /*
6225                  * If the inode was marked as having bad fields in
6226                  * pass1, process it and offer to fix/clear it.
6227                  * (We wait until now so that we can display the
6228                  * pathname to the user.)
6229                  */
6230                 if (ctx->inode_bad_map &&
6231                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6232                                              dirent->inode)) {
6233                         if (e2fsck_process_bad_inode(ctx, ino,
6234                                                      dirent->inode,
6235                                                      buf + fs->blocksize)) {
6236                                 dirent->inode = 0;
6237                                 dir_modified++;
6238                                 goto next;
6239                         }
6240                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6241                                 return DIRENT_ABORT;
6242                 }
6243
6244                 if (check_name(ctx, dirent, &cd->pctx))
6245                         dir_modified++;
6246
6247                 if (check_filetype(ctx, dirent, &cd->pctx))
6248                         dir_modified++;
6249
6250 #ifdef ENABLE_HTREE
6251                 if (dx_db) {
6252                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6253                                        (dirent->name_len & 0xFF),
6254                                        fs->super->s_hash_seed, &hash, 0);
6255                         if (hash < dx_db->min_hash)
6256                                 dx_db->min_hash = hash;
6257                         if (hash > dx_db->max_hash)
6258                                 dx_db->max_hash = hash;
6259                 }
6260 #endif
6261
6262                 /*
6263                  * If this is a directory, then mark its parent in its
6264                  * dir_info structure.  If the parent field is already
6265                  * filled in, then this directory has more than one
6266                  * hard link.  We assume the first link is correct,
6267                  * and ask the user if he/she wants to clear this one.
6268                  */
6269                 if ((dot_state > 1) &&
6270                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6271                                               dirent->inode))) {
6272                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6273                         if (!subdir) {
6274                                 cd->pctx.ino = dirent->inode;
6275                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6276                                 goto abort_free_dict;
6277                         }
6278                         if (subdir->parent) {
6279                                 cd->pctx.ino2 = subdir->parent;
6280                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6281                                                 &cd->pctx)) {
6282                                         dirent->inode = 0;
6283                                         dir_modified++;
6284                                         goto next;
6285                                 }
6286                                 cd->pctx.ino2 = 0;
6287                         } else
6288                                 subdir->parent = ino;
6289                 }
6290
6291                 if (dups_found) {
6292                         ;
6293                 } else if (dict_lookup(&de_dict, dirent)) {
6294                         clear_problem_context(&pctx);
6295                         pctx.ino = ino;
6296                         pctx.dirent = dirent;
6297                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6298                         if (!ctx->dirs_to_hash)
6299                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6300                         if (ctx->dirs_to_hash)
6301                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6302                         dups_found++;
6303                 } else
6304                         dict_alloc_insert(&de_dict, dirent, dirent);
6305
6306                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6307                                         &links);
6308                 if (links > 1)
6309                         ctx->fs_links_count++;
6310                 ctx->fs_total_count++;
6311         next:
6312                 prev = dirent;
6313                 offset += dirent->rec_len;
6314                 dot_state++;
6315         } while (offset < fs->blocksize);
6316 #ifdef ENABLE_HTREE
6317         if (dx_db) {
6318                 cd->pctx.dir = cd->pctx.ino;
6319                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6320                     (dx_db->type == DX_DIRBLOCK_NODE))
6321                         parse_int_node(fs, db, cd, dx_dir, buf);
6322         }
6323 #endif /* ENABLE_HTREE */
6324         if (offset != fs->blocksize) {
6325                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6326                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6327                         dirent->rec_len = cd->pctx.num;
6328                         dir_modified++;
6329                 }
6330         }
6331         if (dir_modified) {
6332                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6333                 if (cd->pctx.errcode) {
6334                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6335                                          &cd->pctx))
6336                                 goto abort_free_dict;
6337                 }
6338                 ext2fs_mark_changed(fs);
6339         }
6340         dict_free_nodes(&de_dict);
6341         return 0;
6342 abort_free_dict:
6343         dict_free_nodes(&de_dict);
6344         ctx->flags |= E2F_FLAG_ABORT;
6345         return DIRENT_ABORT;
6346 }
6347
6348 /*
6349  * This function is called to deallocate a block, and is an interator
6350  * functioned called by deallocate inode via ext2fs_iterate_block().
6351  */
6352 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6353                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6354                                   blk_t ref_block FSCK_ATTR((unused)),
6355                                   int ref_offset FSCK_ATTR((unused)),
6356                                   void *priv_data)
6357 {
6358         e2fsck_t        ctx = (e2fsck_t) priv_data;
6359
6360         if (HOLE_BLKADDR(*block_nr))
6361                 return 0;
6362         if ((*block_nr < fs->super->s_first_data_block) ||
6363             (*block_nr >= fs->super->s_blocks_count))
6364                 return 0;
6365         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6366         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6367         return 0;
6368 }
6369
6370 /*
6371  * This fuction deallocates an inode
6372  */
6373 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6374 {
6375         ext2_filsys fs = ctx->fs;
6376         struct ext2_inode       inode;
6377         struct problem_context  pctx;
6378         __u32                   count;
6379
6380         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6381         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6382         inode.i_links_count = 0;
6383         inode.i_dtime = time(NULL);
6384         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6385         clear_problem_context(&pctx);
6386         pctx.ino = ino;
6387
6388         /*
6389          * Fix up the bitmaps...
6390          */
6391         e2fsck_read_bitmaps(ctx);
6392         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6393         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6394         if (ctx->inode_bad_map)
6395                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6396         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6397
6398         if (inode.i_file_acl &&
6399             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6400                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6401                                                    block_buf, -1, &count);
6402                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6403                         pctx.errcode = 0;
6404                         count = 1;
6405                 }
6406                 if (pctx.errcode) {
6407                         pctx.blk = inode.i_file_acl;
6408                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6409                         ctx->flags |= E2F_FLAG_ABORT;
6410                         return;
6411                 }
6412                 if (count == 0) {
6413                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6414                                                    inode.i_file_acl);
6415                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6416                 }
6417                 inode.i_file_acl = 0;
6418         }
6419
6420         if (!ext2fs_inode_has_valid_blocks(&inode))
6421                 return;
6422
6423         if (LINUX_S_ISREG(inode.i_mode) &&
6424             (inode.i_size_high || inode.i_size & 0x80000000UL))
6425                 ctx->large_files--;
6426
6427         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6428                                             deallocate_inode_block, ctx);
6429         if (pctx.errcode) {
6430                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6431                 ctx->flags |= E2F_FLAG_ABORT;
6432                 return;
6433         }
6434 }
6435
6436 /*
6437  * This fuction clears the htree flag on an inode
6438  */
6439 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6440 {
6441         struct ext2_inode       inode;
6442
6443         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6444         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6445         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6446         if (ctx->dirs_to_hash)
6447                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6448 }
6449
6450
6451 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6452                                     ext2_ino_t ino, char *buf)
6453 {
6454         ext2_filsys fs = ctx->fs;
6455         struct ext2_inode       inode;
6456         int                     inode_modified = 0;
6457         int                     not_fixed = 0;
6458         unsigned char           *frag, *fsize;
6459         struct problem_context  pctx;
6460         int     problem = 0;
6461
6462         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6463
6464         clear_problem_context(&pctx);
6465         pctx.ino = ino;
6466         pctx.dir = dir;
6467         pctx.inode = &inode;
6468
6469         if (inode.i_file_acl &&
6470             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6471             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6472                 inode.i_file_acl = 0;
6473 #if BB_BIG_ENDIAN
6474                 /*
6475                  * This is a special kludge to deal with long symlinks
6476                  * on big endian systems.  i_blocks had already been
6477                  * decremented earlier in pass 1, but since i_file_acl
6478                  * hadn't yet been cleared, ext2fs_read_inode()
6479                  * assumed that the file was short symlink and would
6480                  * not have byte swapped i_block[0].  Hence, we have
6481                  * to byte-swap it here.
6482                  */
6483                 if (LINUX_S_ISLNK(inode.i_mode) &&
6484                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6485                     (inode.i_blocks == fs->blocksize >> 9))
6486                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6487 #endif
6488                 inode_modified++;
6489         } else
6490                 not_fixed++;
6491
6492         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6493             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6494             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6495             !(LINUX_S_ISSOCK(inode.i_mode)))
6496                 problem = PR_2_BAD_MODE;
6497         else if (LINUX_S_ISCHR(inode.i_mode)
6498                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6499                 problem = PR_2_BAD_CHAR_DEV;
6500         else if (LINUX_S_ISBLK(inode.i_mode)
6501                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6502                 problem = PR_2_BAD_BLOCK_DEV;
6503         else if (LINUX_S_ISFIFO(inode.i_mode)
6504                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6505                 problem = PR_2_BAD_FIFO;
6506         else if (LINUX_S_ISSOCK(inode.i_mode)
6507                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6508                 problem = PR_2_BAD_SOCKET;
6509         else if (LINUX_S_ISLNK(inode.i_mode)
6510                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6511                 problem = PR_2_INVALID_SYMLINK;
6512         }
6513
6514         if (problem) {
6515                 if (fix_problem(ctx, problem, &pctx)) {
6516                         deallocate_inode(ctx, ino, 0);
6517                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6518                                 return 0;
6519                         return 1;
6520                 } else
6521                         not_fixed++;
6522                 problem = 0;
6523         }
6524
6525         if (inode.i_faddr) {
6526                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6527                         inode.i_faddr = 0;
6528                         inode_modified++;
6529                 } else
6530                         not_fixed++;
6531         }
6532
6533         switch (fs->super->s_creator_os) {
6534             case EXT2_OS_LINUX:
6535                 frag = &inode.osd2.linux2.l_i_frag;
6536                 fsize = &inode.osd2.linux2.l_i_fsize;
6537                 break;
6538             case EXT2_OS_HURD:
6539                 frag = &inode.osd2.hurd2.h_i_frag;
6540                 fsize = &inode.osd2.hurd2.h_i_fsize;
6541                 break;
6542             case EXT2_OS_MASIX:
6543                 frag = &inode.osd2.masix2.m_i_frag;
6544                 fsize = &inode.osd2.masix2.m_i_fsize;
6545                 break;
6546             default:
6547                 frag = fsize = 0;
6548         }
6549         if (frag && *frag) {
6550                 pctx.num = *frag;
6551                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6552                         *frag = 0;
6553                         inode_modified++;
6554                 } else
6555                         not_fixed++;
6556                 pctx.num = 0;
6557         }
6558         if (fsize && *fsize) {
6559                 pctx.num = *fsize;
6560                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6561                         *fsize = 0;
6562                         inode_modified++;
6563                 } else
6564                         not_fixed++;
6565                 pctx.num = 0;
6566         }
6567
6568         if (inode.i_file_acl &&
6569             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6570              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6571                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6572                         inode.i_file_acl = 0;
6573                         inode_modified++;
6574                 } else
6575                         not_fixed++;
6576         }
6577         if (inode.i_dir_acl &&
6578             LINUX_S_ISDIR(inode.i_mode)) {
6579                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6580                         inode.i_dir_acl = 0;
6581                         inode_modified++;
6582                 } else
6583                         not_fixed++;
6584         }
6585
6586         if (inode_modified)
6587                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6588         if (!not_fixed)
6589                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6590         return 0;
6591 }
6592
6593
6594 /*
6595  * allocate_dir_block --- this function allocates a new directory
6596  *      block for a particular inode; this is done if a directory has
6597  *      a "hole" in it, or if a directory has a illegal block number
6598  *      that was zeroed out and now needs to be replaced.
6599  */
6600 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6601                               struct problem_context *pctx)
6602 {
6603         ext2_filsys fs = ctx->fs;
6604         blk_t                   blk;
6605         char                    *block;
6606         struct ext2_inode       inode;
6607
6608         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6609                 return 1;
6610
6611         /*
6612          * Read the inode and block bitmaps in; we'll be messing with
6613          * them.
6614          */
6615         e2fsck_read_bitmaps(ctx);
6616
6617         /*
6618          * First, find a free block
6619          */
6620         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6621         if (pctx->errcode) {
6622                 pctx->str = "ext2fs_new_block";
6623                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6624                 return 1;
6625         }
6626         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6627         ext2fs_mark_block_bitmap(fs->block_map, blk);
6628         ext2fs_mark_bb_dirty(fs);
6629
6630         /*
6631          * Now let's create the actual data block for the inode
6632          */
6633         if (db->blockcnt)
6634                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6635         else
6636                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6637                                                      EXT2_ROOT_INO, &block);
6638
6639         if (pctx->errcode) {
6640                 pctx->str = "ext2fs_new_dir_block";
6641                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6642                 return 1;
6643         }
6644
6645         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6646         ext2fs_free_mem(&block);
6647         if (pctx->errcode) {
6648                 pctx->str = "ext2fs_write_dir_block";
6649                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6650                 return 1;
6651         }
6652
6653         /*
6654          * Update the inode block count
6655          */
6656         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6657         inode.i_blocks += fs->blocksize / 512;
6658         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6659                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6660         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6661
6662         /*
6663          * Finally, update the block pointers for the inode
6664          */
6665         db->blk = blk;
6666         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6667                                       0, update_dir_block, db);
6668         if (pctx->errcode) {
6669                 pctx->str = "ext2fs_block_iterate";
6670                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6671                 return 1;
6672         }
6673
6674         return 0;
6675 }
6676
6677 /*
6678  * This is a helper function for allocate_dir_block().
6679  */
6680 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6681                             blk_t       *block_nr,
6682                             e2_blkcnt_t blockcnt,
6683                             blk_t ref_block FSCK_ATTR((unused)),
6684                             int ref_offset FSCK_ATTR((unused)),
6685                             void *priv_data)
6686 {
6687         struct ext2_db_entry *db;
6688
6689         db = (struct ext2_db_entry *) priv_data;
6690         if (db->blockcnt == (int) blockcnt) {
6691                 *block_nr = db->blk;
6692                 return BLOCK_CHANGED;
6693         }
6694         return 0;
6695 }
6696
6697 /*
6698  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6699  *
6700  * Pass #3 assures that all directories are connected to the
6701  * filesystem tree, using the following algorithm:
6702  *
6703  * First, the root directory is checked to make sure it exists; if
6704  * not, e2fsck will offer to create a new one.  It is then marked as
6705  * "done".
6706  *
6707  * Then, pass3 interates over all directory inodes; for each directory
6708  * it attempts to trace up the filesystem tree, using dirinfo.parent
6709  * until it reaches a directory which has been marked "done".  If it
6710  * cannot do so, then the directory must be disconnected, and e2fsck
6711  * will offer to reconnect it to /lost+found.  While it is chasing
6712  * parent pointers up the filesystem tree, if pass3 sees a directory
6713  * twice, then it has detected a filesystem loop, and it will again
6714  * offer to reconnect the directory to /lost+found in to break the
6715  * filesystem loop.
6716  *
6717  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6718  * reconnect inodes to /lost+found; this subroutine is also used by
6719  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6720  * is responsible for creating /lost+found if it does not exist.
6721  *
6722  * Pass 3 frees the following data structures:
6723  *      - The dirinfo directory information cache.
6724  */
6725
6726 static void check_root(e2fsck_t ctx);
6727 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6728                            struct problem_context *pctx);
6729 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6730
6731 static ext2fs_inode_bitmap inode_loop_detect;
6732 static ext2fs_inode_bitmap inode_done_map;
6733
6734 static void e2fsck_pass3(e2fsck_t ctx)
6735 {
6736         ext2_filsys fs = ctx->fs;
6737         int             i;
6738         struct problem_context  pctx;
6739         struct dir_info *dir;
6740         unsigned long maxdirs, count;
6741
6742         clear_problem_context(&pctx);
6743
6744         /* Pass 3 */
6745
6746         if (!(ctx->options & E2F_OPT_PREEN))
6747                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6748
6749         /*
6750          * Allocate some bitmaps to do loop detection.
6751          */
6752         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6753                                                     &inode_done_map);
6754         if (pctx.errcode) {
6755                 pctx.num = 2;
6756                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6757                 ctx->flags |= E2F_FLAG_ABORT;
6758                 goto abort_exit;
6759         }
6760         check_root(ctx);
6761         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6762                 goto abort_exit;
6763
6764         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6765
6766         maxdirs = e2fsck_get_num_dirinfo(ctx);
6767         count = 1;
6768
6769         if (ctx->progress)
6770                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6771                         goto abort_exit;
6772
6773         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6774                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775                         goto abort_exit;
6776                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6777                         goto abort_exit;
6778                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6779                         if (check_directory(ctx, dir, &pctx))
6780                                 goto abort_exit;
6781         }
6782
6783         /*
6784          * Force the creation of /lost+found if not present
6785          */
6786         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6787                 e2fsck_get_lost_and_found(ctx, 1);
6788
6789         /*
6790          * If there are any directories that need to be indexed or
6791          * optimized, do it here.
6792          */
6793         e2fsck_rehash_directories(ctx);
6794
6795 abort_exit:
6796         e2fsck_free_dir_info(ctx);
6797         ext2fs_free_inode_bitmap(inode_loop_detect);
6798         inode_loop_detect = 0;
6799         ext2fs_free_inode_bitmap(inode_done_map);
6800         inode_done_map = 0;
6801 }
6802
6803 /*
6804  * This makes sure the root inode is present; if not, we ask if the
6805  * user wants us to create it.  Not creating it is a fatal error.
6806  */
6807 static void check_root(e2fsck_t ctx)
6808 {
6809         ext2_filsys fs = ctx->fs;
6810         blk_t                   blk;
6811         struct ext2_inode       inode;
6812         char *                  block;
6813         struct problem_context  pctx;
6814
6815         clear_problem_context(&pctx);
6816
6817         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6818                 /*
6819                  * If the root inode is not a directory, die here.  The
6820                  * user must have answered 'no' in pass1 when we
6821                  * offered to clear it.
6822                  */
6823                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6824                                                EXT2_ROOT_INO))) {
6825                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6826                         ctx->flags |= E2F_FLAG_ABORT;
6827                 }
6828                 return;
6829         }
6830
6831         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6832                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6833                 ctx->flags |= E2F_FLAG_ABORT;
6834                 return;
6835         }
6836
6837         e2fsck_read_bitmaps(ctx);
6838
6839         /*
6840          * First, find a free block
6841          */
6842         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6843         if (pctx.errcode) {
6844                 pctx.str = "ext2fs_new_block";
6845                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6846                 ctx->flags |= E2F_FLAG_ABORT;
6847                 return;
6848         }
6849         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6850         ext2fs_mark_block_bitmap(fs->block_map, blk);
6851         ext2fs_mark_bb_dirty(fs);
6852
6853         /*
6854          * Now let's create the actual data block for the inode
6855          */
6856         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6857                                             &block);
6858         if (pctx.errcode) {
6859                 pctx.str = "ext2fs_new_dir_block";
6860                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6861                 ctx->flags |= E2F_FLAG_ABORT;
6862                 return;
6863         }
6864
6865         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6866         if (pctx.errcode) {
6867                 pctx.str = "ext2fs_write_dir_block";
6868                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6869                 ctx->flags |= E2F_FLAG_ABORT;
6870                 return;
6871         }
6872         ext2fs_free_mem(&block);
6873
6874         /*
6875          * Set up the inode structure
6876          */
6877         memset(&inode, 0, sizeof(inode));
6878         inode.i_mode = 040755;
6879         inode.i_size = fs->blocksize;
6880         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6881         inode.i_links_count = 2;
6882         inode.i_blocks = fs->blocksize / 512;
6883         inode.i_block[0] = blk;
6884
6885         /*
6886          * Write out the inode.
6887          */
6888         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6889         if (pctx.errcode) {
6890                 pctx.str = "ext2fs_write_inode";
6891                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6892                 ctx->flags |= E2F_FLAG_ABORT;
6893                 return;
6894         }
6895
6896         /*
6897          * Miscellaneous bookkeeping...
6898          */
6899         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6900         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6901         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6902
6903         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6904         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6905         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6906         ext2fs_mark_ib_dirty(fs);
6907 }
6908
6909 /*
6910  * This subroutine is responsible for making sure that a particular
6911  * directory is connected to the root; if it isn't we trace it up as
6912  * far as we can go, and then offer to connect the resulting parent to
6913  * the lost+found.  We have to do loop detection; if we ever discover
6914  * a loop, we treat that as a disconnected directory and offer to
6915  * reparent it to lost+found.
6916  *
6917  * However, loop detection is expensive, because for very large
6918  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6919  * is non-trivial.  Loops in filesystems are also a rare error case,
6920  * and we shouldn't optimize for error cases.  So we try two passes of
6921  * the algorithm.  The first time, we ignore loop detection and merely
6922  * increment a counter; if the counter exceeds some extreme threshold,
6923  * then we try again with the loop detection bitmap enabled.
6924  */
6925 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6926                            struct problem_context *pctx)
6927 {
6928         ext2_filsys     fs = ctx->fs;
6929         struct dir_info *p = dir;
6930         int             loop_pass = 0, parent_count = 0;
6931
6932         if (!p)
6933                 return 0;
6934
6935         while (1) {
6936                 /*
6937                  * Mark this inode as being "done"; by the time we
6938                  * return from this function, the inode we either be
6939                  * verified as being connected to the directory tree,
6940                  * or we will have offered to reconnect this to
6941                  * lost+found.
6942                  *
6943                  * If it was marked done already, then we've reached a
6944                  * parent we've already checked.
6945                  */
6946                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6947                         break;
6948
6949                 /*
6950                  * If this directory doesn't have a parent, or we've
6951                  * seen the parent once already, then offer to
6952                  * reparent it to lost+found
6953                  */
6954                 if (!p->parent ||
6955                     (loop_pass &&
6956                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6957                                               p->parent)))) {
6958                         pctx->ino = p->ino;
6959                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6960                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6961                                         ext2fs_unmark_valid(fs);
6962                                 else {
6963                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
6964                                         p->parent = ctx->lost_and_found;
6965                                         fix_dotdot(ctx, p, ctx->lost_and_found);
6966                                 }
6967                         }
6968                         break;
6969                 }
6970                 p = e2fsck_get_dir_info(ctx, p->parent);
6971                 if (!p) {
6972                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6973                         return 0;
6974                 }
6975                 if (loop_pass) {
6976                         ext2fs_mark_inode_bitmap(inode_loop_detect,
6977                                                  p->ino);
6978                 } else if (parent_count++ > 2048) {
6979                         /*
6980                          * If we've run into a path depth that's
6981                          * greater than 2048, try again with the inode
6982                          * loop bitmap turned on and start from the
6983                          * top.
6984                          */
6985                         loop_pass = 1;
6986                         if (inode_loop_detect)
6987                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
6988                         else {
6989                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6990                                 if (pctx->errcode) {
6991                                         pctx->num = 1;
6992                                         fix_problem(ctx,
6993                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6994                                         ctx->flags |= E2F_FLAG_ABORT;
6995                                         return -1;
6996                                 }
6997                         }
6998                         p = dir;
6999                 }
7000         }
7001
7002         /*
7003          * Make sure that .. and the parent directory are the same;
7004          * offer to fix it if not.
7005          */
7006         if (dir->parent != dir->dotdot) {
7007                 pctx->ino = dir->ino;
7008                 pctx->ino2 = dir->dotdot;
7009                 pctx->dir = dir->parent;
7010                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7011                         fix_dotdot(ctx, dir, dir->parent);
7012         }
7013         return 0;
7014 }
7015
7016 /*
7017  * This routine gets the lost_and_found inode, making it a directory
7018  * if necessary
7019  */
7020 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7021 {
7022         ext2_filsys fs = ctx->fs;
7023         ext2_ino_t                      ino;
7024         blk_t                   blk;
7025         errcode_t               retval;
7026         struct ext2_inode       inode;
7027         char *                  block;
7028         static const char       name[] = "lost+found";
7029         struct  problem_context pctx;
7030         struct dir_info         *dirinfo;
7031
7032         if (ctx->lost_and_found)
7033                 return ctx->lost_and_found;
7034
7035         clear_problem_context(&pctx);
7036
7037         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7038                                sizeof(name)-1, 0, &ino);
7039         if (retval && !fix)
7040                 return 0;
7041         if (!retval) {
7042                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7043                         ctx->lost_and_found = ino;
7044                         return ino;
7045                 }
7046
7047                 /* Lost+found isn't a directory! */
7048                 if (!fix)
7049                         return 0;
7050                 pctx.ino = ino;
7051                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7052                         return 0;
7053
7054                 /* OK, unlink the old /lost+found file. */
7055                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7056                 if (pctx.errcode) {
7057                         pctx.str = "ext2fs_unlink";
7058                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7059                         return 0;
7060                 }
7061                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7062                 if (dirinfo)
7063                         dirinfo->parent = 0;
7064                 e2fsck_adjust_inode_count(ctx, ino, -1);
7065         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7066                 pctx.errcode = retval;
7067                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7068         }
7069         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7070                 return 0;
7071
7072         /*
7073          * Read the inode and block bitmaps in; we'll be messing with
7074          * them.
7075          */
7076         e2fsck_read_bitmaps(ctx);
7077
7078         /*
7079          * First, find a free block
7080          */
7081         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7082         if (retval) {
7083                 pctx.errcode = retval;
7084                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7085                 return 0;
7086         }
7087         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7088         ext2fs_block_alloc_stats(fs, blk, +1);
7089
7090         /*
7091          * Next find a free inode.
7092          */
7093         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7094                                   ctx->inode_used_map, &ino);
7095         if (retval) {
7096                 pctx.errcode = retval;
7097                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7098                 return 0;
7099         }
7100         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7101         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7102         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7103
7104         /*
7105          * Now let's create the actual data block for the inode
7106          */
7107         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7108         if (retval) {
7109                 pctx.errcode = retval;
7110                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7111                 return 0;
7112         }
7113
7114         retval = ext2fs_write_dir_block(fs, blk, block);
7115         ext2fs_free_mem(&block);
7116         if (retval) {
7117                 pctx.errcode = retval;
7118                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7119                 return 0;
7120         }
7121
7122         /*
7123          * Set up the inode structure
7124          */
7125         memset(&inode, 0, sizeof(inode));
7126         inode.i_mode = 040700;
7127         inode.i_size = fs->blocksize;
7128         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7129         inode.i_links_count = 2;
7130         inode.i_blocks = fs->blocksize / 512;
7131         inode.i_block[0] = blk;
7132
7133         /*
7134          * Next, write out the inode.
7135          */
7136         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7137         if (pctx.errcode) {
7138                 pctx.str = "ext2fs_write_inode";
7139                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7140                 return 0;
7141         }
7142         /*
7143          * Finally, create the directory link
7144          */
7145         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7146         if (pctx.errcode) {
7147                 pctx.str = "ext2fs_link";
7148                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7149                 return 0;
7150         }
7151
7152         /*
7153          * Miscellaneous bookkeeping that needs to be kept straight.
7154          */
7155         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7156         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7157         ext2fs_icount_store(ctx->inode_count, ino, 2);
7158         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7159         ctx->lost_and_found = ino;
7160         return ino;
7161 }
7162
7163 /*
7164  * This routine will connect a file to lost+found
7165  */
7166 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7167 {
7168         ext2_filsys fs = ctx->fs;
7169         errcode_t       retval;
7170         char            name[80];
7171         struct problem_context  pctx;
7172         struct ext2_inode       inode;
7173         int             file_type = 0;
7174
7175         clear_problem_context(&pctx);
7176         pctx.ino = ino;
7177
7178         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7179                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7180                         ctx->bad_lost_and_found++;
7181         }
7182         if (ctx->bad_lost_and_found) {
7183                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7184                 return 1;
7185         }
7186
7187         sprintf(name, "#%u", ino);
7188         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7189                 file_type = ext2_file_type(inode.i_mode);
7190         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7191         if (retval == EXT2_ET_DIR_NO_SPACE) {
7192                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7193                         return 1;
7194                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7195                                                  1, 0);
7196                 if (retval) {
7197                         pctx.errcode = retval;
7198                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7199                         return 1;
7200                 }
7201                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7202                                      ino, file_type);
7203         }
7204         if (retval) {
7205                 pctx.errcode = retval;
7206                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7207                 return 1;
7208         }
7209         e2fsck_adjust_inode_count(ctx, ino, 1);
7210
7211         return 0;
7212 }
7213
7214 /*
7215  * Utility routine to adjust the inode counts on an inode.
7216  */
7217 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7218 {
7219         ext2_filsys fs = ctx->fs;
7220         errcode_t               retval;
7221         struct ext2_inode       inode;
7222
7223         if (!ino)
7224                 return 0;
7225
7226         retval = ext2fs_read_inode(fs, ino, &inode);
7227         if (retval)
7228                 return retval;
7229
7230         if (adj == 1) {
7231                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7232                 if (inode.i_links_count == (__u16) ~0)
7233                         return 0;
7234                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7235                 inode.i_links_count++;
7236         } else if (adj == -1) {
7237                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7238                 if (inode.i_links_count == 0)
7239                         return 0;
7240                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7241                 inode.i_links_count--;
7242         }
7243
7244         retval = ext2fs_write_inode(fs, ino, &inode);
7245         if (retval)
7246                 return retval;
7247
7248         return 0;
7249 }
7250
7251 /*
7252  * Fix parent --- this routine fixes up the parent of a directory.
7253  */
7254 struct fix_dotdot_struct {
7255         ext2_filsys     fs;
7256         ext2_ino_t      parent;
7257         int             done;
7258         e2fsck_t        ctx;
7259 };
7260
7261 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7262                            int  offset FSCK_ATTR((unused)),
7263                            int  blocksize FSCK_ATTR((unused)),
7264                            char *buf FSCK_ATTR((unused)),
7265                            void *priv_data)
7266 {
7267         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7268         errcode_t       retval;
7269         struct problem_context pctx;
7270
7271         if ((dirent->name_len & 0xFF) != 2)
7272                 return 0;
7273         if (strncmp(dirent->name, "..", 2))
7274                 return 0;
7275
7276         clear_problem_context(&pctx);
7277
7278         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7279         if (retval) {
7280                 pctx.errcode = retval;
7281                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7282         }
7283         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7284         if (retval) {
7285                 pctx.errcode = retval;
7286                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7287         }
7288         dirent->inode = fp->parent;
7289
7290         fp->done++;
7291         return DIRENT_ABORT | DIRENT_CHANGED;
7292 }
7293
7294 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7295 {
7296         ext2_filsys fs = ctx->fs;
7297         errcode_t       retval;
7298         struct fix_dotdot_struct fp;
7299         struct problem_context pctx;
7300
7301         fp.fs = fs;
7302         fp.parent = parent;
7303         fp.done = 0;
7304         fp.ctx = ctx;
7305
7306         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7307                                     0, fix_dotdot_proc, &fp);
7308         if (retval || !fp.done) {
7309                 clear_problem_context(&pctx);
7310                 pctx.ino = dir->ino;
7311                 pctx.errcode = retval;
7312                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7313                             PR_3_FIX_PARENT_NOFIND, &pctx);
7314                 ext2fs_unmark_valid(fs);
7315         }
7316         dir->dotdot = parent;
7317 }
7318
7319 /*
7320  * These routines are responsible for expanding a /lost+found if it is
7321  * too small.
7322  */
7323
7324 struct expand_dir_struct {
7325         int                     num;
7326         int                     guaranteed_size;
7327         int                     newblocks;
7328         int                     last_block;
7329         errcode_t               err;
7330         e2fsck_t                ctx;
7331 };
7332
7333 static int expand_dir_proc(ext2_filsys fs,
7334                            blk_t        *blocknr,
7335                            e2_blkcnt_t  blockcnt,
7336                            blk_t ref_block FSCK_ATTR((unused)),
7337                            int ref_offset FSCK_ATTR((unused)),
7338                            void *priv_data)
7339 {
7340         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7341         blk_t   new_blk;
7342         static blk_t    last_blk = 0;
7343         char            *block;
7344         errcode_t       retval;
7345         e2fsck_t        ctx;
7346
7347         ctx = es->ctx;
7348
7349         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7350                 return BLOCK_ABORT;
7351
7352         if (blockcnt > 0)
7353                 es->last_block = blockcnt;
7354         if (*blocknr) {
7355                 last_blk = *blocknr;
7356                 return 0;
7357         }
7358         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7359                                   &new_blk);
7360         if (retval) {
7361                 es->err = retval;
7362                 return BLOCK_ABORT;
7363         }
7364         if (blockcnt > 0) {
7365                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7366                 if (retval) {
7367                         es->err = retval;
7368                         return BLOCK_ABORT;
7369                 }
7370                 es->num--;
7371                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7372         } else {
7373                 retval = ext2fs_get_mem(fs->blocksize, &block);
7374                 if (retval) {
7375                         es->err = retval;
7376                         return BLOCK_ABORT;
7377                 }
7378                 memset(block, 0, fs->blocksize);
7379                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7380         }
7381         if (retval) {
7382                 es->err = retval;
7383                 return BLOCK_ABORT;
7384         }
7385         ext2fs_free_mem(&block);
7386         *blocknr = new_blk;
7387         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7388         ext2fs_block_alloc_stats(fs, new_blk, +1);
7389         es->newblocks++;
7390
7391         if (es->num == 0)
7392                 return (BLOCK_CHANGED | BLOCK_ABORT);
7393         else
7394                 return BLOCK_CHANGED;
7395 }
7396
7397 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7398                                   int num, int guaranteed_size)
7399 {
7400         ext2_filsys fs = ctx->fs;
7401         errcode_t       retval;
7402         struct expand_dir_struct es;
7403         struct ext2_inode       inode;
7404
7405         if (!(fs->flags & EXT2_FLAG_RW))
7406                 return EXT2_ET_RO_FILSYS;
7407
7408         /*
7409          * Read the inode and block bitmaps in; we'll be messing with
7410          * them.
7411          */
7412         e2fsck_read_bitmaps(ctx);
7413
7414         retval = ext2fs_check_directory(fs, dir);
7415         if (retval)
7416                 return retval;
7417
7418         es.num = num;
7419         es.guaranteed_size = guaranteed_size;
7420         es.last_block = 0;
7421         es.err = 0;
7422         es.newblocks = 0;
7423         es.ctx = ctx;
7424
7425         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7426                                        0, expand_dir_proc, &es);
7427
7428         if (es.err)
7429                 return es.err;
7430
7431         /*
7432          * Update the size and block count fields in the inode.
7433          */
7434         retval = ext2fs_read_inode(fs, dir, &inode);
7435         if (retval)
7436                 return retval;
7437
7438         inode.i_size = (es.last_block + 1) * fs->blocksize;
7439         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7440
7441         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7442
7443         return 0;
7444 }
7445
7446 /*
7447  * pass4.c -- pass #4 of e2fsck: Check reference counts
7448  *
7449  * Pass 4 frees the following data structures:
7450  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7451  */
7452
7453 /*
7454  * This routine is called when an inode is not connected to the
7455  * directory tree.
7456  *
7457  * This subroutine returns 1 then the caller shouldn't bother with the
7458  * rest of the pass 4 tests.
7459  */
7460 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7461 {
7462         ext2_filsys fs = ctx->fs;
7463         struct ext2_inode       inode;
7464         struct problem_context  pctx;
7465
7466         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7467         clear_problem_context(&pctx);
7468         pctx.ino = i;
7469         pctx.inode = &inode;
7470
7471         /*
7472          * Offer to delete any zero-length files that does not have
7473          * blocks.  If there is an EA block, it might have useful
7474          * information, so we won't prompt to delete it, but let it be
7475          * reconnected to lost+found.
7476          */
7477         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7478                                 LINUX_S_ISDIR(inode.i_mode))) {
7479                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7480                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7481                         inode.i_links_count = 0;
7482                         inode.i_dtime = time(NULL);
7483                         e2fsck_write_inode(ctx, i, &inode,
7484                                            "disconnect_inode");
7485                         /*
7486                          * Fix up the bitmaps...
7487                          */
7488                         e2fsck_read_bitmaps(ctx);
7489                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7490                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7491                         ext2fs_inode_alloc_stats2(fs, i, -1,
7492                                                   LINUX_S_ISDIR(inode.i_mode));
7493                         return 0;
7494                 }
7495         }
7496
7497         /*
7498          * Prompt to reconnect.
7499          */
7500         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7501                 if (e2fsck_reconnect_file(ctx, i))
7502                         ext2fs_unmark_valid(fs);
7503         } else {
7504                 /*
7505                  * If we don't attach the inode, then skip the
7506                  * i_links_test since there's no point in trying to
7507                  * force i_links_count to zero.
7508                  */
7509                 ext2fs_unmark_valid(fs);
7510                 return 1;
7511         }
7512         return 0;
7513 }
7514
7515
7516 static void e2fsck_pass4(e2fsck_t ctx)
7517 {
7518         ext2_filsys fs = ctx->fs;
7519         ext2_ino_t      i;
7520         struct ext2_inode       inode;
7521         struct problem_context  pctx;
7522         __u16   link_count, link_counted;
7523         char    *buf = NULL;
7524         int     group, maxgroup;
7525
7526         /* Pass 4 */
7527
7528         clear_problem_context(&pctx);
7529
7530         if (!(ctx->options & E2F_OPT_PREEN))
7531                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7532
7533         group = 0;
7534         maxgroup = fs->group_desc_count;
7535         if (ctx->progress)
7536                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7537                         return;
7538
7539         for (i=1; i <= fs->super->s_inodes_count; i++) {
7540                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7541                         return;
7542                 if ((i % fs->super->s_inodes_per_group) == 0) {
7543                         group++;
7544                         if (ctx->progress)
7545                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7546                                         return;
7547                 }
7548                 if (i == EXT2_BAD_INO ||
7549                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7550                         continue;
7551                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7552                     (ctx->inode_imagic_map &&
7553                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7554                         continue;
7555                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7556                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7557                 if (link_counted == 0) {
7558                         if (!buf)
7559                                 buf = e2fsck_allocate_memory(ctx,
7560                                      fs->blocksize, "bad_inode buffer");
7561                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7562                                 continue;
7563                         if (disconnect_inode(ctx, i))
7564                                 continue;
7565                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7566                                             &link_count);
7567                         ext2fs_icount_fetch(ctx->inode_count, i,
7568                                             &link_counted);
7569                 }
7570                 if (link_counted != link_count) {
7571                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7572                         pctx.ino = i;
7573                         pctx.inode = &inode;
7574                         if (link_count != inode.i_links_count) {
7575                                 pctx.num = link_count;
7576                                 fix_problem(ctx,
7577                                             PR_4_INCONSISTENT_COUNT, &pctx);
7578                         }
7579                         pctx.num = link_counted;
7580                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7581                                 inode.i_links_count = link_counted;
7582                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7583                         }
7584                 }
7585         }
7586         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7587         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7588         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7589         ctx->inode_imagic_map = 0;
7590         ext2fs_free_mem(&buf);
7591 }
7592
7593 /*
7594  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7595  */
7596
7597 #define NO_BLK ((blk_t) -1)
7598
7599 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7600                             struct problem_context *pctx)
7601 {
7602         switch (problem) {
7603         case PR_5_BLOCK_UNUSED:
7604                 if (pctx->blk == pctx->blk2)
7605                         pctx->blk2 = 0;
7606                 else
7607                         problem = PR_5_BLOCK_RANGE_UNUSED;
7608                 break;
7609         case PR_5_BLOCK_USED:
7610                 if (pctx->blk == pctx->blk2)
7611                         pctx->blk2 = 0;
7612                 else
7613                         problem = PR_5_BLOCK_RANGE_USED;
7614                 break;
7615         case PR_5_INODE_UNUSED:
7616                 if (pctx->ino == pctx->ino2)
7617                         pctx->ino2 = 0;
7618                 else
7619                         problem = PR_5_INODE_RANGE_UNUSED;
7620                 break;
7621         case PR_5_INODE_USED:
7622                 if (pctx->ino == pctx->ino2)
7623                         pctx->ino2 = 0;
7624                 else
7625                         problem = PR_5_INODE_RANGE_USED;
7626                 break;
7627         }
7628         fix_problem(ctx, problem, pctx);
7629         pctx->blk = pctx->blk2 = NO_BLK;
7630         pctx->ino = pctx->ino2 = 0;
7631 }
7632
7633 static void check_block_bitmaps(e2fsck_t ctx)
7634 {
7635         ext2_filsys fs = ctx->fs;
7636         blk_t   i;
7637         int     *free_array;
7638         int     group = 0;
7639         unsigned int    blocks = 0;
7640         unsigned int    free_blocks = 0;
7641         int     group_free = 0;
7642         int     actual, bitmap;
7643         struct problem_context  pctx;
7644         int     problem, save_problem, fixit, had_problem;
7645         errcode_t       retval;
7646
7647         clear_problem_context(&pctx);
7648         free_array = (int *) e2fsck_allocate_memory(ctx,
7649             fs->group_desc_count * sizeof(int), "free block count array");
7650
7651         if ((fs->super->s_first_data_block <
7652              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7653             (fs->super->s_blocks_count-1 >
7654              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7655                 pctx.num = 1;
7656                 pctx.blk = fs->super->s_first_data_block;
7657                 pctx.blk2 = fs->super->s_blocks_count -1;
7658                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7659                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7660                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7661
7662                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7663                 return;
7664         }
7665
7666         if ((fs->super->s_first_data_block <
7667              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7668             (fs->super->s_blocks_count-1 >
7669              ext2fs_get_block_bitmap_end(fs->block_map))) {
7670                 pctx.num = 2;
7671                 pctx.blk = fs->super->s_first_data_block;
7672                 pctx.blk2 = fs->super->s_blocks_count -1;
7673                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7674                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7675                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7676
7677                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7678                 return;
7679         }
7680
7681 redo_counts:
7682         had_problem = 0;
7683         save_problem = 0;
7684         pctx.blk = pctx.blk2 = NO_BLK;
7685         for (i = fs->super->s_first_data_block;
7686              i < fs->super->s_blocks_count;
7687              i++) {
7688                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7689                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7690
7691                 if (actual == bitmap)
7692                         goto do_counts;
7693
7694                 if (!actual && bitmap) {
7695                         /*
7696                          * Block not used, but marked in use in the bitmap.
7697                          */
7698                         problem = PR_5_BLOCK_UNUSED;
7699                 } else {
7700                         /*
7701                          * Block used, but not marked in use in the bitmap.
7702                          */
7703                         problem = PR_5_BLOCK_USED;
7704                 }
7705                 if (pctx.blk == NO_BLK) {
7706                         pctx.blk = pctx.blk2 = i;
7707                         save_problem = problem;
7708                 } else {
7709                         if ((problem == save_problem) &&
7710                             (pctx.blk2 == i-1))
7711                                 pctx.blk2++;
7712                         else {
7713                                 print_bitmap_problem(ctx, save_problem, &pctx);
7714                                 pctx.blk = pctx.blk2 = i;
7715                                 save_problem = problem;
7716                         }
7717                 }
7718                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7719                 had_problem++;
7720
7721         do_counts:
7722                 if (!bitmap) {
7723                         group_free++;
7724                         free_blocks++;
7725                 }
7726                 blocks ++;
7727                 if ((blocks == fs->super->s_blocks_per_group) ||
7728                     (i == fs->super->s_blocks_count-1)) {
7729                         free_array[group] = group_free;
7730                         group ++;
7731                         blocks = 0;
7732                         group_free = 0;
7733                         if (ctx->progress)
7734                                 if ((ctx->progress)(ctx, 5, group,
7735                                                     fs->group_desc_count*2))
7736                                         return;
7737                 }
7738         }
7739         if (pctx.blk != NO_BLK)
7740                 print_bitmap_problem(ctx, save_problem, &pctx);
7741         if (had_problem)
7742                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7743         else
7744                 fixit = -1;
7745         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7746
7747         if (fixit == 1) {
7748                 ext2fs_free_block_bitmap(fs->block_map);
7749                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7750                                                   &fs->block_map);
7751                 if (retval) {
7752                         clear_problem_context(&pctx);
7753                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7754                         ctx->flags |= E2F_FLAG_ABORT;
7755                         return;
7756                 }
7757                 ext2fs_set_bitmap_padding(fs->block_map);
7758                 ext2fs_mark_bb_dirty(fs);
7759
7760                 /* Redo the counts */
7761                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7762                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7763                 goto redo_counts;
7764         } else if (fixit == 0)
7765                 ext2fs_unmark_valid(fs);
7766
7767         for (i = 0; i < fs->group_desc_count; i++) {
7768                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7769                         pctx.group = i;
7770                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7771                         pctx.blk2 = free_array[i];
7772
7773                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7774                                         &pctx)) {
7775                                 fs->group_desc[i].bg_free_blocks_count =
7776                                         free_array[i];
7777                                 ext2fs_mark_super_dirty(fs);
7778                         } else
7779                                 ext2fs_unmark_valid(fs);
7780                 }
7781         }
7782         if (free_blocks != fs->super->s_free_blocks_count) {
7783                 pctx.group = 0;
7784                 pctx.blk = fs->super->s_free_blocks_count;
7785                 pctx.blk2 = free_blocks;
7786
7787                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7788                         fs->super->s_free_blocks_count = free_blocks;
7789                         ext2fs_mark_super_dirty(fs);
7790                 } else
7791                         ext2fs_unmark_valid(fs);
7792         }
7793         ext2fs_free_mem(&free_array);
7794 }
7795
7796 static void check_inode_bitmaps(e2fsck_t ctx)
7797 {
7798         ext2_filsys fs = ctx->fs;
7799         ext2_ino_t      i;
7800         unsigned int    free_inodes = 0;
7801         int             group_free = 0;
7802         int             dirs_count = 0;
7803         int             group = 0;
7804         unsigned int    inodes = 0;
7805         int             *free_array;
7806         int             *dir_array;
7807         int             actual, bitmap;
7808         errcode_t       retval;
7809         struct problem_context  pctx;
7810         int             problem, save_problem, fixit, had_problem;
7811
7812         clear_problem_context(&pctx);
7813         free_array = (int *) e2fsck_allocate_memory(ctx,
7814             fs->group_desc_count * sizeof(int), "free inode count array");
7815
7816         dir_array = (int *) e2fsck_allocate_memory(ctx,
7817            fs->group_desc_count * sizeof(int), "directory count array");
7818
7819         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7820             (fs->super->s_inodes_count >
7821              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7822                 pctx.num = 3;
7823                 pctx.blk = 1;
7824                 pctx.blk2 = fs->super->s_inodes_count;
7825                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7826                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7827                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7828
7829                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7830                 return;
7831         }
7832         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7833             (fs->super->s_inodes_count >
7834              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7835                 pctx.num = 4;
7836                 pctx.blk = 1;
7837                 pctx.blk2 = fs->super->s_inodes_count;
7838                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7839                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7840                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843                 return;
7844         }
7845
7846 redo_counts:
7847         had_problem = 0;
7848         save_problem = 0;
7849         pctx.ino = pctx.ino2 = 0;
7850         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7851                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7852                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7853
7854                 if (actual == bitmap)
7855                         goto do_counts;
7856
7857                 if (!actual && bitmap) {
7858                         /*
7859                          * Inode wasn't used, but marked in bitmap
7860                          */
7861                         problem = PR_5_INODE_UNUSED;
7862                 } else /* if (actual && !bitmap) */ {
7863                         /*
7864                          * Inode used, but not in bitmap
7865                          */
7866                         problem = PR_5_INODE_USED;
7867                 }
7868                 if (pctx.ino == 0) {
7869                         pctx.ino = pctx.ino2 = i;
7870                         save_problem = problem;
7871                 } else {
7872                         if ((problem == save_problem) &&
7873                             (pctx.ino2 == i-1))
7874                                 pctx.ino2++;
7875                         else {
7876                                 print_bitmap_problem(ctx, save_problem, &pctx);
7877                                 pctx.ino = pctx.ino2 = i;
7878                                 save_problem = problem;
7879                         }
7880                 }
7881                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7882                 had_problem++;
7883
7884 do_counts:
7885                 if (!bitmap) {
7886                         group_free++;
7887                         free_inodes++;
7888                 } else {
7889                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7890                                 dirs_count++;
7891                 }
7892                 inodes++;
7893                 if ((inodes == fs->super->s_inodes_per_group) ||
7894                     (i == fs->super->s_inodes_count)) {
7895                         free_array[group] = group_free;
7896                         dir_array[group] = dirs_count;
7897                         group ++;
7898                         inodes = 0;
7899                         group_free = 0;
7900                         dirs_count = 0;
7901                         if (ctx->progress)
7902                                 if ((ctx->progress)(ctx, 5,
7903                                             group + fs->group_desc_count,
7904                                             fs->group_desc_count*2))
7905                                         return;
7906                 }
7907         }
7908         if (pctx.ino)
7909                 print_bitmap_problem(ctx, save_problem, &pctx);
7910
7911         if (had_problem)
7912                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7913         else
7914                 fixit = -1;
7915         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7916
7917         if (fixit == 1) {
7918                 ext2fs_free_inode_bitmap(fs->inode_map);
7919                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7920                                                   &fs->inode_map);
7921                 if (retval) {
7922                         clear_problem_context(&pctx);
7923                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7924                         ctx->flags |= E2F_FLAG_ABORT;
7925                         return;
7926                 }
7927                 ext2fs_set_bitmap_padding(fs->inode_map);
7928                 ext2fs_mark_ib_dirty(fs);
7929
7930                 /* redo counts */
7931                 inodes = 0; free_inodes = 0; group_free = 0;
7932                 dirs_count = 0; group = 0;
7933                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7934                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7935                 goto redo_counts;
7936         } else if (fixit == 0)
7937                 ext2fs_unmark_valid(fs);
7938
7939         for (i = 0; i < fs->group_desc_count; i++) {
7940                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7941                         pctx.group = i;
7942                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7943                         pctx.ino2 = free_array[i];
7944                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7945                                         &pctx)) {
7946                                 fs->group_desc[i].bg_free_inodes_count =
7947                                         free_array[i];
7948                                 ext2fs_mark_super_dirty(fs);
7949                         } else
7950                                 ext2fs_unmark_valid(fs);
7951                 }
7952                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7953                         pctx.group = i;
7954                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7955                         pctx.ino2 = dir_array[i];
7956
7957                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7958                                         &pctx)) {
7959                                 fs->group_desc[i].bg_used_dirs_count =
7960                                         dir_array[i];
7961                                 ext2fs_mark_super_dirty(fs);
7962                         } else
7963                                 ext2fs_unmark_valid(fs);
7964                 }
7965         }
7966         if (free_inodes != fs->super->s_free_inodes_count) {
7967                 pctx.group = -1;
7968                 pctx.ino = fs->super->s_free_inodes_count;
7969                 pctx.ino2 = free_inodes;
7970
7971                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7972                         fs->super->s_free_inodes_count = free_inodes;
7973                         ext2fs_mark_super_dirty(fs);
7974                 } else
7975                         ext2fs_unmark_valid(fs);
7976         }
7977         ext2fs_free_mem(&free_array);
7978         ext2fs_free_mem(&dir_array);
7979 }
7980
7981 static void check_inode_end(e2fsck_t ctx)
7982 {
7983         ext2_filsys fs = ctx->fs;
7984         ext2_ino_t      end, save_inodes_count, i;
7985         struct problem_context  pctx;
7986
7987         clear_problem_context(&pctx);
7988
7989         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7990         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7991                                                      &save_inodes_count);
7992         if (pctx.errcode) {
7993                 pctx.num = 1;
7994                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7995                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7996                 return;
7997         }
7998         if (save_inodes_count == end)
7999                 return;
8000
8001         for (i = save_inodes_count + 1; i <= end; i++) {
8002                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8003                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8004                                 for (i = save_inodes_count + 1; i <= end; i++)
8005                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8006                                                                  i);
8007                                 ext2fs_mark_ib_dirty(fs);
8008                         } else
8009                                 ext2fs_unmark_valid(fs);
8010                         break;
8011                 }
8012         }
8013
8014         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8015                                                      save_inodes_count, 0);
8016         if (pctx.errcode) {
8017                 pctx.num = 2;
8018                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8019                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8020                 return;
8021         }
8022 }
8023
8024 static void check_block_end(e2fsck_t ctx)
8025 {
8026         ext2_filsys fs = ctx->fs;
8027         blk_t   end, save_blocks_count, i;
8028         struct problem_context  pctx;
8029
8030         clear_problem_context(&pctx);
8031
8032         end = fs->block_map->start +
8033                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8034         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8035                                                      &save_blocks_count);
8036         if (pctx.errcode) {
8037                 pctx.num = 3;
8038                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8039                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8040                 return;
8041         }
8042         if (save_blocks_count == end)
8043                 return;
8044
8045         for (i = save_blocks_count + 1; i <= end; i++) {
8046                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8047                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8048                                 for (i = save_blocks_count + 1; i <= end; i++)
8049                                         ext2fs_mark_block_bitmap(fs->block_map,
8050                                                                  i);
8051                                 ext2fs_mark_bb_dirty(fs);
8052                         } else
8053                                 ext2fs_unmark_valid(fs);
8054                         break;
8055                 }
8056         }
8057
8058         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8059                                                      save_blocks_count, 0);
8060         if (pctx.errcode) {
8061                 pctx.num = 4;
8062                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8063                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8064                 return;
8065         }
8066 }
8067
8068 static void e2fsck_pass5(e2fsck_t ctx)
8069 {
8070         struct problem_context  pctx;
8071
8072         /* Pass 5 */
8073
8074         clear_problem_context(&pctx);
8075
8076         if (!(ctx->options & E2F_OPT_PREEN))
8077                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8078
8079         if (ctx->progress)
8080                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8081                         return;
8082
8083         e2fsck_read_bitmaps(ctx);
8084
8085         check_block_bitmaps(ctx);
8086         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8087                 return;
8088         check_inode_bitmaps(ctx);
8089         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8090                 return;
8091         check_inode_end(ctx);
8092         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8093                 return;
8094         check_block_end(ctx);
8095         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8096                 return;
8097
8098         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8099         ctx->inode_used_map = 0;
8100         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8101         ctx->inode_dir_map = 0;
8102         ext2fs_free_block_bitmap(ctx->block_found_map);
8103         ctx->block_found_map = 0;
8104 }
8105
8106 /*
8107  * problem.c --- report filesystem problems to the user
8108  */
8109
8110 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8111 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8112 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8113 #define PR_MSG_ONLY     0x000008 /* Print message only */
8114
8115 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8116
8117 #define PR_FATAL        0x001000 /* Fatal error */
8118 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8119                                  /* ask another */
8120 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8121 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8122 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8123 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8124 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8125
8126
8127 #define PROMPT_NONE     0
8128 #define PROMPT_FIX      1
8129 #define PROMPT_CLEAR    2
8130 #define PROMPT_RELOCATE 3
8131 #define PROMPT_ALLOCATE 4
8132 #define PROMPT_EXPAND   5
8133 #define PROMPT_CONNECT  6
8134 #define PROMPT_CREATE   7
8135 #define PROMPT_SALVAGE  8
8136 #define PROMPT_TRUNCATE 9
8137 #define PROMPT_CLEAR_INODE 10
8138 #define PROMPT_ABORT    11
8139 #define PROMPT_SPLIT    12
8140 #define PROMPT_CONTINUE 13
8141 #define PROMPT_CLONE    14
8142 #define PROMPT_DELETE   15
8143 #define PROMPT_SUPPRESS 16
8144 #define PROMPT_UNLINK   17
8145 #define PROMPT_CLEAR_HTREE 18
8146 #define PROMPT_RECREATE 19
8147 #define PROMPT_NULL     20
8148
8149 struct e2fsck_problem {
8150         problem_t       e2p_code;
8151         const char *    e2p_description;
8152         char            prompt;
8153         int             flags;
8154         problem_t       second_code;
8155 };
8156
8157 struct latch_descr {
8158         int             latch_code;
8159         problem_t       question;
8160         problem_t       end_message;
8161         int             flags;
8162 };
8163
8164 /*
8165  * These are the prompts which are used to ask the user if they want
8166  * to fix a problem.
8167  */
8168 static const char *const prompt[] = {
8169         N_("(no prompt)"),      /* 0 */
8170         N_("Fix"),              /* 1 */
8171         N_("Clear"),            /* 2 */
8172         N_("Relocate"),         /* 3 */
8173         N_("Allocate"),         /* 4 */
8174         N_("Expand"),           /* 5 */
8175         N_("Connect to /lost+found"), /* 6 */
8176         N_("Create"),           /* 7 */
8177         N_("Salvage"),          /* 8 */
8178         N_("Truncate"),         /* 9 */
8179         N_("Clear inode"),      /* 10 */
8180         N_("Abort"),            /* 11 */
8181         N_("Split"),            /* 12 */
8182         N_("Continue"),         /* 13 */
8183         N_("Clone multiply-claimed blocks"), /* 14 */
8184         N_("Delete file"),      /* 15 */
8185         N_("Suppress messages"),/* 16 */
8186         N_("Unlink"),           /* 17 */
8187         N_("Clear HTree index"),/* 18 */
8188         N_("Recreate"),         /* 19 */
8189         "",                     /* 20 */
8190 };
8191
8192 /*
8193  * These messages are printed when we are preen mode and we will be
8194  * automatically fixing the problem.
8195  */
8196 static const char *const preen_msg[] = {
8197         N_("(NONE)"),           /* 0 */
8198         N_("FIXED"),            /* 1 */
8199         N_("CLEARED"),          /* 2 */
8200         N_("RELOCATED"),        /* 3 */
8201         N_("ALLOCATED"),        /* 4 */
8202         N_("EXPANDED"),         /* 5 */
8203         N_("RECONNECTED"),      /* 6 */
8204         N_("CREATED"),          /* 7 */
8205         N_("SALVAGED"),         /* 8 */
8206         N_("TRUNCATED"),        /* 9 */
8207         N_("INODE CLEARED"),    /* 10 */
8208         N_("ABORTED"),          /* 11 */
8209         N_("SPLIT"),            /* 12 */
8210         N_("CONTINUING"),       /* 13 */
8211         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8212         N_("FILE DELETED"),     /* 15 */
8213         N_("SUPPRESSED"),       /* 16 */
8214         N_("UNLINKED"),         /* 17 */
8215         N_("HTREE INDEX CLEARED"),/* 18 */
8216         N_("WILL RECREATE"),    /* 19 */
8217         "",                     /* 20 */
8218 };
8219
8220 static const struct e2fsck_problem problem_table[] = {
8221
8222         /* Pre-Pass 1 errors */
8223
8224         /* Block bitmap not in group */
8225         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8226           PROMPT_RELOCATE, PR_LATCH_RELOC },
8227
8228         /* Inode bitmap not in group */
8229         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8230           PROMPT_RELOCATE, PR_LATCH_RELOC },
8231
8232         /* Inode table not in group */
8233         { PR_0_ITABLE_NOT_GROUP,
8234           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8235           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8236           PROMPT_RELOCATE, PR_LATCH_RELOC },
8237
8238         /* Superblock corrupt */
8239         { PR_0_SB_CORRUPT,
8240           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8241           "@f.  If the @v is valid and it really contains an ext2\n"
8242           "@f (and not swap or ufs or something else), then the @S\n"
8243           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8244           "    e2fsck -b %S <@v>\n\n"),
8245           PROMPT_NONE, PR_FATAL },
8246
8247         /* Filesystem size is wrong */
8248         { PR_0_FS_SIZE_WRONG,
8249           N_("The @f size (according to the @S) is %b @bs\n"
8250           "The physical size of the @v is %c @bs\n"
8251           "Either the @S or the partition table is likely to be corrupt!\n"),
8252           PROMPT_ABORT, 0 },
8253
8254         /* Fragments not supported */
8255         { PR_0_NO_FRAGMENTS,
8256           N_("@S @b_size = %b, fragsize = %c.\n"
8257           "This version of e2fsck does not support fragment sizes different\n"
8258           "from the @b size.\n"),
8259           PROMPT_NONE, PR_FATAL },
8260
8261           /* Bad blocks_per_group */
8262         { PR_0_BLOCKS_PER_GROUP,
8263           N_("@S @bs_per_group = %b, should have been %c\n"),
8264           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8265
8266         /* Bad first_data_block */
8267         { PR_0_FIRST_DATA_BLOCK,
8268           N_("@S first_data_@b = %b, should have been %c\n"),
8269           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8270
8271         /* Adding UUID to filesystem */
8272         { PR_0_ADD_UUID,
8273           N_("@f did not have a UUID; generating one.\n\n"),
8274           PROMPT_NONE, 0 },
8275
8276         /* Relocate hint */
8277         { PR_0_RELOCATE_HINT,
8278           N_("Note: if several inode or block bitmap blocks or part\n"
8279           "of the inode table require relocation, you may wish to try\n"
8280           "running e2fsck with the '-b %S' option first.  The problem\n"
8281           "may lie only with the primary block group descriptors, and\n"
8282           "the backup block group descriptors may be OK.\n\n"),
8283           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8284
8285         /* Miscellaneous superblock corruption */
8286         { PR_0_MISC_CORRUPT_SUPER,
8287           N_("Corruption found in @S.  (%s = %N).\n"),
8288           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8289
8290         /* Error determing physical device size of filesystem */
8291         { PR_0_GETSIZE_ERROR,
8292           N_("Error determining size of the physical @v: %m\n"),
8293           PROMPT_NONE, PR_FATAL },
8294
8295         /* Inode count in superblock is incorrect */
8296         { PR_0_INODE_COUNT_WRONG,
8297           N_("@i count in @S is %i, @s %j.\n"),
8298           PROMPT_FIX, 0 },
8299
8300         { PR_0_HURD_CLEAR_FILETYPE,
8301           N_("The Hurd does not support the filetype feature.\n"),
8302           PROMPT_CLEAR, 0 },
8303
8304         /* Journal inode is invalid */
8305         { PR_0_JOURNAL_BAD_INODE,
8306           N_("@S has an @n ext3 @j (@i %i).\n"),
8307           PROMPT_CLEAR, PR_PREEN_OK },
8308
8309         /* The external journal has (unsupported) multiple filesystems */
8310         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8311           N_("External @j has multiple @f users (unsupported).\n"),
8312           PROMPT_NONE, PR_FATAL },
8313
8314         /* Can't find external journal */
8315         { PR_0_CANT_FIND_JOURNAL,
8316           N_("Can't find external @j\n"),
8317           PROMPT_NONE, PR_FATAL },
8318
8319         /* External journal has bad superblock */
8320         { PR_0_EXT_JOURNAL_BAD_SUPER,
8321           N_("External @j has bad @S\n"),
8322           PROMPT_NONE, PR_FATAL },
8323
8324         /* Superblock has a bad journal UUID */
8325         { PR_0_JOURNAL_BAD_UUID,
8326           N_("External @j does not support this @f\n"),
8327           PROMPT_NONE, PR_FATAL },
8328
8329         /* Journal has an unknown superblock type */
8330         { PR_0_JOURNAL_UNSUPP_SUPER,
8331           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8332              "It is likely that your copy of e2fsck is old and/or doesn't "
8333              "support this @j format.\n"
8334              "It is also possible the @j @S is corrupt.\n"),
8335           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8336
8337         /* Journal superblock is corrupt */
8338         { PR_0_JOURNAL_BAD_SUPER,
8339           N_("Ext3 @j @S is corrupt.\n"),
8340           PROMPT_FIX, PR_PREEN_OK },
8341
8342         /* Superblock flag should be cleared */
8343         { PR_0_JOURNAL_HAS_JOURNAL,
8344           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8345           PROMPT_CLEAR, PR_PREEN_OK },
8346
8347         /* Superblock flag is incorrect */
8348         { PR_0_JOURNAL_RECOVER_SET,
8349           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8350           PROMPT_CLEAR, PR_PREEN_OK },
8351
8352         /* Journal has data, but recovery flag is clear */
8353         { PR_0_JOURNAL_RECOVERY_CLEAR,
8354           N_("ext3 recovery flag is clear, but @j has data.\n"),
8355           PROMPT_NONE, 0 },
8356
8357         /* Ask if we should clear the journal */
8358         { PR_0_JOURNAL_RESET_JOURNAL,
8359           N_("Clear @j"),
8360           PROMPT_NULL, PR_PREEN_NOMSG },
8361
8362         /* Ask if we should run the journal anyway */
8363         { PR_0_JOURNAL_RUN,
8364           N_("Run @j anyway"),
8365           PROMPT_NULL, 0 },
8366
8367         /* Run the journal by default */
8368         { PR_0_JOURNAL_RUN_DEFAULT,
8369           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8370           PROMPT_NONE, 0 },
8371
8372         /* Clearing orphan inode */
8373         { PR_0_ORPHAN_CLEAR_INODE,
8374           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8375           PROMPT_NONE, 0 },
8376
8377         /* Illegal block found in orphaned inode */
8378         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8379            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8380           PROMPT_NONE, 0 },
8381
8382         /* Already cleared block found in orphaned inode */
8383         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8384            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8385           PROMPT_NONE, 0 },
8386
8387         /* Illegal orphan inode in superblock */
8388         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8389           N_("@I @o @i %i in @S.\n"),
8390           PROMPT_NONE, 0 },
8391
8392         /* Illegal inode in orphaned inode list */
8393         { PR_0_ORPHAN_ILLEGAL_INODE,
8394           N_("@I @i %i in @o @i list.\n"),
8395           PROMPT_NONE, 0 },
8396
8397         /* Filesystem revision is 0, but feature flags are set */
8398         { PR_0_FS_REV_LEVEL,
8399           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8400           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8401
8402         /* Journal superblock has an unknown read-only feature flag set */
8403         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8404           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8405           PROMPT_ABORT, 0 },
8406
8407         /* Journal superblock has an unknown incompatible feature flag set */
8408         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8409           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8410           PROMPT_ABORT, 0 },
8411
8412         /* Journal has unsupported version number */
8413         { PR_0_JOURNAL_UNSUPP_VERSION,
8414           N_("@j version not supported by this e2fsck.\n"),
8415           PROMPT_ABORT, 0 },
8416
8417         /* Moving journal to hidden file */
8418         { PR_0_MOVE_JOURNAL,
8419           N_("Moving @j from /%s to hidden @i.\n\n"),
8420           PROMPT_NONE, 0 },
8421
8422         /* Error moving journal to hidden file */
8423         { PR_0_ERR_MOVE_JOURNAL,
8424           N_("Error moving @j: %m\n\n"),
8425           PROMPT_NONE, 0 },
8426
8427         /* Clearing V2 journal superblock */
8428         { PR_0_CLEAR_V2_JOURNAL,
8429           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8430              "Clearing fields beyond the V1 @j @S...\n\n"),
8431           PROMPT_NONE, 0 },
8432
8433         /* Backup journal inode blocks */
8434         { PR_0_BACKUP_JNL,
8435           N_("Backing up @j @i @b information.\n\n"),
8436           PROMPT_NONE, 0 },
8437
8438         /* Reserved blocks w/o resize_inode */
8439         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8440           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8441              "is %N; @s zero.  "),
8442           PROMPT_FIX, 0 },
8443
8444         /* Resize_inode not enabled, but resize inode is non-zero */
8445         { PR_0_CLEAR_RESIZE_INODE,
8446           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8447           PROMPT_CLEAR, 0 },
8448
8449         /* Resize inode invalid */
8450         { PR_0_RESIZE_INODE_INVALID,
8451           N_("Resize @i not valid.  "),
8452           PROMPT_RECREATE, 0 },
8453
8454         /* Pass 1 errors */
8455
8456         /* Pass 1: Checking inodes, blocks, and sizes */
8457         { PR_1_PASS_HEADER,
8458           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8459           PROMPT_NONE, 0 },
8460
8461         /* Root directory is not an inode */
8462         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8463           PROMPT_CLEAR, 0 },
8464
8465         /* Root directory has dtime set */
8466         { PR_1_ROOT_DTIME,
8467           N_("@r has dtime set (probably due to old mke2fs).  "),
8468           PROMPT_FIX, PR_PREEN_OK },
8469
8470         /* Reserved inode has bad mode */
8471         { PR_1_RESERVED_BAD_MODE,
8472           N_("Reserved @i %i (%Q) has @n mode.  "),
8473           PROMPT_CLEAR, PR_PREEN_OK },
8474
8475         /* Deleted inode has zero dtime */
8476         { PR_1_ZERO_DTIME,
8477           N_("@D @i %i has zero dtime.  "),
8478           PROMPT_FIX, PR_PREEN_OK },
8479
8480         /* Inode in use, but dtime set */
8481         { PR_1_SET_DTIME,
8482           N_("@i %i is in use, but has dtime set.  "),
8483           PROMPT_FIX, PR_PREEN_OK },
8484
8485         /* Zero-length directory */
8486         { PR_1_ZERO_LENGTH_DIR,
8487           N_("@i %i is a @z @d.  "),
8488           PROMPT_CLEAR, PR_PREEN_OK },
8489
8490         /* Block bitmap conflicts with some other fs block */
8491         { PR_1_BB_CONFLICT,
8492           N_("@g %g's @b @B at %b @C.\n"),
8493           PROMPT_RELOCATE, 0 },
8494
8495         /* Inode bitmap conflicts with some other fs block */
8496         { PR_1_IB_CONFLICT,
8497           N_("@g %g's @i @B at %b @C.\n"),
8498           PROMPT_RELOCATE, 0 },
8499
8500         /* Inode table conflicts with some other fs block */
8501         { PR_1_ITABLE_CONFLICT,
8502           N_("@g %g's @i table at %b @C.\n"),
8503           PROMPT_RELOCATE, 0 },
8504
8505         /* Block bitmap is on a bad block */
8506         { PR_1_BB_BAD_BLOCK,
8507           N_("@g %g's @b @B (%b) is bad.  "),
8508           PROMPT_RELOCATE, 0 },
8509
8510         /* Inode bitmap is on a bad block */
8511         { PR_1_IB_BAD_BLOCK,
8512           N_("@g %g's @i @B (%b) is bad.  "),
8513           PROMPT_RELOCATE, 0 },
8514
8515         /* Inode has incorrect i_size */
8516         { PR_1_BAD_I_SIZE,
8517           N_("@i %i, i_size is %Is, @s %N.  "),
8518           PROMPT_FIX, PR_PREEN_OK },
8519
8520         /* Inode has incorrect i_blocks */
8521         { PR_1_BAD_I_BLOCKS,
8522           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8523           PROMPT_FIX, PR_PREEN_OK },
8524
8525         /* Illegal blocknumber in inode */
8526         { PR_1_ILLEGAL_BLOCK_NUM,
8527           N_("@I @b #%B (%b) in @i %i.  "),
8528           PROMPT_CLEAR, PR_LATCH_BLOCK },
8529
8530         /* Block number overlaps fs metadata */
8531         { PR_1_BLOCK_OVERLAPS_METADATA,
8532           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8533           PROMPT_CLEAR, PR_LATCH_BLOCK },
8534
8535         /* Inode has illegal blocks (latch question) */
8536         { PR_1_INODE_BLOCK_LATCH,
8537           N_("@i %i has illegal @b(s).  "),
8538           PROMPT_CLEAR, 0 },
8539
8540         /* Too many bad blocks in inode */
8541         { PR_1_TOO_MANY_BAD_BLOCKS,
8542           N_("Too many illegal @bs in @i %i.\n"),
8543           PROMPT_CLEAR_INODE, PR_NO_OK },
8544
8545         /* Illegal block number in bad block inode */
8546         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8547           N_("@I @b #%B (%b) in bad @b @i.  "),
8548           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8549
8550         /* Bad block inode has illegal blocks (latch question) */
8551         { PR_1_INODE_BBLOCK_LATCH,
8552           N_("Bad @b @i has illegal @b(s).  "),
8553           PROMPT_CLEAR, 0 },
8554
8555         /* Duplicate or bad blocks in use! */
8556         { PR_1_DUP_BLOCKS_PREENSTOP,
8557           N_("Duplicate or bad @b in use!\n"),
8558           PROMPT_NONE, 0 },
8559
8560         /* Bad block used as bad block indirect block */
8561         { PR_1_BBINODE_BAD_METABLOCK,
8562           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8563           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8564
8565         /* Inconsistency can't be fixed prompt */
8566         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8567           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8568              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8569              "in the @f.\n"),
8570           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8571
8572         /* Bad primary block */
8573         { PR_1_BAD_PRIMARY_BLOCK,
8574           N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8575           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8576
8577         /* Bad primary block prompt */
8578         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8579           N_("You can remove this @b from the bad @b list and hope\n"
8580              "that the @b is really OK.  But there are no guarantees.\n\n"),
8581           PROMPT_CLEAR, PR_PREEN_NOMSG },
8582
8583         /* Bad primary superblock */
8584         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8585           N_("The primary @S (%b) is on the bad @b list.\n"),
8586           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8587
8588         /* Bad primary block group descriptors */
8589         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8590           N_("Block %b in the primary @g descriptors "
8591           "is on the bad @b list\n"),
8592           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8593
8594         /* Bad superblock in group */
8595         { PR_1_BAD_SUPERBLOCK,
8596           N_("Warning: Group %g's @S (%b) is bad.\n"),
8597           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8598
8599         /* Bad block group descriptors in group */
8600         { PR_1_BAD_GROUP_DESCRIPTORS,
8601           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8602           "@b (%b).\n"),
8603           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8604
8605         /* Block claimed for no reason */
8606         { PR_1_PROGERR_CLAIMED_BLOCK,
8607           N_("Programming error?  @b #%b claimed for no reason in "
8608           "process_bad_@b.\n"),
8609           PROMPT_NONE, PR_PREEN_OK },
8610
8611         /* Error allocating blocks for relocating metadata */
8612         { PR_1_RELOC_BLOCK_ALLOCATE,
8613           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8614           PROMPT_NONE, PR_PREEN_OK },
8615
8616         /* Error allocating block buffer during relocation process */
8617         { PR_1_RELOC_MEMORY_ALLOCATE,
8618           N_("@A @b buffer for relocating %s\n"),
8619           PROMPT_NONE, PR_PREEN_OK },
8620
8621         /* Relocating metadata group information from X to Y */
8622         { PR_1_RELOC_FROM_TO,
8623           N_("Relocating @g %g's %s from %b to %c...\n"),
8624           PROMPT_NONE, PR_PREEN_OK },
8625
8626         /* Relocating metatdata group information to X */
8627         { PR_1_RELOC_TO,
8628           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8629           PROMPT_NONE, PR_PREEN_OK },
8630
8631         /* Block read error during relocation process */
8632         { PR_1_RELOC_READ_ERR,
8633           N_("Warning: could not read @b %b of %s: %m\n"),
8634           PROMPT_NONE, PR_PREEN_OK },
8635
8636         /* Block write error during relocation process */
8637         { PR_1_RELOC_WRITE_ERR,
8638           N_("Warning: could not write @b %b for %s: %m\n"),
8639           PROMPT_NONE, PR_PREEN_OK },
8640
8641         /* Error allocating inode bitmap */
8642         { PR_1_ALLOCATE_IBITMAP_ERROR,
8643           N_("@A @i @B (%N): %m\n"),
8644           PROMPT_NONE, PR_FATAL },
8645
8646         /* Error allocating block bitmap */
8647         { PR_1_ALLOCATE_BBITMAP_ERROR,
8648           N_("@A @b @B (%N): %m\n"),
8649           PROMPT_NONE, PR_FATAL },
8650
8651         /* Error allocating icount structure */
8652         { PR_1_ALLOCATE_ICOUNT,
8653           N_("@A icount link information: %m\n"),
8654           PROMPT_NONE, PR_FATAL },
8655
8656         /* Error allocating dbcount */
8657         { PR_1_ALLOCATE_DBCOUNT,
8658           N_("@A @d @b array: %m\n"),
8659           PROMPT_NONE, PR_FATAL },
8660
8661         /* Error while scanning inodes */
8662         { PR_1_ISCAN_ERROR,
8663           N_("Error while scanning @is (%i): %m\n"),
8664           PROMPT_NONE, PR_FATAL },
8665
8666         /* Error while iterating over blocks */
8667         { PR_1_BLOCK_ITERATE,
8668           N_("Error while iterating over @bs in @i %i: %m\n"),
8669           PROMPT_NONE, PR_FATAL },
8670
8671         /* Error while storing inode count information */
8672         { PR_1_ICOUNT_STORE,
8673           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8674           PROMPT_NONE, PR_FATAL },
8675
8676         /* Error while storing directory block information */
8677         { PR_1_ADD_DBLOCK,
8678           N_("Error storing @d @b information "
8679           "(@i=%i, @b=%b, num=%N): %m\n"),
8680           PROMPT_NONE, PR_FATAL },
8681
8682         /* Error while reading inode (for clearing) */
8683         { PR_1_READ_INODE,
8684           N_("Error reading @i %i: %m\n"),
8685           PROMPT_NONE, PR_FATAL },
8686
8687         /* Suppress messages prompt */
8688         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8689
8690         /* Imagic flag set on an inode when filesystem doesn't support it */
8691         { PR_1_SET_IMAGIC,
8692           N_("@i %i has imagic flag set.  "),
8693           PROMPT_CLEAR, 0 },
8694
8695         /* Immutable flag set on a device or socket inode */
8696         { PR_1_SET_IMMUTABLE,
8697           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8698              "or append-only flag set.  "),
8699           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8700
8701         /* Compression flag set on an inode when filesystem doesn't support it */
8702         { PR_1_COMPR_SET,
8703           N_("@i %i has @cion flag set on @f without @cion support.  "),
8704           PROMPT_CLEAR, 0 },
8705
8706         /* Non-zero size for device, fifo or socket inode */
8707         { PR_1_SET_NONZSIZE,
8708           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8709           PROMPT_FIX, PR_PREEN_OK },
8710
8711         /* Filesystem revision is 0, but feature flags are set */
8712         { PR_1_FS_REV_LEVEL,
8713           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8714           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8715
8716         /* Journal inode is not in use, but contains data */
8717         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8718           N_("@j @i is not in use, but contains data.  "),
8719           PROMPT_CLEAR, PR_PREEN_OK },
8720
8721         /* Journal has bad mode */
8722         { PR_1_JOURNAL_BAD_MODE,
8723           N_("@j is not regular file.  "),
8724           PROMPT_FIX, PR_PREEN_OK },
8725
8726         /* Deal with inodes that were part of orphan linked list */
8727         { PR_1_LOW_DTIME,
8728           N_("@i %i was part of the @o @i list.  "),
8729           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8730
8731         /* Deal with inodes that were part of corrupted orphan linked
8732            list (latch question) */
8733         { PR_1_ORPHAN_LIST_REFUGEES,
8734           N_("@is that were part of a corrupted orphan linked list found.  "),
8735           PROMPT_FIX, 0 },
8736
8737         /* Error allocating refcount structure */
8738         { PR_1_ALLOCATE_REFCOUNT,
8739           N_("@A refcount structure (%N): %m\n"),
8740           PROMPT_NONE, PR_FATAL },
8741
8742         /* Error reading extended attribute block */
8743         { PR_1_READ_EA_BLOCK,
8744           N_("Error reading @a @b %b for @i %i.  "),
8745           PROMPT_CLEAR, 0 },
8746
8747         /* Invalid extended attribute block */
8748         { PR_1_BAD_EA_BLOCK,
8749           N_("@i %i has a bad @a @b %b.  "),
8750           PROMPT_CLEAR, 0 },
8751
8752         /* Error reading Extended Attribute block while fixing refcount */
8753         { PR_1_EXTATTR_READ_ABORT,
8754           N_("Error reading @a @b %b (%m).  "),
8755           PROMPT_ABORT, 0 },
8756
8757         /* Extended attribute reference count incorrect */
8758         { PR_1_EXTATTR_REFCOUNT,
8759           N_("@a @b %b has reference count %B, @s %N.  "),
8760           PROMPT_FIX, 0 },
8761
8762         /* Error writing Extended Attribute block while fixing refcount */
8763         { PR_1_EXTATTR_WRITE,
8764           N_("Error writing @a @b %b (%m).  "),
8765           PROMPT_ABORT, 0 },
8766
8767         /* Multiple EA blocks not supported */
8768         { PR_1_EA_MULTI_BLOCK,
8769           N_("@a @b %b has h_@bs > 1.  "),
8770           PROMPT_CLEAR, 0},
8771
8772         /* Error allocating EA region allocation structure */
8773         { PR_1_EA_ALLOC_REGION,
8774           N_("@A @a @b %b.  "),
8775           PROMPT_ABORT, 0},
8776
8777         /* Error EA allocation collision */
8778         { PR_1_EA_ALLOC_COLLISION,
8779           N_("@a @b %b is corrupt (allocation collision).  "),
8780           PROMPT_CLEAR, 0},
8781
8782         /* Bad extended attribute name */
8783         { PR_1_EA_BAD_NAME,
8784           N_("@a @b %b is corrupt (@n name).  "),
8785           PROMPT_CLEAR, 0},
8786
8787         /* Bad extended attribute value */
8788         { PR_1_EA_BAD_VALUE,
8789           N_("@a @b %b is corrupt (@n value).  "),
8790           PROMPT_CLEAR, 0},
8791
8792         /* Inode too big (latch question) */
8793         { PR_1_INODE_TOOBIG,
8794           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8795
8796         /* Directory too big */
8797         { PR_1_TOOBIG_DIR,
8798           N_("@b #%B (%b) causes @d to be too big.  "),
8799           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8800
8801         /* Regular file too big */
8802         { PR_1_TOOBIG_REG,
8803           N_("@b #%B (%b) causes file to be too big.  "),
8804           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8805
8806         /* Symlink too big */
8807         { PR_1_TOOBIG_SYMLINK,
8808           N_("@b #%B (%b) causes symlink to be too big.  "),
8809           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8810
8811         /* INDEX_FL flag set on a non-HTREE filesystem */
8812         { PR_1_HTREE_SET,
8813           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8814           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8815
8816         /* INDEX_FL flag set on a non-directory */
8817         { PR_1_HTREE_NODIR,
8818           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8819           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8820
8821         /* Invalid root node in HTREE directory */
8822         { PR_1_HTREE_BADROOT,
8823           N_("@h %i has an @n root node.\n"),
8824           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8825
8826         /* Unsupported hash version in HTREE directory */
8827         { PR_1_HTREE_HASHV,
8828           N_("@h %i has an unsupported hash version (%N)\n"),
8829           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8830
8831         /* Incompatible flag in HTREE root node */
8832         { PR_1_HTREE_INCOMPAT,
8833           N_("@h %i uses an incompatible htree root node flag.\n"),
8834           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8835
8836         /* HTREE too deep */
8837         { PR_1_HTREE_DEPTH,
8838           N_("@h %i has a tree depth (%N) which is too big\n"),
8839           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8840
8841         /* Bad block has indirect block that conflicts with filesystem block */
8842         { PR_1_BB_FS_BLOCK,
8843           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8844              "@f metadata.  "),
8845           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8846
8847         /* Resize inode failed */
8848         { PR_1_RESIZE_INODE_CREATE,
8849           N_("Resize @i (re)creation failed: %m."),
8850           PROMPT_ABORT, 0 },
8851
8852         /* invalid inode->i_extra_isize */
8853         { PR_1_EXTRA_ISIZE,
8854           N_("@i %i has a extra size (%IS) which is @n\n"),
8855           PROMPT_FIX, PR_PREEN_OK },
8856
8857         /* invalid ea entry->e_name_len */
8858         { PR_1_ATTR_NAME_LEN,
8859           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8860           PROMPT_CLEAR, PR_PREEN_OK },
8861
8862         /* invalid ea entry->e_value_size */
8863         { PR_1_ATTR_VALUE_SIZE,
8864           N_("@a in @i %i has a value size (%N) which is @n\n"),
8865           PROMPT_CLEAR, PR_PREEN_OK },
8866
8867         /* invalid ea entry->e_value_offs */
8868         { PR_1_ATTR_VALUE_OFFSET,
8869           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8870           PROMPT_CLEAR, PR_PREEN_OK },
8871
8872         /* invalid ea entry->e_value_block */
8873         { PR_1_ATTR_VALUE_BLOCK,
8874           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8875           PROMPT_CLEAR, PR_PREEN_OK },
8876
8877         /* invalid ea entry->e_hash */
8878         { PR_1_ATTR_HASH,
8879           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8880           PROMPT_CLEAR, PR_PREEN_OK },
8881
8882         /* Pass 1b errors */
8883
8884         /* Pass 1B: Rescan for duplicate/bad blocks */
8885         { PR_1B_PASS_HEADER,
8886           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8887           "Pass 1B: Rescanning for @m @bs\n"),
8888           PROMPT_NONE, 0 },
8889
8890         /* Duplicate/bad block(s) header */
8891         { PR_1B_DUP_BLOCK_HEADER,
8892           N_("@m @b(s) in @i %i:"),
8893           PROMPT_NONE, 0 },
8894
8895         /* Duplicate/bad block(s) in inode */
8896         { PR_1B_DUP_BLOCK,
8897           " %b",
8898           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8899
8900         /* Duplicate/bad block(s) end */
8901         { PR_1B_DUP_BLOCK_END,
8902           "\n",
8903           PROMPT_NONE, PR_PREEN_NOHDR },
8904
8905         /* Error while scanning inodes */
8906         { PR_1B_ISCAN_ERROR,
8907           N_("Error while scanning inodes (%i): %m\n"),
8908           PROMPT_NONE, PR_FATAL },
8909
8910         /* Error allocating inode bitmap */
8911         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8912           N_("@A @i @B (@i_dup_map): %m\n"),
8913           PROMPT_NONE, PR_FATAL },
8914
8915         /* Error while iterating over blocks */
8916         { PR_1B_BLOCK_ITERATE,
8917           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8918           PROMPT_NONE, 0 },
8919
8920         /* Error adjusting EA refcount */
8921         { PR_1B_ADJ_EA_REFCOUNT,
8922           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8923           PROMPT_NONE, 0 },
8924
8925
8926         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8927         { PR_1C_PASS_HEADER,
8928           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8929           PROMPT_NONE, 0 },
8930
8931
8932         /* Pass 1D: Reconciling multiply-claimed blocks */
8933         { PR_1D_PASS_HEADER,
8934           N_("Pass 1D: Reconciling @m @bs\n"),
8935           PROMPT_NONE, 0 },
8936
8937         /* File has duplicate blocks */
8938         { PR_1D_DUP_FILE,
8939           N_("File %Q (@i #%i, mod time %IM)\n"
8940           "  has %B @m @b(s), shared with %N file(s):\n"),
8941           PROMPT_NONE, 0 },
8942
8943         /* List of files sharing duplicate blocks */
8944         { PR_1D_DUP_FILE_LIST,
8945           N_("\t%Q (@i #%i, mod time %IM)\n"),
8946           PROMPT_NONE, 0 },
8947
8948         /* File sharing blocks with filesystem metadata  */
8949         { PR_1D_SHARE_METADATA,
8950           N_("\t<@f metadata>\n"),
8951           PROMPT_NONE, 0 },
8952
8953         /* Report of how many duplicate/bad inodes */
8954         { PR_1D_NUM_DUP_INODES,
8955           N_("(There are %N @is containing @m @bs.)\n\n"),
8956           PROMPT_NONE, 0 },
8957
8958         /* Duplicated blocks already reassigned or cloned. */
8959         { PR_1D_DUP_BLOCKS_DEALT,
8960           N_("@m @bs already reassigned or cloned.\n\n"),
8961           PROMPT_NONE, 0 },
8962
8963         /* Clone duplicate/bad blocks? */
8964         { PR_1D_CLONE_QUESTION,
8965           "", PROMPT_CLONE, PR_NO_OK },
8966
8967         /* Delete file? */
8968         { PR_1D_DELETE_QUESTION,
8969           "", PROMPT_DELETE, 0 },
8970
8971         /* Couldn't clone file (error) */
8972         { PR_1D_CLONE_ERROR,
8973           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8974
8975         /* Pass 2 errors */
8976
8977         /* Pass 2: Checking directory structure */
8978         { PR_2_PASS_HEADER,
8979           N_("Pass 2: Checking @d structure\n"),
8980           PROMPT_NONE, 0 },
8981
8982         /* Bad inode number for '.' */
8983         { PR_2_BAD_INODE_DOT,
8984           N_("@n @i number for '.' in @d @i %i.\n"),
8985           PROMPT_FIX, 0 },
8986
8987         /* Directory entry has bad inode number */
8988         { PR_2_BAD_INO,
8989           N_("@E has @n @i #: %Di.\n"),
8990           PROMPT_CLEAR, 0 },
8991
8992         /* Directory entry has deleted or unused inode */
8993         { PR_2_UNUSED_INODE,
8994           N_("@E has @D/unused @i %Di.  "),
8995           PROMPT_CLEAR, PR_PREEN_OK },
8996
8997         /* Directry entry is link to '.' */
8998         { PR_2_LINK_DOT,
8999           N_("@E @L to '.'  "),
9000           PROMPT_CLEAR, 0 },
9001
9002         /* Directory entry points to inode now located in a bad block */
9003         { PR_2_BB_INODE,
9004           N_("@E points to @i (%Di) located in a bad @b.\n"),
9005           PROMPT_CLEAR, 0 },
9006
9007         /* Directory entry contains a link to a directory */
9008         { PR_2_LINK_DIR,
9009           N_("@E @L to @d %P (%Di).\n"),
9010           PROMPT_CLEAR, 0 },
9011
9012         /* Directory entry contains a link to the root directry */
9013         { PR_2_LINK_ROOT,
9014           N_("@E @L to the @r.\n"),
9015           PROMPT_CLEAR, 0 },
9016
9017         /* Directory entry has illegal characters in its name */
9018         { PR_2_BAD_NAME,
9019           N_("@E has illegal characters in its name.\n"),
9020           PROMPT_FIX, 0 },
9021
9022         /* Missing '.' in directory inode */
9023         { PR_2_MISSING_DOT,
9024           N_("Missing '.' in @d @i %i.\n"),
9025           PROMPT_FIX, 0 },
9026
9027         /* Missing '..' in directory inode */
9028         { PR_2_MISSING_DOT_DOT,
9029           N_("Missing '..' in @d @i %i.\n"),
9030           PROMPT_FIX, 0 },
9031
9032         /* First entry in directory inode doesn't contain '.' */
9033         { PR_2_1ST_NOT_DOT,
9034           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9035           PROMPT_FIX, 0 },
9036
9037         /* Second entry in directory inode doesn't contain '..' */
9038         { PR_2_2ND_NOT_DOT_DOT,
9039           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9040           PROMPT_FIX, 0 },
9041
9042         /* i_faddr should be zero */
9043         { PR_2_FADDR_ZERO,
9044           N_("i_faddr @F %IF, @s zero.\n"),
9045           PROMPT_CLEAR, 0 },
9046
9047         /* i_file_acl should be zero */
9048         { PR_2_FILE_ACL_ZERO,
9049           N_("i_file_acl @F %If, @s zero.\n"),
9050           PROMPT_CLEAR, 0 },
9051
9052         /* i_dir_acl should be zero */
9053         { PR_2_DIR_ACL_ZERO,
9054           N_("i_dir_acl @F %Id, @s zero.\n"),
9055           PROMPT_CLEAR, 0 },
9056
9057         /* i_frag should be zero */
9058         { PR_2_FRAG_ZERO,
9059           N_("i_frag @F %N, @s zero.\n"),
9060           PROMPT_CLEAR, 0 },
9061
9062         /* i_fsize should be zero */
9063         { PR_2_FSIZE_ZERO,
9064           N_("i_fsize @F %N, @s zero.\n"),
9065           PROMPT_CLEAR, 0 },
9066
9067         /* inode has bad mode */
9068         { PR_2_BAD_MODE,
9069           N_("@i %i (%Q) has @n mode (%Im).\n"),
9070           PROMPT_CLEAR, 0 },
9071
9072         /* directory corrupted */
9073         { PR_2_DIR_CORRUPTED,
9074           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9075           PROMPT_SALVAGE, 0 },
9076
9077         /* filename too long */
9078         { PR_2_FILENAME_LONG,
9079           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9080           PROMPT_TRUNCATE, 0 },
9081
9082         /* Directory inode has a missing block (hole) */
9083         { PR_2_DIRECTORY_HOLE,
9084           N_("@d @i %i has an unallocated @b #%B.  "),
9085           PROMPT_ALLOCATE, 0 },
9086
9087         /* '.' is not NULL terminated */
9088         { PR_2_DOT_NULL_TERM,
9089           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9090           PROMPT_FIX, 0 },
9091
9092         /* '..' is not NULL terminated */
9093         { PR_2_DOT_DOT_NULL_TERM,
9094           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9095           PROMPT_FIX, 0 },
9096
9097         /* Illegal character device inode */
9098         { PR_2_BAD_CHAR_DEV,
9099           N_("@i %i (%Q) is an @I character @v.\n"),
9100           PROMPT_CLEAR, 0 },
9101
9102         /* Illegal block device inode */
9103         { PR_2_BAD_BLOCK_DEV,
9104           N_("@i %i (%Q) is an @I @b @v.\n"),
9105           PROMPT_CLEAR, 0 },
9106
9107         /* Duplicate '.' entry */
9108         { PR_2_DUP_DOT,
9109           N_("@E is duplicate '.' @e.\n"),
9110           PROMPT_FIX, 0 },
9111
9112         /* Duplicate '..' entry */
9113         { PR_2_DUP_DOT_DOT,
9114           N_("@E is duplicate '..' @e.\n"),
9115           PROMPT_FIX, 0 },
9116
9117         /* Internal error: couldn't find dir_info */
9118         { PR_2_NO_DIRINFO,
9119           N_("Internal error: cannot find dir_info for %i.\n"),
9120           PROMPT_NONE, PR_FATAL },
9121
9122         /* Final rec_len is wrong */
9123         { PR_2_FINAL_RECLEN,
9124           N_("@E has rec_len of %Dr, @s %N.\n"),
9125           PROMPT_FIX, 0 },
9126
9127         /* Error allocating icount structure */
9128         { PR_2_ALLOCATE_ICOUNT,
9129           N_("@A icount structure: %m\n"),
9130           PROMPT_NONE, PR_FATAL },
9131
9132         /* Error iterating over directory blocks */
9133         { PR_2_DBLIST_ITERATE,
9134           N_("Error iterating over @d @bs: %m\n"),
9135           PROMPT_NONE, PR_FATAL },
9136
9137         /* Error reading directory block */
9138         { PR_2_READ_DIRBLOCK,
9139           N_("Error reading @d @b %b (@i %i): %m\n"),
9140           PROMPT_CONTINUE, 0 },
9141
9142         /* Error writing directory block */
9143         { PR_2_WRITE_DIRBLOCK,
9144           N_("Error writing @d @b %b (@i %i): %m\n"),
9145           PROMPT_CONTINUE, 0 },
9146
9147         /* Error allocating new directory block */
9148         { PR_2_ALLOC_DIRBOCK,
9149           N_("@A new @d @b for @i %i (%s): %m\n"),
9150           PROMPT_NONE, 0 },
9151
9152         /* Error deallocating inode */
9153         { PR_2_DEALLOC_INODE,
9154           N_("Error deallocating @i %i: %m\n"),
9155           PROMPT_NONE, PR_FATAL },
9156
9157         /* Directory entry for '.' is big.  Split? */
9158         { PR_2_SPLIT_DOT,
9159           N_("@d @e for '.' is big.  "),
9160           PROMPT_SPLIT, PR_NO_OK },
9161
9162         /* Illegal FIFO inode */
9163         { PR_2_BAD_FIFO,
9164           N_("@i %i (%Q) is an @I FIFO.\n"),
9165           PROMPT_CLEAR, 0 },
9166
9167         /* Illegal socket inode */
9168         { PR_2_BAD_SOCKET,
9169           N_("@i %i (%Q) is an @I socket.\n"),
9170           PROMPT_CLEAR, 0 },
9171
9172         /* Directory filetype not set */
9173         { PR_2_SET_FILETYPE,
9174           N_("Setting filetype for @E to %N.\n"),
9175           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9176
9177         /* Directory filetype incorrect */
9178         { PR_2_BAD_FILETYPE,
9179           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9180           PROMPT_FIX, 0 },
9181
9182         /* Directory filetype set on filesystem */
9183         { PR_2_CLEAR_FILETYPE,
9184           N_("@E has filetype set.\n"),
9185           PROMPT_CLEAR, PR_PREEN_OK },
9186
9187         /* Directory filename is null */
9188         { PR_2_NULL_NAME,
9189           N_("@E has a @z name.\n"),
9190           PROMPT_CLEAR, 0 },
9191
9192         /* Invalid symlink */
9193         { PR_2_INVALID_SYMLINK,
9194           N_("Symlink %Q (@i #%i) is @n.\n"),
9195           PROMPT_CLEAR, 0 },
9196
9197         /* i_file_acl (extended attribute block) is bad */
9198         { PR_2_FILE_ACL_BAD,
9199           N_("@a @b @F @n (%If).\n"),
9200           PROMPT_CLEAR, 0 },
9201
9202         /* Filesystem contains large files, but has no such flag in sb */
9203         { PR_2_FEATURE_LARGE_FILES,
9204           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9205           PROMPT_FIX, 0 },
9206
9207         /* Node in HTREE directory not referenced */
9208         { PR_2_HTREE_NOTREF,
9209           N_("@p @h %d: node (%B) not referenced\n"),
9210           PROMPT_NONE, 0 },
9211
9212         /* Node in HTREE directory referenced twice */
9213         { PR_2_HTREE_DUPREF,
9214           N_("@p @h %d: node (%B) referenced twice\n"),
9215           PROMPT_NONE, 0 },
9216
9217         /* Node in HTREE directory has bad min hash */
9218         { PR_2_HTREE_MIN_HASH,
9219           N_("@p @h %d: node (%B) has bad min hash\n"),
9220           PROMPT_NONE, 0 },
9221
9222         /* Node in HTREE directory has bad max hash */
9223         { PR_2_HTREE_MAX_HASH,
9224           N_("@p @h %d: node (%B) has bad max hash\n"),
9225           PROMPT_NONE, 0 },
9226
9227         /* Clear invalid HTREE directory */
9228         { PR_2_HTREE_CLEAR,
9229           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9230
9231         /* Bad block in htree interior node */
9232         { PR_2_HTREE_BADBLK,
9233           N_("@p @h %d (%q): bad @b number %b.\n"),
9234           PROMPT_CLEAR_HTREE, 0 },
9235
9236         /* Error adjusting EA refcount */
9237         { PR_2_ADJ_EA_REFCOUNT,
9238           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9239           PROMPT_NONE, PR_FATAL },
9240
9241         /* Invalid HTREE root node */
9242         { PR_2_HTREE_BAD_ROOT,
9243           N_("@p @h %d: root node is @n\n"),
9244           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9245
9246         /* Invalid HTREE limit */
9247         { PR_2_HTREE_BAD_LIMIT,
9248           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9249           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9250
9251         /* Invalid HTREE count */
9252         { PR_2_HTREE_BAD_COUNT,
9253           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9254           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9255
9256         /* HTREE interior node has out-of-order hashes in table */
9257         { PR_2_HTREE_HASH_ORDER,
9258           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9259           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9260
9261         /* Node in HTREE directory has invalid depth */
9262         { PR_2_HTREE_BAD_DEPTH,
9263           N_("@p @h %d: node (%B) has @n depth\n"),
9264           PROMPT_NONE, 0 },
9265
9266         /* Duplicate directory entry found */
9267         { PR_2_DUPLICATE_DIRENT,
9268           N_("Duplicate @E found.  "),
9269           PROMPT_CLEAR, 0 },
9270
9271         /* Non-unique filename found */
9272         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9273           N_("@E has a non-unique filename.\nRename to %s"),
9274           PROMPT_NULL, 0 },
9275
9276         /* Duplicate directory entry found */
9277         { PR_2_REPORT_DUP_DIRENT,
9278           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9279           PROMPT_NONE, 0 },
9280
9281         /* Pass 3 errors */
9282
9283         /* Pass 3: Checking directory connectivity */
9284         { PR_3_PASS_HEADER,
9285           N_("Pass 3: Checking @d connectivity\n"),
9286           PROMPT_NONE, 0 },
9287
9288         /* Root inode not allocated */
9289         { PR_3_NO_ROOT_INODE,
9290           N_("@r not allocated.  "),
9291           PROMPT_ALLOCATE, 0 },
9292
9293         /* No room in lost+found */
9294         { PR_3_EXPAND_LF_DIR,
9295           N_("No room in @l @d.  "),
9296           PROMPT_EXPAND, 0 },
9297
9298         /* Unconnected directory inode */
9299         { PR_3_UNCONNECTED_DIR,
9300           N_("Unconnected @d @i %i (%p)\n"),
9301           PROMPT_CONNECT, 0 },
9302
9303         /* /lost+found not found */
9304         { PR_3_NO_LF_DIR,
9305           N_("/@l not found.  "),
9306           PROMPT_CREATE, PR_PREEN_OK },
9307
9308         /* .. entry is incorrect */
9309         { PR_3_BAD_DOT_DOT,
9310           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9311           PROMPT_FIX, 0 },
9312
9313         /* Bad or non-existent /lost+found.  Cannot reconnect */
9314         { PR_3_NO_LPF,
9315           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9316           PROMPT_NONE, 0 },
9317
9318         /* Could not expand /lost+found */
9319         { PR_3_CANT_EXPAND_LPF,
9320           N_("Could not expand /@l: %m\n"),
9321           PROMPT_NONE, 0 },
9322
9323         /* Could not reconnect inode */
9324         { PR_3_CANT_RECONNECT,
9325           N_("Could not reconnect %i: %m\n"),
9326           PROMPT_NONE, 0 },
9327
9328         /* Error while trying to find /lost+found */
9329         { PR_3_ERR_FIND_LPF,
9330           N_("Error while trying to find /@l: %m\n"),
9331           PROMPT_NONE, 0 },
9332
9333         /* Error in ext2fs_new_block while creating /lost+found */
9334         { PR_3_ERR_LPF_NEW_BLOCK,
9335           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9336           PROMPT_NONE, 0 },
9337
9338         /* Error in ext2fs_new_inode while creating /lost+found */
9339         { PR_3_ERR_LPF_NEW_INODE,
9340           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9341           PROMPT_NONE, 0 },
9342
9343         /* Error in ext2fs_new_dir_block while creating /lost+found */
9344         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9345           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9346           PROMPT_NONE, 0 },
9347
9348         /* Error while writing directory block for /lost+found */
9349         { PR_3_ERR_LPF_WRITE_BLOCK,
9350           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9351           PROMPT_NONE, 0 },
9352
9353         /* Error while adjusting inode count */
9354         { PR_3_ADJUST_INODE,
9355           N_("Error while adjusting @i count on @i %i\n"),
9356           PROMPT_NONE, 0 },
9357
9358         /* Couldn't fix parent directory -- error */
9359         { PR_3_FIX_PARENT_ERR,
9360           N_("Couldn't fix parent of @i %i: %m\n\n"),
9361           PROMPT_NONE, 0 },
9362
9363         /* Couldn't fix parent directory -- couldn't find it */
9364         { PR_3_FIX_PARENT_NOFIND,
9365           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9366           PROMPT_NONE, 0 },
9367
9368         /* Error allocating inode bitmap */
9369         { PR_3_ALLOCATE_IBITMAP_ERROR,
9370           N_("@A @i @B (%N): %m\n"),
9371           PROMPT_NONE, PR_FATAL },
9372
9373         /* Error creating root directory */
9374         { PR_3_CREATE_ROOT_ERROR,
9375           N_("Error creating root @d (%s): %m\n"),
9376           PROMPT_NONE, PR_FATAL },
9377
9378         /* Error creating lost and found directory */
9379         { PR_3_CREATE_LPF_ERROR,
9380           N_("Error creating /@l @d (%s): %m\n"),
9381           PROMPT_NONE, PR_FATAL },
9382
9383         /* Root inode is not directory; aborting */
9384         { PR_3_ROOT_NOT_DIR_ABORT,
9385           N_("@r is not a @d; aborting.\n"),
9386           PROMPT_NONE, PR_FATAL },
9387
9388         /* Cannot proceed without a root inode. */
9389         { PR_3_NO_ROOT_INODE_ABORT,
9390           N_("can't proceed without a @r.\n"),
9391           PROMPT_NONE, PR_FATAL },
9392
9393         /* Internal error: couldn't find dir_info */
9394         { PR_3_NO_DIRINFO,
9395           N_("Internal error: cannot find dir_info for %i.\n"),
9396           PROMPT_NONE, PR_FATAL },
9397
9398         /* Lost+found not a directory */
9399         { PR_3_LPF_NOTDIR,
9400           N_("/@l is not a @d (ino=%i)\n"),
9401           PROMPT_UNLINK, 0 },
9402
9403         /* Pass 3A Directory Optimization       */
9404
9405         /* Pass 3A: Optimizing directories */
9406         { PR_3A_PASS_HEADER,
9407           N_("Pass 3A: Optimizing directories\n"),
9408           PROMPT_NONE, PR_PREEN_NOMSG },
9409
9410         /* Error iterating over directories */
9411         { PR_3A_OPTIMIZE_ITER,
9412           N_("Failed to create dirs_to_hash iterator: %m"),
9413           PROMPT_NONE, 0 },
9414
9415         /* Error rehash directory */
9416         { PR_3A_OPTIMIZE_DIR_ERR,
9417           N_("Failed to optimize directory %q (%d): %m"),
9418           PROMPT_NONE, 0 },
9419
9420         /* Rehashing dir header */
9421         { PR_3A_OPTIMIZE_DIR_HEADER,
9422           N_("Optimizing directories: "),
9423           PROMPT_NONE, PR_MSG_ONLY },
9424
9425         /* Rehashing directory %d */
9426         { PR_3A_OPTIMIZE_DIR,
9427           " %d",
9428           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9429
9430         /* Rehashing dir end */
9431         { PR_3A_OPTIMIZE_DIR_END,
9432           "\n",
9433           PROMPT_NONE, PR_PREEN_NOHDR },
9434
9435         /* Pass 4 errors */
9436
9437         /* Pass 4: Checking reference counts */
9438         { PR_4_PASS_HEADER,
9439           N_("Pass 4: Checking reference counts\n"),
9440           PROMPT_NONE, 0 },
9441
9442         /* Unattached zero-length inode */
9443         { PR_4_ZERO_LEN_INODE,
9444           N_("@u @z @i %i.  "),
9445           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9446
9447         /* Unattached inode */
9448         { PR_4_UNATTACHED_INODE,
9449           N_("@u @i %i\n"),
9450           PROMPT_CONNECT, 0 },
9451
9452         /* Inode ref count wrong */
9453         { PR_4_BAD_REF_COUNT,
9454           N_("@i %i ref count is %Il, @s %N.  "),
9455           PROMPT_FIX, PR_PREEN_OK },
9456
9457         { PR_4_INCONSISTENT_COUNT,
9458           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9459           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9460           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9461           "They @s the same!\n"),
9462           PROMPT_NONE, 0 },
9463
9464         /* Pass 5 errors */
9465
9466         /* Pass 5: Checking group summary information */
9467         { PR_5_PASS_HEADER,
9468           N_("Pass 5: Checking @g summary information\n"),
9469           PROMPT_NONE, 0 },
9470
9471         /* Padding at end of inode bitmap is not set. */
9472         { PR_5_INODE_BMAP_PADDING,
9473           N_("Padding at end of @i @B is not set. "),
9474           PROMPT_FIX, PR_PREEN_OK },
9475
9476         /* Padding at end of block bitmap is not set. */
9477         { PR_5_BLOCK_BMAP_PADDING,
9478           N_("Padding at end of @b @B is not set. "),
9479           PROMPT_FIX, PR_PREEN_OK },
9480
9481         /* Block bitmap differences header */
9482         { PR_5_BLOCK_BITMAP_HEADER,
9483           N_("@b @B differences: "),
9484           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9485
9486         /* Block not used, but marked in bitmap */
9487         { PR_5_BLOCK_UNUSED,
9488           " -%b",
9489           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9490
9491         /* Block used, but not marked used in bitmap */
9492         { PR_5_BLOCK_USED,
9493           " +%b",
9494           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9495
9496         /* Block bitmap differences end */
9497         { PR_5_BLOCK_BITMAP_END,
9498           "\n",
9499           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9500
9501         /* Inode bitmap differences header */
9502         { PR_5_INODE_BITMAP_HEADER,
9503           N_("@i @B differences: "),
9504           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9505
9506         /* Inode not used, but marked in bitmap */
9507         { PR_5_INODE_UNUSED,
9508           " -%i",
9509           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9510
9511         /* Inode used, but not marked used in bitmap */
9512         { PR_5_INODE_USED,
9513           " +%i",
9514           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9515
9516         /* Inode bitmap differences end */
9517         { PR_5_INODE_BITMAP_END,
9518           "\n",
9519           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9520
9521         /* Free inodes count for group wrong */
9522         { PR_5_FREE_INODE_COUNT_GROUP,
9523           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9524           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9525
9526         /* Directories count for group wrong */
9527         { PR_5_FREE_DIR_COUNT_GROUP,
9528           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9529           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9530
9531         /* Free inodes count wrong */
9532         { PR_5_FREE_INODE_COUNT,
9533           N_("Free @is count wrong (%i, counted=%j).\n"),
9534           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9535
9536         /* Free blocks count for group wrong */
9537         { PR_5_FREE_BLOCK_COUNT_GROUP,
9538           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9539           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9540
9541         /* Free blocks count wrong */
9542         { PR_5_FREE_BLOCK_COUNT,
9543           N_("Free @bs count wrong (%b, counted=%c).\n"),
9544           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9545
9546         /* Programming error: bitmap endpoints don't match */
9547         { PR_5_BMAP_ENDPOINTS,
9548           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9549           "match calculated @B endpoints (%i, %j)\n"),
9550           PROMPT_NONE, PR_FATAL },
9551
9552         /* Internal error: fudging end of bitmap */
9553         { PR_5_FUDGE_BITMAP_ERROR,
9554           N_("Internal error: fudging end of bitmap (%N)\n"),
9555           PROMPT_NONE, PR_FATAL },
9556
9557         /* Error copying in replacement inode bitmap */
9558         { PR_5_COPY_IBITMAP_ERROR,
9559           N_("Error copying in replacement @i @B: %m\n"),
9560           PROMPT_NONE, PR_FATAL },
9561
9562         /* Error copying in replacement block bitmap */
9563         { PR_5_COPY_BBITMAP_ERROR,
9564           N_("Error copying in replacement @b @B: %m\n"),
9565           PROMPT_NONE, PR_FATAL },
9566
9567         /* Block range not used, but marked in bitmap */
9568         { PR_5_BLOCK_RANGE_UNUSED,
9569           " -(%b--%c)",
9570           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9571
9572         /* Block range used, but not marked used in bitmap */
9573         { PR_5_BLOCK_RANGE_USED,
9574           " +(%b--%c)",
9575           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9576
9577         /* Inode range not used, but marked in bitmap */
9578         { PR_5_INODE_RANGE_UNUSED,
9579           " -(%i--%j)",
9580           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9581
9582         /* Inode range used, but not marked used in bitmap */
9583         { PR_5_INODE_RANGE_USED,
9584           " +(%i--%j)",
9585           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9586
9587         { 0 }
9588 };
9589
9590 /*
9591  * This is the latch flags register.  It allows several problems to be
9592  * "latched" together.  This means that the user has to answer but one
9593  * question for the set of problems, and all of the associated
9594  * problems will be either fixed or not fixed.
9595  */
9596 static struct latch_descr pr_latch_info[] = {
9597         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9598         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9599         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9600         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9601         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9602         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9603         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9604         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9605         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9606         { -1, 0, 0 },
9607 };
9608
9609 static const struct e2fsck_problem *find_problem(problem_t code)
9610 {
9611         int     i;
9612
9613         for (i=0; problem_table[i].e2p_code; i++) {
9614                 if (problem_table[i].e2p_code == code)
9615                         return &problem_table[i];
9616         }
9617         return 0;
9618 }
9619
9620 static struct latch_descr *find_latch(int code)
9621 {
9622         int     i;
9623
9624         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9625                 if (pr_latch_info[i].latch_code == code)
9626                         return &pr_latch_info[i];
9627         }
9628         return 0;
9629 }
9630
9631 int end_problem_latch(e2fsck_t ctx, int mask)
9632 {
9633         struct latch_descr *ldesc;
9634         struct problem_context pctx;
9635         int answer = -1;
9636
9637         ldesc = find_latch(mask);
9638         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9639                 clear_problem_context(&pctx);
9640                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9641         }
9642         ldesc->flags &= ~(PRL_VARIABLE);
9643         return answer;
9644 }
9645
9646 int set_latch_flags(int mask, int setflags, int clearflags)
9647 {
9648         struct latch_descr *ldesc;
9649
9650         ldesc = find_latch(mask);
9651         if (!ldesc)
9652                 return -1;
9653         ldesc->flags |= setflags;
9654         ldesc->flags &= ~clearflags;
9655         return 0;
9656 }
9657
9658 void clear_problem_context(struct problem_context *ctx)
9659 {
9660         memset(ctx, 0, sizeof(struct problem_context));
9661         ctx->blkcount = -1;
9662         ctx->group = -1;
9663 }
9664
9665 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9666 {
9667         ext2_filsys fs = ctx->fs;
9668         const struct e2fsck_problem *ptr;
9669         struct latch_descr *ldesc = NULL;
9670         const char *message;
9671         int             def_yn, answer, ans;
9672         int             print_answer = 0;
9673         int             suppress = 0;
9674
9675         ptr = find_problem(code);
9676         if (!ptr) {
9677                 printf(_("Unhandled error code (0x%x)!\n"), code);
9678                 return 0;
9679         }
9680         def_yn = 1;
9681         if ((ptr->flags & PR_NO_DEFAULT) ||
9682             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9683             (ctx->options & E2F_OPT_NO))
9684                 def_yn= 0;
9685
9686         /*
9687          * Do special latch processing.  This is where we ask the
9688          * latch question, if it exists
9689          */
9690         if (ptr->flags & PR_LATCH_MASK) {
9691                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9692                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9693                         ans = fix_problem(ctx, ldesc->question, pctx);
9694                         if (ans == 1)
9695                                 ldesc->flags |= PRL_YES;
9696                         if (ans == 0)
9697                                 ldesc->flags |= PRL_NO;
9698                         ldesc->flags |= PRL_LATCHED;
9699                 }
9700                 if (ldesc->flags & PRL_SUPPRESS)
9701                         suppress++;
9702         }
9703         if ((ptr->flags & PR_PREEN_NOMSG) &&
9704             (ctx->options & E2F_OPT_PREEN))
9705                 suppress++;
9706         if ((ptr->flags & PR_NO_NOMSG) &&
9707             (ctx->options & E2F_OPT_NO))
9708                 suppress++;
9709         if (!suppress) {
9710                 message = ptr->e2p_description;
9711                 if ((ctx->options & E2F_OPT_PREEN) &&
9712                     !(ptr->flags & PR_PREEN_NOHDR)) {
9713                         printf("%s: ", ctx->device_name ?
9714                                ctx->device_name : ctx->filesystem_name);
9715                 }
9716                 if (*message)
9717                         print_e2fsck_message(ctx, _(message), pctx, 1);
9718         }
9719         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9720                 preenhalt(ctx);
9721
9722         if (ptr->flags & PR_FATAL)
9723                 bb_error_msg_and_die(0);
9724
9725         if (ptr->prompt == PROMPT_NONE) {
9726                 if (ptr->flags & PR_NOCOLLATE)
9727                         answer = -1;
9728                 else
9729                         answer = def_yn;
9730         } else {
9731                 if (ctx->options & E2F_OPT_PREEN) {
9732                         answer = def_yn;
9733                         if (!(ptr->flags & PR_PREEN_NOMSG))
9734                                 print_answer = 1;
9735                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9736                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9737                         if (!suppress)
9738                                 print_answer = 1;
9739                         if (ldesc->flags & PRL_YES)
9740                                 answer = 1;
9741                         else
9742                                 answer = 0;
9743                 } else
9744                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9745                 if (!answer && !(ptr->flags & PR_NO_OK))
9746                         ext2fs_unmark_valid(fs);
9747
9748                 if (print_answer)
9749                         printf("%s.\n", answer ?
9750                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9751
9752         }
9753
9754         if ((ptr->prompt == PROMPT_ABORT) && answer)
9755                 bb_error_msg_and_die(0);
9756
9757         if (ptr->flags & PR_AFTER_CODE)
9758                 answer = fix_problem(ctx, ptr->second_code, pctx);
9759
9760         return answer;
9761 }
9762
9763 /*
9764  * linux/fs/recovery.c
9765  *
9766  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9767  */
9768
9769 /*
9770  * Maintain information about the progress of the recovery job, so that
9771  * the different passes can carry information between them.
9772  */
9773 struct recovery_info
9774 {
9775         tid_t           start_transaction;
9776         tid_t           end_transaction;
9777
9778         int             nr_replays;
9779         int             nr_revokes;
9780         int             nr_revoke_hits;
9781 };
9782
9783 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9784 static int do_one_pass(journal_t *journal,
9785                                 struct recovery_info *info, enum passtype pass);
9786 static int scan_revoke_records(journal_t *, struct buffer_head *,
9787                                 tid_t, struct recovery_info *);
9788
9789 /*
9790  * Read a block from the journal
9791  */
9792
9793 static int jread(struct buffer_head **bhp, journal_t *journal,
9794                  unsigned int offset)
9795 {
9796         int err;
9797         unsigned long blocknr;
9798         struct buffer_head *bh;
9799
9800         *bhp = NULL;
9801
9802         err = journal_bmap(journal, offset, &blocknr);
9803
9804         if (err) {
9805                 printf("JBD: bad block at offset %u\n", offset);
9806                 return err;
9807         }
9808
9809         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9810         if (!bh)
9811                 return -ENOMEM;
9812
9813         if (!buffer_uptodate(bh)) {
9814                 /* If this is a brand new buffer, start readahead.
9815                    Otherwise, we assume we are already reading it.  */
9816                 if (!buffer_req(bh))
9817                         do_readahead(journal, offset);
9818                 wait_on_buffer(bh);
9819         }
9820
9821         if (!buffer_uptodate(bh)) {
9822                 printf("JBD: Failed to read block at offset %u\n", offset);
9823                 brelse(bh);
9824                 return -EIO;
9825         }
9826
9827         *bhp = bh;
9828         return 0;
9829 }
9830
9831
9832 /*
9833  * Count the number of in-use tags in a journal descriptor block.
9834  */
9835
9836 static int count_tags(struct buffer_head *bh, int size)
9837 {
9838         char *                  tagp;
9839         journal_block_tag_t *   tag;
9840         int                     nr = 0;
9841
9842         tagp = &bh->b_data[sizeof(journal_header_t)];
9843
9844         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9845                 tag = (journal_block_tag_t *) tagp;
9846
9847                 nr++;
9848                 tagp += sizeof(journal_block_tag_t);
9849                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9850                         tagp += 16;
9851
9852                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9853                         break;
9854         }
9855
9856         return nr;
9857 }
9858
9859
9860 /* Make sure we wrap around the log correctly! */
9861 #define wrap(journal, var)                                            \
9862 do {                                                                \
9863         if (var >= (journal)->j_last)                                   \
9864                 var -= ((journal)->j_last - (journal)->j_first);        \
9865 } while (0)
9866
9867 /**
9868  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9869  * @journal: the journal to recover
9870  *
9871  * The primary function for recovering the log contents when mounting a
9872  * journaled device.
9873  *
9874  * Recovery is done in three passes.  In the first pass, we look for the
9875  * end of the log.  In the second, we assemble the list of revoke
9876  * blocks.  In the third and final pass, we replay any un-revoked blocks
9877  * in the log.
9878  */
9879 int journal_recover(journal_t *journal)
9880 {
9881         int                     err;
9882         journal_superblock_t *  sb;
9883
9884         struct recovery_info    info;
9885
9886         memset(&info, 0, sizeof(info));
9887         sb = journal->j_superblock;
9888
9889         /*
9890          * The journal superblock's s_start field (the current log head)
9891          * is always zero if, and only if, the journal was cleanly
9892          * unmounted.
9893          */
9894
9895         if (!sb->s_start) {
9896                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9897                 return 0;
9898         }
9899
9900         err = do_one_pass(journal, &info, PASS_SCAN);
9901         if (!err)
9902                 err = do_one_pass(journal, &info, PASS_REVOKE);
9903         if (!err)
9904                 err = do_one_pass(journal, &info, PASS_REPLAY);
9905
9906         /* Restart the log at the next transaction ID, thus invalidating
9907          * any existing commit records in the log. */
9908         journal->j_transaction_sequence = ++info.end_transaction;
9909
9910         journal_clear_revoke(journal);
9911         sync_blockdev(journal->j_fs_dev);
9912         return err;
9913 }
9914
9915 static int do_one_pass(journal_t *journal,
9916                         struct recovery_info *info, enum passtype pass)
9917 {
9918         unsigned int            first_commit_ID, next_commit_ID;
9919         unsigned long           next_log_block;
9920         int                     err, success = 0;
9921         journal_superblock_t *  sb;
9922         journal_header_t *      tmp;
9923         struct buffer_head *    bh;
9924         unsigned int            sequence;
9925         int                     blocktype;
9926
9927         /* Precompute the maximum metadata descriptors in a descriptor block */
9928         int                     MAX_BLOCKS_PER_DESC;
9929         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9930                                / sizeof(journal_block_tag_t));
9931
9932         /*
9933          * First thing is to establish what we expect to find in the log
9934          * (in terms of transaction IDs), and where (in terms of log
9935          * block offsets): query the superblock.
9936          */
9937
9938         sb = journal->j_superblock;
9939         next_commit_ID = ntohl(sb->s_sequence);
9940         next_log_block = ntohl(sb->s_start);
9941
9942         first_commit_ID = next_commit_ID;
9943         if (pass == PASS_SCAN)
9944                 info->start_transaction = first_commit_ID;
9945
9946         /*
9947          * Now we walk through the log, transaction by transaction,
9948          * making sure that each transaction has a commit block in the
9949          * expected place.  Each complete transaction gets replayed back
9950          * into the main filesystem.
9951          */
9952
9953         while (1) {
9954                 int                     flags;
9955                 char *                  tagp;
9956                 journal_block_tag_t *   tag;
9957                 struct buffer_head *    obh;
9958                 struct buffer_head *    nbh;
9959
9960                 /* If we already know where to stop the log traversal,
9961                  * check right now that we haven't gone past the end of
9962                  * the log. */
9963
9964                 if (pass != PASS_SCAN)
9965                         if (tid_geq(next_commit_ID, info->end_transaction))
9966                                 break;
9967
9968                 /* Skip over each chunk of the transaction looking
9969                  * either the next descriptor block or the final commit
9970                  * record. */
9971
9972                 err = jread(&bh, journal, next_log_block);
9973                 if (err)
9974                         goto failed;
9975
9976                 next_log_block++;
9977                 wrap(journal, next_log_block);
9978
9979                 /* What kind of buffer is it?
9980                  *
9981                  * If it is a descriptor block, check that it has the
9982                  * expected sequence number.  Otherwise, we're all done
9983                  * here. */
9984
9985                 tmp = (journal_header_t *)bh->b_data;
9986
9987                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9988                         brelse(bh);
9989                         break;
9990                 }
9991
9992                 blocktype = ntohl(tmp->h_blocktype);
9993                 sequence = ntohl(tmp->h_sequence);
9994
9995                 if (sequence != next_commit_ID) {
9996                         brelse(bh);
9997                         break;
9998                 }
9999
10000                 /* OK, we have a valid descriptor block which matches
10001                  * all of the sequence number checks.  What are we going
10002                  * to do with it?  That depends on the pass... */
10003
10004                 switch (blocktype) {
10005                 case JFS_DESCRIPTOR_BLOCK:
10006                         /* If it is a valid descriptor block, replay it
10007                          * in pass REPLAY; otherwise, just skip over the
10008                          * blocks it describes. */
10009                         if (pass != PASS_REPLAY) {
10010                                 next_log_block +=
10011                                         count_tags(bh, journal->j_blocksize);
10012                                 wrap(journal, next_log_block);
10013                                 brelse(bh);
10014                                 continue;
10015                         }
10016
10017                         /* A descriptor block: we can now write all of
10018                          * the data blocks.  Yay, useful work is finally
10019                          * getting done here! */
10020
10021                         tagp = &bh->b_data[sizeof(journal_header_t)];
10022                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10023                                <= journal->j_blocksize) {
10024                                 unsigned long io_block;
10025
10026                                 tag = (journal_block_tag_t *) tagp;
10027                                 flags = ntohl(tag->t_flags);
10028
10029                                 io_block = next_log_block++;
10030                                 wrap(journal, next_log_block);
10031                                 err = jread(&obh, journal, io_block);
10032                                 if (err) {
10033                                         /* Recover what we can, but
10034                                          * report failure at the end. */
10035                                         success = err;
10036                                         printf("JBD: IO error %d recovering "
10037                                                 "block %ld in log\n",
10038                                                 err, io_block);
10039                                 } else {
10040                                         unsigned long blocknr;
10041
10042                                         blocknr = ntohl(tag->t_blocknr);
10043
10044                                         /* If the block has been
10045                                          * revoked, then we're all done
10046                                          * here. */
10047                                         if (journal_test_revoke
10048                                             (journal, blocknr,
10049                                              next_commit_ID)) {
10050                                                 brelse(obh);
10051                                                 ++info->nr_revoke_hits;
10052                                                 goto skip_write;
10053                                         }
10054
10055                                         /* Find a buffer for the new
10056                                          * data being restored */
10057                                         nbh = getblk(journal->j_fs_dev,
10058                                                        blocknr,
10059                                                      journal->j_blocksize);
10060                                         if (nbh == NULL) {
10061                                                 printf("JBD: Out of memory "
10062                                                        "during recovery.\n");
10063                                                 err = -ENOMEM;
10064                                                 brelse(bh);
10065                                                 brelse(obh);
10066                                                 goto failed;
10067                                         }
10068
10069                                         lock_buffer(nbh);
10070                                         memcpy(nbh->b_data, obh->b_data,
10071                                                         journal->j_blocksize);
10072                                         if (flags & JFS_FLAG_ESCAPE) {
10073                                                 *((unsigned int *)bh->b_data) =
10074                                                         htonl(JFS_MAGIC_NUMBER);
10075                                         }
10076
10077                                         mark_buffer_uptodate(nbh, 1);
10078                                         mark_buffer_dirty(nbh);
10079                                         ++info->nr_replays;
10080                                         /* ll_rw_block(WRITE, 1, &nbh); */
10081                                         unlock_buffer(nbh);
10082                                         brelse(obh);
10083                                         brelse(nbh);
10084                                 }
10085
10086                         skip_write:
10087                                 tagp += sizeof(journal_block_tag_t);
10088                                 if (!(flags & JFS_FLAG_SAME_UUID))
10089                                         tagp += 16;
10090
10091                                 if (flags & JFS_FLAG_LAST_TAG)
10092                                         break;
10093                         }
10094
10095                         brelse(bh);
10096                         continue;
10097
10098                 case JFS_COMMIT_BLOCK:
10099                         /* Found an expected commit block: not much to
10100                          * do other than move on to the next sequence
10101                          * number. */
10102                         brelse(bh);
10103                         next_commit_ID++;
10104                         continue;
10105
10106                 case JFS_REVOKE_BLOCK:
10107                         /* If we aren't in the REVOKE pass, then we can
10108                          * just skip over this block. */
10109                         if (pass != PASS_REVOKE) {
10110                                 brelse(bh);
10111                                 continue;
10112                         }
10113
10114                         err = scan_revoke_records(journal, bh,
10115                                                   next_commit_ID, info);
10116                         brelse(bh);
10117                         if (err)
10118                                 goto failed;
10119                         continue;
10120
10121                 default:
10122                         goto done;
10123                 }
10124         }
10125
10126  done:
10127         /*
10128          * We broke out of the log scan loop: either we came to the
10129          * known end of the log or we found an unexpected block in the
10130          * log.  If the latter happened, then we know that the "current"
10131          * transaction marks the end of the valid log.
10132          */
10133
10134         if (pass == PASS_SCAN)
10135                 info->end_transaction = next_commit_ID;
10136         else {
10137                 /* It's really bad news if different passes end up at
10138                  * different places (but possible due to IO errors). */
10139                 if (info->end_transaction != next_commit_ID) {
10140                         printf("JBD: recovery pass %d ended at "
10141                                 "transaction %u, expected %u\n",
10142                                 pass, next_commit_ID, info->end_transaction);
10143                         if (!success)
10144                                 success = -EIO;
10145                 }
10146         }
10147
10148         return success;
10149
10150  failed:
10151         return err;
10152 }
10153
10154
10155 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10156
10157 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10158                                tid_t sequence, struct recovery_info *info)
10159 {
10160         journal_revoke_header_t *header;
10161         int offset, max;
10162
10163         header = (journal_revoke_header_t *) bh->b_data;
10164         offset = sizeof(journal_revoke_header_t);
10165         max = ntohl(header->r_count);
10166
10167         while (offset < max) {
10168                 unsigned long blocknr;
10169                 int err;
10170
10171                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10172                 offset += 4;
10173                 err = journal_set_revoke(journal, blocknr, sequence);
10174                 if (err)
10175                         return err;
10176                 ++info->nr_revokes;
10177         }
10178         return 0;
10179 }
10180
10181
10182 /*
10183  * rehash.c --- rebuild hash tree directories
10184  *
10185  * This algorithm is designed for simplicity of implementation and to
10186  * pack the directory as much as possible.  It however requires twice
10187  * as much memory as the size of the directory.  The maximum size
10188  * directory supported using a 4k blocksize is roughly a gigabyte, and
10189  * so there may very well be problems with machines that don't have
10190  * virtual memory, and obscenely large directories.
10191  *
10192  * An alternate algorithm which is much more disk intensive could be
10193  * written, and probably will need to be written in the future.  The
10194  * design goals of such an algorithm are: (a) use (roughly) constant
10195  * amounts of memory, no matter how large the directory, (b) the
10196  * directory must be safe at all times, even if e2fsck is interrupted
10197  * in the middle, (c) we must use minimal amounts of extra disk
10198  * blocks.  This pretty much requires an incremental approach, where
10199  * we are reading from one part of the directory, and inserting into
10200  * the front half.  So the algorithm will have to keep track of a
10201  * moving block boundary between the new tree and the old tree, and
10202  * files will need to be moved from the old directory and inserted
10203  * into the new tree.  If the new directory requires space which isn't
10204  * yet available, blocks from the beginning part of the old directory
10205  * may need to be moved to the end of the directory to make room for
10206  * the new tree:
10207  *
10208  *    --------------------------------------------------------
10209  *    |  new tree   |        | old tree                      |
10210  *    --------------------------------------------------------
10211  *                  ^ ptr    ^ptr
10212  *                tail new   head old
10213  *
10214  * This is going to be a pain in the tuckus to implement, and will
10215  * require a lot more disk accesses.  So I'm going to skip it for now;
10216  * it's only really going to be an issue for really, really big
10217  * filesystems (when we reach the level of tens of millions of files
10218  * in a single directory).  It will probably be easier to simply
10219  * require that e2fsck use VM first.
10220  */
10221
10222 struct fill_dir_struct {
10223         char *buf;
10224         struct ext2_inode *inode;
10225         int err;
10226         e2fsck_t ctx;
10227         struct hash_entry *harray;
10228         int max_array, num_array;
10229         int dir_size;
10230         int compress;
10231         ino_t parent;
10232 };
10233
10234 struct hash_entry {
10235         ext2_dirhash_t  hash;
10236         ext2_dirhash_t  minor_hash;
10237         struct ext2_dir_entry   *dir;
10238 };
10239
10240 struct out_dir {
10241         int             num;
10242         int             max;
10243         char            *buf;
10244         ext2_dirhash_t  *hashes;
10245 };
10246
10247 static int fill_dir_block(ext2_filsys fs,
10248                           blk_t *block_nr,
10249                           e2_blkcnt_t blockcnt,
10250                           blk_t ref_block FSCK_ATTR((unused)),
10251                           int ref_offset FSCK_ATTR((unused)),
10252                           void *priv_data)
10253 {
10254         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10255         struct hash_entry       *new_array, *ent;
10256         struct ext2_dir_entry   *dirent;
10257         char                    *dir;
10258         unsigned int            offset, dir_offset;
10259
10260         if (blockcnt < 0)
10261                 return 0;
10262
10263         offset = blockcnt * fs->blocksize;
10264         if (offset + fs->blocksize > fd->inode->i_size) {
10265                 fd->err = EXT2_ET_DIR_CORRUPTED;
10266                 return BLOCK_ABORT;
10267         }
10268         dir = (fd->buf+offset);
10269         if (HOLE_BLKADDR(*block_nr)) {
10270                 memset(dir, 0, fs->blocksize);
10271                 dirent = (struct ext2_dir_entry *) dir;
10272                 dirent->rec_len = fs->blocksize;
10273         } else {
10274                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10275                 if (fd->err)
10276                         return BLOCK_ABORT;
10277         }
10278         /* While the directory block is "hot", index it. */
10279         dir_offset = 0;
10280         while (dir_offset < fs->blocksize) {
10281                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10282                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10283                     (dirent->rec_len < 8) ||
10284                     ((dirent->rec_len % 4) != 0) ||
10285                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10286                         fd->err = EXT2_ET_DIR_CORRUPTED;
10287                         return BLOCK_ABORT;
10288                 }
10289                 dir_offset += dirent->rec_len;
10290                 if (dirent->inode == 0)
10291                         continue;
10292                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10293                     (dirent->name[0] == '.'))
10294                         continue;
10295                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10296                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10297                         fd->parent = dirent->inode;
10298                         continue;
10299                 }
10300                 if (fd->num_array >= fd->max_array) {
10301                         new_array = xrealloc(fd->harray,
10302                             sizeof(struct hash_entry) * (fd->max_array+500));
10303                         fd->harray = new_array;
10304                         fd->max_array += 500;
10305                 }
10306                 ent = fd->harray + fd->num_array++;
10307                 ent->dir = dirent;
10308                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10309                 if (fd->compress)
10310                         ent->hash = ent->minor_hash = 0;
10311                 else {
10312                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10313                                                  dirent->name,
10314                                                  dirent->name_len & 0xFF,
10315                                                  fs->super->s_hash_seed,
10316                                                  &ent->hash, &ent->minor_hash);
10317                         if (fd->err)
10318                                 return BLOCK_ABORT;
10319                 }
10320         }
10321
10322         return 0;
10323 }
10324
10325 /* Used for sorting the hash entry */
10326 static int name_cmp(const void *a, const void *b)
10327 {
10328         const struct hash_entry *he_a = (const struct hash_entry *) a;
10329         const struct hash_entry *he_b = (const struct hash_entry *) b;
10330         int     ret;
10331         int     min_len;
10332
10333         min_len = he_a->dir->name_len;
10334         if (min_len > he_b->dir->name_len)
10335                 min_len = he_b->dir->name_len;
10336
10337         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10338         if (ret == 0) {
10339                 if (he_a->dir->name_len > he_b->dir->name_len)
10340                         ret = 1;
10341                 else if (he_a->dir->name_len < he_b->dir->name_len)
10342                         ret = -1;
10343                 else
10344                         ret = he_b->dir->inode - he_a->dir->inode;
10345         }
10346         return ret;
10347 }
10348
10349 /* Used for sorting the hash entry */
10350 static int hash_cmp(const void *a, const void *b)
10351 {
10352         const struct hash_entry *he_a = (const struct hash_entry *) a;
10353         const struct hash_entry *he_b = (const struct hash_entry *) b;
10354         int     ret;
10355
10356         if (he_a->hash > he_b->hash)
10357                 ret = 1;
10358         else if (he_a->hash < he_b->hash)
10359                 ret = -1;
10360         else {
10361                 if (he_a->minor_hash > he_b->minor_hash)
10362                         ret = 1;
10363                 else if (he_a->minor_hash < he_b->minor_hash)
10364                         ret = -1;
10365                 else
10366                         ret = name_cmp(a, b);
10367         }
10368         return ret;
10369 }
10370
10371 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10372                                 int blocks)
10373 {
10374         void                    *new_mem;
10375
10376         if (outdir->max) {
10377                 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10378                 outdir->buf = new_mem;
10379                 new_mem = xrealloc(outdir->hashes,
10380                                   blocks * sizeof(ext2_dirhash_t));
10381                 outdir->hashes = new_mem;
10382         } else {
10383                 outdir->buf = xmalloc(blocks * fs->blocksize);
10384                 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10385                 outdir->num = 0;
10386         }
10387         outdir->max = blocks;
10388         return 0;
10389 }
10390
10391 static void free_out_dir(struct out_dir *outdir)
10392 {
10393         free(outdir->buf);
10394         free(outdir->hashes);
10395         outdir->max = 0;
10396         outdir->num =0;
10397 }
10398
10399 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10400                          char ** ret)
10401 {
10402         errcode_t       retval;
10403
10404         if (outdir->num >= outdir->max) {
10405                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10406                 if (retval)
10407                         return retval;
10408         }
10409         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10410         memset(*ret, 0, fs->blocksize);
10411         return 0;
10412 }
10413
10414 /*
10415  * This function is used to make a unique filename.  We do this by
10416  * appending ~0, and then incrementing the number.  However, we cannot
10417  * expand the length of the filename beyond the padding available in
10418  * the directory entry.
10419  */
10420 static void mutate_name(char *str, __u16 *len)
10421 {
10422         int     i;
10423         __u16   l = *len & 0xFF, h = *len & 0xff00;
10424
10425         /*
10426          * First check to see if it looks the name has been mutated
10427          * already
10428          */
10429         for (i = l-1; i > 0; i--) {
10430                 if (!isdigit(str[i]))
10431                         break;
10432         }
10433         if ((i == l-1) || (str[i] != '~')) {
10434                 if (((l-1) & 3) < 2)
10435                         l += 2;
10436                 else
10437                         l = (l+3) & ~3;
10438                 str[l-2] = '~';
10439                 str[l-1] = '0';
10440                 *len = l | h;
10441                 return;
10442         }
10443         for (i = l-1; i >= 0; i--) {
10444                 if (isdigit(str[i])) {
10445                         if (str[i] == '9')
10446                                 str[i] = '0';
10447                         else {
10448                                 str[i]++;
10449                                 return;
10450                         }
10451                         continue;
10452                 }
10453                 if (i == 1) {
10454                         if (str[0] == 'z')
10455                                 str[0] = 'A';
10456                         else if (str[0] == 'Z') {
10457                                 str[0] = '~';
10458                                 str[1] = '0';
10459                         } else
10460                                 str[0]++;
10461                 } else if (i > 0) {
10462                         str[i] = '1';
10463                         str[i-1] = '~';
10464                 } else {
10465                         if (str[0] == '~')
10466                                 str[0] = 'a';
10467                         else
10468                                 str[0]++;
10469                 }
10470                 break;
10471         }
10472 }
10473
10474 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10475                                     ext2_ino_t ino,
10476                                     struct fill_dir_struct *fd)
10477 {
10478         struct problem_context  pctx;
10479         struct hash_entry       *ent, *prev;
10480         int                     i, j;
10481         int                     fixed = 0;
10482         char                    new_name[256];
10483         __u16                   new_len;
10484
10485         clear_problem_context(&pctx);
10486         pctx.ino = ino;
10487
10488         for (i=1; i < fd->num_array; i++) {
10489                 ent = fd->harray + i;
10490                 prev = ent - 1;
10491                 if (!ent->dir->inode ||
10492                     ((ent->dir->name_len & 0xFF) !=
10493                      (prev->dir->name_len & 0xFF)) ||
10494                     (strncmp(ent->dir->name, prev->dir->name,
10495                              ent->dir->name_len & 0xFF)))
10496                         continue;
10497                 pctx.dirent = ent->dir;
10498                 if ((ent->dir->inode == prev->dir->inode) &&
10499                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10500                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10501                         ent->dir->inode = 0;
10502                         fixed++;
10503                         continue;
10504                 }
10505                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10506                 new_len = ent->dir->name_len;
10507                 mutate_name(new_name, &new_len);
10508                 for (j=0; j < fd->num_array; j++) {
10509                         if ((i==j) ||
10510                             ((ent->dir->name_len & 0xFF) !=
10511                              (fd->harray[j].dir->name_len & 0xFF)) ||
10512                             (strncmp(new_name, fd->harray[j].dir->name,
10513                                      new_len & 0xFF)))
10514                                 continue;
10515                         mutate_name(new_name, &new_len);
10516
10517                         j = -1;
10518                 }
10519                 new_name[new_len & 0xFF] = 0;
10520                 pctx.str = new_name;
10521                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10522                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10523                         ent->dir->name_len = new_len;
10524                         ext2fs_dirhash(fs->super->s_def_hash_version,
10525                                        ent->dir->name,
10526                                        ent->dir->name_len & 0xFF,
10527                                        fs->super->s_hash_seed,
10528                                        &ent->hash, &ent->minor_hash);
10529                         fixed++;
10530                 }
10531         }
10532         return fixed;
10533 }
10534
10535
10536 static errcode_t copy_dir_entries(ext2_filsys fs,
10537                                   struct fill_dir_struct *fd,
10538                                   struct out_dir *outdir)
10539 {
10540         errcode_t               retval;
10541         char                    *block_start;
10542         struct hash_entry       *ent;
10543         struct ext2_dir_entry   *dirent;
10544         int                     i, rec_len, left;
10545         ext2_dirhash_t          prev_hash;
10546         int                     offset;
10547
10548         outdir->max = 0;
10549         retval = alloc_size_dir(fs, outdir,
10550                                 (fd->dir_size / fs->blocksize) + 2);
10551         if (retval)
10552                 return retval;
10553         outdir->num = fd->compress ? 0 : 1;
10554         offset = 0;
10555         outdir->hashes[0] = 0;
10556         prev_hash = 1;
10557         if ((retval = get_next_block(fs, outdir, &block_start)))
10558                 return retval;
10559         dirent = (struct ext2_dir_entry *) block_start;
10560         left = fs->blocksize;
10561         for (i=0; i < fd->num_array; i++) {
10562                 ent = fd->harray + i;
10563                 if (ent->dir->inode == 0)
10564                         continue;
10565                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10566                 if (rec_len > left) {
10567                         if (left)
10568                                 dirent->rec_len += left;
10569                         if ((retval = get_next_block(fs, outdir,
10570                                                       &block_start)))
10571                                 return retval;
10572                         offset = 0;
10573                 }
10574                 left = fs->blocksize - offset;
10575                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10576                 if (offset == 0) {
10577                         if (ent->hash == prev_hash)
10578                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10579                         else
10580                                 outdir->hashes[outdir->num-1] = ent->hash;
10581                 }
10582                 dirent->inode = ent->dir->inode;
10583                 dirent->name_len = ent->dir->name_len;
10584                 dirent->rec_len = rec_len;
10585                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10586                 offset += rec_len;
10587                 left -= rec_len;
10588                 if (left < 12) {
10589                         dirent->rec_len += left;
10590                         offset += left;
10591                         left = 0;
10592                 }
10593                 prev_hash = ent->hash;
10594         }
10595         if (left)
10596                 dirent->rec_len += left;
10597
10598         return 0;
10599 }
10600
10601
10602 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10603                                     ext2_ino_t ino, ext2_ino_t parent)
10604 {
10605         struct ext2_dir_entry           *dir;
10606         struct ext2_dx_root_info        *root;
10607         struct ext2_dx_countlimit       *limits;
10608         int                             filetype = 0;
10609
10610         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10611                 filetype = EXT2_FT_DIR << 8;
10612
10613         memset(buf, 0, fs->blocksize);
10614         dir = (struct ext2_dir_entry *) buf;
10615         dir->inode = ino;
10616         dir->name[0] = '.';
10617         dir->name_len = 1 | filetype;
10618         dir->rec_len = 12;
10619         dir = (struct ext2_dir_entry *) (buf + 12);
10620         dir->inode = parent;
10621         dir->name[0] = '.';
10622         dir->name[1] = '.';
10623         dir->name_len = 2 | filetype;
10624         dir->rec_len = fs->blocksize - 12;
10625
10626         root = (struct ext2_dx_root_info *) (buf+24);
10627         root->reserved_zero = 0;
10628         root->hash_version = fs->super->s_def_hash_version;
10629         root->info_length = 8;
10630         root->indirect_levels = 0;
10631         root->unused_flags = 0;
10632
10633         limits = (struct ext2_dx_countlimit *) (buf+32);
10634         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10635         limits->count = 0;
10636
10637         return root;
10638 }
10639
10640
10641 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10642 {
10643         struct ext2_dir_entry           *dir;
10644         struct ext2_dx_countlimit       *limits;
10645
10646         memset(buf, 0, fs->blocksize);
10647         dir = (struct ext2_dir_entry *) buf;
10648         dir->inode = 0;
10649         dir->rec_len = fs->blocksize;
10650
10651         limits = (struct ext2_dx_countlimit *) (buf+8);
10652         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10653         limits->count = 0;
10654
10655         return (struct ext2_dx_entry *) limits;
10656 }
10657
10658 /*
10659  * This function takes the leaf nodes which have been written in
10660  * outdir, and populates the root node and any necessary interior nodes.
10661  */
10662 static errcode_t calculate_tree(ext2_filsys fs,
10663                                 struct out_dir *outdir,
10664                                 ext2_ino_t ino,
10665                                 ext2_ino_t parent)
10666 {
10667         struct ext2_dx_root_info        *root_info;
10668         struct ext2_dx_entry            *root, *dx_ent = NULL;
10669         struct ext2_dx_countlimit       *root_limit, *limit;
10670         errcode_t                       retval;
10671         char                            * block_start;
10672         int                             i, c1, c2, nblks;
10673         int                             limit_offset, root_offset;
10674
10675         root_info = set_root_node(fs, outdir->buf, ino, parent);
10676         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10677                 root_info->info_length;
10678         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10679         c1 = root_limit->limit;
10680         nblks = outdir->num;
10681
10682         /* Write out the pointer blocks */
10683         if (nblks-1 <= c1) {
10684                 /* Just write out the root block, and we're done */
10685                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10686                 for (i=1; i < nblks; i++) {
10687                         root->block = ext2fs_cpu_to_le32(i);
10688                         if (i != 1)
10689                                 root->hash =
10690                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10691                         root++;
10692                         c1--;
10693                 }
10694         } else {
10695                 c2 = 0;
10696                 limit = 0;
10697                 root_info->indirect_levels = 1;
10698                 for (i=1; i < nblks; i++) {
10699                         if (c1 == 0)
10700                                 return ENOSPC;
10701                         if (c2 == 0) {
10702                                 if (limit)
10703                                         limit->limit = limit->count =
10704                 ext2fs_cpu_to_le16(limit->limit);
10705                                 root = (struct ext2_dx_entry *)
10706                                         (outdir->buf + root_offset);
10707                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10708                                 if (i != 1)
10709                                         root->hash =
10710                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10711                                 if ((retval =  get_next_block(fs, outdir,
10712                                                               &block_start)))
10713                                         return retval;
10714                                 dx_ent = set_int_node(fs, block_start);
10715                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10716                                 c2 = limit->limit;
10717                                 root_offset += sizeof(struct ext2_dx_entry);
10718                                 c1--;
10719                         }
10720                         dx_ent->block = ext2fs_cpu_to_le32(i);
10721                         if (c2 != limit->limit)
10722                                 dx_ent->hash =
10723                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10724                         dx_ent++;
10725                         c2--;
10726                 }
10727                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10728                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10729         }
10730         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10731         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10732         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10733
10734         return 0;
10735 }
10736
10737 struct write_dir_struct {
10738         struct out_dir *outdir;
10739         errcode_t       err;
10740         e2fsck_t        ctx;
10741         int             cleared;
10742 };
10743
10744 /*
10745  * Helper function which writes out a directory block.
10746  */
10747 static int write_dir_block(ext2_filsys fs,
10748                            blk_t        *block_nr,
10749                            e2_blkcnt_t blockcnt,
10750                            blk_t ref_block FSCK_ATTR((unused)),
10751                            int ref_offset FSCK_ATTR((unused)),
10752                            void *priv_data)
10753 {
10754         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10755         blk_t   blk;
10756         char    *dir;
10757
10758         if (*block_nr == 0)
10759                 return 0;
10760         if (blockcnt >= wd->outdir->num) {
10761                 e2fsck_read_bitmaps(wd->ctx);
10762                 blk = *block_nr;
10763                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10764                 ext2fs_block_alloc_stats(fs, blk, -1);
10765                 *block_nr = 0;
10766                 wd->cleared++;
10767                 return BLOCK_CHANGED;
10768         }
10769         if (blockcnt < 0)
10770                 return 0;
10771
10772         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10773         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10774         if (wd->err)
10775                 return BLOCK_ABORT;
10776         return 0;
10777 }
10778
10779 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10780                                  struct out_dir *outdir,
10781                                  ext2_ino_t ino, int compress)
10782 {
10783         struct write_dir_struct wd;
10784         errcode_t       retval;
10785         struct ext2_inode       inode;
10786
10787         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10788         if (retval)
10789                 return retval;
10790
10791         wd.outdir = outdir;
10792         wd.err = 0;
10793         wd.ctx = ctx;
10794         wd.cleared = 0;
10795
10796         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10797                                        write_dir_block, &wd);
10798         if (retval)
10799                 return retval;
10800         if (wd.err)
10801                 return wd.err;
10802
10803         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10804         if (compress)
10805                 inode.i_flags &= ~EXT2_INDEX_FL;
10806         else
10807                 inode.i_flags |= EXT2_INDEX_FL;
10808         inode.i_size = outdir->num * fs->blocksize;
10809         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10810         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10811
10812         return 0;
10813 }
10814
10815 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10816 {
10817         ext2_filsys             fs = ctx->fs;
10818         errcode_t               retval;
10819         struct ext2_inode       inode;
10820         char                    *dir_buf = NULL;
10821         struct fill_dir_struct  fd;
10822         struct out_dir          outdir;
10823
10824         outdir.max = outdir.num = 0;
10825         outdir.buf = 0;
10826         outdir.hashes = 0;
10827         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10828
10829         retval = ENOMEM;
10830         fd.harray = 0;
10831         dir_buf = xmalloc(inode.i_size);
10832
10833         fd.max_array = inode.i_size / 32;
10834         fd.num_array = 0;
10835         fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10836
10837         fd.ctx = ctx;
10838         fd.buf = dir_buf;
10839         fd.inode = &inode;
10840         fd.err = 0;
10841         fd.dir_size = 0;
10842         fd.compress = 0;
10843         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10844             (inode.i_size / fs->blocksize) < 2)
10845                 fd.compress = 1;
10846         fd.parent = 0;
10847
10848         /* Read in the entire directory into memory */
10849         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10850                                        fill_dir_block, &fd);
10851         if (fd.err) {
10852                 retval = fd.err;
10853                 goto errout;
10854         }
10855
10856         /* Sort the list */
10857 resort:
10858         if (fd.compress)
10859                 qsort(fd.harray+2, fd.num_array-2,
10860                       sizeof(struct hash_entry), name_cmp);
10861         else
10862                 qsort(fd.harray, fd.num_array,
10863                       sizeof(struct hash_entry), hash_cmp);
10864
10865         /*
10866          * Look for duplicates
10867          */
10868         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10869                 goto resort;
10870
10871         if (ctx->options & E2F_OPT_NO) {
10872                 retval = 0;
10873                 goto errout;
10874         }
10875
10876         /*
10877          * Copy the directory entries.  In a htree directory these
10878          * will become the leaf nodes.
10879          */
10880         retval = copy_dir_entries(fs, &fd, &outdir);
10881         if (retval)
10882                 goto errout;
10883
10884         free(dir_buf); dir_buf = 0;
10885
10886         if (!fd.compress) {
10887                 /* Calculate the interior nodes */
10888                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10889                 if (retval)
10890                         goto errout;
10891         }
10892
10893         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10894
10895 errout:
10896         free(dir_buf);
10897         free(fd.harray);
10898
10899         free_out_dir(&outdir);
10900         return retval;
10901 }
10902
10903 void e2fsck_rehash_directories(e2fsck_t ctx)
10904 {
10905         struct problem_context  pctx;
10906         struct dir_info         *dir;
10907         ext2_u32_iterate        iter;
10908         ext2_ino_t              ino;
10909         errcode_t               retval;
10910         int                     i, cur, max, all_dirs, dir_index, first = 1;
10911
10912         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10913
10914         if (!ctx->dirs_to_hash && !all_dirs)
10915                 return;
10916
10917         e2fsck_get_lost_and_found(ctx, 0);
10918
10919         clear_problem_context(&pctx);
10920
10921         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10922         cur = 0;
10923         if (all_dirs) {
10924                 i = 0;
10925                 max = e2fsck_get_num_dirinfo(ctx);
10926         } else {
10927                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10928                                                        &iter);
10929                 if (retval) {
10930                         pctx.errcode = retval;
10931                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10932                         return;
10933                 }
10934                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10935         }
10936         while (1) {
10937                 if (all_dirs) {
10938                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10939                                 break;
10940                         ino = dir->ino;
10941                 } else {
10942                         if (!ext2fs_u32_list_iterate(iter, &ino))
10943                                 break;
10944                 }
10945                 if (ino == ctx->lost_and_found)
10946                         continue;
10947                 pctx.dir = ino;
10948                 if (first) {
10949                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10950                         first = 0;
10951                 }
10952                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10953                 if (pctx.errcode) {
10954                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10955                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10956                 }
10957                 if (ctx->progress && !ctx->progress_fd)
10958                         e2fsck_simple_progress(ctx, "Rebuilding directory",
10959                                100.0 * (float) (++cur) / (float) max, ino);
10960         }
10961         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10962         if (!all_dirs)
10963                 ext2fs_u32_list_iterate_end(iter);
10964
10965         ext2fs_u32_list_free(ctx->dirs_to_hash);
10966         ctx->dirs_to_hash = 0;
10967 }
10968
10969 /*
10970  * linux/fs/revoke.c
10971  *
10972  * Journal revoke routines for the generic filesystem journaling code;
10973  * part of the ext2fs journaling system.
10974  *
10975  * Revoke is the mechanism used to prevent old log records for deleted
10976  * metadata from being replayed on top of newer data using the same
10977  * blocks.  The revoke mechanism is used in two separate places:
10978  *
10979  * + Commit: during commit we write the entire list of the current
10980  *   transaction's revoked blocks to the journal
10981  *
10982  * + Recovery: during recovery we record the transaction ID of all
10983  *   revoked blocks.  If there are multiple revoke records in the log
10984  *   for a single block, only the last one counts, and if there is a log
10985  *   entry for a block beyond the last revoke, then that log entry still
10986  *   gets replayed.
10987  *
10988  * We can get interactions between revokes and new log data within a
10989  * single transaction:
10990  *
10991  * Block is revoked and then journaled:
10992  *   The desired end result is the journaling of the new block, so we
10993  *   cancel the revoke before the transaction commits.
10994  *
10995  * Block is journaled and then revoked:
10996  *   The revoke must take precedence over the write of the block, so we
10997  *   need either to cancel the journal entry or to write the revoke
10998  *   later in the log than the log block.  In this case, we choose the
10999  *   latter: journaling a block cancels any revoke record for that block
11000  *   in the current transaction, so any revoke for that block in the
11001  *   transaction must have happened after the block was journaled and so
11002  *   the revoke must take precedence.
11003  *
11004  * Block is revoked and then written as data:
11005  *   The data write is allowed to succeed, but the revoke is _not_
11006  *   cancelled.  We still need to prevent old log records from
11007  *   overwriting the new data.  We don't even need to clear the revoke
11008  *   bit here.
11009  *
11010  * Revoke information on buffers is a tri-state value:
11011  *
11012  * RevokeValid clear:   no cached revoke status, need to look it up
11013  * RevokeValid set, Revoked clear:
11014  *                      buffer has not been revoked, and cancel_revoke
11015  *                      need do nothing.
11016  * RevokeValid set, Revoked set:
11017  *                      buffer has been revoked.
11018  */
11019
11020 static kmem_cache_t *revoke_record_cache;
11021 static kmem_cache_t *revoke_table_cache;
11022
11023 /* Each revoke record represents one single revoked block.  During
11024    journal replay, this involves recording the transaction ID of the
11025    last transaction to revoke this block. */
11026
11027 struct jbd_revoke_record_s
11028 {
11029         struct list_head  hash;
11030         tid_t             sequence;     /* Used for recovery only */
11031         unsigned long     blocknr;
11032 };
11033
11034
11035 /* The revoke table is just a simple hash table of revoke records. */
11036 struct jbd_revoke_table_s
11037 {
11038         /* It is conceivable that we might want a larger hash table
11039          * for recovery.  Must be a power of two. */
11040         int               hash_size;
11041         int               hash_shift;
11042         struct list_head *hash_table;
11043 };
11044
11045
11046 /* Utility functions to maintain the revoke table */
11047
11048 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11049 static int hash(journal_t *journal, unsigned long block)
11050 {
11051         struct jbd_revoke_table_s *table = journal->j_revoke;
11052         int hash_shift = table->hash_shift;
11053
11054         return ((block << (hash_shift - 6)) ^
11055                 (block >> 13) ^
11056                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11057 }
11058
11059 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11060                               tid_t seq)
11061 {
11062         struct list_head *hash_list;
11063         struct jbd_revoke_record_s *record;
11064
11065         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11066         if (!record)
11067                 goto oom;
11068
11069         record->sequence = seq;
11070         record->blocknr = blocknr;
11071         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11072         list_add(&record->hash, hash_list);
11073         return 0;
11074
11075 oom:
11076         return -ENOMEM;
11077 }
11078
11079 /* Find a revoke record in the journal's hash table. */
11080
11081 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11082                                                       unsigned long blocknr)
11083 {
11084         struct list_head *hash_list;
11085         struct jbd_revoke_record_s *record;
11086
11087         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11088
11089         record = (struct jbd_revoke_record_s *) hash_list->next;
11090         while (&(record->hash) != hash_list) {
11091                 if (record->blocknr == blocknr)
11092                         return record;
11093                 record = (struct jbd_revoke_record_s *) record->hash.next;
11094         }
11095         return NULL;
11096 }
11097
11098 int journal_init_revoke_caches(void)
11099 {
11100         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11101         if (revoke_record_cache == 0)
11102                 return -ENOMEM;
11103
11104         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11105         if (revoke_table_cache == 0) {
11106                 do_cache_destroy(revoke_record_cache);
11107                 revoke_record_cache = NULL;
11108                 return -ENOMEM;
11109         }
11110         return 0;
11111 }
11112
11113 void journal_destroy_revoke_caches(void)
11114 {
11115         do_cache_destroy(revoke_record_cache);
11116         revoke_record_cache = 0;
11117         do_cache_destroy(revoke_table_cache);
11118         revoke_table_cache = 0;
11119 }
11120
11121 /* Initialise the revoke table for a given journal to a given size. */
11122
11123 int journal_init_revoke(journal_t *journal, int hash_size)
11124 {
11125         int shift, tmp;
11126
11127         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11128         if (!journal->j_revoke)
11129                 return -ENOMEM;
11130
11131         /* Check that the hash_size is a power of two */
11132         journal->j_revoke->hash_size = hash_size;
11133
11134         shift = 0;
11135         tmp = hash_size;
11136         while ((tmp >>= 1UL) != 0UL)
11137                 shift++;
11138         journal->j_revoke->hash_shift = shift;
11139
11140         journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11141
11142         for (tmp = 0; tmp < hash_size; tmp++)
11143                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11144
11145         return 0;
11146 }
11147
11148 /* Destoy a journal's revoke table.  The table must already be empty! */
11149
11150 void journal_destroy_revoke(journal_t *journal)
11151 {
11152         struct jbd_revoke_table_s *table;
11153         struct list_head *hash_list;
11154         int i;
11155
11156         table = journal->j_revoke;
11157         if (!table)
11158                 return;
11159
11160         for (i=0; i<table->hash_size; i++) {
11161                 hash_list = &table->hash_table[i];
11162         }
11163
11164         free(table->hash_table);
11165         free(table);
11166         journal->j_revoke = NULL;
11167 }
11168
11169 /*
11170  * Revoke support for recovery.
11171  *
11172  * Recovery needs to be able to:
11173  *
11174  *  record all revoke records, including the tid of the latest instance
11175  *  of each revoke in the journal
11176  *
11177  *  check whether a given block in a given transaction should be replayed
11178  *  (ie. has not been revoked by a revoke record in that or a subsequent
11179  *  transaction)
11180  *
11181  *  empty the revoke table after recovery.
11182  */
11183
11184 /*
11185  * First, setting revoke records.  We create a new revoke record for
11186  * every block ever revoked in the log as we scan it for recovery, and
11187  * we update the existing records if we find multiple revokes for a
11188  * single block.
11189  */
11190
11191 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11192                        tid_t sequence)
11193 {
11194         struct jbd_revoke_record_s *record;
11195
11196         record = find_revoke_record(journal, blocknr);
11197         if (record) {
11198                 /* If we have multiple occurences, only record the
11199                  * latest sequence number in the hashed record */
11200                 if (tid_gt(sequence, record->sequence))
11201                         record->sequence = sequence;
11202                 return 0;
11203         }
11204         return insert_revoke_hash(journal, blocknr, sequence);
11205 }
11206
11207 /*
11208  * Test revoke records.  For a given block referenced in the log, has
11209  * that block been revoked?  A revoke record with a given transaction
11210  * sequence number revokes all blocks in that transaction and earlier
11211  * ones, but later transactions still need replayed.
11212  */
11213
11214 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11215                         tid_t sequence)
11216 {
11217         struct jbd_revoke_record_s *record;
11218
11219         record = find_revoke_record(journal, blocknr);
11220         if (!record)
11221                 return 0;
11222         if (tid_gt(sequence, record->sequence))
11223                 return 0;
11224         return 1;
11225 }
11226
11227 /*
11228  * Finally, once recovery is over, we need to clear the revoke table so
11229  * that it can be reused by the running filesystem.
11230  */
11231
11232 void journal_clear_revoke(journal_t *journal)
11233 {
11234         int i;
11235         struct list_head *hash_list;
11236         struct jbd_revoke_record_s *record;
11237         struct jbd_revoke_table_s *revoke_var;
11238
11239         revoke_var = journal->j_revoke;
11240
11241         for (i = 0; i < revoke_var->hash_size; i++) {
11242                 hash_list = &revoke_var->hash_table[i];
11243                 while (!list_empty(hash_list)) {
11244                         record = (struct jbd_revoke_record_s*) hash_list->next;
11245                         list_del(&record->hash);
11246                         free(record);
11247                 }
11248         }
11249 }
11250
11251 /*
11252  * e2fsck.c - superblock checks
11253  */
11254
11255 #define MIN_CHECK 1
11256 #define MAX_CHECK 2
11257
11258 static void check_super_value(e2fsck_t ctx, const char *descr,
11259                               unsigned long value, int flags,
11260                               unsigned long min_val, unsigned long max_val)
11261 {
11262         struct          problem_context pctx;
11263
11264         if (((flags & MIN_CHECK) && (value < min_val)) ||
11265             ((flags & MAX_CHECK) && (value > max_val))) {
11266                 clear_problem_context(&pctx);
11267                 pctx.num = value;
11268                 pctx.str = descr;
11269                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11270                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11271         }
11272 }
11273
11274 /*
11275  * This routine may get stubbed out in special compilations of the
11276  * e2fsck code..
11277  */
11278 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11279 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11280 {
11281         return (ext2fs_get_device_size(ctx->filesystem_name,
11282                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11283                                        &ctx->num_blocks));
11284 }
11285 #endif
11286
11287 /*
11288  * helper function to release an inode
11289  */
11290 struct process_block_struct {
11291         e2fsck_t        ctx;
11292         char            *buf;
11293         struct problem_context *pctx;
11294         int             truncating;
11295         int             truncate_offset;
11296         e2_blkcnt_t     truncate_block;
11297         int             truncated_blocks;
11298         int             abort;
11299         errcode_t       errcode;
11300 };
11301
11302 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11303                                e2_blkcnt_t blockcnt,
11304                                blk_t    ref_blk FSCK_ATTR((unused)),
11305                                int      ref_offset FSCK_ATTR((unused)),
11306                                void *priv_data)
11307 {
11308         struct process_block_struct *pb;
11309         e2fsck_t                ctx;
11310         struct problem_context  *pctx;
11311         blk_t                   blk = *block_nr;
11312         int                     retval = 0;
11313
11314         pb = (struct process_block_struct *) priv_data;
11315         ctx = pb->ctx;
11316         pctx = pb->pctx;
11317
11318         pctx->blk = blk;
11319         pctx->blkcount = blockcnt;
11320
11321         if (HOLE_BLKADDR(blk))
11322                 return 0;
11323
11324         if ((blk < fs->super->s_first_data_block) ||
11325             (blk >= fs->super->s_blocks_count)) {
11326                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11327         return_abort:
11328                 pb->abort = 1;
11329                 return BLOCK_ABORT;
11330         }
11331
11332         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11333                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11334                 goto return_abort;
11335         }
11336
11337         /*
11338          * If we are deleting an orphan, then we leave the fields alone.
11339          * If we are truncating an orphan, then update the inode fields
11340          * and clean up any partial block data.
11341          */
11342         if (pb->truncating) {
11343                 /*
11344                  * We only remove indirect blocks if they are
11345                  * completely empty.
11346                  */
11347                 if (blockcnt < 0) {
11348                         int     i, limit;
11349                         blk_t   *bp;
11350
11351                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11352                                                         pb->buf);
11353                         if (pb->errcode)
11354                                 goto return_abort;
11355
11356                         limit = fs->blocksize >> 2;
11357                         for (i = 0, bp = (blk_t *) pb->buf;
11358                              i < limit;  i++, bp++)
11359                                 if (*bp)
11360                                         return 0;
11361                 }
11362                 /*
11363                  * We don't remove direct blocks until we've reached
11364                  * the truncation block.
11365                  */
11366                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11367                         return 0;
11368                 /*
11369                  * If part of the last block needs truncating, we do
11370                  * it here.
11371                  */
11372                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11373                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11374                                                         pb->buf);
11375                         if (pb->errcode)
11376                                 goto return_abort;
11377                         memset(pb->buf + pb->truncate_offset, 0,
11378                                fs->blocksize - pb->truncate_offset);
11379                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11380                                                          pb->buf);
11381                         if (pb->errcode)
11382                                 goto return_abort;
11383                 }
11384                 pb->truncated_blocks++;
11385                 *block_nr = 0;
11386                 retval |= BLOCK_CHANGED;
11387         }
11388
11389         ext2fs_block_alloc_stats(fs, blk, -1);
11390         return retval;
11391 }
11392
11393 /*
11394  * This function releases an inode.  Returns 1 if an inconsistency was
11395  * found.  If the inode has a link count, then it is being truncated and
11396  * not deleted.
11397  */
11398 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11399                                 struct ext2_inode *inode, char *block_buf,
11400                                 struct problem_context *pctx)
11401 {
11402         struct process_block_struct     pb;
11403         ext2_filsys                     fs = ctx->fs;
11404         errcode_t                       retval;
11405         __u32                           count;
11406
11407         if (!ext2fs_inode_has_valid_blocks(inode))
11408                 return 0;
11409
11410         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11411         pb.ctx = ctx;
11412         pb.abort = 0;
11413         pb.errcode = 0;
11414         pb.pctx = pctx;
11415         if (inode->i_links_count) {
11416                 pb.truncating = 1;
11417                 pb.truncate_block = (e2_blkcnt_t)
11418                         ((((long long)inode->i_size_high << 32) +
11419                           inode->i_size + fs->blocksize - 1) /
11420                          fs->blocksize);
11421                 pb.truncate_offset = inode->i_size % fs->blocksize;
11422         } else {
11423                 pb.truncating = 0;
11424                 pb.truncate_block = 0;
11425                 pb.truncate_offset = 0;
11426         }
11427         pb.truncated_blocks = 0;
11428         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11429                                       block_buf, release_inode_block, &pb);
11430         if (retval) {
11431                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11432                         ino);
11433                 return 1;
11434         }
11435         if (pb.abort)
11436                 return 1;
11437
11438         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11439         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11440
11441         if (pb.truncated_blocks)
11442                 inode->i_blocks -= pb.truncated_blocks *
11443                         (fs->blocksize / 512);
11444
11445         if (inode->i_file_acl) {
11446                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11447                                                    block_buf, -1, &count);
11448                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11449                         retval = 0;
11450                         count = 1;
11451                 }
11452                 if (retval) {
11453                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11454                                 ino);
11455                         return 1;
11456                 }
11457                 if (count == 0)
11458                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11459                 inode->i_file_acl = 0;
11460         }
11461         return 0;
11462 }
11463
11464 /*
11465  * This function releases all of the orphan inodes.  It returns 1 if
11466  * it hit some error, and 0 on success.
11467  */
11468 static int release_orphan_inodes(e2fsck_t ctx)
11469 {
11470         ext2_filsys fs = ctx->fs;
11471         ext2_ino_t      ino, next_ino;
11472         struct ext2_inode inode;
11473         struct problem_context pctx;
11474         char *block_buf;
11475
11476         if ((ino = fs->super->s_last_orphan) == 0)
11477                 return 0;
11478
11479         /*
11480          * Win or lose, we won't be using the head of the orphan inode
11481          * list again.
11482          */
11483         fs->super->s_last_orphan = 0;
11484         ext2fs_mark_super_dirty(fs);
11485
11486         /*
11487          * If the filesystem contains errors, don't run the orphan
11488          * list, since the orphan list can't be trusted; and we're
11489          * going to be running a full e2fsck run anyway...
11490          */
11491         if (fs->super->s_state & EXT2_ERROR_FS)
11492                 return 0;
11493
11494         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11495             (ino > fs->super->s_inodes_count)) {
11496                 clear_problem_context(&pctx);
11497                 pctx.ino = ino;
11498                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11499                 return 1;
11500         }
11501
11502         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11503                                                     "block iterate buffer");
11504         e2fsck_read_bitmaps(ctx);
11505
11506         while (ino) {
11507                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11508                 clear_problem_context(&pctx);
11509                 pctx.ino = ino;
11510                 pctx.inode = &inode;
11511                 pctx.str = inode.i_links_count ? _("Truncating") :
11512                         _("Clearing");
11513
11514                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11515
11516                 next_ino = inode.i_dtime;
11517                 if (next_ino &&
11518                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11519                      (next_ino > fs->super->s_inodes_count))) {
11520                         pctx.ino = next_ino;
11521                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11522                         goto return_abort;
11523                 }
11524
11525                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11526                         goto return_abort;
11527
11528                 if (!inode.i_links_count) {
11529                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11530                                                   LINUX_S_ISDIR(inode.i_mode));
11531                         inode.i_dtime = time(NULL);
11532                 } else {
11533                         inode.i_dtime = 0;
11534                 }
11535                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11536                 ino = next_ino;
11537         }
11538         ext2fs_free_mem(&block_buf);
11539         return 0;
11540 return_abort:
11541         ext2fs_free_mem(&block_buf);
11542         return 1;
11543 }
11544
11545 /*
11546  * Check the resize inode to make sure it is sane.  We check both for
11547  * the case where on-line resizing is not enabled (in which case the
11548  * resize inode should be cleared) as well as the case where on-line
11549  * resizing is enabled.
11550  */
11551 static void check_resize_inode(e2fsck_t ctx)
11552 {
11553         ext2_filsys fs = ctx->fs;
11554         struct ext2_inode inode;
11555         struct problem_context  pctx;
11556         int             i, j, gdt_off, ind_off;
11557         blk_t           blk, pblk, expect;
11558         __u32           *dind_buf = NULL, *ind_buf;
11559         errcode_t       retval;
11560
11561         clear_problem_context(&pctx);
11562
11563         /*
11564          * If the resize inode feature isn't set, then
11565          * s_reserved_gdt_blocks must be zero.
11566          */
11567         if (!(fs->super->s_feature_compat &
11568               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11569                 if (fs->super->s_reserved_gdt_blocks) {
11570                         pctx.num = fs->super->s_reserved_gdt_blocks;
11571                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11572                                         &pctx)) {
11573                                 fs->super->s_reserved_gdt_blocks = 0;
11574                                 ext2fs_mark_super_dirty(fs);
11575                         }
11576                 }
11577         }
11578
11579         /* Read the resize inode */
11580         pctx.ino = EXT2_RESIZE_INO;
11581         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11582         if (retval) {
11583                 if (fs->super->s_feature_compat &
11584                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11585                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11586                 return;
11587         }
11588
11589         /*
11590          * If the resize inode feature isn't set, check to make sure
11591          * the resize inode is cleared; then we're done.
11592          */
11593         if (!(fs->super->s_feature_compat &
11594               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11595                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11596                         if (inode.i_block[i])
11597                                 break;
11598                 }
11599                 if ((i < EXT2_N_BLOCKS) &&
11600                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11601                         memset(&inode, 0, sizeof(inode));
11602                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11603                                            "clear_resize");
11604                 }
11605                 return;
11606         }
11607
11608         /*
11609          * The resize inode feature is enabled; check to make sure the
11610          * only block in use is the double indirect block
11611          */
11612         blk = inode.i_block[EXT2_DIND_BLOCK];
11613         for (i=0; i < EXT2_N_BLOCKS; i++) {
11614                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11615                         break;
11616         }
11617         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11618             !(inode.i_mode & LINUX_S_IFREG) ||
11619             (blk < fs->super->s_first_data_block ||
11620              blk >= fs->super->s_blocks_count)) {
11621         resize_inode_invalid:
11622                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11623                         memset(&inode, 0, sizeof(inode));
11624                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11625                                            "clear_resize");
11626                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11627                 }
11628                 if (!(ctx->options & E2F_OPT_READONLY)) {
11629                         fs->super->s_state &= ~EXT2_VALID_FS;
11630                         ext2fs_mark_super_dirty(fs);
11631                 }
11632                 goto cleanup;
11633         }
11634         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11635                                                     "resize dind buffer");
11636         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11637
11638         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11639         if (retval)
11640                 goto resize_inode_invalid;
11641
11642         gdt_off = fs->desc_blocks;
11643         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11644         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11645              i++, gdt_off++, pblk++) {
11646                 gdt_off %= fs->blocksize/4;
11647                 if (dind_buf[gdt_off] != pblk)
11648                         goto resize_inode_invalid;
11649                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11650                 if (retval)
11651                         goto resize_inode_invalid;
11652                 ind_off = 0;
11653                 for (j = 1; j < fs->group_desc_count; j++) {
11654                         if (!ext2fs_bg_has_super(fs, j))
11655                                 continue;
11656                         expect = pblk + (j * fs->super->s_blocks_per_group);
11657                         if (ind_buf[ind_off] != expect)
11658                                 goto resize_inode_invalid;
11659                         ind_off++;
11660                 }
11661         }
11662
11663 cleanup:
11664         ext2fs_free_mem(&dind_buf);
11665
11666  }
11667
11668 static void check_super_block(e2fsck_t ctx)
11669 {
11670         ext2_filsys fs = ctx->fs;
11671         blk_t   first_block, last_block;
11672         struct ext2_super_block *sb = fs->super;
11673         struct ext2_group_desc *gd;
11674         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11675         blk_t   bpg_max;
11676         int     inodes_per_block;
11677         int     ipg_max;
11678         int     inode_size;
11679         dgrp_t  i;
11680         blk_t   should_be;
11681         struct problem_context  pctx;
11682         __u32   free_blocks = 0, free_inodes = 0;
11683
11684         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11685         ipg_max = inodes_per_block * (blocks_per_group - 4);
11686         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11687                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11688         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11689         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11690                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11691
11692         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11693                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11694         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11695                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11696         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11697                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11698
11699         clear_problem_context(&pctx);
11700
11701         /*
11702          * Verify the super block constants...
11703          */
11704         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11705                           MIN_CHECK, 1, 0);
11706         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11707                           MIN_CHECK, 1, 0);
11708         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11709                           MAX_CHECK, 0, sb->s_blocks_count);
11710         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11711                           MIN_CHECK | MAX_CHECK, 0,
11712                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11713         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11714                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11715         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11716                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11717                           bpg_max);
11718         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11719                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11720         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11721                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11722         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11723                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11724         check_super_value(ctx, "reserved_gdt_blocks",
11725                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11726                           fs->blocksize/4);
11727         inode_size = EXT2_INODE_SIZE(sb);
11728         check_super_value(ctx, "inode_size",
11729                           inode_size, MIN_CHECK | MAX_CHECK,
11730                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11731         if (inode_size & (inode_size - 1)) {
11732                 pctx.num = inode_size;
11733                 pctx.str = "inode_size";
11734                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11735                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11736                 return;
11737         }
11738
11739         if (!ctx->num_blocks) {
11740                 pctx.errcode = e2fsck_get_device_size(ctx);
11741                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11742                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11743                         ctx->flags |= E2F_FLAG_ABORT;
11744                         return;
11745                 }
11746                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11747                     (ctx->num_blocks < sb->s_blocks_count)) {
11748                         pctx.blk = sb->s_blocks_count;
11749                         pctx.blk2 = ctx->num_blocks;
11750                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11751                                 ctx->flags |= E2F_FLAG_ABORT;
11752                                 return;
11753                         }
11754                 }
11755         }
11756
11757         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11758                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11759                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11760                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11761                 ctx->flags |= E2F_FLAG_ABORT;
11762                 return;
11763         }
11764
11765         should_be = sb->s_frags_per_group >>
11766                 (sb->s_log_block_size - sb->s_log_frag_size);
11767         if (sb->s_blocks_per_group != should_be) {
11768                 pctx.blk = sb->s_blocks_per_group;
11769                 pctx.blk2 = should_be;
11770                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11771                 ctx->flags |= E2F_FLAG_ABORT;
11772                 return;
11773         }
11774
11775         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11776         if (sb->s_first_data_block != should_be) {
11777                 pctx.blk = sb->s_first_data_block;
11778                 pctx.blk2 = should_be;
11779                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11780                 ctx->flags |= E2F_FLAG_ABORT;
11781                 return;
11782         }
11783
11784         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11785         if (sb->s_inodes_count != should_be) {
11786                 pctx.ino = sb->s_inodes_count;
11787                 pctx.ino2 = should_be;
11788                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11789                         sb->s_inodes_count = should_be;
11790                         ext2fs_mark_super_dirty(fs);
11791                 }
11792         }
11793
11794         /*
11795          * Verify the group descriptors....
11796          */
11797         first_block =  sb->s_first_data_block;
11798         last_block = first_block + blocks_per_group;
11799
11800         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11801                 pctx.group = i;
11802
11803                 if (i == fs->group_desc_count - 1)
11804                         last_block = sb->s_blocks_count;
11805                 if ((gd->bg_block_bitmap < first_block) ||
11806                     (gd->bg_block_bitmap >= last_block)) {
11807                         pctx.blk = gd->bg_block_bitmap;
11808                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11809                                 gd->bg_block_bitmap = 0;
11810                 }
11811                 if (gd->bg_block_bitmap == 0) {
11812                         ctx->invalid_block_bitmap_flag[i]++;
11813                         ctx->invalid_bitmaps++;
11814                 }
11815                 if ((gd->bg_inode_bitmap < first_block) ||
11816                     (gd->bg_inode_bitmap >= last_block)) {
11817                         pctx.blk = gd->bg_inode_bitmap;
11818                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11819                                 gd->bg_inode_bitmap = 0;
11820                 }
11821                 if (gd->bg_inode_bitmap == 0) {
11822                         ctx->invalid_inode_bitmap_flag[i]++;
11823                         ctx->invalid_bitmaps++;
11824                 }
11825                 if ((gd->bg_inode_table < first_block) ||
11826                     ((gd->bg_inode_table +
11827                       fs->inode_blocks_per_group - 1) >= last_block)) {
11828                         pctx.blk = gd->bg_inode_table;
11829                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11830                                 gd->bg_inode_table = 0;
11831                 }
11832                 if (gd->bg_inode_table == 0) {
11833                         ctx->invalid_inode_table_flag[i]++;
11834                         ctx->invalid_bitmaps++;
11835                 }
11836                 free_blocks += gd->bg_free_blocks_count;
11837                 free_inodes += gd->bg_free_inodes_count;
11838                 first_block += sb->s_blocks_per_group;
11839                 last_block += sb->s_blocks_per_group;
11840
11841                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11842                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11843                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11844                         ext2fs_unmark_valid(fs);
11845
11846         }
11847
11848         /*
11849          * Update the global counts from the block group counts.  This
11850          * is needed for an experimental patch which eliminates
11851          * locking the entire filesystem when allocating blocks or
11852          * inodes; if the filesystem is not unmounted cleanly, the
11853          * global counts may not be accurate.
11854          */
11855         if ((free_blocks != sb->s_free_blocks_count) ||
11856             (free_inodes != sb->s_free_inodes_count)) {
11857                 if (ctx->options & E2F_OPT_READONLY)
11858                         ext2fs_unmark_valid(fs);
11859                 else {
11860                         sb->s_free_blocks_count = free_blocks;
11861                         sb->s_free_inodes_count = free_inodes;
11862                         ext2fs_mark_super_dirty(fs);
11863                 }
11864         }
11865
11866         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11867             (sb->s_free_inodes_count > sb->s_inodes_count))
11868                 ext2fs_unmark_valid(fs);
11869
11870
11871         /*
11872          * If we have invalid bitmaps, set the error state of the
11873          * filesystem.
11874          */
11875         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11876                 sb->s_state &= ~EXT2_VALID_FS;
11877                 ext2fs_mark_super_dirty(fs);
11878         }
11879
11880         clear_problem_context(&pctx);
11881
11882         /*
11883          * If the UUID field isn't assigned, assign it.
11884          */
11885         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11886                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11887                         uuid_generate(sb->s_uuid);
11888                         ext2fs_mark_super_dirty(fs);
11889                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11890                 }
11891         }
11892
11893         /* FIXME - HURD support?
11894          * For the Hurd, check to see if the filetype option is set,
11895          * since it doesn't support it.
11896          */
11897         if (!(ctx->options & E2F_OPT_READONLY) &&
11898             fs->super->s_creator_os == EXT2_OS_HURD &&
11899             (fs->super->s_feature_incompat &
11900              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11901                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11902                         fs->super->s_feature_incompat &=
11903                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11904                         ext2fs_mark_super_dirty(fs);
11905
11906                 }
11907         }
11908
11909         /*
11910          * If we have any of the compatibility flags set, we need to have a
11911          * revision 1 filesystem.  Most kernels will not check the flags on
11912          * a rev 0 filesystem and we may have corruption issues because of
11913          * the incompatible changes to the filesystem.
11914          */
11915         if (!(ctx->options & E2F_OPT_READONLY) &&
11916             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11917             (fs->super->s_feature_compat ||
11918              fs->super->s_feature_ro_compat ||
11919              fs->super->s_feature_incompat) &&
11920             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11921                 ext2fs_update_dynamic_rev(fs);
11922                 ext2fs_mark_super_dirty(fs);
11923         }
11924
11925         check_resize_inode(ctx);
11926
11927         /*
11928          * Clean up any orphan inodes, if present.
11929          */
11930         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11931                 fs->super->s_state &= ~EXT2_VALID_FS;
11932                 ext2fs_mark_super_dirty(fs);
11933         }
11934
11935         /*
11936          * Move the ext3 journal file, if necessary.
11937          */
11938         e2fsck_move_ext3_journal(ctx);
11939 }
11940
11941 /*
11942  * swapfs.c --- byte-swap an ext2 filesystem
11943  */
11944
11945 #ifdef ENABLE_SWAPFS
11946
11947 struct swap_block_struct {
11948         ext2_ino_t      ino;
11949         int             isdir;
11950         errcode_t       errcode;
11951         char            *dir_buf;
11952         struct ext2_inode *inode;
11953 };
11954
11955 /*
11956  * This is a helper function for block_iterate.  We mark all of the
11957  * indirect and direct blocks as changed, so that block_iterate will
11958  * write them out.
11959  */
11960 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11961                       void *priv_data)
11962 {
11963         errcode_t       retval;
11964
11965         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11966
11967         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11968                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11969                 if (retval) {
11970                         sb->errcode = retval;
11971                         return BLOCK_ABORT;
11972                 }
11973                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11974                 if (retval) {
11975                         sb->errcode = retval;
11976                         return BLOCK_ABORT;
11977                 }
11978         }
11979         if (blockcnt >= 0) {
11980                 if (blockcnt < EXT2_NDIR_BLOCKS)
11981                         return 0;
11982                 return BLOCK_CHANGED;
11983         }
11984         if (blockcnt == BLOCK_COUNT_IND) {
11985                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11986                         return 0;
11987                 return BLOCK_CHANGED;
11988         }
11989         if (blockcnt == BLOCK_COUNT_DIND) {
11990                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11991                         return 0;
11992                 return BLOCK_CHANGED;
11993         }
11994         if (blockcnt == BLOCK_COUNT_TIND) {
11995                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
11996                         return 0;
11997                 return BLOCK_CHANGED;
11998         }
11999         return BLOCK_CHANGED;
12000 }
12001
12002 /*
12003  * This function is responsible for byte-swapping all of the indirect,
12004  * block pointers.  It is also responsible for byte-swapping directories.
12005  */
12006 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12007                               struct ext2_inode *inode)
12008 {
12009         errcode_t                       retval;
12010         struct swap_block_struct        sb;
12011
12012         sb.ino = ino;
12013         sb.inode = inode;
12014         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12015         sb.errcode = 0;
12016         sb.isdir = 0;
12017         if (LINUX_S_ISDIR(inode->i_mode))
12018                 sb.isdir = 1;
12019
12020         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12021                                       swap_block, &sb);
12022         if (retval) {
12023                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12024                 ctx->flags |= E2F_FLAG_ABORT;
12025                 return;
12026         }
12027         if (sb.errcode) {
12028                 bb_error_msg(_("while calling iterator function"));
12029                 ctx->flags |= E2F_FLAG_ABORT;
12030                 return;
12031         }
12032 }
12033
12034 static void swap_inodes(e2fsck_t ctx)
12035 {
12036         ext2_filsys fs = ctx->fs;
12037         dgrp_t                  group;
12038         unsigned int            i;
12039         ext2_ino_t              ino = 1;
12040         char                    *buf, *block_buf;
12041         errcode_t               retval;
12042         struct ext2_inode *     inode;
12043
12044         e2fsck_use_inode_shortcuts(ctx, 1);
12045
12046         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12047                                 &buf);
12048         if (retval) {
12049                 bb_error_msg(_("while allocating inode buffer"));
12050                 ctx->flags |= E2F_FLAG_ABORT;
12051                 return;
12052         }
12053         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12054                                                     "block interate buffer");
12055         for (group = 0; group < fs->group_desc_count; group++) {
12056                 retval = io_channel_read_blk(fs->io,
12057                       fs->group_desc[group].bg_inode_table,
12058                       fs->inode_blocks_per_group, buf);
12059                 if (retval) {
12060                         bb_error_msg(_("while reading inode table (group %d)"),
12061                                 group);
12062                         ctx->flags |= E2F_FLAG_ABORT;
12063                         return;
12064                 }
12065                 inode = (struct ext2_inode *) buf;
12066                 for (i=0; i < fs->super->s_inodes_per_group;
12067                      i++, ino++, inode++) {
12068                         ctx->stashed_ino = ino;
12069                         ctx->stashed_inode = inode;
12070
12071                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12072                                 ext2fs_swap_inode(fs, inode, inode, 0);
12073
12074                         /*
12075                          * Skip deleted files.
12076                          */
12077                         if (inode->i_links_count == 0)
12078                                 continue;
12079
12080                         if (LINUX_S_ISDIR(inode->i_mode) ||
12081                             ((inode->i_block[EXT2_IND_BLOCK] ||
12082                               inode->i_block[EXT2_DIND_BLOCK] ||
12083                               inode->i_block[EXT2_TIND_BLOCK]) &&
12084                              ext2fs_inode_has_valid_blocks(inode)))
12085                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12086
12087                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12088                                 return;
12089
12090                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12091                                 ext2fs_swap_inode(fs, inode, inode, 1);
12092                 }
12093                 retval = io_channel_write_blk(fs->io,
12094                       fs->group_desc[group].bg_inode_table,
12095                       fs->inode_blocks_per_group, buf);
12096                 if (retval) {
12097                         bb_error_msg(_("while writing inode table (group %d)"),
12098                                 group);
12099                         ctx->flags |= E2F_FLAG_ABORT;
12100                         return;
12101                 }
12102         }
12103         ext2fs_free_mem(&buf);
12104         ext2fs_free_mem(&block_buf);
12105         e2fsck_use_inode_shortcuts(ctx, 0);
12106         ext2fs_flush_icache(fs);
12107 }
12108
12109 #if defined(__powerpc__) && BB_BIG_ENDIAN
12110 /*
12111  * On the PowerPC, the big-endian variant of the ext2 filesystem
12112  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12113  * of each word.  Thus a bitmap with only bit 0 set would be, as
12114  * a string of bytes, 00 00 00 01 00 ...
12115  * To cope with this, we byte-reverse each word of a bitmap if
12116  * we have a big-endian filesystem, that is, if we are *not*
12117  * byte-swapping other word-sized numbers.
12118  */
12119 #define EXT2_BIG_ENDIAN_BITMAPS
12120 #endif
12121
12122 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12123 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12124 {
12125         __u32 *p = (__u32 *) bmap->bitmap;
12126         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12127
12128         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12129                 *p = ext2fs_swab32(*p);
12130 }
12131 #endif
12132
12133
12134 #ifdef ENABLE_SWAPFS
12135 static void swap_filesys(e2fsck_t ctx)
12136 {
12137         ext2_filsys fs = ctx->fs;
12138         if (!(ctx->options & E2F_OPT_PREEN))
12139                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12140
12141         /* Byte swap */
12142
12143         if (fs->super->s_mnt_count) {
12144                 fprintf(stderr, _("%s: the filesystem must be freshly "
12145                         "checked using fsck\n"
12146                         "and not mounted before trying to "
12147                         "byte-swap it.\n"), ctx->device_name);
12148                 ctx->flags |= E2F_FLAG_ABORT;
12149                 return;
12150         }
12151         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12152                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12153                                EXT2_FLAG_SWAP_BYTES_WRITE);
12154                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12155         } else {
12156                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12157                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12158         }
12159         swap_inodes(ctx);
12160         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12161                 return;
12162         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12163                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12164         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12165                        EXT2_FLAG_SWAP_BYTES_WRITE);
12166
12167 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12168         e2fsck_read_bitmaps(ctx);
12169         ext2fs_swap_bitmap(fs->inode_map);
12170         ext2fs_swap_bitmap(fs->block_map);
12171         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12172 #endif
12173         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12174         ext2fs_flush(fs);
12175         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12176 }
12177 #endif  /* ENABLE_SWAPFS */
12178
12179 #endif
12180
12181 /*
12182  * util.c --- miscellaneous utilities
12183  */
12184
12185
12186 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12187                              const char *description)
12188 {
12189         void *ret;
12190         char buf[256];
12191
12192         ret = xzalloc(size);
12193         return ret;
12194 }
12195
12196 static char *string_copy(const char *str, int len)
12197 {
12198         char    *ret;
12199
12200         if (!str)
12201                 return NULL;
12202         if (!len)
12203                 len = strlen(str);
12204         ret = xmalloc(len+1);
12205         strncpy(ret, str, len);
12206         ret[len] = 0;
12207         return ret;
12208 }
12209
12210 #ifndef HAVE_CONIO_H
12211 static int read_a_char(void)
12212 {
12213         char    c;
12214         int     r;
12215         int     fail = 0;
12216
12217         while (1) {
12218                 if (e2fsck_global_ctx &&
12219                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12220                         return 3;
12221                 }
12222                 r = read(0, &c, 1);
12223                 if (r == 1)
12224                         return c;
12225                 if (fail++ > 100)
12226                         break;
12227         }
12228         return EOF;
12229 }
12230 #endif
12231
12232 static int ask_yn(const char * string, int def)
12233 {
12234         int             c;
12235         const char      *defstr;
12236         static const char short_yes[] = "yY";
12237         static const char short_no[] = "nN";
12238
12239 #ifdef HAVE_TERMIOS_H
12240         struct termios  termios, tmp;
12241
12242         tcgetattr (0, &termios);
12243         tmp = termios;
12244         tmp.c_lflag &= ~(ICANON | ECHO);
12245         tmp.c_cc[VMIN] = 1;
12246         tmp.c_cc[VTIME] = 0;
12247         tcsetattr_stdin_TCSANOW(&tmp);
12248 #endif
12249
12250         if (def == 1)
12251                 defstr = "<y>";
12252         else if (def == 0)
12253                 defstr = "<n>";
12254         else
12255                 defstr = " (y/n)";
12256         printf("%s%s? ", string, defstr);
12257         while (1) {
12258                 fflush (stdout);
12259                 if ((c = read_a_char()) == EOF)
12260                         break;
12261                 if (c == 3) {
12262 #ifdef HAVE_TERMIOS_H
12263                         tcsetattr_stdin_TCSANOW(&termios);
12264 #endif
12265                         if (e2fsck_global_ctx &&
12266                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12267                                 puts("\n");
12268                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12269                         }
12270                         puts(_("cancelled!\n"));
12271                         return 0;
12272                 }
12273                 if (strchr(short_yes, (char) c)) {
12274                         def = 1;
12275                         break;
12276                 }
12277                 else if (strchr(short_no, (char) c)) {
12278                         def = 0;
12279                         break;
12280                 }
12281                 else if ((c == ' ' || c == '\n') && (def != -1))
12282                         break;
12283         }
12284         if (def)
12285                 puts("yes\n");
12286         else
12287                 puts ("no\n");
12288 #ifdef HAVE_TERMIOS_H
12289         tcsetattr_stdin_TCSANOW(&termios);
12290 #endif
12291         return def;
12292 }
12293
12294 int ask (e2fsck_t ctx, const char * string, int def)
12295 {
12296         if (ctx->options & E2F_OPT_NO) {
12297                 printf(_("%s? no\n\n"), string);
12298                 return 0;
12299         }
12300         if (ctx->options & E2F_OPT_YES) {
12301                 printf(_("%s? yes\n\n"), string);
12302                 return 1;
12303         }
12304         if (ctx->options & E2F_OPT_PREEN) {
12305                 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12306                 return def;
12307         }
12308         return ask_yn(string, def);
12309 }
12310
12311 void e2fsck_read_bitmaps(e2fsck_t ctx)
12312 {
12313         ext2_filsys fs = ctx->fs;
12314         errcode_t       retval;
12315
12316         if (ctx->invalid_bitmaps) {
12317                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12318                         ctx->device_name);
12319                 bb_error_msg_and_die(0);
12320         }
12321
12322         ehandler_operation(_("reading inode and block bitmaps"));
12323         retval = ext2fs_read_bitmaps(fs);
12324         ehandler_operation(0);
12325         if (retval) {
12326                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12327                         ctx->device_name);
12328                 bb_error_msg_and_die(0);
12329         }
12330 }
12331
12332 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12333 {
12334         ext2_filsys fs = ctx->fs;
12335         errcode_t       retval;
12336
12337         if (ext2fs_test_bb_dirty(fs)) {
12338                 ehandler_operation(_("writing block bitmaps"));
12339                 retval = ext2fs_write_block_bitmap(fs);
12340                 ehandler_operation(0);
12341                 if (retval) {
12342                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12343                                 ctx->device_name);
12344                         bb_error_msg_and_die(0);
12345                 }
12346         }
12347
12348         if (ext2fs_test_ib_dirty(fs)) {
12349                 ehandler_operation(_("writing inode bitmaps"));
12350                 retval = ext2fs_write_inode_bitmap(fs);
12351                 ehandler_operation(0);
12352                 if (retval) {
12353                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12354                                 ctx->device_name);
12355                         bb_error_msg_and_die(0);
12356                 }
12357         }
12358 }
12359
12360 void preenhalt(e2fsck_t ctx)
12361 {
12362         ext2_filsys fs = ctx->fs;
12363
12364         if (!(ctx->options & E2F_OPT_PREEN))
12365                 return;
12366         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12367                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12368                ctx->device_name);
12369         if (fs != NULL) {
12370                 fs->super->s_state |= EXT2_ERROR_FS;
12371                 ext2fs_mark_super_dirty(fs);
12372                 ext2fs_close(fs);
12373         }
12374         exit(EXIT_UNCORRECTED);
12375 }
12376
12377 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12378                               struct ext2_inode * inode, const char *proc)
12379 {
12380         int retval;
12381
12382         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12383         if (retval) {
12384                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12385                 bb_error_msg_and_die(0);
12386         }
12387 }
12388
12389 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12390                                struct ext2_inode * inode, int bufsize,
12391                                const char *proc)
12392 {
12393         int retval;
12394
12395         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12396         if (retval) {
12397                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12398                 bb_error_msg_and_die(0);
12399         }
12400 }
12401
12402 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12403                                struct ext2_inode * inode, const char *proc)
12404 {
12405         int retval;
12406
12407         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12408         if (retval) {
12409                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12410                 bb_error_msg_and_die(0);
12411         }
12412 }
12413
12414 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12415                    io_manager manager)
12416 {
12417         struct ext2_super_block *sb;
12418         io_channel              io = NULL;
12419         void                    *buf = NULL;
12420         int                     blocksize;
12421         blk_t                   superblock, ret_sb = 8193;
12422
12423         if (fs && fs->super) {
12424                 ret_sb = (fs->super->s_blocks_per_group +
12425                           fs->super->s_first_data_block);
12426                 if (ctx) {
12427                         ctx->superblock = ret_sb;
12428                         ctx->blocksize = fs->blocksize;
12429                 }
12430                 return ret_sb;
12431         }
12432
12433         if (ctx) {
12434                 if (ctx->blocksize) {
12435                         ret_sb = ctx->blocksize * 8;
12436                         if (ctx->blocksize == 1024)
12437                                 ret_sb++;
12438                         ctx->superblock = ret_sb;
12439                         return ret_sb;
12440                 }
12441                 ctx->superblock = ret_sb;
12442                 ctx->blocksize = 1024;
12443         }
12444
12445         if (!name || !manager)
12446                 goto cleanup;
12447
12448         if (manager->open(name, 0, &io) != 0)
12449                 goto cleanup;
12450
12451         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12452                 goto cleanup;
12453         sb = (struct ext2_super_block *) buf;
12454
12455         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12456              blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12457                 superblock = blocksize*8;
12458                 if (blocksize == 1024)
12459                         superblock++;
12460                 io_channel_set_blksize(io, blocksize);
12461                 if (io_channel_read_blk(io, superblock,
12462                                         -SUPERBLOCK_SIZE, buf))
12463                         continue;
12464 #if BB_BIG_ENDIAN
12465                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12466                         ext2fs_swap_super(sb);
12467 #endif
12468                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12469                         ret_sb = superblock;
12470                         if (ctx) {
12471                                 ctx->superblock = superblock;
12472                                 ctx->blocksize = blocksize;
12473                         }
12474                         break;
12475                 }
12476         }
12477
12478 cleanup:
12479         if (io)
12480                 io_channel_close(io);
12481         ext2fs_free_mem(&buf);
12482         return ret_sb;
12483 }
12484
12485
12486 /*
12487  * This function runs through the e2fsck passes and calls them all,
12488  * returning restart, abort, or cancel as necessary...
12489  */
12490 typedef void (*pass_t)(e2fsck_t ctx);
12491
12492 static const pass_t e2fsck_passes[] = {
12493         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12494         e2fsck_pass5, 0 };
12495
12496 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12497
12498 static int e2fsck_run(e2fsck_t ctx)
12499 {
12500         int     i;
12501         pass_t  e2fsck_pass;
12502
12503         if (setjmp(ctx->abort_loc)) {
12504                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12505                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12506         }
12507         ctx->flags |= E2F_FLAG_SETJMP_OK;
12508
12509         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12510                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12511                         break;
12512                 e2fsck_pass(ctx);
12513                 if (ctx->progress)
12514                         (void) (ctx->progress)(ctx, 0, 0, 0);
12515         }
12516         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12517
12518         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12519                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12520         return 0;
12521 }
12522
12523
12524 /*
12525  * unix.c - The unix-specific code for e2fsck
12526  */
12527
12528
12529 /* Command line options */
12530 static int swapfs;
12531 #ifdef ENABLE_SWAPFS
12532 static int normalize_swapfs;
12533 #endif
12534 static int cflag;               /* check disk */
12535 static int show_version_only;
12536 static int verbose;
12537
12538 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12539
12540 static void show_stats(e2fsck_t ctx)
12541 {
12542         ext2_filsys fs = ctx->fs;
12543         int inodes, inodes_used, blocks, blocks_used;
12544         int dir_links;
12545         int num_files, num_links;
12546         int frag_percent;
12547
12548         dir_links = 2 * ctx->fs_directory_count - 1;
12549         num_files = ctx->fs_total_count - dir_links;
12550         num_links = ctx->fs_links_count - dir_links;
12551         inodes = fs->super->s_inodes_count;
12552         inodes_used = (fs->super->s_inodes_count -
12553                        fs->super->s_free_inodes_count);
12554         blocks = fs->super->s_blocks_count;
12555         blocks_used = (fs->super->s_blocks_count -
12556                        fs->super->s_free_blocks_count);
12557
12558         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12559         frag_percent = (frag_percent + 5) / 10;
12560
12561         if (!verbose) {
12562                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12563                        ctx->device_name, inodes_used, inodes,
12564                        frag_percent / 10, frag_percent % 10,
12565                        blocks_used, blocks);
12566                 return;
12567         }
12568         printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12569                 100 * inodes_used / inodes);
12570         printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12571                 P_E2("", "s", ctx->fs_fragmented),
12572                 frag_percent / 10, frag_percent % 10);
12573         printf(_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12574                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12575         printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12576                 (int) ((long long) 100 * blocks_used / blocks));
12577         printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12578         printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12579         printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12580         printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12581         printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12582         printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12583         printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12584         printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12585         printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12586         printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12587         printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12588 }
12589
12590 static void check_mount(e2fsck_t ctx)
12591 {
12592         errcode_t       retval;
12593         int             cont;
12594
12595         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12596                                          &ctx->mount_flags);
12597         if (retval) {
12598                 bb_error_msg(_("while determining whether %s is mounted"),
12599                         ctx->filesystem_name);
12600                 return;
12601         }
12602
12603         /*
12604          * If the filesystem isn't mounted, or it's the root filesystem
12605          * and it's mounted read-only, then everything's fine.
12606          */
12607         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12608             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12609              (ctx->mount_flags & EXT2_MF_READONLY)))
12610                 return;
12611
12612         if (ctx->options & E2F_OPT_READONLY) {
12613                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12614                 return;
12615         }
12616
12617         printf(_("%s is mounted.  "), ctx->filesystem_name);
12618         if (!ctx->interactive)
12619                 bb_error_msg_and_die(_("can't continue, aborting"));
12620         printf(_("\n\n\007\007\007\007WARNING!!!  "
12621                "Running e2fsck on a mounted filesystem may cause\n"
12622                "SEVERE filesystem damage.\007\007\007\n\n"));
12623         cont = ask_yn(_("Do you really want to continue"), -1);
12624         if (!cont) {
12625                 printf(_("check aborted.\n"));
12626                 exit(0);
12627         }
12628 }
12629
12630 static int is_on_batt(void)
12631 {
12632         FILE    *f;
12633         DIR     *d;
12634         char    tmp[80], tmp2[80], fname[80];
12635         unsigned int    acflag;
12636         struct dirent*  de;
12637
12638         f = fopen_for_read("/proc/apm");
12639         if (f) {
12640                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12641                         acflag = 1;
12642                 fclose(f);
12643                 return (acflag != 1);
12644         }
12645         d = opendir("/proc/acpi/ac_adapter");
12646         if (d) {
12647                 while ((de=readdir(d)) != NULL) {
12648                         if (!strncmp(".", de->d_name, 1))
12649                                 continue;
12650                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12651                                  de->d_name);
12652                         f = fopen_for_read(fname);
12653                         if (!f)
12654                                 continue;
12655                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12656                                 tmp[0] = 0;
12657                         fclose(f);
12658                         if (strncmp(tmp, "off-line", 8) == 0) {
12659                                 closedir(d);
12660                                 return 1;
12661                         }
12662                 }
12663                 closedir(d);
12664         }
12665         return 0;
12666 }
12667
12668 /*
12669  * This routine checks to see if a filesystem can be skipped; if so,
12670  * it will exit with EXIT_OK.  Under some conditions it will print a
12671  * message explaining why a check is being forced.
12672  */
12673 static void check_if_skip(e2fsck_t ctx)
12674 {
12675         ext2_filsys fs = ctx->fs;
12676         const char *reason = NULL;
12677         unsigned int reason_arg = 0;
12678         long next_check;
12679         int batt = is_on_batt();
12680         time_t now = time(NULL);
12681
12682         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12683                 return;
12684
12685         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12686             !ext2fs_test_valid(fs))
12687                 reason = _(" contains a file system with errors");
12688         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12689                 reason = _(" was not cleanly unmounted");
12690         else if ((fs->super->s_max_mnt_count > 0) &&
12691                  (fs->super->s_mnt_count >=
12692                   (unsigned) fs->super->s_max_mnt_count)) {
12693                 reason = _(" has been mounted %u times without being checked");
12694                 reason_arg = fs->super->s_mnt_count;
12695                 if (batt && (fs->super->s_mnt_count <
12696                              (unsigned) fs->super->s_max_mnt_count*2))
12697                         reason = 0;
12698         } else if (fs->super->s_checkinterval &&
12699                    ((now - fs->super->s_lastcheck) >=
12700                     fs->super->s_checkinterval)) {
12701                 reason = _(" has gone %u days without being checked");
12702                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12703                 if (batt && ((now - fs->super->s_lastcheck) <
12704                              fs->super->s_checkinterval*2))
12705                         reason = 0;
12706         }
12707         if (reason) {
12708                 fputs(ctx->device_name, stdout);
12709                 printf(reason, reason_arg);
12710                 fputs(_(", check forced.\n"), stdout);
12711                 return;
12712         }
12713         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12714                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12715                fs->super->s_inodes_count,
12716                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12717                fs->super->s_blocks_count);
12718         next_check = 100000;
12719         if (fs->super->s_max_mnt_count > 0) {
12720                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12721                 if (next_check <= 0)
12722                         next_check = 1;
12723         }
12724         if (fs->super->s_checkinterval &&
12725             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12726                 next_check = 1;
12727         if (next_check <= 5) {
12728                 if (next_check == 1)
12729                         fputs(_(" (check after next mount)"), stdout);
12730                 else
12731                         printf(_(" (check in %ld mounts)"), next_check);
12732         }
12733         bb_putchar('\n');
12734         ext2fs_close(fs);
12735         ctx->fs = NULL;
12736         e2fsck_free_context(ctx);
12737         exit(EXIT_OK);
12738 }
12739
12740 /*
12741  * For completion notice
12742  */
12743 struct percent_tbl {
12744         int     max_pass;
12745         int     table[32];
12746 };
12747 static const struct percent_tbl e2fsck_tbl = {
12748         5, { 0, 70, 90, 92,  95, 100 }
12749 };
12750
12751 static char bar[128], spaces[128];
12752
12753 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12754                           int max)
12755 {
12756         float   percent;
12757
12758         if (pass <= 0)
12759                 return 0.0;
12760         if (pass > tbl->max_pass || max == 0)
12761                 return 100.0;
12762         percent = ((float) curr) / ((float) max);
12763         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12764                 + tbl->table[pass-1]);
12765 }
12766
12767 void e2fsck_clear_progbar(e2fsck_t ctx)
12768 {
12769         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12770                 return;
12771
12772         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12773                ctx->stop_meta);
12774         fflush(stdout);
12775         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12776 }
12777
12778 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12779                            unsigned int dpynum)
12780 {
12781         static const char spinner[] = "\\|/-";
12782         int     i;
12783         unsigned int    tick;
12784         struct timeval  tv;
12785         int dpywidth;
12786         int fixed_percent;
12787
12788         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12789                 return 0;
12790
12791         /*
12792          * Calculate the new progress position.  If the
12793          * percentage hasn't changed, then we skip out right
12794          * away.
12795          */
12796         fixed_percent = (int) ((10 * percent) + 0.5);
12797         if (ctx->progress_last_percent == fixed_percent)
12798                 return 0;
12799         ctx->progress_last_percent = fixed_percent;
12800
12801         /*
12802          * If we've already updated the spinner once within
12803          * the last 1/8th of a second, no point doing it
12804          * again.
12805          */
12806         gettimeofday(&tv, NULL);
12807         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12808         if ((tick == ctx->progress_last_time) &&
12809             (fixed_percent != 0) && (fixed_percent != 1000))
12810                 return 0;
12811         ctx->progress_last_time = tick;
12812
12813         /*
12814          * Advance the spinner, and note that the progress bar
12815          * will be on the screen
12816          */
12817         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12818         ctx->flags |= E2F_FLAG_PROG_BAR;
12819
12820         dpywidth = 66 - strlen(label);
12821         dpywidth = 8 * (dpywidth / 8);
12822         if (dpynum)
12823                 dpywidth -= 8;
12824
12825         i = ((percent * dpywidth) + 50) / 100;
12826         printf("%s%s: |%s%s", ctx->start_meta, label,
12827                bar + (sizeof(bar) - (i+1)),
12828                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12829         if (fixed_percent == 1000)
12830                 bb_putchar('|');
12831         else
12832                 bb_putchar(spinner[ctx->progress_pos & 3]);
12833         printf(" %4.1f%%  ", percent);
12834         if (dpynum)
12835                 printf("%u\r", dpynum);
12836         else
12837                 fputs(" \r", stdout);
12838         fputs(ctx->stop_meta, stdout);
12839
12840         if (fixed_percent == 1000)
12841                 e2fsck_clear_progbar(ctx);
12842         fflush(stdout);
12843
12844         return 0;
12845 }
12846
12847 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12848                                   unsigned long cur, unsigned long max)
12849 {
12850         char buf[80];
12851         float percent;
12852
12853         if (pass == 0)
12854                 return 0;
12855
12856         if (ctx->progress_fd) {
12857                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12858                 xwrite_str(ctx->progress_fd, buf);
12859         } else {
12860                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12861                 e2fsck_simple_progress(ctx, ctx->device_name,
12862                                        percent, 0);
12863         }
12864         return 0;
12865 }
12866
12867 static void reserve_stdio_fds(void)
12868 {
12869         int     fd;
12870
12871         while (1) {
12872                 fd = open(bb_dev_null, O_RDWR);
12873                 if (fd > 2)
12874                         break;
12875                 if (fd < 0) {
12876                         fprintf(stderr, _("ERROR: Cannot open "
12877                                 "/dev/null (%s)\n"),
12878                                 strerror(errno));
12879                         break;
12880                 }
12881         }
12882         close(fd);
12883 }
12884
12885 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12886 {
12887         e2fsck_t ctx = e2fsck_global_ctx;
12888
12889         if (!ctx)
12890                 return;
12891
12892         ctx->progress = e2fsck_update_progress;
12893         ctx->progress_fd = 0;
12894 }
12895
12896 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12897 {
12898         e2fsck_t ctx = e2fsck_global_ctx;
12899
12900         if (!ctx)
12901                 return;
12902
12903         e2fsck_clear_progbar(ctx);
12904         ctx->progress = 0;
12905 }
12906
12907 static void signal_cancel(int sig FSCK_ATTR((unused)))
12908 {
12909         e2fsck_t ctx = e2fsck_global_ctx;
12910
12911         if (!ctx)
12912                 exit(FSCK_CANCELED);
12913
12914         ctx->flags |= E2F_FLAG_CANCEL;
12915 }
12916
12917 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12918 {
12919         char    *buf, *token, *next, *p, *arg;
12920         int     ea_ver;
12921         int     extended_usage = 0;
12922
12923         buf = string_copy(opts, 0);
12924         for (token = buf; token && *token; token = next) {
12925                 p = strchr(token, ',');
12926                 next = 0;
12927                 if (p) {
12928                         *p = 0;
12929                         next = p+1;
12930                 }
12931                 arg = strchr(token, '=');
12932                 if (arg) {
12933                         *arg = 0;
12934                         arg++;
12935                 }
12936                 if (strcmp(token, "ea_ver") == 0) {
12937                         if (!arg) {
12938                                 extended_usage++;
12939                                 continue;
12940                         }
12941                         ea_ver = strtoul(arg, &p, 0);
12942                         if (*p ||
12943                             ((ea_ver != 1) && (ea_ver != 2))) {
12944                                 fprintf(stderr,
12945                                         _("Invalid EA version.\n"));
12946                                 extended_usage++;
12947                                 continue;
12948                         }
12949                         ctx->ext_attr_ver = ea_ver;
12950                 } else {
12951                         fprintf(stderr, _("Unknown extended option: %s\n"),
12952                                 token);
12953                         extended_usage++;
12954                 }
12955         }
12956         if (extended_usage) {
12957                 bb_error_msg_and_die(
12958                         "Extended options are separated by commas, "
12959                         "and may take an argument which\n"
12960                         "is set off by an equals ('=') sign.  "
12961                         "Valid extended options are:\n"
12962                         "\tea_ver=<ea_version (1 or 2)>\n\n");
12963         }
12964 }
12965
12966
12967 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12968 {
12969         int             flush = 0;
12970         int             c, fd;
12971         e2fsck_t        ctx;
12972         errcode_t       retval;
12973         struct sigaction        sa;
12974         char            *extended_opts = NULL;
12975
12976         retval = e2fsck_allocate_context(&ctx);
12977         if (retval)
12978                 return retval;
12979
12980         *ret_ctx = ctx;
12981
12982         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12983         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12984         if (isatty(0) && isatty(1)) {
12985                 ctx->interactive = 1;
12986         } else {
12987                 ctx->start_meta[0] = '\001';
12988                 ctx->stop_meta[0] = '\002';
12989         }
12990         memset(bar, '=', sizeof(bar)-1);
12991         memset(spaces, ' ', sizeof(spaces)-1);
12992         blkid_get_cache(&ctx->blkid, NULL);
12993
12994         if (argc && *argv)
12995                 ctx->program_name = *argv;
12996         else
12997                 ctx->program_name = "e2fsck";
12998         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
12999                 switch (c) {
13000                 case 'C':
13001                         ctx->progress = e2fsck_update_progress;
13002                         ctx->progress_fd = atoi(optarg);
13003                         if (!ctx->progress_fd)
13004                                 break;
13005                         /* Validate the file descriptor to avoid disasters */
13006                         fd = dup(ctx->progress_fd);
13007                         if (fd < 0) {
13008                                 fprintf(stderr,
13009                                 _("Error validating file descriptor %d: %s\n"),
13010                                         ctx->progress_fd,
13011                                         error_message(errno));
13012                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13013                         } else
13014                                 close(fd);
13015                         break;
13016                 case 'D':
13017                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13018                         break;
13019                 case 'E':
13020                         extended_opts = optarg;
13021                         break;
13022                 case 'p':
13023                 case 'a':
13024                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13025                         conflict_opt:
13026                                 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13027                         }
13028                         ctx->options |= E2F_OPT_PREEN;
13029                         break;
13030                 case 'n':
13031                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13032                                 goto conflict_opt;
13033                         ctx->options |= E2F_OPT_NO;
13034                         break;
13035                 case 'y':
13036                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13037                                 goto conflict_opt;
13038                         ctx->options |= E2F_OPT_YES;
13039                         break;
13040                 case 't':
13041                         /* FIXME - This needs to go away in a future path - will change binary */
13042                         fprintf(stderr, _("The -t option is not "
13043                                 "supported on this version of e2fsck.\n"));
13044                         break;
13045                 case 'c':
13046                         if (cflag++)
13047                                 ctx->options |= E2F_OPT_WRITECHECK;
13048                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13049                         break;
13050                 case 'r':
13051                         /* What we do by default, anyway! */
13052                         break;
13053                 case 'b':
13054                         ctx->use_superblock = atoi(optarg);
13055                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13056                         break;
13057                 case 'B':
13058                         ctx->blocksize = atoi(optarg);
13059                         break;
13060                 case 'I':
13061                         ctx->inode_buffer_blocks = atoi(optarg);
13062                         break;
13063                 case 'j':
13064                         ctx->journal_name = string_copy(optarg, 0);
13065                         break;
13066                 case 'P':
13067                         ctx->process_inode_size = atoi(optarg);
13068                         break;
13069                 case 'd':
13070                         ctx->options |= E2F_OPT_DEBUG;
13071                         break;
13072                 case 'f':
13073                         ctx->options |= E2F_OPT_FORCE;
13074                         break;
13075                 case 'F':
13076                         flush = 1;
13077                         break;
13078                 case 'v':
13079                         verbose = 1;
13080                         break;
13081                 case 'V':
13082                         show_version_only = 1;
13083                         break;
13084                 case 'N':
13085                         ctx->device_name = optarg;
13086                         break;
13087 #ifdef ENABLE_SWAPFS
13088                 case 's':
13089                         normalize_swapfs = 1;
13090                 case 'S':
13091                         swapfs = 1;
13092                         break;
13093 #else
13094                 case 's':
13095                 case 'S':
13096                         fprintf(stderr, _("Byte-swapping filesystems "
13097                                           "not compiled in this version "
13098                                           "of e2fsck\n"));
13099                         exit(1);
13100 #endif
13101                 default:
13102                         bb_show_usage();
13103                 }
13104         if (show_version_only)
13105                 return 0;
13106         if (optind != argc - 1)
13107                 bb_show_usage();
13108         if ((ctx->options & E2F_OPT_NO) &&
13109             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13110                 ctx->options |= E2F_OPT_READONLY;
13111         ctx->io_options = strchr(argv[optind], '?');
13112         if (ctx->io_options)
13113                 *ctx->io_options++ = 0;
13114         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13115         if (!ctx->filesystem_name) {
13116                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13117                 bb_error_msg_and_die(0);
13118         }
13119         if (extended_opts)
13120                 parse_extended_opts(ctx, extended_opts);
13121
13122         if (flush) {
13123                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13124                 if (fd < 0) {
13125                         bb_error_msg(_("while opening %s for flushing"),
13126                                 ctx->filesystem_name);
13127                         bb_error_msg_and_die(0);
13128                 }
13129                 if ((retval = ext2fs_sync_device(fd, 1))) {
13130                         bb_error_msg(_("while trying to flush %s"),
13131                                 ctx->filesystem_name);
13132                         bb_error_msg_and_die(0);
13133                 }
13134                 close(fd);
13135         }
13136 #ifdef ENABLE_SWAPFS
13137         if (swapfs && cflag) {
13138                         fprintf(stderr, _("Incompatible options not "
13139                                           "allowed when byte-swapping.\n"));
13140                         exit(EXIT_USAGE);
13141         }
13142 #endif
13143         /*
13144          * Set up signal action
13145          */
13146         memset(&sa, 0, sizeof(struct sigaction));
13147         sa.sa_handler = signal_cancel;
13148         sigaction(SIGINT, &sa, 0);
13149         sigaction(SIGTERM, &sa, 0);
13150 #ifdef SA_RESTART
13151         sa.sa_flags = SA_RESTART;
13152 #endif
13153         e2fsck_global_ctx = ctx;
13154         sa.sa_handler = signal_progress_on;
13155         sigaction(SIGUSR1, &sa, 0);
13156         sa.sa_handler = signal_progress_off;
13157         sigaction(SIGUSR2, &sa, 0);
13158
13159         /* Update our PATH to include /sbin if we need to run badblocks  */
13160         if (cflag)
13161                 e2fs_set_sbin_path();
13162         return 0;
13163 }
13164
13165 static const char my_ver_string[] = E2FSPROGS_VERSION;
13166 static const char my_ver_date[] = E2FSPROGS_DATE;
13167
13168 int e2fsck_main (int argc, char **argv);
13169 int e2fsck_main (int argc, char **argv)
13170 {
13171         errcode_t       retval;
13172         int             exit_value = EXIT_OK;
13173         ext2_filsys     fs = 0;
13174         io_manager      io_ptr;
13175         struct ext2_super_block *sb;
13176         const char      *lib_ver_date;
13177         int             my_ver, lib_ver;
13178         e2fsck_t        ctx;
13179         struct problem_context pctx;
13180         int flags, run_result;
13181
13182         clear_problem_context(&pctx);
13183
13184         my_ver = ext2fs_parse_version_string(my_ver_string);
13185         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13186         if (my_ver > lib_ver) {
13187                 fprintf( stderr, _("Error: ext2fs library version "
13188                         "out of date!\n"));
13189                 show_version_only++;
13190         }
13191
13192         retval = PRS(argc, argv, &ctx);
13193         if (retval) {
13194                 bb_error_msg(_("while trying to initialize program"));
13195                 exit(EXIT_ERROR);
13196         }
13197         reserve_stdio_fds();
13198
13199         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13200                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13201                          my_ver_date);
13202
13203         if (show_version_only) {
13204                 fprintf(stderr, _("\tUsing %s, %s\n"),
13205                         error_message(EXT2_ET_BASE), lib_ver_date);
13206                 exit(EXIT_OK);
13207         }
13208
13209         check_mount(ctx);
13210
13211         if (!(ctx->options & E2F_OPT_PREEN) &&
13212             !(ctx->options & E2F_OPT_NO) &&
13213             !(ctx->options & E2F_OPT_YES)) {
13214                 if (!ctx->interactive)
13215                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13216         }
13217         ctx->superblock = ctx->use_superblock;
13218 restart:
13219 #ifdef CONFIG_TESTIO_DEBUG
13220         io_ptr = test_io_manager;
13221         test_io_backing_manager = unix_io_manager;
13222 #else
13223         io_ptr = unix_io_manager;
13224 #endif
13225         flags = 0;
13226         if ((ctx->options & E2F_OPT_READONLY) == 0)
13227                 flags |= EXT2_FLAG_RW;
13228
13229         if (ctx->superblock && ctx->blocksize) {
13230                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13231                                       flags, ctx->superblock, ctx->blocksize,
13232                                       io_ptr, &fs);
13233         } else if (ctx->superblock) {
13234                 int blocksize;
13235                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13236                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13237                         retval = ext2fs_open2(ctx->filesystem_name,
13238                                               ctx->io_options, flags,
13239                                               ctx->superblock, blocksize,
13240                                               io_ptr, &fs);
13241                         if (!retval)
13242                                 break;
13243                 }
13244         } else
13245                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13246                                       flags, 0, 0, io_ptr, &fs);
13247         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13248             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13249             ((retval == EXT2_ET_BAD_MAGIC) ||
13250              ((retval == 0) && ext2fs_check_desc(fs)))) {
13251                 if (!fs || (fs->group_desc_count > 1)) {
13252                         printf(_("%s trying backup blocks...\n"),
13253                                retval ? _("Couldn't find ext2 superblock,") :
13254                                _("Group descriptors look bad..."));
13255                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13256                         if (fs)
13257                                 ext2fs_close(fs);
13258                         goto restart;
13259                 }
13260         }
13261         if (retval) {
13262                 bb_error_msg(_("while trying to open %s"),
13263                         ctx->filesystem_name);
13264                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13265                         printf(_("The filesystem revision is apparently "
13266                                "too high for this version of e2fsck.\n"
13267                                "(Or the filesystem superblock "
13268                                "is corrupt)\n\n"));
13269                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13270                 } else if (retval == EXT2_ET_SHORT_READ)
13271                         printf(_("Could this be a zero-length partition?\n"));
13272                 else if ((retval == EPERM) || (retval == EACCES))
13273                         printf(_("You must have %s access to the "
13274                                "filesystem or be root\n"),
13275                                (ctx->options & E2F_OPT_READONLY) ?
13276                                "r/o" : "r/w");
13277                 else if (retval == ENXIO)
13278                         printf(_("Possibly non-existent or swap device?\n"));
13279 #ifdef EROFS
13280                 else if (retval == EROFS)
13281                         printf(_("Disk write-protected; use the -n option "
13282                                "to do a read-only\n"
13283                                "check of the device.\n"));
13284 #endif
13285                 else
13286                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13287                 bb_error_msg_and_die(0);
13288         }
13289         ctx->fs = fs;
13290         fs->priv_data = ctx;
13291         sb = fs->super;
13292         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13293                 bb_error_msg(_("while trying to open %s"),
13294                         ctx->filesystem_name);
13295         get_newer:
13296                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13297         }
13298
13299         /*
13300          * Set the device name, which is used whenever we print error
13301          * or informational messages to the user.
13302          */
13303         if (ctx->device_name == 0 &&
13304             (sb->s_volume_name[0] != 0)) {
13305                 ctx->device_name = string_copy(sb->s_volume_name,
13306                                                sizeof(sb->s_volume_name));
13307         }
13308         if (ctx->device_name == 0)
13309                 ctx->device_name = ctx->filesystem_name;
13310
13311         /*
13312          * Make sure the ext3 superblock fields are consistent.
13313          */
13314         retval = e2fsck_check_ext3_journal(ctx);
13315         if (retval) {
13316                 bb_error_msg(_("while checking ext3 journal for %s"),
13317                         ctx->device_name);
13318                 bb_error_msg_and_die(0);
13319         }
13320
13321         /*
13322          * Check to see if we need to do ext3-style recovery.  If so,
13323          * do it, and then restart the fsck.
13324          */
13325         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13326                 if (ctx->options & E2F_OPT_READONLY) {
13327                         printf(_("Warning: skipping journal recovery "
13328                                  "because doing a read-only filesystem "
13329                                  "check.\n"));
13330                         io_channel_flush(ctx->fs->io);
13331                 } else {
13332                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13333                                 /*
13334                                  * Whoops, we attempted to run the
13335                                  * journal twice.  This should never
13336                                  * happen, unless the hardware or
13337                                  * device driver is being bogus.
13338                                  */
13339                                 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13340                                 bb_error_msg_and_die(0);
13341                         }
13342                         retval = e2fsck_run_ext3_journal(ctx);
13343                         if (retval) {
13344                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13345                                         ctx->device_name);
13346                                 bb_error_msg_and_die(0);
13347                         }
13348                         ext2fs_close(ctx->fs);
13349                         ctx->fs = 0;
13350                         ctx->flags |= E2F_FLAG_RESTARTED;
13351                         goto restart;
13352                 }
13353         }
13354
13355         /*
13356          * Check for compatibility with the feature sets.  We need to
13357          * be more stringent than ext2fs_open().
13358          */
13359         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13360             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13361                 bb_error_msg("(%s)", ctx->device_name);
13362                 goto get_newer;
13363         }
13364         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13365                 bb_error_msg("(%s)", ctx->device_name);
13366                 goto get_newer;
13367         }
13368 #ifdef ENABLE_COMPRESSION
13369         /* FIXME - do we support this at all? */
13370         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13371                 bb_error_msg(_("warning: compression support is experimental"));
13372 #endif
13373 #ifndef ENABLE_HTREE
13374         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13375                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13376                           "but filesystem %s has HTREE directories."),
13377                         ctx->device_name);
13378                 goto get_newer;
13379         }
13380 #endif
13381
13382         /*
13383          * If the user specified a specific superblock, presumably the
13384          * master superblock has been trashed.  So we mark the
13385          * superblock as dirty, so it can be written out.
13386          */
13387         if (ctx->superblock &&
13388             !(ctx->options & E2F_OPT_READONLY))
13389                 ext2fs_mark_super_dirty(fs);
13390
13391         /*
13392          * We only update the master superblock because (a) paranoia;
13393          * we don't want to corrupt the backup superblocks, and (b) we
13394          * don't need to update the mount count and last checked
13395          * fields in the backup superblock (the kernel doesn't
13396          * update the backup superblocks anyway).
13397          */
13398         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13399
13400         ehandler_init(fs->io);
13401
13402         if (ctx->superblock)
13403                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13404         ext2fs_mark_valid(fs);
13405         check_super_block(ctx);
13406         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13407                 bb_error_msg_and_die(0);
13408         check_if_skip(ctx);
13409         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13410                 bb_error_msg_and_die(0);
13411 #ifdef ENABLE_SWAPFS
13412
13413 #ifdef WORDS_BIGENDIAN
13414 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13415 #else
13416 #define NATIVE_FLAG 0
13417 #endif
13418
13419
13420         if (normalize_swapfs) {
13421                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13422                         fprintf(stderr, _("%s: Filesystem byte order "
13423                                 "already normalized.\n"), ctx->device_name);
13424                         bb_error_msg_and_die(0);
13425                 }
13426         }
13427         if (swapfs) {
13428                 swap_filesys(ctx);
13429                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13430                         bb_error_msg_and_die(0);
13431         }
13432 #endif
13433
13434         /*
13435          * Mark the system as valid, 'til proven otherwise
13436          */
13437         ext2fs_mark_valid(fs);
13438
13439         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13440         if (retval) {
13441                 bb_error_msg(_("while reading bad blocks inode"));
13442                 preenhalt(ctx);
13443                 printf(_("This doesn't bode well,"
13444                          " but we'll try to go on...\n"));
13445         }
13446
13447         run_result = e2fsck_run(ctx);
13448         e2fsck_clear_progbar(ctx);
13449         if (run_result == E2F_FLAG_RESTART) {
13450                 printf(_("Restarting e2fsck from the beginning...\n"));
13451                 retval = e2fsck_reset_context(ctx);
13452                 if (retval) {
13453                         bb_error_msg(_("while resetting context"));
13454                         bb_error_msg_and_die(0);
13455                 }
13456                 ext2fs_close(fs);
13457                 goto restart;
13458         }
13459         if (run_result & E2F_FLAG_CANCEL) {
13460                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13461                        ctx->device_name : ctx->filesystem_name);
13462                 exit_value |= FSCK_CANCELED;
13463         }
13464         if (run_result & E2F_FLAG_ABORT)
13465                 bb_error_msg_and_die(_("aborted"));
13466
13467         /* Cleanup */
13468         if (ext2fs_test_changed(fs)) {
13469                 exit_value |= EXIT_NONDESTRUCT;
13470                 if (!(ctx->options & E2F_OPT_PREEN))
13471                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13472                                ctx->device_name);
13473                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13474                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13475                                ctx->device_name);
13476                         exit_value |= EXIT_DESTRUCT;
13477                 }
13478         }
13479         if (!ext2fs_test_valid(fs)) {
13480                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13481                          "errors **********\n\n"), ctx->device_name);
13482                 exit_value |= EXIT_UNCORRECTED;
13483                 exit_value &= ~EXIT_NONDESTRUCT;
13484         }
13485         if (exit_value & FSCK_CANCELED)
13486                 exit_value &= ~EXIT_NONDESTRUCT;
13487         else {
13488                 show_stats(ctx);
13489                 if (!(ctx->options & E2F_OPT_READONLY)) {
13490                         if (ext2fs_test_valid(fs)) {
13491                                 if (!(sb->s_state & EXT2_VALID_FS))
13492                                         exit_value |= EXIT_NONDESTRUCT;
13493                                 sb->s_state = EXT2_VALID_FS;
13494                         } else
13495                                 sb->s_state &= ~EXT2_VALID_FS;
13496                         sb->s_mnt_count = 0;
13497                         sb->s_lastcheck = time(NULL);
13498                         ext2fs_mark_super_dirty(fs);
13499                 }
13500         }
13501
13502         e2fsck_write_bitmaps(ctx);
13503
13504         ext2fs_close(fs);
13505         ctx->fs = NULL;
13506         free(ctx->filesystem_name);
13507         free(ctx->journal_name);
13508         e2fsck_free_context(ctx);
13509
13510         return exit_value;
13511 }