fix assorted unused code and wrong format specs found by cppchekc (bug 6716)
[platform/upstream/busybox.git] / e2fsprogs / old_e2fsprogs / e2fsck.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * e2fsck
4  *
5  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6  * Copyright (C) 2006 Garrett Kajmowicz
7  *
8  * Dictionary Abstract Data Type
9  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10  * Free Software License:
11  * All rights are reserved by the author, with the following exceptions:
12  * Permission is granted to freely reproduce and distribute this software,
13  * possibly in exchange for a fee, provided that this copyright notice appears
14  * intact. Permission is also granted to adapt this software to produce
15  * derivative works, as long as the modified versions carry this copyright
16  * notice and additional notices stating that the work has been modified.
17  * This source code may be translated into executable form and incorporated
18  * into proprietary software; there is no requirement for such software to
19  * contain a copyright notice related to this source.
20  *
21  * linux/fs/recovery  and linux/fs/revoke
22  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23  *
24  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25  *
26  * Journal recovery routines for the generic filesystem journaling code;
27  * part of the ext2fs journaling system.
28  *
29  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
30  */
31
32 /*
33 //usage:#define e2fsck_trivial_usage
34 //usage:       "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] "
35 //usage:       "[-I inode_buffer_blocks] [-P process_inode_size] "
36 //usage:       "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] "
37 //usage:       "[-E extended-options] device"
38 //usage:#define e2fsck_full_usage "\n\n"
39 //usage:       "Check ext2/ext3 file system\n"
40 //usage:     "\n        -p              Automatic repair (no questions)"
41 //usage:     "\n        -n              Make no changes to the filesystem"
42 //usage:     "\n        -y              Assume 'yes' to all questions"
43 //usage:     "\n        -c              Check for bad blocks and add them to the badblock list"
44 //usage:     "\n        -f              Force checking even if filesystem is marked clean"
45 //usage:     "\n        -v              Verbose"
46 //usage:     "\n        -b superblock   Use alternative superblock"
47 //usage:     "\n        -B blocksize    Force blocksize when looking for superblock"
48 //usage:     "\n        -j journal      Set location of the external journal"
49 //usage:     "\n        -l file         Add to badblocks list"
50 //usage:     "\n        -L file         Set badblocks list"
51 */
52
53 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
54
55 #define _(x) x
56 #define N_(x) x
57
58 /*
59  * Procedure declarations
60  */
61
62 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
63
64 /* pass1.c */
65 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
66
67 /* pass2.c */
68 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
69                                     ext2_ino_t ino, char *buf);
70
71 /* pass3.c */
72 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
73 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
74                                          int num, int gauranteed_size);
75 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
76 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
77                                            int adj);
78
79 /* rehash.c */
80 static void e2fsck_rehash_directories(e2fsck_t ctx);
81
82 /* util.c */
83 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
84                                     const char *description);
85 static int ask(e2fsck_t ctx, const char * string, int def);
86 static void e2fsck_read_bitmaps(e2fsck_t ctx);
87 static void preenhalt(e2fsck_t ctx);
88 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
89                               struct ext2_inode * inode, const char * proc);
90 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
91                                struct ext2_inode * inode, const char * proc);
92 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
93                            const char *name, io_manager manager);
94
95 /* unix.c */
96 static void e2fsck_clear_progbar(e2fsck_t ctx);
97 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
98                                   float percent, unsigned int dpynum);
99
100
101 /*
102  * problem.h --- e2fsck problem error codes
103  */
104
105 typedef __u32 problem_t;
106
107 struct problem_context {
108         errcode_t       errcode;
109         ext2_ino_t      ino, ino2, dir;
110         struct ext2_inode *inode;
111         struct ext2_dir_entry *dirent;
112         blk_t           blk, blk2;
113         e2_blkcnt_t     blkcount;
114         int             group;
115         __u64           num;
116         const char      *str;
117 };
118
119
120 /*
121  * Function declarations
122  */
123 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
124 static int end_problem_latch(e2fsck_t ctx, int mask);
125 static int set_latch_flags(int mask, int setflags, int clearflags);
126 static void clear_problem_context(struct problem_context *ctx);
127
128 /*
129  * Dictionary Abstract Data Type
130  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
131  *
132  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
133  * kazlib_1_20
134  */
135
136 #ifndef DICT_H
137 #define DICT_H
138
139 /*
140  * Blurb for inclusion into C++ translation units
141  */
142
143 typedef unsigned long dictcount_t;
144 #define DICTCOUNT_T_MAX ULONG_MAX
145
146 /*
147  * The dictionary is implemented as a red-black tree
148  */
149
150 typedef enum { dnode_red, dnode_black } dnode_color_t;
151
152 typedef struct dnode_t {
153         struct dnode_t *dict_left;
154         struct dnode_t *dict_right;
155         struct dnode_t *dict_parent;
156         dnode_color_t dict_color;
157         const void *dict_key;
158         void *dict_data;
159 } dnode_t;
160
161 typedef int (*dict_comp_t)(const void *, const void *);
162 typedef void (*dnode_free_t)(dnode_t *);
163
164 typedef struct dict_t {
165         dnode_t dict_nilnode;
166         dictcount_t dict_nodecount;
167         dictcount_t dict_maxcount;
168         dict_comp_t dict_compare;
169         dnode_free_t dict_freenode;
170         int dict_dupes;
171 } dict_t;
172
173 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
174
175 typedef struct dict_load_t {
176         dict_t *dict_dictptr;
177         dnode_t dict_nilnode;
178 } dict_load_t;
179
180 #define dict_count(D) ((D)->dict_nodecount)
181 #define dnode_get(N) ((N)->dict_data)
182 #define dnode_getkey(N) ((N)->dict_key)
183
184 #endif
185
186 /*
187  * Compatibility header file for e2fsck which should be included
188  * instead of linux/jfs.h
189  *
190  * Copyright (C) 2000 Stephen C. Tweedie
191  */
192
193 /*
194  * Pull in the definition of the e2fsck context structure
195  */
196
197 struct buffer_head {
198         char            b_data[8192];
199         e2fsck_t        b_ctx;
200         io_channel      b_io;
201         int             b_size;
202         blk_t           b_blocknr;
203         int             b_dirty;
204         int             b_uptodate;
205         int             b_err;
206 };
207
208
209 #define K_DEV_FS        1
210 #define K_DEV_JOURNAL   2
211
212 #define lock_buffer(bh) do {} while (0)
213 #define unlock_buffer(bh) do {} while (0)
214 #define buffer_req(bh) 1
215 #define do_readahead(journal, start) do {} while (0)
216
217 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
218
219 typedef struct {
220         int     object_length;
221 } kmem_cache_t;
222
223 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
224
225 /*
226  * We use the standard libext2fs portability tricks for inline
227  * functions.
228  */
229
230 static kmem_cache_t * do_cache_create(int len)
231 {
232         kmem_cache_t *new_cache;
233
234         new_cache = xmalloc(sizeof(*new_cache));
235         new_cache->object_length = len;
236         return new_cache;
237 }
238
239 static void do_cache_destroy(kmem_cache_t *cache)
240 {
241         free(cache);
242 }
243
244
245 /*
246  * Dictionary Abstract Data Type
247  */
248
249
250 /*
251  * These macros provide short convenient names for structure members,
252  * which are embellished with dict_ prefixes so that they are
253  * properly confined to the documented namespace. It's legal for a
254  * program which uses dict to define, for instance, a macro called ``parent''.
255  * Such a macro would interfere with the dnode_t struct definition.
256  * In general, highly portable and reusable C modules which expose their
257  * structures need to confine structure member names to well-defined spaces.
258  * The resulting identifiers aren't necessarily convenient to use, nor
259  * readable, in the implementation, however!
260  */
261
262 #define left dict_left
263 #define right dict_right
264 #define parent dict_parent
265 #define color dict_color
266 #define key dict_key
267 #define data dict_data
268
269 #define nilnode dict_nilnode
270 #define maxcount dict_maxcount
271 #define compare dict_compare
272 #define dupes dict_dupes
273
274 #define dict_root(D) ((D)->nilnode.left)
275 #define dict_nil(D) (&(D)->nilnode)
276
277 static void dnode_free(dnode_t *node);
278
279 /*
280  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
281  * its right child C are rearranged so that the P instead becomes the left
282  * child of C.   The left subtree of C is inherited as the new right subtree
283  * for P.  The ordering of the keys within the tree is thus preserved.
284  */
285
286 static void rotate_left(dnode_t *upper)
287 {
288         dnode_t *lower, *lowleft, *upparent;
289
290         lower = upper->right;
291         upper->right = lowleft = lower->left;
292         lowleft->parent = upper;
293
294         lower->parent = upparent = upper->parent;
295
296         /* don't need to check for root node here because root->parent is
297            the sentinel nil node, and root->parent->left points back to root */
298
299         if (upper == upparent->left) {
300                 upparent->left = lower;
301         } else {
302                 assert (upper == upparent->right);
303                 upparent->right = lower;
304         }
305
306         lower->left = upper;
307         upper->parent = lower;
308 }
309
310 /*
311  * This operation is the ``mirror'' image of rotate_left. It is
312  * the same procedure, but with left and right interchanged.
313  */
314
315 static void rotate_right(dnode_t *upper)
316 {
317         dnode_t *lower, *lowright, *upparent;
318
319         lower = upper->left;
320         upper->left = lowright = lower->right;
321         lowright->parent = upper;
322
323         lower->parent = upparent = upper->parent;
324
325         if (upper == upparent->right) {
326                 upparent->right = lower;
327         } else {
328                 assert (upper == upparent->left);
329                 upparent->left = lower;
330         }
331
332         lower->right = upper;
333         upper->parent = lower;
334 }
335
336 /*
337  * Do a postorder traversal of the tree rooted at the specified
338  * node and free everything under it.  Used by dict_free().
339  */
340
341 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
342 {
343         if (node == nil)
344                 return;
345         free_nodes(dict, node->left, nil);
346         free_nodes(dict, node->right, nil);
347         dict->dict_freenode(node);
348 }
349
350 /*
351  * Verify that the tree contains the given node. This is done by
352  * traversing all of the nodes and comparing their pointers to the
353  * given pointer. Returns 1 if the node is found, otherwise
354  * returns zero. It is intended for debugging purposes.
355  */
356
357 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
358 {
359         if (root != nil) {
360                 return root == node
361                         || verify_dict_has_node(nil, root->left, node)
362                         || verify_dict_has_node(nil, root->right, node);
363         }
364         return 0;
365 }
366
367
368 /*
369  * Select a different set of node allocator routines.
370  */
371
372 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
373 {
374         assert(dict_count(dict) == 0);
375         dict->dict_freenode = fr;
376 }
377
378 /*
379  * Free all the nodes in the dictionary by using the dictionary's
380  * installed free routine. The dictionary is emptied.
381  */
382
383 static void dict_free_nodes(dict_t *dict)
384 {
385         dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
386         free_nodes(dict, root, nil);
387         dict->dict_nodecount = 0;
388         dict->nilnode.left = &dict->nilnode;
389         dict->nilnode.right = &dict->nilnode;
390 }
391
392 /*
393  * Initialize a user-supplied dictionary object.
394  */
395
396 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
397 {
398         dict->compare = comp;
399         dict->dict_freenode = dnode_free;
400         dict->dict_nodecount = 0;
401         dict->maxcount = maxcount;
402         dict->nilnode.left = &dict->nilnode;
403         dict->nilnode.right = &dict->nilnode;
404         dict->nilnode.parent = &dict->nilnode;
405         dict->nilnode.color = dnode_black;
406         dict->dupes = 0;
407         return dict;
408 }
409
410 /*
411  * Locate a node in the dictionary having the given key.
412  * If the node is not found, a null a pointer is returned (rather than
413  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
414  * located node is returned.
415  */
416
417 static dnode_t *dict_lookup(dict_t *dict, const void *key)
418 {
419         dnode_t *root = dict_root(dict);
420         dnode_t *nil = dict_nil(dict);
421         dnode_t *saved;
422         int result;
423
424         /* simple binary search adapted for trees that contain duplicate keys */
425
426         while (root != nil) {
427                 result = dict->compare(key, root->key);
428                 if (result < 0)
429                         root = root->left;
430                 else if (result > 0)
431                         root = root->right;
432                 else {
433                         if (!dict->dupes) { /* no duplicates, return match          */
434                                 return root;
435                         } else {            /* could be dupes, find leftmost one    */
436                                 do {
437                                         saved = root;
438                                         root = root->left;
439                                         while (root != nil && dict->compare(key, root->key))
440                                                 root = root->right;
441                                 } while (root != nil);
442                                 return saved;
443                         }
444                 }
445         }
446
447         return NULL;
448 }
449
450 /*
451  * Insert a node into the dictionary. The node should have been
452  * initialized with a data field. All other fields are ignored.
453  * The behavior is undefined if the user attempts to insert into
454  * a dictionary that is already full (for which the dict_isfull()
455  * function returns true).
456  */
457
458 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
459 {
460         dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
461         dnode_t *parent = nil, *uncle, *grandpa;
462         int result = -1;
463
464         node->key = key;
465
466         /* basic binary tree insert */
467
468         while (where != nil) {
469                 parent = where;
470                 result = dict->compare(key, where->key);
471                 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
472                 assert(dict->dupes || result != 0);
473                 if (result < 0)
474                         where = where->left;
475                 else
476                         where = where->right;
477         }
478
479         assert(where == nil);
480
481         if (result < 0)
482                 parent->left = node;
483         else
484                 parent->right = node;
485
486         node->parent = parent;
487         node->left = nil;
488         node->right = nil;
489
490         dict->dict_nodecount++;
491
492         /* red black adjustments */
493
494         node->color = dnode_red;
495
496         while (parent->color == dnode_red) {
497                 grandpa = parent->parent;
498                 if (parent == grandpa->left) {
499                         uncle = grandpa->right;
500                         if (uncle->color == dnode_red) {    /* red parent, red uncle */
501                                 parent->color = dnode_black;
502                                 uncle->color = dnode_black;
503                                 grandpa->color = dnode_red;
504                                 node = grandpa;
505                                 parent = grandpa->parent;
506                         } else {                            /* red parent, black uncle */
507                                 if (node == parent->right) {
508                                         rotate_left(parent);
509                                         parent = node;
510                                         assert (grandpa == parent->parent);
511                                         /* rotation between parent and child preserves grandpa */
512                                 }
513                                 parent->color = dnode_black;
514                                 grandpa->color = dnode_red;
515                                 rotate_right(grandpa);
516                                 break;
517                         }
518                 } else {        /* symmetric cases: parent == parent->parent->right */
519                         uncle = grandpa->left;
520                         if (uncle->color == dnode_red) {
521                                 parent->color = dnode_black;
522                                 uncle->color = dnode_black;
523                                 grandpa->color = dnode_red;
524                                 node = grandpa;
525                                 parent = grandpa->parent;
526                         } else {
527                                 if (node == parent->left) {
528                                         rotate_right(parent);
529                                         parent = node;
530                                         assert (grandpa == parent->parent);
531                                 }
532                                 parent->color = dnode_black;
533                                 grandpa->color = dnode_red;
534                                 rotate_left(grandpa);
535                                 break;
536                         }
537                 }
538         }
539
540         dict_root(dict)->color = dnode_black;
541 }
542
543 /*
544  * Allocate a node using the dictionary's allocator routine, give it
545  * the data item.
546  */
547
548 static dnode_t *dnode_init(dnode_t *dnode, void *data)
549 {
550         dnode->data = data;
551         dnode->parent = NULL;
552         dnode->left = NULL;
553         dnode->right = NULL;
554         return dnode;
555 }
556
557 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
558 {
559         dnode_t *node = xmalloc(sizeof(dnode_t));
560
561         dnode_init(node, data);
562         dict_insert(dict, node, key);
563         return 1;
564 }
565
566 /*
567  * Return the node with the lowest (leftmost) key. If the dictionary is empty
568  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
569  */
570
571 static dnode_t *dict_first(dict_t *dict)
572 {
573         dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
574
575         if (root != nil)
576                 while ((left = root->left) != nil)
577                         root = left;
578
579         return (root == nil) ? NULL : root;
580 }
581
582 /*
583  * Return the given node's successor node---the node which has the
584  * next key in the left to right ordering. If the node has
585  * no successor, a null pointer is returned rather than a pointer to
586  * the nil node.
587  */
588
589 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
590 {
591         dnode_t *nil = dict_nil(dict), *parent, *left;
592
593         if (curr->right != nil) {
594                 curr = curr->right;
595                 while ((left = curr->left) != nil)
596                         curr = left;
597                 return curr;
598         }
599
600         parent = curr->parent;
601
602         while (parent != nil && curr == parent->right) {
603                 curr = parent;
604                 parent = curr->parent;
605         }
606
607         return (parent == nil) ? NULL : parent;
608 }
609
610
611 static void dnode_free(dnode_t *node)
612 {
613         free(node);
614 }
615
616
617 #undef left
618 #undef right
619 #undef parent
620 #undef color
621 #undef key
622 #undef data
623
624 #undef nilnode
625 #undef maxcount
626 #undef compare
627 #undef dupes
628
629
630 /*
631  * dirinfo.c --- maintains the directory information table for e2fsck.
632  */
633
634 /*
635  * This subroutine is called during pass1 to create a directory info
636  * entry.  During pass1, the passed-in parent is 0; it will get filled
637  * in during pass2.
638  */
639 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
640 {
641         struct dir_info *dir;
642         int             i, j;
643         ext2_ino_t      num_dirs;
644         errcode_t       retval;
645         unsigned long   old_size;
646
647         if (!ctx->dir_info) {
648                 ctx->dir_info_count = 0;
649                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
650                 if (retval)
651                         num_dirs = 1024;        /* Guess */
652                 ctx->dir_info_size = num_dirs + 10;
653                 ctx->dir_info  = (struct dir_info *)
654                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
655                                                * sizeof (struct dir_info),
656                                                "directory map");
657         }
658
659         if (ctx->dir_info_count >= ctx->dir_info_size) {
660                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
661                 ctx->dir_info_size += 10;
662                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
663                                            sizeof(struct dir_info),
664                                            &ctx->dir_info);
665                 if (retval) {
666                         ctx->dir_info_size -= 10;
667                         return;
668                 }
669         }
670
671         /*
672          * Normally, add_dir_info is called with each inode in
673          * sequential order; but once in a while (like when pass 3
674          * needs to recreate the root directory or lost+found
675          * directory) it is called out of order.  In those cases, we
676          * need to move the dir_info entries down to make room, since
677          * the dir_info array needs to be sorted by inode number for
678          * get_dir_info()'s sake.
679          */
680         if (ctx->dir_info_count &&
681             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
682                 for (i = ctx->dir_info_count-1; i > 0; i--)
683                         if (ctx->dir_info[i-1].ino < ino)
684                                 break;
685                 dir = &ctx->dir_info[i];
686                 if (dir->ino != ino)
687                         for (j = ctx->dir_info_count++; j > i; j--)
688                                 ctx->dir_info[j] = ctx->dir_info[j-1];
689         } else
690                 dir = &ctx->dir_info[ctx->dir_info_count++];
691
692         dir->ino = ino;
693         dir->dotdot = parent;
694         dir->parent = parent;
695 }
696
697 /*
698  * get_dir_info() --- given an inode number, try to find the directory
699  * information entry for it.
700  */
701 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
702 {
703         int     low, high, mid;
704
705         low = 0;
706         high = ctx->dir_info_count-1;
707         if (!ctx->dir_info)
708                 return 0;
709         if (ino == ctx->dir_info[low].ino)
710                 return &ctx->dir_info[low];
711         if  (ino == ctx->dir_info[high].ino)
712                 return &ctx->dir_info[high];
713
714         while (low < high) {
715                 mid = (low+high)/2;
716                 if (mid == low || mid == high)
717                         break;
718                 if (ino == ctx->dir_info[mid].ino)
719                         return &ctx->dir_info[mid];
720                 if (ino < ctx->dir_info[mid].ino)
721                         high = mid;
722                 else
723                         low = mid;
724         }
725         return 0;
726 }
727
728 /*
729  * Free the dir_info structure when it isn't needed any more.
730  */
731 static void e2fsck_free_dir_info(e2fsck_t ctx)
732 {
733         ext2fs_free_mem(&ctx->dir_info);
734         ctx->dir_info_size = 0;
735         ctx->dir_info_count = 0;
736 }
737
738 /*
739  * Return the count of number of directories in the dir_info structure
740  */
741 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
742 {
743         return ctx->dir_info_count;
744 }
745
746 /*
747  * A simple interator function
748  */
749 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
750 {
751         if (*control >= ctx->dir_info_count)
752                 return 0;
753
754         return ctx->dir_info + (*control)++;
755 }
756
757 /*
758  * dirinfo.c --- maintains the directory information table for e2fsck.
759  *
760  */
761
762 #ifdef ENABLE_HTREE
763
764 /*
765  * This subroutine is called during pass1 to create a directory info
766  * entry.  During pass1, the passed-in parent is 0; it will get filled
767  * in during pass2.
768  */
769 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
770 {
771         struct dx_dir_info *dir;
772         int             i, j;
773         errcode_t       retval;
774         unsigned long   old_size;
775
776         if (!ctx->dx_dir_info) {
777                 ctx->dx_dir_info_count = 0;
778                 ctx->dx_dir_info_size = 100; /* Guess */
779                 ctx->dx_dir_info  = (struct dx_dir_info *)
780                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
781                                                * sizeof (struct dx_dir_info),
782                                                "directory map");
783         }
784
785         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
786                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
787                 ctx->dx_dir_info_size += 10;
788                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
789                                            sizeof(struct dx_dir_info),
790                                            &ctx->dx_dir_info);
791                 if (retval) {
792                         ctx->dx_dir_info_size -= 10;
793                         return;
794                 }
795         }
796
797         /*
798          * Normally, add_dx_dir_info is called with each inode in
799          * sequential order; but once in a while (like when pass 3
800          * needs to recreate the root directory or lost+found
801          * directory) it is called out of order.  In those cases, we
802          * need to move the dx_dir_info entries down to make room, since
803          * the dx_dir_info array needs to be sorted by inode number for
804          * get_dx_dir_info()'s sake.
805          */
806         if (ctx->dx_dir_info_count &&
807             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
808                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
809                         if (ctx->dx_dir_info[i-1].ino < ino)
810                                 break;
811                 dir = &ctx->dx_dir_info[i];
812                 if (dir->ino != ino)
813                         for (j = ctx->dx_dir_info_count++; j > i; j--)
814                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
815         } else
816                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
817
818         dir->ino = ino;
819         dir->numblocks = num_blocks;
820         dir->hashversion = 0;
821         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
822                                        * sizeof (struct dx_dirblock_info),
823                                        "dx_block info array");
824 }
825
826 /*
827  * get_dx_dir_info() --- given an inode number, try to find the directory
828  * information entry for it.
829  */
830 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
831 {
832         int     low, high, mid;
833
834         low = 0;
835         high = ctx->dx_dir_info_count-1;
836         if (!ctx->dx_dir_info)
837                 return 0;
838         if (ino == ctx->dx_dir_info[low].ino)
839                 return &ctx->dx_dir_info[low];
840         if  (ino == ctx->dx_dir_info[high].ino)
841                 return &ctx->dx_dir_info[high];
842
843         while (low < high) {
844                 mid = (low+high)/2;
845                 if (mid == low || mid == high)
846                         break;
847                 if (ino == ctx->dx_dir_info[mid].ino)
848                         return &ctx->dx_dir_info[mid];
849                 if (ino < ctx->dx_dir_info[mid].ino)
850                         high = mid;
851                 else
852                         low = mid;
853         }
854         return 0;
855 }
856
857 /*
858  * Free the dx_dir_info structure when it isn't needed any more.
859  */
860 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
861 {
862         int     i;
863         struct dx_dir_info *dir;
864
865         if (ctx->dx_dir_info) {
866                 dir = ctx->dx_dir_info;
867                 for (i=0; i < ctx->dx_dir_info_count; i++) {
868                         ext2fs_free_mem(&dir->dx_block);
869                 }
870                 ext2fs_free_mem(&ctx->dx_dir_info);
871         }
872         ctx->dx_dir_info_size = 0;
873         ctx->dx_dir_info_count = 0;
874 }
875
876 /*
877  * A simple interator function
878  */
879 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
880 {
881         if (*control >= ctx->dx_dir_info_count)
882                 return 0;
883
884         return ctx->dx_dir_info + (*control)++;
885 }
886
887 #endif /* ENABLE_HTREE */
888 /*
889  * e2fsck.c - a consistency checker for the new extended file system.
890  *
891  */
892
893 /*
894  * This function allocates an e2fsck context
895  */
896 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
897 {
898         e2fsck_t        context;
899         errcode_t       retval;
900
901         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
902         if (retval)
903                 return retval;
904
905         memset(context, 0, sizeof(struct e2fsck_struct));
906
907         context->process_inode_size = 256;
908         context->ext_attr_ver = 2;
909
910         *ret = context;
911         return 0;
912 }
913
914 struct ea_refcount_el {
915         blk_t   ea_blk;
916         int     ea_count;
917 };
918
919 struct ea_refcount {
920         blk_t           count;
921         blk_t           size;
922         blk_t           cursor;
923         struct ea_refcount_el   *list;
924 };
925
926 static void ea_refcount_free(ext2_refcount_t refcount)
927 {
928         if (!refcount)
929                 return;
930
931         ext2fs_free_mem(&refcount->list);
932         ext2fs_free_mem(&refcount);
933 }
934
935 /*
936  * This function resets an e2fsck context; it is called when e2fsck
937  * needs to be restarted.
938  */
939 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
940 {
941         ctx->flags = 0;
942         ctx->lost_and_found = 0;
943         ctx->bad_lost_and_found = 0;
944         ext2fs_free_inode_bitmap(ctx->inode_used_map);
945         ctx->inode_used_map = 0;
946         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
947         ctx->inode_dir_map = 0;
948         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
949         ctx->inode_reg_map = 0;
950         ext2fs_free_block_bitmap(ctx->block_found_map);
951         ctx->block_found_map = 0;
952         ext2fs_free_icount(ctx->inode_link_info);
953         ctx->inode_link_info = 0;
954         if (ctx->journal_io) {
955                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
956                         io_channel_close(ctx->journal_io);
957                 ctx->journal_io = 0;
958         }
959         if (ctx->fs) {
960                 ext2fs_free_dblist(ctx->fs->dblist);
961                 ctx->fs->dblist = 0;
962         }
963         e2fsck_free_dir_info(ctx);
964 #ifdef ENABLE_HTREE
965         e2fsck_free_dx_dir_info(ctx);
966 #endif
967         ea_refcount_free(ctx->refcount);
968         ctx->refcount = 0;
969         ea_refcount_free(ctx->refcount_extra);
970         ctx->refcount_extra = 0;
971         ext2fs_free_block_bitmap(ctx->block_dup_map);
972         ctx->block_dup_map = 0;
973         ext2fs_free_block_bitmap(ctx->block_ea_map);
974         ctx->block_ea_map = 0;
975         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
976         ctx->inode_bad_map = 0;
977         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
978         ctx->inode_imagic_map = 0;
979         ext2fs_u32_list_free(ctx->dirs_to_hash);
980         ctx->dirs_to_hash = 0;
981
982         /*
983          * Clear the array of invalid meta-data flags
984          */
985         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
986         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
987         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
988
989         /* Clear statistic counters */
990         ctx->fs_directory_count = 0;
991         ctx->fs_regular_count = 0;
992         ctx->fs_blockdev_count = 0;
993         ctx->fs_chardev_count = 0;
994         ctx->fs_links_count = 0;
995         ctx->fs_symlinks_count = 0;
996         ctx->fs_fast_symlinks_count = 0;
997         ctx->fs_fifo_count = 0;
998         ctx->fs_total_count = 0;
999         ctx->fs_sockets_count = 0;
1000         ctx->fs_ind_count = 0;
1001         ctx->fs_dind_count = 0;
1002         ctx->fs_tind_count = 0;
1003         ctx->fs_fragmented = 0;
1004         ctx->large_files = 0;
1005
1006         /* Reset the superblock to the user's requested value */
1007         ctx->superblock = ctx->use_superblock;
1008
1009         return 0;
1010 }
1011
1012 static void e2fsck_free_context(e2fsck_t ctx)
1013 {
1014         if (!ctx)
1015                 return;
1016
1017         e2fsck_reset_context(ctx);
1018         if (ctx->blkid)
1019                 blkid_put_cache(ctx->blkid);
1020
1021         ext2fs_free_mem(&ctx);
1022 }
1023
1024 /*
1025  * ea_refcount.c
1026  */
1027
1028 /*
1029  * The strategy we use for keeping track of EA refcounts is as
1030  * follows.  We keep a sorted array of first EA blocks and its
1031  * reference counts.  Once the refcount has dropped to zero, it is
1032  * removed from the array to save memory space.  Once the EA block is
1033  * checked, its bit is set in the block_ea_map bitmap.
1034  */
1035
1036
1037 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1038 {
1039         ext2_refcount_t refcount;
1040         errcode_t       retval;
1041         size_t          bytes;
1042
1043         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1044         if (retval)
1045                 return retval;
1046         memset(refcount, 0, sizeof(struct ea_refcount));
1047
1048         if (!size)
1049                 size = 500;
1050         refcount->size = size;
1051         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1052 #ifdef DEBUG
1053         printf("Refcount allocated %d entries, %lu bytes.\n",
1054                refcount->size, bytes);
1055 #endif
1056         retval = ext2fs_get_mem(bytes, &refcount->list);
1057         if (retval)
1058                 goto errout;
1059         memset(refcount->list, 0, bytes);
1060
1061         refcount->count = 0;
1062         refcount->cursor = 0;
1063
1064         *ret = refcount;
1065         return 0;
1066
1067 errout:
1068         ea_refcount_free(refcount);
1069         return retval;
1070 }
1071
1072 /*
1073  * collapse_refcount() --- go through the refcount array, and get rid
1074  * of any count == zero entries
1075  */
1076 static void refcount_collapse(ext2_refcount_t refcount)
1077 {
1078         unsigned int    i, j;
1079         struct ea_refcount_el   *list;
1080
1081         list = refcount->list;
1082         for (i = 0, j = 0; i < refcount->count; i++) {
1083                 if (list[i].ea_count) {
1084                         if (i != j)
1085                                 list[j] = list[i];
1086                         j++;
1087                 }
1088         }
1089 #if defined(DEBUG) || defined(TEST_PROGRAM)
1090         printf("Refcount_collapse: size was %d, now %d\n",
1091                refcount->count, j);
1092 #endif
1093         refcount->count = j;
1094 }
1095
1096
1097 /*
1098  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1099  *      specified position.
1100  */
1101 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1102                                                  blk_t blk, int pos)
1103 {
1104         struct ea_refcount_el   *el;
1105         errcode_t               retval;
1106         blk_t                   new_size = 0;
1107         int                     num;
1108
1109         if (refcount->count >= refcount->size) {
1110                 new_size = refcount->size + 100;
1111 #ifdef DEBUG
1112                 printf("Reallocating refcount %d entries...\n", new_size);
1113 #endif
1114                 retval = ext2fs_resize_mem((size_t) refcount->size *
1115                                            sizeof(struct ea_refcount_el),
1116                                            (size_t) new_size *
1117                                            sizeof(struct ea_refcount_el),
1118                                            &refcount->list);
1119                 if (retval)
1120                         return 0;
1121                 refcount->size = new_size;
1122         }
1123         num = (int) refcount->count - pos;
1124         if (num < 0)
1125                 return 0;       /* should never happen */
1126         if (num) {
1127                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1128                         sizeof(struct ea_refcount_el) * num);
1129         }
1130         refcount->count++;
1131         el = &refcount->list[pos];
1132         el->ea_count = 0;
1133         el->ea_blk = blk;
1134         return el;
1135 }
1136
1137
1138 /*
1139  * get_refcount_el() --- given an block number, try to find refcount
1140  *      information in the sorted list.  If the create flag is set,
1141  *      and we can't find an entry, create one in the sorted list.
1142  */
1143 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1144                                               blk_t blk, int create)
1145 {
1146         float   range;
1147         int     low, high, mid;
1148         blk_t   lowval, highval;
1149
1150         if (!refcount || !refcount->list)
1151                 return 0;
1152 retry:
1153         low = 0;
1154         high = (int) refcount->count-1;
1155         if (create && ((refcount->count == 0) ||
1156                        (blk > refcount->list[high].ea_blk))) {
1157                 if (refcount->count >= refcount->size)
1158                         refcount_collapse(refcount);
1159
1160                 return insert_refcount_el(refcount, blk,
1161                                           (unsigned) refcount->count);
1162         }
1163         if (refcount->count == 0)
1164                 return 0;
1165
1166         if (refcount->cursor >= refcount->count)
1167                 refcount->cursor = 0;
1168         if (blk == refcount->list[refcount->cursor].ea_blk)
1169                 return &refcount->list[refcount->cursor++];
1170 #ifdef DEBUG
1171         printf("Non-cursor get_refcount_el: %u\n", blk);
1172 #endif
1173         while (low <= high) {
1174                 if (low == high)
1175                         mid = low;
1176                 else {
1177                         /* Interpolate for efficiency */
1178                         lowval = refcount->list[low].ea_blk;
1179                         highval = refcount->list[high].ea_blk;
1180
1181                         if (blk < lowval)
1182                                 range = 0;
1183                         else if (blk > highval)
1184                                 range = 1;
1185                         else
1186                                 range = ((float) (blk - lowval)) /
1187                                         (highval - lowval);
1188                         mid = low + ((int) (range * (high-low)));
1189                 }
1190
1191                 if (blk == refcount->list[mid].ea_blk) {
1192                         refcount->cursor = mid+1;
1193                         return &refcount->list[mid];
1194                 }
1195                 if (blk < refcount->list[mid].ea_blk)
1196                         high = mid-1;
1197                 else
1198                         low = mid+1;
1199         }
1200         /*
1201          * If we need to create a new entry, it should be right at
1202          * low (where high will be left at low-1).
1203          */
1204         if (create) {
1205                 if (refcount->count >= refcount->size) {
1206                         refcount_collapse(refcount);
1207                         if (refcount->count < refcount->size)
1208                                 goto retry;
1209                 }
1210                 return insert_refcount_el(refcount, blk, low);
1211         }
1212         return 0;
1213 }
1214
1215 static errcode_t
1216 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1217 {
1218         struct ea_refcount_el   *el;
1219
1220         el = get_refcount_el(refcount, blk, 1);
1221         if (!el)
1222                 return EXT2_ET_NO_MEMORY;
1223         el->ea_count++;
1224
1225         if (ret)
1226                 *ret = el->ea_count;
1227         return 0;
1228 }
1229
1230 static errcode_t
1231 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1232 {
1233         struct ea_refcount_el   *el;
1234
1235         el = get_refcount_el(refcount, blk, 0);
1236         if (!el || el->ea_count == 0)
1237                 return EXT2_ET_INVALID_ARGUMENT;
1238
1239         el->ea_count--;
1240
1241         if (ret)
1242                 *ret = el->ea_count;
1243         return 0;
1244 }
1245
1246 static errcode_t
1247 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1248 {
1249         struct ea_refcount_el   *el;
1250
1251         /*
1252          * Get the refcount element
1253          */
1254         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1255         if (!el)
1256                 return count ? EXT2_ET_NO_MEMORY : 0;
1257         el->ea_count = count;
1258         return 0;
1259 }
1260
1261 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1262 {
1263         refcount->cursor = 0;
1264 }
1265
1266
1267 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1268 {
1269         struct ea_refcount_el   *list;
1270
1271         while (1) {
1272                 if (refcount->cursor >= refcount->count)
1273                         return 0;
1274                 list = refcount->list;
1275                 if (list[refcount->cursor].ea_count) {
1276                         if (ret)
1277                                 *ret = list[refcount->cursor].ea_count;
1278                         return list[refcount->cursor++].ea_blk;
1279                 }
1280                 refcount->cursor++;
1281         }
1282 }
1283
1284
1285 /*
1286  * ehandler.c --- handle bad block errors which come up during the
1287  *      course of an e2fsck session.
1288  */
1289
1290
1291 static const char *operation;
1292
1293 static errcode_t
1294 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1295                          void *data, size_t size FSCK_ATTR((unused)),
1296                          int actual FSCK_ATTR((unused)), errcode_t error)
1297 {
1298         int     i;
1299         char    *p;
1300         ext2_filsys fs = (ext2_filsys) channel->app_data;
1301         e2fsck_t ctx;
1302
1303         ctx = (e2fsck_t) fs->priv_data;
1304
1305         /*
1306          * If more than one block was read, try reading each block
1307          * separately.  We could use the actual bytes read to figure
1308          * out where to start, but we don't bother.
1309          */
1310         if (count > 1) {
1311                 p = (char *) data;
1312                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1313                         error = io_channel_read_blk(channel, block,
1314                                                     1, p);
1315                         if (error)
1316                                 return error;
1317                 }
1318                 return 0;
1319         }
1320         if (operation)
1321                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1322                        error_message(error), operation);
1323         else
1324                 printf(_("Error reading block %lu (%s).  "), block,
1325                        error_message(error));
1326         preenhalt(ctx);
1327         if (ask(ctx, _("Ignore error"), 1)) {
1328                 if (ask(ctx, _("Force rewrite"), 1))
1329                         io_channel_write_blk(channel, block, 1, data);
1330                 return 0;
1331         }
1332
1333         return error;
1334 }
1335
1336 static errcode_t
1337 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1338                         const void *data, size_t size FSCK_ATTR((unused)),
1339                         int actual FSCK_ATTR((unused)), errcode_t error)
1340 {
1341         int             i;
1342         const char      *p;
1343         ext2_filsys fs = (ext2_filsys) channel->app_data;
1344         e2fsck_t ctx;
1345
1346         ctx = (e2fsck_t) fs->priv_data;
1347
1348         /*
1349          * If more than one block was written, try writing each block
1350          * separately.  We could use the actual bytes read to figure
1351          * out where to start, but we don't bother.
1352          */
1353         if (count > 1) {
1354                 p = (const char *) data;
1355                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1356                         error = io_channel_write_blk(channel, block,
1357                                                      1, p);
1358                         if (error)
1359                                 return error;
1360                 }
1361                 return 0;
1362         }
1363
1364         if (operation)
1365                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1366                        error_message(error), operation);
1367         else
1368                 printf(_("Error writing block %lu (%s).  "), block,
1369                        error_message(error));
1370         preenhalt(ctx);
1371         if (ask(ctx, _("Ignore error"), 1))
1372                 return 0;
1373
1374         return error;
1375 }
1376
1377 static const char *ehandler_operation(const char *op)
1378 {
1379         const char *ret = operation;
1380
1381         operation = op;
1382         return ret;
1383 }
1384
1385 static void ehandler_init(io_channel channel)
1386 {
1387         channel->read_error = e2fsck_handle_read_error;
1388         channel->write_error = e2fsck_handle_write_error;
1389 }
1390
1391 /*
1392  * journal.c --- code for handling the "ext3" journal
1393  *
1394  * Copyright (C) 2000 Andreas Dilger
1395  * Copyright (C) 2000 Theodore Ts'o
1396  *
1397  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1398  * Copyright (C) 1999 Red Hat Software
1399  *
1400  * This file may be redistributed under the terms of the
1401  * GNU General Public License version 2 or at your discretion
1402  * any later version.
1403  */
1404
1405 /*
1406  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1407  * This creates a larger static binary, and a smaller binary using
1408  * shared libraries.  It's also probably slightly less CPU-efficient,
1409  * which is why it's not on by default.  But, it's a good way of
1410  * testing the functions in inode_io.c and fileio.c.
1411  */
1412 #undef USE_INODE_IO
1413
1414 /* Kernel compatibility functions for handling the journal.  These allow us
1415  * to use the recovery.c file virtually unchanged from the kernel, so we
1416  * don't have to do much to keep kernel and user recovery in sync.
1417  */
1418 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1419 {
1420 #ifdef USE_INODE_IO
1421         *phys = block;
1422         return 0;
1423 #else
1424         struct inode    *inode = journal->j_inode;
1425         errcode_t       retval;
1426         blk_t           pblk;
1427
1428         if (!inode) {
1429                 *phys = block;
1430                 return 0;
1431         }
1432
1433         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1434                             &inode->i_ext2, NULL, 0, block, &pblk);
1435         *phys = pblk;
1436         return retval;
1437 #endif
1438 }
1439
1440 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1441 {
1442         struct buffer_head *bh;
1443
1444         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1445         if (!bh)
1446                 return NULL;
1447
1448         bh->b_ctx = kdev->k_ctx;
1449         if (kdev->k_dev == K_DEV_FS)
1450                 bh->b_io = kdev->k_ctx->fs->io;
1451         else
1452                 bh->b_io = kdev->k_ctx->journal_io;
1453         bh->b_size = blocksize;
1454         bh->b_blocknr = blocknr;
1455
1456         return bh;
1457 }
1458
1459 static void sync_blockdev(kdev_t kdev)
1460 {
1461         io_channel      io;
1462
1463         if (kdev->k_dev == K_DEV_FS)
1464                 io = kdev->k_ctx->fs->io;
1465         else
1466                 io = kdev->k_ctx->journal_io;
1467
1468         io_channel_flush(io);
1469 }
1470
1471 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1472 {
1473         int retval;
1474         struct buffer_head *bh;
1475
1476         for (; nr > 0; --nr) {
1477                 bh = *bhp++;
1478                 if (rw == READ && !bh->b_uptodate) {
1479                         retval = io_channel_read_blk(bh->b_io,
1480                                                      bh->b_blocknr,
1481                                                      1, bh->b_data);
1482                         if (retval) {
1483                                 bb_error_msg("while reading block %lu",
1484                                         (unsigned long) bh->b_blocknr);
1485                                 bh->b_err = retval;
1486                                 continue;
1487                         }
1488                         bh->b_uptodate = 1;
1489                 } else if (rw == WRITE && bh->b_dirty) {
1490                         retval = io_channel_write_blk(bh->b_io,
1491                                                       bh->b_blocknr,
1492                                                       1, bh->b_data);
1493                         if (retval) {
1494                                 bb_error_msg("while writing block %lu",
1495                                         (unsigned long) bh->b_blocknr);
1496                                 bh->b_err = retval;
1497                                 continue;
1498                         }
1499                         bh->b_dirty = 0;
1500                         bh->b_uptodate = 1;
1501                 }
1502         }
1503 }
1504
1505 static void mark_buffer_dirty(struct buffer_head *bh)
1506 {
1507         bh->b_dirty = 1;
1508 }
1509
1510 static inline void mark_buffer_clean(struct buffer_head * bh)
1511 {
1512         bh->b_dirty = 0;
1513 }
1514
1515 static void brelse(struct buffer_head *bh)
1516 {
1517         if (bh->b_dirty)
1518                 ll_rw_block(WRITE, 1, &bh);
1519         ext2fs_free_mem(&bh);
1520 }
1521
1522 static int buffer_uptodate(struct buffer_head *bh)
1523 {
1524         return bh->b_uptodate;
1525 }
1526
1527 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1528 {
1529         bh->b_uptodate = val;
1530 }
1531
1532 static void wait_on_buffer(struct buffer_head *bh)
1533 {
1534         if (!bh->b_uptodate)
1535                 ll_rw_block(READ, 1, &bh);
1536 }
1537
1538
1539 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1540 {
1541         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1542
1543         /* if we had an error doing journal recovery, we need a full fsck */
1544         if (error)
1545                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1546         ext2fs_mark_super_dirty(ctx->fs);
1547 }
1548
1549 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1550 {
1551         struct ext2_super_block *sb = ctx->fs->super;
1552         struct ext2_super_block jsuper;
1553         struct problem_context  pctx;
1554         struct buffer_head      *bh;
1555         struct inode            *j_inode = NULL;
1556         struct kdev_s           *dev_fs = NULL, *dev_journal;
1557         const char              *journal_name = NULL;
1558         journal_t               *journal = NULL;
1559         errcode_t               retval = 0;
1560         io_manager              io_ptr = 0;
1561         unsigned long           start = 0;
1562         blk_t                   blk;
1563         int                     ext_journal = 0;
1564         int                     tried_backup_jnl = 0;
1565         int                     i;
1566
1567         clear_problem_context(&pctx);
1568
1569         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1570         if (!journal) {
1571                 return EXT2_ET_NO_MEMORY;
1572         }
1573
1574         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1575         if (!dev_fs) {
1576                 retval = EXT2_ET_NO_MEMORY;
1577                 goto errout;
1578         }
1579         dev_journal = dev_fs+1;
1580
1581         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1582         dev_fs->k_dev = K_DEV_FS;
1583         dev_journal->k_dev = K_DEV_JOURNAL;
1584
1585         journal->j_dev = dev_journal;
1586         journal->j_fs_dev = dev_fs;
1587         journal->j_inode = NULL;
1588         journal->j_blocksize = ctx->fs->blocksize;
1589
1590         if (uuid_is_null(sb->s_journal_uuid)) {
1591                 if (!sb->s_journal_inum)
1592                         return EXT2_ET_BAD_INODE_NUM;
1593                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1594                                                  "journal inode");
1595                 if (!j_inode) {
1596                         retval = EXT2_ET_NO_MEMORY;
1597                         goto errout;
1598                 }
1599
1600                 j_inode->i_ctx = ctx;
1601                 j_inode->i_ino = sb->s_journal_inum;
1602
1603                 if ((retval = ext2fs_read_inode(ctx->fs,
1604                                                 sb->s_journal_inum,
1605                                                 &j_inode->i_ext2))) {
1606                 try_backup_journal:
1607                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1608                             tried_backup_jnl)
1609                                 goto errout;
1610                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1611                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1612                                EXT2_N_BLOCKS*4);
1613                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1614                         j_inode->i_ext2.i_links_count = 1;
1615                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1616                         tried_backup_jnl++;
1617                 }
1618                 if (!j_inode->i_ext2.i_links_count ||
1619                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1620                         retval = EXT2_ET_NO_JOURNAL;
1621                         goto try_backup_journal;
1622                 }
1623                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1624                     JFS_MIN_JOURNAL_BLOCKS) {
1625                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1626                         goto try_backup_journal;
1627                 }
1628                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1629                         blk = j_inode->i_ext2.i_block[i];
1630                         if (!blk) {
1631                                 if (i < EXT2_NDIR_BLOCKS) {
1632                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1633                                         goto try_backup_journal;
1634                                 }
1635                                 continue;
1636                         }
1637                         if (blk < sb->s_first_data_block ||
1638                             blk >= sb->s_blocks_count) {
1639                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1640                                 goto try_backup_journal;
1641                         }
1642                 }
1643                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1644
1645 #ifdef USE_INODE_IO
1646                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1647                                                  &j_inode->i_ext2,
1648                                                  &journal_name);
1649                 if (retval)
1650                         goto errout;
1651
1652                 io_ptr = inode_io_manager;
1653 #else
1654                 journal->j_inode = j_inode;
1655                 ctx->journal_io = ctx->fs->io;
1656                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1657                         goto errout;
1658 #endif
1659         } else {
1660                 ext_journal = 1;
1661                 if (!ctx->journal_name) {
1662                         char uuid[37];
1663
1664                         uuid_unparse(sb->s_journal_uuid, uuid);
1665                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1666                                                               "UUID", uuid);
1667                         if (!ctx->journal_name)
1668                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1669                 }
1670                 journal_name = ctx->journal_name;
1671
1672                 if (!journal_name) {
1673                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1674                         return EXT2_ET_LOAD_EXT_JOURNAL;
1675                 }
1676
1677                 io_ptr = unix_io_manager;
1678         }
1679
1680 #ifndef USE_INODE_IO
1681         if (ext_journal)
1682 #endif
1683                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1684                                       &ctx->journal_io);
1685         if (retval)
1686                 goto errout;
1687
1688         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1689
1690         if (ext_journal) {
1691                 if (ctx->fs->blocksize == 1024)
1692                         start = 1;
1693                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1694                 if (!bh) {
1695                         retval = EXT2_ET_NO_MEMORY;
1696                         goto errout;
1697                 }
1698                 ll_rw_block(READ, 1, &bh);
1699                 if ((retval = bh->b_err) != 0)
1700                         goto errout;
1701                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1702                        sizeof(jsuper));
1703                 brelse(bh);
1704 #if BB_BIG_ENDIAN
1705                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1706                         ext2fs_swap_super(&jsuper);
1707 #endif
1708                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1709                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1710                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1711                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1712                         goto errout;
1713                 }
1714                 /* Make sure the journal UUID is correct */
1715                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1716                            sizeof(jsuper.s_uuid))) {
1717                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1718                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1719                         goto errout;
1720                 }
1721
1722                 journal->j_maxlen = jsuper.s_blocks_count;
1723                 start++;
1724         }
1725
1726         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1727                 retval = EXT2_ET_NO_MEMORY;
1728                 goto errout;
1729         }
1730
1731         journal->j_sb_buffer = bh;
1732         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1733
1734 #ifdef USE_INODE_IO
1735         ext2fs_free_mem(&j_inode);
1736 #endif
1737
1738         *ret_journal = journal;
1739         return 0;
1740
1741 errout:
1742         ext2fs_free_mem(&dev_fs);
1743         ext2fs_free_mem(&j_inode);
1744         ext2fs_free_mem(&journal);
1745         return retval;
1746 }
1747
1748 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1749                                               struct problem_context *pctx)
1750 {
1751         struct ext2_super_block *sb = ctx->fs->super;
1752         int recover = ctx->fs->super->s_feature_incompat &
1753                 EXT3_FEATURE_INCOMPAT_RECOVER;
1754         int has_journal = ctx->fs->super->s_feature_compat &
1755                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1756
1757         if (has_journal || sb->s_journal_inum) {
1758                 /* The journal inode is bogus, remove and force full fsck */
1759                 pctx->ino = sb->s_journal_inum;
1760                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1761                         if (has_journal && sb->s_journal_inum)
1762                                 printf("*** ext3 journal has been deleted - "
1763                                        "filesystem is now ext2 only ***\n\n");
1764                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1765                         sb->s_journal_inum = 0;
1766                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1767                         e2fsck_clear_recover(ctx, 1);
1768                         return 0;
1769                 }
1770                 return EXT2_ET_BAD_INODE_NUM;
1771         } else if (recover) {
1772                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1773                         e2fsck_clear_recover(ctx, 1);
1774                         return 0;
1775                 }
1776                 return EXT2_ET_UNSUPP_FEATURE;
1777         }
1778         return 0;
1779 }
1780
1781 #define V1_SB_SIZE      0x0024
1782 static void clear_v2_journal_fields(journal_t *journal)
1783 {
1784         e2fsck_t ctx = journal->j_dev->k_ctx;
1785         struct problem_context pctx;
1786
1787         clear_problem_context(&pctx);
1788
1789         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1790                 return;
1791
1792         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1793                ctx->fs->blocksize-V1_SB_SIZE);
1794         mark_buffer_dirty(journal->j_sb_buffer);
1795 }
1796
1797
1798 static errcode_t e2fsck_journal_load(journal_t *journal)
1799 {
1800         e2fsck_t ctx = journal->j_dev->k_ctx;
1801         journal_superblock_t *jsb;
1802         struct buffer_head *jbh = journal->j_sb_buffer;
1803         struct problem_context pctx;
1804
1805         clear_problem_context(&pctx);
1806
1807         ll_rw_block(READ, 1, &jbh);
1808         if (jbh->b_err) {
1809                 bb_error_msg(_("reading journal superblock"));
1810                 return jbh->b_err;
1811         }
1812
1813         jsb = journal->j_superblock;
1814         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1815         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1816                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1817
1818         switch (ntohl(jsb->s_header.h_blocktype)) {
1819         case JFS_SUPERBLOCK_V1:
1820                 journal->j_format_version = 1;
1821                 if (jsb->s_feature_compat ||
1822                     jsb->s_feature_incompat ||
1823                     jsb->s_feature_ro_compat ||
1824                     jsb->s_nr_users)
1825                         clear_v2_journal_fields(journal);
1826                 break;
1827
1828         case JFS_SUPERBLOCK_V2:
1829                 journal->j_format_version = 2;
1830                 if (ntohl(jsb->s_nr_users) > 1 &&
1831                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1832                         clear_v2_journal_fields(journal);
1833                 if (ntohl(jsb->s_nr_users) > 1) {
1834                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1835                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1836                 }
1837                 break;
1838
1839         /*
1840          * These should never appear in a journal super block, so if
1841          * they do, the journal is badly corrupted.
1842          */
1843         case JFS_DESCRIPTOR_BLOCK:
1844         case JFS_COMMIT_BLOCK:
1845         case JFS_REVOKE_BLOCK:
1846                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1847
1848         /* If we don't understand the superblock major type, but there
1849          * is a magic number, then it is likely to be a new format we
1850          * just don't understand, so leave it alone. */
1851         default:
1852                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1853         }
1854
1855         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1856                 return EXT2_ET_UNSUPP_FEATURE;
1857
1858         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1859                 return EXT2_ET_RO_UNSUPP_FEATURE;
1860
1861         /* We have now checked whether we know enough about the journal
1862          * format to be able to proceed safely, so any other checks that
1863          * fail we should attempt to recover from. */
1864         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1865                 bb_error_msg(_("%s: no valid journal superblock found"),
1866                         ctx->device_name);
1867                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1868         }
1869
1870         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1871                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1872         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1873                 bb_error_msg(_("%s: journal too short"),
1874                         ctx->device_name);
1875                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1876         }
1877
1878         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1879         journal->j_transaction_sequence = journal->j_tail_sequence;
1880         journal->j_tail = ntohl(jsb->s_start);
1881         journal->j_first = ntohl(jsb->s_first);
1882         journal->j_last = ntohl(jsb->s_maxlen);
1883
1884         return 0;
1885 }
1886
1887 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1888                                        journal_t *journal)
1889 {
1890         char *p;
1891         union {
1892                 uuid_t uuid;
1893                 __u32 val[4];
1894         } u;
1895         __u32 new_seq = 0;
1896         int i;
1897
1898         /* Leave a valid existing V1 superblock signature alone.
1899          * Anything unrecognizable we overwrite with a new V2
1900          * signature. */
1901
1902         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1903             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1904                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1905                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1906         }
1907
1908         /* Zero out everything else beyond the superblock header */
1909
1910         p = ((char *) jsb) + sizeof(journal_header_t);
1911         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1912
1913         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1914         jsb->s_maxlen = htonl(journal->j_maxlen);
1915         jsb->s_first = htonl(1);
1916
1917         /* Initialize the journal sequence number so that there is "no"
1918          * chance we will find old "valid" transactions in the journal.
1919          * This avoids the need to zero the whole journal (slow to do,
1920          * and risky when we are just recovering the filesystem).
1921          */
1922         uuid_generate(u.uuid);
1923         for (i = 0; i < 4; i ++)
1924                 new_seq ^= u.val[i];
1925         jsb->s_sequence = htonl(new_seq);
1926
1927         mark_buffer_dirty(journal->j_sb_buffer);
1928         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1929 }
1930
1931 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1932                                                   journal_t *journal,
1933                                                   struct problem_context *pctx)
1934 {
1935         struct ext2_super_block *sb = ctx->fs->super;
1936         int recover = ctx->fs->super->s_feature_incompat &
1937                 EXT3_FEATURE_INCOMPAT_RECOVER;
1938
1939         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1940                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1941                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1942                                                    journal);
1943                         journal->j_transaction_sequence = 1;
1944                         e2fsck_clear_recover(ctx, recover);
1945                         return 0;
1946                 }
1947                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1948         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1949                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1950
1951         return 0;
1952 }
1953
1954 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1955                                    int reset, int drop)
1956 {
1957         journal_superblock_t *jsb;
1958
1959         if (drop)
1960                 mark_buffer_clean(journal->j_sb_buffer);
1961         else if (!(ctx->options & E2F_OPT_READONLY)) {
1962                 jsb = journal->j_superblock;
1963                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1964                 if (reset)
1965                         jsb->s_start = 0; /* this marks the journal as empty */
1966                 mark_buffer_dirty(journal->j_sb_buffer);
1967         }
1968         brelse(journal->j_sb_buffer);
1969
1970         if (ctx->journal_io) {
1971                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1972                         io_channel_close(ctx->journal_io);
1973                 ctx->journal_io = 0;
1974         }
1975
1976 #ifndef USE_INODE_IO
1977         ext2fs_free_mem(&journal->j_inode);
1978 #endif
1979         ext2fs_free_mem(&journal->j_fs_dev);
1980         ext2fs_free_mem(&journal);
1981 }
1982
1983 /*
1984  * This function makes sure that the superblock fields regarding the
1985  * journal are consistent.
1986  */
1987 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1988 {
1989         struct ext2_super_block *sb = ctx->fs->super;
1990         journal_t *journal;
1991         int recover = ctx->fs->super->s_feature_incompat &
1992                 EXT3_FEATURE_INCOMPAT_RECOVER;
1993         struct problem_context pctx;
1994         problem_t problem;
1995         int reset = 0, force_fsck = 0;
1996         int retval;
1997
1998         /* If we don't have any journal features, don't do anything more */
1999         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2000             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2001             uuid_is_null(sb->s_journal_uuid))
2002                 return 0;
2003
2004         clear_problem_context(&pctx);
2005         pctx.num = sb->s_journal_inum;
2006
2007         retval = e2fsck_get_journal(ctx, &journal);
2008         if (retval) {
2009                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2010                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2011                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2012                     (retval == EXT2_ET_NO_JOURNAL))
2013                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2014                 return retval;
2015         }
2016
2017         retval = e2fsck_journal_load(journal);
2018         if (retval) {
2019                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2020                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2021                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2022                                   &pctx))) ||
2023                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2024                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2025                                   &pctx))) ||
2026                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2027                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2028                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2029                                                                   &pctx);
2030                 e2fsck_journal_release(ctx, journal, 0, 1);
2031                 return retval;
2032         }
2033
2034         /*
2035          * We want to make the flags consistent here.  We will not leave with
2036          * needs_recovery set but has_journal clear.  We can't get in a loop
2037          * with -y, -n, or -p, only if a user isn't making up their mind.
2038          */
2039 no_has_journal:
2040         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2041                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2042                 pctx.str = "inode";
2043                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2044                         if (recover &&
2045                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2046                                 goto no_has_journal;
2047                         /*
2048                          * Need a full fsck if we are releasing a
2049                          * journal stored on a reserved inode.
2050                          */
2051                         force_fsck = recover ||
2052                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2053                         /* Clear all of the journal fields */
2054                         sb->s_journal_inum = 0;
2055                         sb->s_journal_dev = 0;
2056                         memset(sb->s_journal_uuid, 0,
2057                                sizeof(sb->s_journal_uuid));
2058                         e2fsck_clear_recover(ctx, force_fsck);
2059                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2060                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2061                         ext2fs_mark_super_dirty(ctx->fs);
2062                 }
2063         }
2064
2065         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2066             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2067             journal->j_superblock->s_start != 0) {
2068                 /* Print status information */
2069                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2070                 if (ctx->superblock)
2071                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2072                 else
2073                         problem = PR_0_JOURNAL_RUN;
2074                 if (fix_problem(ctx, problem, &pctx)) {
2075                         ctx->options |= E2F_OPT_FORCE;
2076                         sb->s_feature_incompat |=
2077                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2078                         ext2fs_mark_super_dirty(ctx->fs);
2079                 } else if (fix_problem(ctx,
2080                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2081                         reset = 1;
2082                         sb->s_state &= ~EXT2_VALID_FS;
2083                         ext2fs_mark_super_dirty(ctx->fs);
2084                 }
2085                 /*
2086                  * If the user answers no to the above question, we
2087                  * ignore the fact that journal apparently has data;
2088                  * accidentally replaying over valid data would be far
2089                  * worse than skipping a questionable recovery.
2090                  *
2091                  * XXX should we abort with a fatal error here?  What
2092                  * will the ext3 kernel code do if a filesystem with
2093                  * !NEEDS_RECOVERY but with a non-zero
2094                  * journal->j_superblock->s_start is mounted?
2095                  */
2096         }
2097
2098         e2fsck_journal_release(ctx, journal, reset, 0);
2099         return retval;
2100 }
2101
2102 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2103 {
2104         journal_t *journal;
2105         int retval;
2106
2107         journal_init_revoke_caches();
2108         retval = e2fsck_get_journal(ctx, &journal);
2109         if (retval)
2110                 return retval;
2111
2112         retval = e2fsck_journal_load(journal);
2113         if (retval)
2114                 goto errout;
2115
2116         retval = journal_init_revoke(journal, 1024);
2117         if (retval)
2118                 goto errout;
2119
2120         retval = -journal_recover(journal);
2121         if (retval)
2122                 goto errout;
2123
2124         if (journal->j_superblock->s_errno) {
2125                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2126                 ext2fs_mark_super_dirty(ctx->fs);
2127                 journal->j_superblock->s_errno = 0;
2128                 mark_buffer_dirty(journal->j_sb_buffer);
2129         }
2130
2131 errout:
2132         journal_destroy_revoke(journal);
2133         journal_destroy_revoke_caches();
2134         e2fsck_journal_release(ctx, journal, 1, 0);
2135         return retval;
2136 }
2137
2138 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2139 {
2140         io_manager io_ptr = ctx->fs->io->manager;
2141         int blocksize = ctx->fs->blocksize;
2142         errcode_t       retval, recover_retval;
2143
2144         printf(_("%s: recovering journal\n"), ctx->device_name);
2145         if (ctx->options & E2F_OPT_READONLY) {
2146                 printf(_("%s: won't do journal recovery while read-only\n"),
2147                        ctx->device_name);
2148                 return EXT2_ET_FILE_RO;
2149         }
2150
2151         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2152                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2153
2154         recover_retval = recover_ext3_journal(ctx);
2155
2156         /*
2157          * Reload the filesystem context to get up-to-date data from disk
2158          * because journal recovery will change the filesystem under us.
2159          */
2160         ext2fs_close(ctx->fs);
2161         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2162                              ctx->superblock, blocksize, io_ptr,
2163                              &ctx->fs);
2164
2165         if (retval) {
2166                 bb_error_msg(_("while trying to re-open %s"),
2167                         ctx->device_name);
2168                 bb_error_msg_and_die(0);
2169         }
2170         ctx->fs->priv_data = ctx;
2171
2172         /* Set the superblock flags */
2173         e2fsck_clear_recover(ctx, recover_retval);
2174         return recover_retval;
2175 }
2176
2177 /*
2178  * This function will move the journal inode from a visible file in
2179  * the filesystem directory hierarchy to the reserved inode if necessary.
2180  */
2181 static const char *const journal_names[] = {
2182         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2183
2184 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2185 {
2186         struct ext2_super_block *sb = ctx->fs->super;
2187         struct problem_context  pctx;
2188         struct ext2_inode       inode;
2189         ext2_filsys             fs = ctx->fs;
2190         ext2_ino_t              ino;
2191         errcode_t               retval;
2192         const char *const *    cpp;
2193         int                     group, mount_flags;
2194
2195         clear_problem_context(&pctx);
2196
2197         /*
2198          * If the filesystem is opened read-only, or there is no
2199          * journal, then do nothing.
2200          */
2201         if ((ctx->options & E2F_OPT_READONLY) ||
2202             (sb->s_journal_inum == 0) ||
2203             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2204                 return;
2205
2206         /*
2207          * Read in the journal inode
2208          */
2209         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2210                 return;
2211
2212         /*
2213          * If it's necessary to backup the journal inode, do so.
2214          */
2215         if ((sb->s_jnl_backup_type == 0) ||
2216             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2217              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2218                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2219                         memcpy(sb->s_jnl_blocks, inode.i_block,
2220                                EXT2_N_BLOCKS*4);
2221                         sb->s_jnl_blocks[16] = inode.i_size;
2222                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2223                         ext2fs_mark_super_dirty(fs);
2224                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2225                 }
2226         }
2227
2228         /*
2229          * If the journal is already the hidden inode, then do nothing
2230          */
2231         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2232                 return;
2233
2234         /*
2235          * The journal inode had better have only one link and not be readable.
2236          */
2237         if (inode.i_links_count != 1)
2238                 return;
2239
2240         /*
2241          * If the filesystem is mounted, or we can't tell whether
2242          * or not it's mounted, do nothing.
2243          */
2244         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2245         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2246                 return;
2247
2248         /*
2249          * If we can't find the name of the journal inode, then do
2250          * nothing.
2251          */
2252         for (cpp = journal_names; *cpp; cpp++) {
2253                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2254                                        strlen(*cpp), 0, &ino);
2255                 if ((retval == 0) && (ino == sb->s_journal_inum))
2256                         break;
2257         }
2258         if (*cpp == 0)
2259                 return;
2260
2261         /* We need the inode bitmap to be loaded */
2262         retval = ext2fs_read_bitmaps(fs);
2263         if (retval)
2264                 return;
2265
2266         pctx.str = *cpp;
2267         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2268                 return;
2269
2270         /*
2271          * OK, we've done all the checks, let's actually move the
2272          * journal inode.  Errors at this point mean we need to force
2273          * an ext2 filesystem check.
2274          */
2275         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2276                 goto err_out;
2277         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2278                 goto err_out;
2279         sb->s_journal_inum = EXT2_JOURNAL_INO;
2280         ext2fs_mark_super_dirty(fs);
2281         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2282         inode.i_links_count = 0;
2283         inode.i_dtime = time(NULL);
2284         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2285                 goto err_out;
2286
2287         group = ext2fs_group_of_ino(fs, ino);
2288         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2289         ext2fs_mark_ib_dirty(fs);
2290         fs->group_desc[group].bg_free_inodes_count++;
2291         fs->super->s_free_inodes_count++;
2292         return;
2293
2294 err_out:
2295         pctx.errcode = retval;
2296         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2297         fs->super->s_state &= ~EXT2_VALID_FS;
2298         ext2fs_mark_super_dirty(fs);
2299 }
2300
2301 /*
2302  * message.c --- print e2fsck messages (with compression)
2303  *
2304  * print_e2fsck_message() prints a message to the user, using
2305  * compression techniques and expansions of abbreviations.
2306  *
2307  * The following % expansions are supported:
2308  *
2309  *      %b      <blk>                   block number
2310  *      %B      <blkcount>              integer
2311  *      %c      <blk2>                  block number
2312  *      %Di     <dirent>->ino           inode number
2313  *      %Dn     <dirent>->name          string
2314  *      %Dr     <dirent>->rec_len
2315  *      %Dl     <dirent>->name_len
2316  *      %Dt     <dirent>->filetype
2317  *      %d      <dir>                   inode number
2318  *      %g      <group>                 integer
2319  *      %i      <ino>                   inode number
2320  *      %Is     <inode> -> i_size
2321  *      %IS     <inode> -> i_extra_isize
2322  *      %Ib     <inode> -> i_blocks
2323  *      %Il     <inode> -> i_links_count
2324  *      %Im     <inode> -> i_mode
2325  *      %IM     <inode> -> i_mtime
2326  *      %IF     <inode> -> i_faddr
2327  *      %If     <inode> -> i_file_acl
2328  *      %Id     <inode> -> i_dir_acl
2329  *      %Iu     <inode> -> i_uid
2330  *      %Ig     <inode> -> i_gid
2331  *      %j      <ino2>                  inode number
2332  *      %m      <com_err error message>
2333  *      %N      <num>
2334  *      %p      ext2fs_get_pathname of directory <ino>
2335  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2336  *                      the containing directory.  (If dirent is NULL
2337  *                      then return the pathname of directory <ino2>)
2338  *      %q      ext2fs_get_pathname of directory <dir>
2339  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2340  *                      the containing directory.
2341  *      %s      <str>                   miscellaneous string
2342  *      %S      backup superblock
2343  *      %X      <num> hexadecimal format
2344  *
2345  * The following '@' expansions are supported:
2346  *
2347  *      @a      extended attribute
2348  *      @A      error allocating
2349  *      @b      block
2350  *      @B      bitmap
2351  *      @c      compress
2352  *      @C      conflicts with some other fs block
2353  *      @D      deleted
2354  *      @d      directory
2355  *      @e      entry
2356  *      @E      Entry '%Dn' in %p (%i)
2357  *      @f      filesystem
2358  *      @F      for @i %i (%Q) is
2359  *      @g      group
2360  *      @h      HTREE directory inode
2361  *      @i      inode
2362  *      @I      illegal
2363  *      @j      journal
2364  *      @l      lost+found
2365  *      @L      is a link
2366  *      @m      multiply-claimed
2367  *      @n      invalid
2368  *      @o      orphaned
2369  *      @p      problem in
2370  *      @r      root inode
2371  *      @s      should be
2372  *      @S      superblock
2373  *      @u      unattached
2374  *      @v      device
2375  *      @z      zero-length
2376  */
2377
2378
2379 /*
2380  * This structure defines the abbreviations used by the text strings
2381  * below.  The first character in the string is the index letter.  An
2382  * abbreviation of the form '@<i>' is expanded by looking up the index
2383  * letter <i> in the table below.
2384  */
2385 static const char *const abbrevs[] = {
2386         N_("aextended attribute"),
2387         N_("Aerror allocating"),
2388         N_("bblock"),
2389         N_("Bbitmap"),
2390         N_("ccompress"),
2391         N_("Cconflicts with some other fs @b"),
2392         N_("iinode"),
2393         N_("Iillegal"),
2394         N_("jjournal"),
2395         N_("Ddeleted"),
2396         N_("ddirectory"),
2397         N_("eentry"),
2398         N_("E@e '%Dn' in %p (%i)"),
2399         N_("ffilesystem"),
2400         N_("Ffor @i %i (%Q) is"),
2401         N_("ggroup"),
2402         N_("hHTREE @d @i"),
2403         N_("llost+found"),
2404         N_("Lis a link"),
2405         N_("mmultiply-claimed"),
2406         N_("ninvalid"),
2407         N_("oorphaned"),
2408         N_("pproblem in"),
2409         N_("rroot @i"),
2410         N_("sshould be"),
2411         N_("Ssuper@b"),
2412         N_("uunattached"),
2413         N_("vdevice"),
2414         N_("zzero-length"),
2415         "@@",
2416         0
2417         };
2418
2419 /*
2420  * Give more user friendly names to the "special" inodes.
2421  */
2422 #define num_special_inodes      11
2423 static const char *const special_inode_name[] =
2424 {
2425         N_("<The NULL inode>"),                 /* 0 */
2426         N_("<The bad blocks inode>"),           /* 1 */
2427         "/",                                    /* 2 */
2428         N_("<The ACL index inode>"),            /* 3 */
2429         N_("<The ACL data inode>"),             /* 4 */
2430         N_("<The boot loader inode>"),          /* 5 */
2431         N_("<The undelete directory inode>"),   /* 6 */
2432         N_("<The group descriptor inode>"),     /* 7 */
2433         N_("<The journal inode>"),              /* 8 */
2434         N_("<Reserved inode 9>"),               /* 9 */
2435         N_("<Reserved inode 10>"),              /* 10 */
2436 };
2437
2438 /*
2439  * This function does "safe" printing.  It will convert non-printable
2440  * ASCII characters using '^' and M- notation.
2441  */
2442 static void safe_print(const char *cp, int len)
2443 {
2444         unsigned char   ch;
2445
2446         if (len < 0)
2447                 len = strlen(cp);
2448
2449         while (len--) {
2450                 ch = *cp++;
2451                 if (ch > 128) {
2452                         fputs("M-", stdout);
2453                         ch -= 128;
2454                 }
2455                 if ((ch < 32) || (ch == 0x7f)) {
2456                         bb_putchar('^');
2457                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2458                 }
2459                 bb_putchar(ch);
2460         }
2461 }
2462
2463
2464 /*
2465  * This function prints a pathname, using the ext2fs_get_pathname
2466  * function
2467  */
2468 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2469 {
2470         errcode_t       retval;
2471         char            *path;
2472
2473         if (!dir && (ino < num_special_inodes)) {
2474                 fputs(_(special_inode_name[ino]), stdout);
2475                 return;
2476         }
2477
2478         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2479         if (retval)
2480                 fputs("???", stdout);
2481         else {
2482                 safe_print(path, -1);
2483                 ext2fs_free_mem(&path);
2484         }
2485 }
2486
2487 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2488                           struct problem_context *pctx, int first);
2489 /*
2490  * This function handles the '@' expansion.  We allow recursive
2491  * expansion; an @ expression can contain further '@' and '%'
2492  * expressions.
2493  */
2494 static void expand_at_expression(e2fsck_t ctx, char ch,
2495                                           struct problem_context *pctx,
2496                                           int *first)
2497 {
2498         const char *const *cpp;
2499         const char *str;
2500
2501         /* Search for the abbreviation */
2502         for (cpp = abbrevs; *cpp; cpp++) {
2503                 if (ch == *cpp[0])
2504                         break;
2505         }
2506         if (*cpp) {
2507                 str = _(*cpp) + 1;
2508                 if (*first && islower(*str)) {
2509                         *first = 0;
2510                         bb_putchar(toupper(*str++));
2511                 }
2512                 print_e2fsck_message(ctx, str, pctx, *first);
2513         } else
2514                 printf("@%c", ch);
2515 }
2516
2517 /*
2518  * This function expands '%IX' expressions
2519  */
2520 static void expand_inode_expression(char ch,
2521                                              struct problem_context *ctx)
2522 {
2523         struct ext2_inode       *inode;
2524         struct ext2_inode_large *large_inode;
2525         char *                  time_str;
2526         time_t                  t;
2527         int                     do_gmt = -1;
2528
2529         if (!ctx || !ctx->inode)
2530                 goto no_inode;
2531
2532         inode = ctx->inode;
2533         large_inode = (struct ext2_inode_large *) inode;
2534
2535         switch (ch) {
2536         case 's':
2537                 if (LINUX_S_ISDIR(inode->i_mode))
2538                         printf("%u", inode->i_size);
2539                 else {
2540                         printf("%"PRIu64, (inode->i_size |
2541                                         ((uint64_t) inode->i_size_high << 32)));
2542                 }
2543                 break;
2544         case 'S':
2545                 printf("%u", large_inode->i_extra_isize);
2546                 break;
2547         case 'b':
2548                 printf("%u", inode->i_blocks);
2549                 break;
2550         case 'l':
2551                 printf("%d", inode->i_links_count);
2552                 break;
2553         case 'm':
2554                 printf("0%o", inode->i_mode);
2555                 break;
2556         case 'M':
2557                 /* The diet libc doesn't respect the TZ environemnt variable */
2558                 if (do_gmt == -1) {
2559                         time_str = getenv("TZ");
2560                         if (!time_str)
2561                                 time_str = "";
2562                         do_gmt = !strcmp(time_str, "GMT");
2563                 }
2564                 t = inode->i_mtime;
2565                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2566                 printf("%.24s", time_str);
2567                 break;
2568         case 'F':
2569                 printf("%u", inode->i_faddr);
2570                 break;
2571         case 'f':
2572                 printf("%u", inode->i_file_acl);
2573                 break;
2574         case 'd':
2575                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2576                               inode->i_dir_acl : 0));
2577                 break;
2578         case 'u':
2579                 printf("%d", (inode->i_uid |
2580                               (inode->osd2.linux2.l_i_uid_high << 16)));
2581                 break;
2582         case 'g':
2583                 printf("%d", (inode->i_gid |
2584                               (inode->osd2.linux2.l_i_gid_high << 16)));
2585                 break;
2586         default:
2587         no_inode:
2588                 printf("%%I%c", ch);
2589                 break;
2590         }
2591 }
2592
2593 /*
2594  * This function expands '%dX' expressions
2595  */
2596 static void expand_dirent_expression(char ch,
2597                                               struct problem_context *ctx)
2598 {
2599         struct ext2_dir_entry   *dirent;
2600         int     len;
2601
2602         if (!ctx || !ctx->dirent)
2603                 goto no_dirent;
2604
2605         dirent = ctx->dirent;
2606
2607         switch (ch) {
2608         case 'i':
2609                 printf("%u", dirent->inode);
2610                 break;
2611         case 'n':
2612                 len = dirent->name_len & 0xFF;
2613                 if (len > EXT2_NAME_LEN)
2614                         len = EXT2_NAME_LEN;
2615                 if (len > dirent->rec_len)
2616                         len = dirent->rec_len;
2617                 safe_print(dirent->name, len);
2618                 break;
2619         case 'r':
2620                 printf("%u", dirent->rec_len);
2621                 break;
2622         case 'l':
2623                 printf("%u", dirent->name_len & 0xFF);
2624                 break;
2625         case 't':
2626                 printf("%u", dirent->name_len >> 8);
2627                 break;
2628         default:
2629         no_dirent:
2630                 printf("%%D%c", ch);
2631                 break;
2632         }
2633 }
2634
2635 static void expand_percent_expression(ext2_filsys fs, char ch,
2636                                                struct problem_context *ctx)
2637 {
2638         if (!ctx)
2639                 goto no_context;
2640
2641         switch (ch) {
2642         case '%':
2643                 bb_putchar('%');
2644                 break;
2645         case 'b':
2646                 printf("%u", ctx->blk);
2647                 break;
2648         case 'B':
2649                 printf("%"PRIi64, ctx->blkcount);
2650                 break;
2651         case 'c':
2652                 printf("%u", ctx->blk2);
2653                 break;
2654         case 'd':
2655                 printf("%u", ctx->dir);
2656                 break;
2657         case 'g':
2658                 printf("%d", ctx->group);
2659                 break;
2660         case 'i':
2661                 printf("%u", ctx->ino);
2662                 break;
2663         case 'j':
2664                 printf("%u", ctx->ino2);
2665                 break;
2666         case 'm':
2667                 fputs(error_message(ctx->errcode), stdout);
2668                 break;
2669         case 'N':
2670                 printf("%"PRIi64, ctx->num);
2671                 break;
2672         case 'p':
2673                 print_pathname(fs, ctx->ino, 0);
2674                 break;
2675         case 'P':
2676                 print_pathname(fs, ctx->ino2,
2677                                ctx->dirent ? ctx->dirent->inode : 0);
2678                 break;
2679         case 'q':
2680                 print_pathname(fs, ctx->dir, 0);
2681                 break;
2682         case 'Q':
2683                 print_pathname(fs, ctx->dir, ctx->ino);
2684                 break;
2685         case 'S':
2686                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2687                 break;
2688         case 's':
2689                 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2690                 break;
2691         case 'X':
2692                 printf("0x%"PRIi64, ctx->num);
2693                 break;
2694         default:
2695         no_context:
2696                 printf("%%%c", ch);
2697                 break;
2698         }
2699 }
2700
2701
2702 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2703                           struct problem_context *pctx, int first)
2704 {
2705         ext2_filsys fs = ctx->fs;
2706         const char *    cp;
2707         int             i;
2708
2709         e2fsck_clear_progbar(ctx);
2710         for (cp = msg; *cp; cp++) {
2711                 if (cp[0] == '@') {
2712                         cp++;
2713                         expand_at_expression(ctx, *cp, pctx, &first);
2714                 } else if (cp[0] == '%' && cp[1] == 'I') {
2715                         cp += 2;
2716                         expand_inode_expression(*cp, pctx);
2717                 } else if (cp[0] == '%' && cp[1] == 'D') {
2718                         cp += 2;
2719                         expand_dirent_expression(*cp, pctx);
2720                 } else if ((cp[0] == '%')) {
2721                         cp++;
2722                         expand_percent_expression(fs, *cp, pctx);
2723                 } else {
2724                         for (i=0; cp[i]; i++)
2725                                 if ((cp[i] == '@') || cp[i] == '%')
2726                                         break;
2727                         printf("%.*s", i, cp);
2728                         cp += i-1;
2729                 }
2730                 first = 0;
2731         }
2732 }
2733
2734
2735 /*
2736  * region.c --- code which manages allocations within a region.
2737  */
2738
2739 struct region_el {
2740         region_addr_t   start;
2741         region_addr_t   end;
2742         struct region_el *next;
2743 };
2744
2745 struct region_struct {
2746         region_addr_t   min;
2747         region_addr_t   max;
2748         struct region_el *allocated;
2749 };
2750
2751 static region_t region_create(region_addr_t min, region_addr_t max)
2752 {
2753         region_t        region;
2754
2755         region = xzalloc(sizeof(struct region_struct));
2756         region->min = min;
2757         region->max = max;
2758         return region;
2759 }
2760
2761 static void region_free(region_t region)
2762 {
2763         struct region_el        *r, *next;
2764
2765         for (r = region->allocated; r; r = next) {
2766                 next = r->next;
2767                 free(r);
2768         }
2769         memset(region, 0, sizeof(struct region_struct));
2770         free(region);
2771 }
2772
2773 static int region_allocate(region_t region, region_addr_t start, int n)
2774 {
2775         struct region_el        *r, *new_region, *prev, *next;
2776         region_addr_t end;
2777
2778         end = start+n;
2779         if ((start < region->min) || (end > region->max))
2780                 return -1;
2781         if (n == 0)
2782                 return 1;
2783
2784         /*
2785          * Search through the linked list.  If we find that it
2786          * conflicts witih something that's already allocated, return
2787          * 1; if we can find an existing region which we can grow, do
2788          * so.  Otherwise, stop when we find the appropriate place
2789          * insert a new region element into the linked list.
2790          */
2791         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2792                 if (((start >= r->start) && (start < r->end)) ||
2793                     ((end > r->start) && (end <= r->end)) ||
2794                     ((start <= r->start) && (end >= r->end)))
2795                         return 1;
2796                 if (end == r->start) {
2797                         r->start = start;
2798                         return 0;
2799                 }
2800                 if (start == r->end) {
2801                         if ((next = r->next)) {
2802                                 if (end > next->start)
2803                                         return 1;
2804                                 if (end == next->start) {
2805                                         r->end = next->end;
2806                                         r->next = next->next;
2807                                         free(next);
2808                                         return 0;
2809                                 }
2810                         }
2811                         r->end = end;
2812                         return 0;
2813                 }
2814                 if (start < r->start)
2815                         break;
2816         }
2817         /*
2818          * Insert a new region element structure into the linked list
2819          */
2820         new_region = xmalloc(sizeof(struct region_el));
2821         new_region->start = start;
2822         new_region->end = start + n;
2823         new_region->next = r;
2824         if (prev)
2825                 prev->next = new_region;
2826         else
2827                 region->allocated = new_region;
2828         return 0;
2829 }
2830
2831 /*
2832  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2833  *
2834  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2835  * and applies the following tests to each inode:
2836  *
2837  *      - The mode field of the inode must be legal.
2838  *      - The size and block count fields of the inode are correct.
2839  *      - A data block must not be used by another inode
2840  *
2841  * Pass 1 also gathers the collects the following information:
2842  *
2843  *      - A bitmap of which inodes are in use.          (inode_used_map)
2844  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2845  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2846  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2847  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2848  *      - A bitmap of which blocks are in use.          (block_found_map)
2849  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2850  *      - The data blocks of the directory inodes.      (dir_map)
2851  *
2852  * Pass 1 is designed to stash away enough information so that the
2853  * other passes should not need to read in the inode information
2854  * during the normal course of a filesystem check.  (Althogh if an
2855  * inconsistency is detected, other passes may need to read in an
2856  * inode to fix it.)
2857  *
2858  * Note that pass 1B will be invoked if there are any duplicate blocks
2859  * found.
2860  */
2861
2862
2863 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2864                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2865                          int ref_offset, void *priv_data);
2866 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2867                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2868                              int ref_offset, void *priv_data);
2869 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2870                          char *block_buf);
2871 static void mark_table_blocks(e2fsck_t ctx);
2872 static void alloc_imagic_map(e2fsck_t ctx);
2873 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2874 static void handle_fs_bad_blocks(e2fsck_t ctx);
2875 static void process_inodes(e2fsck_t ctx, char *block_buf);
2876 static int process_inode_cmp(const void *a, const void *b);
2877 static errcode_t scan_callback(ext2_filsys fs,
2878                                   dgrp_t group, void * priv_data);
2879 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2880                                     char *block_buf, int adjust_sign);
2881 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2882
2883 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2884                                struct ext2_inode * inode, int bufsize,
2885                                const char *proc);
2886
2887 struct process_block_struct_1 {
2888         ext2_ino_t      ino;
2889         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2890                                 fragmented:1, compressed:1, bbcheck:1;
2891         blk_t           num_blocks;
2892         blk_t           max_blocks;
2893         e2_blkcnt_t     last_block;
2894         int             num_illegal_blocks;
2895         blk_t           previous_block;
2896         struct ext2_inode *inode;
2897         struct problem_context *pctx;
2898         ext2fs_block_bitmap fs_meta_blocks;
2899         e2fsck_t        ctx;
2900 };
2901
2902 struct process_inode_block {
2903         ext2_ino_t ino;
2904         struct ext2_inode inode;
2905 };
2906
2907 struct scan_callback_struct {
2908         e2fsck_t        ctx;
2909         char            *block_buf;
2910 };
2911
2912 /*
2913  * For the inodes to process list.
2914  */
2915 static struct process_inode_block *inodes_to_process;
2916 static int process_inode_count;
2917
2918 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2919                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2920
2921 /*
2922  * Free all memory allocated by pass1 in preparation for restarting
2923  * things.
2924  */
2925 static void unwind_pass1(void)
2926 {
2927         ext2fs_free_mem(&inodes_to_process);
2928 }
2929
2930 /*
2931  * Check to make sure a device inode is real.  Returns 1 if the device
2932  * checks out, 0 if not.
2933  *
2934  * Note: this routine is now also used to check FIFO's and Sockets,
2935  * since they have the same requirement; the i_block fields should be
2936  * zero.
2937  */
2938 static int
2939 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2940 {
2941         int     i;
2942
2943         /*
2944          * If i_blocks is non-zero, or the index flag is set, then
2945          * this is a bogus device/fifo/socket
2946          */
2947         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2948             (inode->i_flags & EXT2_INDEX_FL))
2949                 return 0;
2950
2951         /*
2952          * We should be able to do the test below all the time, but
2953          * because the kernel doesn't forcibly clear the device
2954          * inode's additional i_block fields, there are some rare
2955          * occasions when a legitimate device inode will have non-zero
2956          * additional i_block fields.  So for now, we only complain
2957          * when the immutable flag is set, which should never happen
2958          * for devices.  (And that's when the problem is caused, since
2959          * you can't set or clear immutable flags for devices.)  Once
2960          * the kernel has been fixed we can change this...
2961          */
2962         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2963                 for (i=4; i < EXT2_N_BLOCKS; i++)
2964                         if (inode->i_block[i])
2965                                 return 0;
2966         }
2967         return 1;
2968 }
2969
2970 /*
2971  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2972  * checks out, 0 if not.
2973  */
2974 static int
2975 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2976 {
2977         unsigned int len;
2978         int i;
2979         blk_t   blocks;
2980
2981         if ((inode->i_size_high || inode->i_size == 0) ||
2982             (inode->i_flags & EXT2_INDEX_FL))
2983                 return 0;
2984
2985         blocks = ext2fs_inode_data_blocks(fs, inode);
2986         if (blocks) {
2987                 if ((inode->i_size >= fs->blocksize) ||
2988                     (blocks != fs->blocksize >> 9) ||
2989                     (inode->i_block[0] < fs->super->s_first_data_block) ||
2990                     (inode->i_block[0] >= fs->super->s_blocks_count))
2991                         return 0;
2992
2993                 for (i = 1; i < EXT2_N_BLOCKS; i++)
2994                         if (inode->i_block[i])
2995                                 return 0;
2996
2997                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2998                         return 0;
2999
3000                 len = strnlen(buf, fs->blocksize);
3001                 if (len == fs->blocksize)
3002                         return 0;
3003         } else {
3004                 if (inode->i_size >= sizeof(inode->i_block))
3005                         return 0;
3006
3007                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3008                 if (len == sizeof(inode->i_block))
3009                         return 0;
3010         }
3011         if (len != inode->i_size)
3012                 return 0;
3013         return 1;
3014 }
3015
3016 /*
3017  * If the immutable (or append-only) flag is set on the inode, offer
3018  * to clear it.
3019  */
3020 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3021 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3022 {
3023         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3024                 return;
3025
3026         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3027                 return;
3028
3029         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3030         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3031 }
3032
3033 /*
3034  * If device, fifo or socket, check size is zero -- if not offer to
3035  * clear it
3036  */
3037 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3038 {
3039         struct ext2_inode *inode = pctx->inode;
3040
3041         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3042                 return;
3043
3044         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3045                 return;
3046
3047         inode->i_size = 0;
3048         inode->i_size_high = 0;
3049         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3050 }
3051
3052 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3053 {
3054         struct ext2_super_block *sb = ctx->fs->super;
3055         struct ext2_inode_large *inode;
3056         struct ext2_ext_attr_entry *entry;
3057         char *start, *end;
3058         int storage_size, remain, offs;
3059         int problem = 0;
3060
3061         inode = (struct ext2_inode_large *) pctx->inode;
3062         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3063                 inode->i_extra_isize;
3064         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3065                 inode->i_extra_isize + sizeof(__u32);
3066         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3067         entry = (struct ext2_ext_attr_entry *) start;
3068
3069         /* scan all entry's headers first */
3070
3071         /* take finish entry 0UL into account */
3072         remain = storage_size - sizeof(__u32);
3073         offs = end - start;
3074
3075         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3076
3077                 /* header eats this space */
3078                 remain -= sizeof(struct ext2_ext_attr_entry);
3079
3080                 /* is attribute name valid? */
3081                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3082                         pctx->num = entry->e_name_len;
3083                         problem = PR_1_ATTR_NAME_LEN;
3084                         goto fix;
3085                 }
3086
3087                 /* attribute len eats this space */
3088                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3089
3090                 /* check value size */
3091                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3092                         pctx->num = entry->e_value_size;
3093                         problem = PR_1_ATTR_VALUE_SIZE;
3094                         goto fix;
3095                 }
3096
3097                 /* check value placement */
3098                 if (entry->e_value_offs +
3099                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3100                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3101                         pctx->num = entry->e_value_offs;
3102                         problem = PR_1_ATTR_VALUE_OFFSET;
3103                         goto fix;
3104                 }
3105
3106                 /* e_value_block must be 0 in inode's ea */
3107                 if (entry->e_value_block != 0) {
3108                         pctx->num = entry->e_value_block;
3109                         problem = PR_1_ATTR_VALUE_BLOCK;
3110                         goto fix;
3111                 }
3112
3113                 /* e_hash must be 0 in inode's ea */
3114                 if (entry->e_hash != 0) {
3115                         pctx->num = entry->e_hash;
3116                         problem = PR_1_ATTR_HASH;
3117                         goto fix;
3118                 }
3119
3120                 remain -= entry->e_value_size;
3121                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3122
3123                 entry = EXT2_EXT_ATTR_NEXT(entry);
3124         }
3125 fix:
3126         /*
3127          * it seems like a corruption. it's very unlikely we could repair
3128          * EA(s) in automatic fashion -bzzz
3129          */
3130         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3131                 return;
3132
3133         /* simple remove all possible EA(s) */
3134         *((__u32 *)start) = 0UL;
3135         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3136                                 EXT2_INODE_SIZE(sb), "pass1");
3137 }
3138
3139 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3140 {
3141         struct ext2_super_block *sb = ctx->fs->super;
3142         struct ext2_inode_large *inode;
3143         __u32 *eamagic;
3144         int min, max;
3145
3146         inode = (struct ext2_inode_large *) pctx->inode;
3147         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3148                 /* this isn't large inode. so, nothing to check */
3149                 return;
3150         }
3151
3152         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3153         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3154         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3155         /*
3156          * For now we will allow i_extra_isize to be 0, but really
3157          * implementations should never allow i_extra_isize to be 0
3158          */
3159         if (inode->i_extra_isize &&
3160             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3161                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3162                         return;
3163                 inode->i_extra_isize = min;
3164                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3165                                         EXT2_INODE_SIZE(sb), "pass1");
3166                 return;
3167         }
3168
3169         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3170                         inode->i_extra_isize);
3171         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3172                 /* it seems inode has an extended attribute(s) in body */
3173                 check_ea_in_inode(ctx, pctx);
3174         }
3175 }
3176
3177 static void e2fsck_pass1(e2fsck_t ctx)
3178 {
3179         int     i;
3180         __u64   max_sizes;
3181         ext2_filsys fs = ctx->fs;
3182         ext2_ino_t      ino;
3183         struct ext2_inode *inode;
3184         ext2_inode_scan scan;
3185         char            *block_buf;
3186         unsigned char   frag, fsize;
3187         struct          problem_context pctx;
3188         struct          scan_callback_struct scan_struct;
3189         struct ext2_super_block *sb = ctx->fs->super;
3190         int             imagic_fs;
3191         int             busted_fs_time = 0;
3192         int             inode_size;
3193
3194         clear_problem_context(&pctx);
3195
3196         if (!(ctx->options & E2F_OPT_PREEN))
3197                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3198
3199         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3200             !(ctx->options & E2F_OPT_NO)) {
3201                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3202                         ctx->dirs_to_hash = 0;
3203         }
3204
3205         /* Pass 1 */
3206
3207 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3208
3209         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3210                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3211                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3212                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3213                 max_sizes = (max_sizes * (1UL << i)) - 1;
3214                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3215         }
3216 #undef EXT2_BPP
3217
3218         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3219
3220         /*
3221          * Allocate bitmaps structures
3222          */
3223         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3224                                               &ctx->inode_used_map);
3225         if (pctx.errcode) {
3226                 pctx.num = 1;
3227                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3228                 ctx->flags |= E2F_FLAG_ABORT;
3229                 return;
3230         }
3231         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3232                                 _("directory inode map"), &ctx->inode_dir_map);
3233         if (pctx.errcode) {
3234                 pctx.num = 2;
3235                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3236                 ctx->flags |= E2F_FLAG_ABORT;
3237                 return;
3238         }
3239         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3240                         _("regular file inode map"), &ctx->inode_reg_map);
3241         if (pctx.errcode) {
3242                 pctx.num = 6;
3243                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3244                 ctx->flags |= E2F_FLAG_ABORT;
3245                 return;
3246         }
3247         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3248                                               &ctx->block_found_map);
3249         if (pctx.errcode) {
3250                 pctx.num = 1;
3251                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3252                 ctx->flags |= E2F_FLAG_ABORT;
3253                 return;
3254         }
3255         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3256                                              &ctx->inode_link_info);
3257         if (pctx.errcode) {
3258                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3259                 ctx->flags |= E2F_FLAG_ABORT;
3260                 return;
3261         }
3262         inode_size = EXT2_INODE_SIZE(fs->super);
3263         inode = (struct ext2_inode *)
3264                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3265
3266         inodes_to_process = (struct process_inode_block *)
3267                 e2fsck_allocate_memory(ctx,
3268                                        (ctx->process_inode_size *
3269                                         sizeof(struct process_inode_block)),
3270                                        "array of inodes to process");
3271         process_inode_count = 0;
3272
3273         pctx.errcode = ext2fs_init_dblist(fs, 0);
3274         if (pctx.errcode) {
3275                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3276                 ctx->flags |= E2F_FLAG_ABORT;
3277                 return;
3278         }
3279
3280         /*
3281          * If the last orphan field is set, clear it, since the pass1
3282          * processing will automatically find and clear the orphans.
3283          * In the future, we may want to try using the last_orphan
3284          * linked list ourselves, but for now, we clear it so that the
3285          * ext3 mount code won't get confused.
3286          */
3287         if (!(ctx->options & E2F_OPT_READONLY)) {
3288                 if (fs->super->s_last_orphan) {
3289                         fs->super->s_last_orphan = 0;
3290                         ext2fs_mark_super_dirty(fs);
3291                 }
3292         }
3293
3294         mark_table_blocks(ctx);
3295         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3296                                                     "block interate buffer");
3297         e2fsck_use_inode_shortcuts(ctx, 1);
3298         ehandler_operation(_("doing inode scan"));
3299         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3300                                               &scan);
3301         if (pctx.errcode) {
3302                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3303                 ctx->flags |= E2F_FLAG_ABORT;
3304                 return;
3305         }
3306         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3307         ctx->stashed_inode = inode;
3308         scan_struct.ctx = ctx;
3309         scan_struct.block_buf = block_buf;
3310         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3311         if (ctx->progress)
3312                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3313                         return;
3314         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3315             (fs->super->s_mtime < fs->super->s_inodes_count))
3316                 busted_fs_time = 1;
3317
3318         while (1) {
3319                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3320                                                           inode, inode_size);
3321                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3322                         return;
3323                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3324                         continue;
3325                 }
3326                 if (pctx.errcode) {
3327                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3328                         ctx->flags |= E2F_FLAG_ABORT;
3329                         return;
3330                 }
3331                 if (!ino)
3332                         break;
3333                 pctx.ino = ino;
3334                 pctx.inode = inode;
3335                 ctx->stashed_ino = ino;
3336                 if (inode->i_links_count) {
3337                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3338                                            ino, inode->i_links_count);
3339                         if (pctx.errcode) {
3340                                 pctx.num = inode->i_links_count;
3341                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3342                                 ctx->flags |= E2F_FLAG_ABORT;
3343                                 return;
3344                         }
3345                 }
3346                 if (ino == EXT2_BAD_INO) {
3347                         struct process_block_struct_1 pb;
3348
3349                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3350                                                           &pb.fs_meta_blocks);
3351                         if (pctx.errcode) {
3352                                 pctx.num = 4;
3353                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3354                                 ctx->flags |= E2F_FLAG_ABORT;
3355                                 return;
3356                         }
3357                         pb.ino = EXT2_BAD_INO;
3358                         pb.num_blocks = pb.last_block = 0;
3359                         pb.num_illegal_blocks = 0;
3360                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3361                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3362                         pb.inode = inode;
3363                         pb.pctx = &pctx;
3364                         pb.ctx = ctx;
3365                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3366                                      block_buf, process_bad_block, &pb);
3367                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3368                         if (pctx.errcode) {
3369                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3370                                 ctx->flags |= E2F_FLAG_ABORT;
3371                                 return;
3372                         }
3373                         if (pb.bbcheck)
3374                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3375                                 ctx->flags |= E2F_FLAG_ABORT;
3376                                 return;
3377                         }
3378                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3379                         clear_problem_context(&pctx);
3380                         continue;
3381                 } else if (ino == EXT2_ROOT_INO) {
3382                         /*
3383                          * Make sure the root inode is a directory; if
3384                          * not, offer to clear it.  It will be
3385                          * regnerated in pass #3.
3386                          */
3387                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3388                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3389                                         inode->i_dtime = time(NULL);
3390                                         inode->i_links_count = 0;
3391                                         ext2fs_icount_store(ctx->inode_link_info,
3392                                                             ino, 0);
3393                                         e2fsck_write_inode(ctx, ino, inode,
3394                                                            "pass1");
3395                                 }
3396                         }
3397                         /*
3398                          * If dtime is set, offer to clear it.  mke2fs
3399                          * version 0.2b created filesystems with the
3400                          * dtime field set for the root and lost+found
3401                          * directories.  We won't worry about
3402                          * /lost+found, since that can be regenerated
3403                          * easily.  But we will fix the root directory
3404                          * as a special case.
3405                          */
3406                         if (inode->i_dtime && inode->i_links_count) {
3407                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3408                                         inode->i_dtime = 0;
3409                                         e2fsck_write_inode(ctx, ino, inode,
3410                                                            "pass1");
3411                                 }
3412                         }
3413                 } else if (ino == EXT2_JOURNAL_INO) {
3414                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3415                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3416                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3417                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3418                                                 &pctx)) {
3419                                         inode->i_mode = LINUX_S_IFREG;
3420                                         e2fsck_write_inode(ctx, ino, inode,
3421                                                            "pass1");
3422                                 }
3423                                 check_blocks(ctx, &pctx, block_buf);
3424                                 continue;
3425                         }
3426                         if ((inode->i_links_count || inode->i_blocks ||
3427                              inode->i_block[0]) &&
3428                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3429                                         &pctx)) {
3430                                 memset(inode, 0, inode_size);
3431                                 ext2fs_icount_store(ctx->inode_link_info,
3432                                                     ino, 0);
3433                                 e2fsck_write_inode_full(ctx, ino, inode,
3434                                                         inode_size, "pass1");
3435                         }
3436                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3437                         int     problem = 0;
3438
3439                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3440                         if (ino == EXT2_BOOT_LOADER_INO) {
3441                                 if (LINUX_S_ISDIR(inode->i_mode))
3442                                         problem = PR_1_RESERVED_BAD_MODE;
3443                         } else if (ino == EXT2_RESIZE_INO) {
3444                                 if (inode->i_mode &&
3445                                     !LINUX_S_ISREG(inode->i_mode))
3446                                         problem = PR_1_RESERVED_BAD_MODE;
3447                         } else {
3448                                 if (inode->i_mode != 0)
3449                                         problem = PR_1_RESERVED_BAD_MODE;
3450                         }
3451                         if (problem) {
3452                                 if (fix_problem(ctx, problem, &pctx)) {
3453                                         inode->i_mode = 0;
3454                                         e2fsck_write_inode(ctx, ino, inode,
3455                                                            "pass1");
3456                                 }
3457                         }
3458                         check_blocks(ctx, &pctx, block_buf);
3459                         continue;
3460                 }
3461                 /*
3462                  * Check for inodes who might have been part of the
3463                  * orphaned list linked list.  They should have gotten
3464                  * dealt with by now, unless the list had somehow been
3465                  * corrupted.
3466                  *
3467                  * FIXME: In the future, inodes which are still in use
3468                  * (and which are therefore) pending truncation should
3469                  * be handled specially.  Right now we just clear the
3470                  * dtime field, and the normal e2fsck handling of
3471                  * inodes where i_size and the inode blocks are
3472                  * inconsistent is to fix i_size, instead of releasing
3473                  * the extra blocks.  This won't catch the inodes that
3474                  * was at the end of the orphan list, but it's better
3475                  * than nothing.  The right answer is that there
3476                  * shouldn't be any bugs in the orphan list handling.  :-)
3477                  */
3478                 if (inode->i_dtime && !busted_fs_time &&
3479                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3480                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3481                                 inode->i_dtime = inode->i_links_count ?
3482                                         0 : time(NULL);
3483                                 e2fsck_write_inode(ctx, ino, inode,
3484                                                    "pass1");
3485                         }
3486                 }
3487
3488                 /*
3489                  * This code assumes that deleted inodes have
3490                  * i_links_count set to 0.
3491                  */
3492                 if (!inode->i_links_count) {
3493                         if (!inode->i_dtime && inode->i_mode) {
3494                                 if (fix_problem(ctx,
3495                                             PR_1_ZERO_DTIME, &pctx)) {
3496                                         inode->i_dtime = time(NULL);
3497                                         e2fsck_write_inode(ctx, ino, inode,
3498                                                            "pass1");
3499                                 }
3500                         }
3501                         continue;
3502                 }
3503                 /*
3504                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3505                  * deleted files.  Oops.
3506                  *
3507                  * Since all new ext2 implementations get this right,
3508                  * we now assume that the case of non-zero
3509                  * i_links_count and non-zero dtime means that we
3510                  * should keep the file, not delete it.
3511                  *
3512                  */
3513                 if (inode->i_dtime) {
3514                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3515                                 inode->i_dtime = 0;
3516                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3517                         }
3518                 }
3519
3520                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3521                 switch (fs->super->s_creator_os) {
3522                     case EXT2_OS_LINUX:
3523                         frag = inode->osd2.linux2.l_i_frag;
3524                         fsize = inode->osd2.linux2.l_i_fsize;
3525                         break;
3526                     case EXT2_OS_HURD:
3527                         frag = inode->osd2.hurd2.h_i_frag;
3528                         fsize = inode->osd2.hurd2.h_i_fsize;
3529                         break;
3530                     case EXT2_OS_MASIX:
3531                         frag = inode->osd2.masix2.m_i_frag;
3532                         fsize = inode->osd2.masix2.m_i_fsize;
3533                         break;
3534                     default:
3535                         frag = fsize = 0;
3536                 }
3537
3538                 if (inode->i_faddr || frag || fsize ||
3539                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3540                         mark_inode_bad(ctx, ino);
3541                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3542                         if (imagic_fs) {
3543                                 if (!ctx->inode_imagic_map)
3544                                         alloc_imagic_map(ctx);
3545                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3546                                                          ino);
3547                         } else {
3548                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3549                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3550                                         e2fsck_write_inode(ctx, ino,
3551                                                            inode, "pass1");
3552                                 }
3553                         }
3554                 }
3555
3556                 check_inode_extra_space(ctx, &pctx);
3557
3558                 if (LINUX_S_ISDIR(inode->i_mode)) {
3559                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3560                         e2fsck_add_dir_info(ctx, ino, 0);
3561                         ctx->fs_directory_count++;
3562                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3563                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3564                         ctx->fs_regular_count++;
3565                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3566                            e2fsck_pass1_check_device_inode(fs, inode)) {
3567                         check_immutable(ctx, &pctx);
3568                         check_size(ctx, &pctx);
3569                         ctx->fs_chardev_count++;
3570                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3571                            e2fsck_pass1_check_device_inode(fs, inode)) {
3572                         check_immutable(ctx, &pctx);
3573                         check_size(ctx, &pctx);
3574                         ctx->fs_blockdev_count++;
3575                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3576                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3577                         check_immutable(ctx, &pctx);
3578                         ctx->fs_symlinks_count++;
3579                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3580                                 ctx->fs_fast_symlinks_count++;
3581                                 check_blocks(ctx, &pctx, block_buf);
3582                                 continue;
3583                         }
3584                 }
3585                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3586                          e2fsck_pass1_check_device_inode(fs, inode)) {
3587                         check_immutable(ctx, &pctx);
3588                         check_size(ctx, &pctx);
3589                         ctx->fs_fifo_count++;
3590                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3591                            e2fsck_pass1_check_device_inode(fs, inode)) {
3592                         check_immutable(ctx, &pctx);
3593                         check_size(ctx, &pctx);
3594                         ctx->fs_sockets_count++;
3595                 } else
3596                         mark_inode_bad(ctx, ino);
3597                 if (inode->i_block[EXT2_IND_BLOCK])
3598                         ctx->fs_ind_count++;
3599                 if (inode->i_block[EXT2_DIND_BLOCK])
3600                         ctx->fs_dind_count++;
3601                 if (inode->i_block[EXT2_TIND_BLOCK])
3602                         ctx->fs_tind_count++;
3603                 if (inode->i_block[EXT2_IND_BLOCK] ||
3604                     inode->i_block[EXT2_DIND_BLOCK] ||
3605                     inode->i_block[EXT2_TIND_BLOCK] ||
3606                     inode->i_file_acl) {
3607                         inodes_to_process[process_inode_count].ino = ino;
3608                         inodes_to_process[process_inode_count].inode = *inode;
3609                         process_inode_count++;
3610                 } else
3611                         check_blocks(ctx, &pctx, block_buf);
3612
3613                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3614                         return;
3615
3616                 if (process_inode_count >= ctx->process_inode_size) {
3617                         process_inodes(ctx, block_buf);
3618
3619                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3620                                 return;
3621                 }
3622         }
3623         process_inodes(ctx, block_buf);
3624         ext2fs_close_inode_scan(scan);
3625         ehandler_operation(0);
3626
3627         /*
3628          * If any extended attribute blocks' reference counts need to
3629          * be adjusted, either up (ctx->refcount_extra), or down
3630          * (ctx->refcount), then fix them.
3631          */
3632         if (ctx->refcount) {
3633                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3634                 ea_refcount_free(ctx->refcount);
3635                 ctx->refcount = 0;
3636         }
3637         if (ctx->refcount_extra) {
3638                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3639                                         block_buf, +1);
3640                 ea_refcount_free(ctx->refcount_extra);
3641                 ctx->refcount_extra = 0;
3642         }
3643
3644         if (ctx->invalid_bitmaps)
3645                 handle_fs_bad_blocks(ctx);
3646
3647         /* We don't need the block_ea_map any more */
3648         ext2fs_free_block_bitmap(ctx->block_ea_map);
3649         ctx->block_ea_map = 0;
3650
3651         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3652                 ext2fs_block_bitmap save_bmap;
3653
3654                 save_bmap = fs->block_map;
3655                 fs->block_map = ctx->block_found_map;
3656                 clear_problem_context(&pctx);
3657                 pctx.errcode = ext2fs_create_resize_inode(fs);
3658                 if (pctx.errcode) {
3659                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3660                         /* Should never get here */
3661                         ctx->flags |= E2F_FLAG_ABORT;
3662                         return;
3663                 }
3664                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3665                                   "recreate inode");
3666                 inode->i_mtime = time(NULL);
3667                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3668                                   "recreate inode");
3669                 fs->block_map = save_bmap;
3670                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3671         }
3672
3673         if (ctx->flags & E2F_FLAG_RESTART) {
3674                 /*
3675                  * Only the master copy of the superblock and block
3676                  * group descriptors are going to be written during a
3677                  * restart, so set the superblock to be used to be the
3678                  * master superblock.
3679                  */
3680                 ctx->use_superblock = 0;
3681                 unwind_pass1();
3682                 goto endit;
3683         }
3684
3685         if (ctx->block_dup_map) {
3686                 if (ctx->options & E2F_OPT_PREEN) {
3687                         clear_problem_context(&pctx);
3688                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3689                 }
3690                 e2fsck_pass1_dupblocks(ctx, block_buf);
3691         }
3692         ext2fs_free_mem(&inodes_to_process);
3693 endit:
3694         e2fsck_use_inode_shortcuts(ctx, 0);
3695
3696         ext2fs_free_mem(&block_buf);
3697         ext2fs_free_mem(&inode);
3698 }
3699
3700 /*
3701  * When the inode_scan routines call this callback at the end of the
3702  * glock group, call process_inodes.
3703  */
3704 static errcode_t scan_callback(ext2_filsys fs,
3705                                dgrp_t group, void * priv_data)
3706 {
3707         struct scan_callback_struct *scan_struct;
3708         e2fsck_t ctx;
3709
3710         scan_struct = (struct scan_callback_struct *) priv_data;
3711         ctx = scan_struct->ctx;
3712
3713         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3714
3715         if (ctx->progress)
3716                 if ((ctx->progress)(ctx, 1, group+1,
3717                                     ctx->fs->group_desc_count))
3718                         return EXT2_ET_CANCEL_REQUESTED;
3719
3720         return 0;
3721 }
3722
3723 /*
3724  * Process the inodes in the "inodes to process" list.
3725  */
3726 static void process_inodes(e2fsck_t ctx, char *block_buf)
3727 {
3728         int                     i;
3729         struct ext2_inode       *old_stashed_inode;
3730         ext2_ino_t              old_stashed_ino;
3731         const char              *old_operation;
3732         char                    buf[80];
3733         struct problem_context  pctx;
3734
3735         /* begin process_inodes */
3736         if (process_inode_count == 0)
3737                 return;
3738         old_operation = ehandler_operation(0);
3739         old_stashed_inode = ctx->stashed_inode;
3740         old_stashed_ino = ctx->stashed_ino;
3741         qsort(inodes_to_process, process_inode_count,
3742                       sizeof(struct process_inode_block), process_inode_cmp);
3743         clear_problem_context(&pctx);
3744         for (i=0; i < process_inode_count; i++) {
3745                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3746                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3747                 sprintf(buf, _("reading indirect blocks of inode %u"),
3748                         pctx.ino);
3749                 ehandler_operation(buf);
3750                 check_blocks(ctx, &pctx, block_buf);
3751                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3752                         break;
3753         }
3754         ctx->stashed_inode = old_stashed_inode;
3755         ctx->stashed_ino = old_stashed_ino;
3756         process_inode_count = 0;
3757         /* end process inodes */
3758
3759         ehandler_operation(old_operation);
3760 }
3761
3762 static int process_inode_cmp(const void *a, const void *b)
3763 {
3764         const struct process_inode_block *ib_a =
3765                 (const struct process_inode_block *) a;
3766         const struct process_inode_block *ib_b =
3767                 (const struct process_inode_block *) b;
3768         int     ret;
3769
3770         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3771                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3772         if (ret == 0)
3773                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3774         return ret;
3775 }
3776
3777 /*
3778  * Mark an inode as being bad in some what
3779  */
3780 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3781 {
3782         struct          problem_context pctx;
3783
3784         if (!ctx->inode_bad_map) {
3785                 clear_problem_context(&pctx);
3786
3787                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3788                             _("bad inode map"), &ctx->inode_bad_map);
3789                 if (pctx.errcode) {
3790                         pctx.num = 3;
3791                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3792                         /* Should never get here */
3793                         ctx->flags |= E2F_FLAG_ABORT;
3794                         return;
3795                 }
3796         }
3797         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3798 }
3799
3800
3801 /*
3802  * This procedure will allocate the inode imagic table
3803  */
3804 static void alloc_imagic_map(e2fsck_t ctx)
3805 {
3806         struct          problem_context pctx;
3807
3808         clear_problem_context(&pctx);
3809         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3810                                               _("imagic inode map"),
3811                                               &ctx->inode_imagic_map);
3812         if (pctx.errcode) {
3813                 pctx.num = 5;
3814                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3815                 /* Should never get here */
3816                 ctx->flags |= E2F_FLAG_ABORT;
3817                 return;
3818         }
3819 }
3820
3821 /*
3822  * Marks a block as in use, setting the dup_map if it's been set
3823  * already.  Called by process_block and process_bad_block.
3824  *
3825  * WARNING: Assumes checks have already been done to make sure block
3826  * is valid.  This is true in both process_block and process_bad_block.
3827  */
3828 static void mark_block_used(e2fsck_t ctx, blk_t block)
3829 {
3830         struct          problem_context pctx;
3831
3832         clear_problem_context(&pctx);
3833
3834         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3835                 if (!ctx->block_dup_map) {
3836                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3837                               _("multiply claimed block map"),
3838                               &ctx->block_dup_map);
3839                         if (pctx.errcode) {
3840                                 pctx.num = 3;
3841                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3842                                             &pctx);
3843                                 /* Should never get here */
3844                                 ctx->flags |= E2F_FLAG_ABORT;
3845                                 return;
3846                         }
3847                 }
3848                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3849         } else {
3850                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3851         }
3852 }
3853
3854 /*
3855  * Adjust the extended attribute block's reference counts at the end
3856  * of pass 1, either by subtracting out references for EA blocks that
3857  * are still referenced in ctx->refcount, or by adding references for
3858  * EA blocks that had extra references as accounted for in
3859  * ctx->refcount_extra.
3860  */
3861 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3862                                     char *block_buf, int adjust_sign)
3863 {
3864         struct ext2_ext_attr_header     *header;
3865         struct problem_context          pctx;
3866         ext2_filsys                     fs = ctx->fs;
3867         blk_t                           blk;
3868         __u32                           should_be;
3869         int                             count;
3870
3871         clear_problem_context(&pctx);
3872
3873         ea_refcount_intr_begin(refcount);
3874         while (1) {
3875                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3876                         break;
3877                 pctx.blk = blk;
3878                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3879                 if (pctx.errcode) {
3880                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3881                         return;
3882                 }
3883                 header = (struct ext2_ext_attr_header *) block_buf;
3884                 pctx.blkcount = header->h_refcount;
3885                 should_be = header->h_refcount + adjust_sign * count;
3886                 pctx.num = should_be;
3887                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3888                         header->h_refcount = should_be;
3889                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3890                                                              block_buf);
3891                         if (pctx.errcode) {
3892                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3893                                 continue;
3894                         }
3895                 }
3896         }
3897 }
3898
3899 /*
3900  * Handle processing the extended attribute blocks
3901  */
3902 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3903                            char *block_buf)
3904 {
3905         ext2_filsys fs = ctx->fs;
3906         ext2_ino_t      ino = pctx->ino;
3907         struct ext2_inode *inode = pctx->inode;
3908         blk_t           blk;
3909         char *          end;
3910         struct ext2_ext_attr_header *header;
3911         struct ext2_ext_attr_entry *entry;
3912         int             count;
3913         region_t        region;
3914
3915         blk = inode->i_file_acl;
3916         if (blk == 0)
3917                 return 0;
3918
3919         /*
3920          * If the Extended attribute flag isn't set, then a non-zero
3921          * file acl means that the inode is corrupted.
3922          *
3923          * Or if the extended attribute block is an invalid block,
3924          * then the inode is also corrupted.
3925          */
3926         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3927             (blk < fs->super->s_first_data_block) ||
3928             (blk >= fs->super->s_blocks_count)) {
3929                 mark_inode_bad(ctx, ino);
3930                 return 0;
3931         }
3932
3933         /* If ea bitmap hasn't been allocated, create it */
3934         if (!ctx->block_ea_map) {
3935                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3936                                                       _("ext attr block map"),
3937                                                       &ctx->block_ea_map);
3938                 if (pctx->errcode) {
3939                         pctx->num = 2;
3940                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3941                         ctx->flags |= E2F_FLAG_ABORT;
3942                         return 0;
3943                 }
3944         }
3945
3946         /* Create the EA refcount structure if necessary */
3947         if (!ctx->refcount) {
3948                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3949                 if (pctx->errcode) {
3950                         pctx->num = 1;
3951                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3952                         ctx->flags |= E2F_FLAG_ABORT;
3953                         return 0;
3954                 }
3955         }
3956
3957         /* Have we seen this EA block before? */
3958         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3959                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3960                         return 1;
3961                 /* Ooops, this EA was referenced more than it stated */
3962                 if (!ctx->refcount_extra) {
3963                         pctx->errcode = ea_refcount_create(0,
3964                                            &ctx->refcount_extra);
3965                         if (pctx->errcode) {
3966                                 pctx->num = 2;
3967                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3968                                 ctx->flags |= E2F_FLAG_ABORT;
3969                                 return 0;
3970                         }
3971                 }
3972                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3973                 return 1;
3974         }
3975
3976         /*
3977          * OK, we haven't seen this EA block yet.  So we need to
3978          * validate it
3979          */
3980         pctx->blk = blk;
3981         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3982         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3983                 goto clear_extattr;
3984         header = (struct ext2_ext_attr_header *) block_buf;
3985         pctx->blk = inode->i_file_acl;
3986         if (((ctx->ext_attr_ver == 1) &&
3987              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3988             ((ctx->ext_attr_ver == 2) &&
3989              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3990                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3991                         goto clear_extattr;
3992         }
3993
3994         if (header->h_blocks != 1) {
3995                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3996                         goto clear_extattr;
3997         }
3998
3999         region = region_create(0, fs->blocksize);
4000         if (!region) {
4001                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4002                 ctx->flags |= E2F_FLAG_ABORT;
4003                 return 0;
4004         }
4005         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4006                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4007                         goto clear_extattr;
4008         }
4009
4010         entry = (struct ext2_ext_attr_entry *)(header+1);
4011         end = block_buf + fs->blocksize;
4012         while ((char *)entry < end && *(__u32 *)entry) {
4013                 if (region_allocate(region, (char *)entry - (char *)header,
4014                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4015                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4016                                 goto clear_extattr;
4017                 }
4018                 if ((ctx->ext_attr_ver == 1 &&
4019                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4020                     (ctx->ext_attr_ver == 2 &&
4021                      entry->e_name_index == 0)) {
4022                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4023                                 goto clear_extattr;
4024                 }
4025                 if (entry->e_value_block != 0) {
4026                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4027                                 goto clear_extattr;
4028                 }
4029                 if (entry->e_value_size &&
4030                     region_allocate(region, entry->e_value_offs,
4031                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4032                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4033                                 goto clear_extattr;
4034                 }
4035                 entry = EXT2_EXT_ATTR_NEXT(entry);
4036         }
4037         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4038                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4039                         goto clear_extattr;
4040         }
4041         region_free(region);
4042
4043         count = header->h_refcount - 1;
4044         if (count)
4045                 ea_refcount_store(ctx->refcount, blk, count);
4046         mark_block_used(ctx, blk);
4047         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4048
4049         return 1;
4050
4051 clear_extattr:
4052         inode->i_file_acl = 0;
4053         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4054         return 0;
4055 }
4056
4057 /* Returns 1 if bad htree, 0 if OK */
4058 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4059                         ext2_ino_t ino FSCK_ATTR((unused)),
4060                         struct ext2_inode *inode,
4061                         char *block_buf)
4062 {
4063         struct ext2_dx_root_info        *root;
4064         ext2_filsys                     fs = ctx->fs;
4065         errcode_t                       retval;
4066         blk_t                           blk;
4067
4068         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4069              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4070             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4071              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4072                 return 1;
4073
4074         blk = inode->i_block[0];
4075         if (((blk == 0) ||
4076              (blk < fs->super->s_first_data_block) ||
4077              (blk >= fs->super->s_blocks_count)) &&
4078             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4079                 return 1;
4080
4081         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4082         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4083                 return 1;
4084
4085         /* XXX should check that beginning matches a directory */
4086         root = (struct ext2_dx_root_info *) (block_buf + 24);
4087
4088         if ((root->reserved_zero || root->info_length < 8) &&
4089             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4090                 return 1;
4091
4092         pctx->num = root->hash_version;
4093         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4094             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4095             (root->hash_version != EXT2_HASH_TEA) &&
4096             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4097                 return 1;
4098
4099         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4100             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4101                 return 1;
4102
4103         pctx->num = root->indirect_levels;
4104         if ((root->indirect_levels > 1) &&
4105             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4106                 return 1;
4107
4108         return 0;
4109 }
4110
4111 /*
4112  * This subroutine is called on each inode to account for all of the
4113  * blocks used by that inode.
4114  */
4115 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4116                          char *block_buf)
4117 {
4118         ext2_filsys fs = ctx->fs;
4119         struct process_block_struct_1 pb;
4120         ext2_ino_t      ino = pctx->ino;
4121         struct ext2_inode *inode = pctx->inode;
4122         int             bad_size = 0;
4123         int             dirty_inode = 0;
4124         __u64           size;
4125
4126         pb.ino = ino;
4127         pb.num_blocks = 0;
4128         pb.last_block = -1;
4129         pb.num_illegal_blocks = 0;
4130         pb.suppress = 0; pb.clear = 0;
4131         pb.fragmented = 0;
4132         pb.compressed = 0;
4133         pb.previous_block = 0;
4134         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4135         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4136         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4137         pb.inode = inode;
4138         pb.pctx = pctx;
4139         pb.ctx = ctx;
4140         pctx->ino = ino;
4141         pctx->errcode = 0;
4142
4143         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4144                 if (fs->super->s_feature_incompat &
4145                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4146                         pb.compressed = 1;
4147                 else {
4148                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4149                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4150                                 dirty_inode++;
4151                         }
4152                 }
4153         }
4154
4155         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4156                 pb.num_blocks++;
4157
4158         if (ext2fs_inode_has_valid_blocks(inode))
4159                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4160                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4161                                        block_buf, process_block, &pb);
4162         end_problem_latch(ctx, PR_LATCH_BLOCK);
4163         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4164         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4165                 goto out;
4166         if (pctx->errcode)
4167                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4168
4169         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4170                 ctx->fs_fragmented++;
4171
4172         if (pb.clear) {
4173                 inode->i_links_count = 0;
4174                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4175                 inode->i_dtime = time(NULL);
4176                 dirty_inode++;
4177                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4178                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4179                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4180                 /*
4181                  * The inode was probably partially accounted for
4182                  * before processing was aborted, so we need to
4183                  * restart the pass 1 scan.
4184                  */
4185                 ctx->flags |= E2F_FLAG_RESTART;
4186                 goto out;
4187         }
4188
4189         if (inode->i_flags & EXT2_INDEX_FL) {
4190                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4191                         inode->i_flags &= ~EXT2_INDEX_FL;
4192                         dirty_inode++;
4193                 } else {
4194 #ifdef ENABLE_HTREE
4195                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4196 #endif
4197                 }
4198         }
4199         if (ctx->dirs_to_hash && pb.is_dir &&
4200             !(inode->i_flags & EXT2_INDEX_FL) &&
4201             ((inode->i_size / fs->blocksize) >= 3))
4202                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4203
4204         if (!pb.num_blocks && pb.is_dir) {
4205                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4206                         inode->i_links_count = 0;
4207                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4208                         inode->i_dtime = time(NULL);
4209                         dirty_inode++;
4210                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4211                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4212                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4213                         ctx->fs_directory_count--;
4214                         goto out;
4215                 }
4216         }
4217
4218         pb.num_blocks *= (fs->blocksize / 512);
4219
4220         if (pb.is_dir) {
4221                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4222                 if (nblock > (pb.last_block + 1))
4223                         bad_size = 1;
4224                 else if (nblock < (pb.last_block + 1)) {
4225                         if (((pb.last_block + 1) - nblock) >
4226                             fs->super->s_prealloc_dir_blocks)
4227                                 bad_size = 2;
4228                 }
4229         } else {
4230                 size = EXT2_I_SIZE(inode);
4231                 if ((pb.last_block >= 0) &&
4232                     (size < (__u64) pb.last_block * fs->blocksize))
4233                         bad_size = 3;
4234                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4235                         bad_size = 4;
4236         }
4237         /* i_size for symlinks is checked elsewhere */
4238         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4239                 pctx->num = (pb.last_block+1) * fs->blocksize;
4240                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4241                         inode->i_size = pctx->num;
4242                         if (!LINUX_S_ISDIR(inode->i_mode))
4243                                 inode->i_size_high = pctx->num >> 32;
4244                         dirty_inode++;
4245                 }
4246                 pctx->num = 0;
4247         }
4248         if (LINUX_S_ISREG(inode->i_mode) &&
4249             (inode->i_size_high || inode->i_size & 0x80000000UL))
4250                 ctx->large_files++;
4251         if (pb.num_blocks != inode->i_blocks) {
4252                 pctx->num = pb.num_blocks;
4253                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4254                         inode->i_blocks = pb.num_blocks;
4255                         dirty_inode++;
4256                 }
4257                 pctx->num = 0;
4258         }
4259 out:
4260         if (dirty_inode)
4261                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4262 }
4263
4264
4265 /*
4266  * This is a helper function for check_blocks().
4267  */
4268 static int process_block(ext2_filsys fs,
4269                   blk_t *block_nr,
4270                   e2_blkcnt_t blockcnt,
4271                   blk_t ref_block FSCK_ATTR((unused)),
4272                   int ref_offset FSCK_ATTR((unused)),
4273                   void *priv_data)
4274 {
4275         struct process_block_struct_1 *p;
4276         struct problem_context *pctx;
4277         blk_t   blk = *block_nr;
4278         int     ret_code = 0;
4279         int     problem = 0;
4280         e2fsck_t        ctx;
4281
4282         p = (struct process_block_struct_1 *) priv_data;
4283         pctx = p->pctx;
4284         ctx = p->ctx;
4285
4286         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4287                 /* todo: Check that the comprblk_fl is high, that the
4288                    blkaddr pattern looks right (all non-holes up to
4289                    first EXT2FS_COMPRESSED_BLKADDR, then all
4290                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4291                    that the feature_incompat bit is high, and that the
4292                    inode is a regular file.  If we're doing a "full
4293                    check" (a concept introduced to e2fsck by e2compr,
4294                    meaning that we look at data blocks as well as
4295                    metadata) then call some library routine that
4296                    checks the compressed data.  I'll have to think
4297                    about this, because one particularly important
4298                    problem to be able to fix is to recalculate the
4299                    cluster size if necessary.  I think that perhaps
4300                    we'd better do most/all e2compr-specific checks
4301                    separately, after the non-e2compr checks.  If not
4302                    doing a full check, it may be useful to test that
4303                    the personality is linux; e.g. if it isn't then
4304                    perhaps this really is just an illegal block. */
4305                 return 0;
4306         }
4307
4308         if (blk == 0) {
4309                 if (p->is_dir == 0) {
4310                         /*
4311                          * Should never happen, since only directories
4312                          * get called with BLOCK_FLAG_HOLE
4313                          */
4314 #ifdef DEBUG_E2FSCK
4315                         printf("process_block() called with blk == 0, "
4316                                "blockcnt=%d, inode %lu???\n",
4317                                blockcnt, p->ino);
4318 #endif
4319                         return 0;
4320                 }
4321                 if (blockcnt < 0)
4322                         return 0;
4323                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4324                         goto mark_dir;
4325                 }
4326                 return 0;
4327         }
4328
4329         /*
4330          * Simplistic fragmentation check.  We merely require that the
4331          * file be contiguous.  (Which can never be true for really
4332          * big files that are greater than a block group.)
4333          */
4334         if (!HOLE_BLKADDR(p->previous_block)) {
4335                 if (p->previous_block+1 != blk)
4336                         p->fragmented = 1;
4337         }
4338         p->previous_block = blk;
4339
4340         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4341                 problem = PR_1_TOOBIG_DIR;
4342         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4343                 problem = PR_1_TOOBIG_REG;
4344         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4345                 problem = PR_1_TOOBIG_SYMLINK;
4346
4347         if (blk < fs->super->s_first_data_block ||
4348             blk >= fs->super->s_blocks_count)
4349                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4350
4351         if (problem) {
4352                 p->num_illegal_blocks++;
4353                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4354                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4355                                 p->clear = 1;
4356                                 return BLOCK_ABORT;
4357                         }
4358                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4359                                 p->suppress = 1;
4360                                 set_latch_flags(PR_LATCH_BLOCK,
4361                                                 PRL_SUPPRESS, 0);
4362                         }
4363                 }
4364                 pctx->blk = blk;
4365                 pctx->blkcount = blockcnt;
4366                 if (fix_problem(ctx, problem, pctx)) {
4367                         blk = *block_nr = 0;
4368                         ret_code = BLOCK_CHANGED;
4369                         goto mark_dir;
4370                 } else
4371                         return 0;
4372         }
4373
4374         if (p->ino == EXT2_RESIZE_INO) {
4375                 /*
4376                  * The resize inode has already be sanity checked
4377                  * during pass #0 (the superblock checks).  All we
4378                  * have to do is mark the double indirect block as
4379                  * being in use; all of the other blocks are handled
4380                  * by mark_table_blocks()).
4381                  */
4382                 if (blockcnt == BLOCK_COUNT_DIND)
4383                         mark_block_used(ctx, blk);
4384         } else
4385                 mark_block_used(ctx, blk);
4386         p->num_blocks++;
4387         if (blockcnt >= 0)
4388                 p->last_block = blockcnt;
4389 mark_dir:
4390         if (p->is_dir && (blockcnt >= 0)) {
4391                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4392                                                     blk, blockcnt);
4393                 if (pctx->errcode) {
4394                         pctx->blk = blk;
4395                         pctx->num = blockcnt;
4396                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4397                         /* Should never get here */
4398                         ctx->flags |= E2F_FLAG_ABORT;
4399                         return BLOCK_ABORT;
4400                 }
4401         }
4402         return ret_code;
4403 }
4404
4405 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4406                       blk_t *block_nr,
4407                       e2_blkcnt_t blockcnt,
4408                       blk_t ref_block FSCK_ATTR((unused)),
4409                       int ref_offset FSCK_ATTR((unused)),
4410                       void *priv_data EXT2FS_ATTR((unused)))
4411 {
4412         /*
4413          * Note: This function processes blocks for the bad blocks
4414          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4415          */
4416
4417         printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4418         return BLOCK_ERROR;
4419 }
4420
4421 /*
4422  * This routine gets called at the end of pass 1 if bad blocks are
4423  * detected in the superblock, group descriptors, inode_bitmaps, or
4424  * block bitmaps.  At this point, all of the blocks have been mapped
4425  * out, so we can try to allocate new block(s) to replace the bad
4426  * blocks.
4427  */
4428 static void handle_fs_bad_blocks(e2fsck_t ctx)
4429 {
4430         printf("Bad blocks detected on your filesystem\n"
4431                 "You should get your data off as the device will soon die\n");
4432 }
4433
4434 /*
4435  * This routine marks all blocks which are used by the superblock,
4436  * group descriptors, inode bitmaps, and block bitmaps.
4437  */
4438 static void mark_table_blocks(e2fsck_t ctx)
4439 {
4440         ext2_filsys fs = ctx->fs;
4441         blk_t   block, b;
4442         dgrp_t  i;
4443         int     j;
4444         struct problem_context pctx;
4445
4446         clear_problem_context(&pctx);
4447
4448         block = fs->super->s_first_data_block;
4449         for (i = 0; i < fs->group_desc_count; i++) {
4450                 pctx.group = i;
4451
4452                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4453
4454                 /*
4455                  * Mark the blocks used for the inode table
4456                  */
4457                 if (fs->group_desc[i].bg_inode_table) {
4458                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4459                              j < fs->inode_blocks_per_group;
4460                              j++, b++) {
4461                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4462                                                              b)) {
4463                                         pctx.blk = b;
4464                                         if (fix_problem(ctx,
4465                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4466                                                 ctx->invalid_inode_table_flag[i]++;
4467                                                 ctx->invalid_bitmaps++;
4468                                         }
4469                                 } else {
4470                                         ext2fs_mark_block_bitmap(ctx->block_found_map, b);
4471                                 }
4472                         }
4473                 }
4474
4475                 /*
4476                  * Mark block used for the block bitmap
4477                  */
4478                 if (fs->group_desc[i].bg_block_bitmap) {
4479                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4480                                      fs->group_desc[i].bg_block_bitmap)) {
4481                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4482                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4483                                         ctx->invalid_block_bitmap_flag[i]++;
4484                                         ctx->invalid_bitmaps++;
4485                                 }
4486                         } else {
4487                                 ext2fs_mark_block_bitmap(ctx->block_found_map,
4488                                         fs->group_desc[i].bg_block_bitmap);
4489                         }
4490                 }
4491                 /*
4492                  * Mark block used for the inode bitmap
4493                  */
4494                 if (fs->group_desc[i].bg_inode_bitmap) {
4495                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4496                                      fs->group_desc[i].bg_inode_bitmap)) {
4497                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4498                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4499                                         ctx->invalid_inode_bitmap_flag[i]++;
4500                                         ctx->invalid_bitmaps++;
4501                                 }
4502                         } else {
4503                                 ext2fs_mark_block_bitmap(ctx->block_found_map,
4504                                         fs->group_desc[i].bg_inode_bitmap);
4505                         }
4506                 }
4507                 block += fs->super->s_blocks_per_group;
4508         }
4509 }
4510
4511 /*
4512  * Thes subroutines short circuits ext2fs_get_blocks and
4513  * ext2fs_check_directory; we use them since we already have the inode
4514  * structure, so there's no point in letting the ext2fs library read
4515  * the inode again.
4516  */
4517 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4518                                   blk_t *blocks)
4519 {
4520         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521         int     i;
4522
4523         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4524                 return EXT2_ET_CALLBACK_NOTHANDLED;
4525
4526         for (i=0; i < EXT2_N_BLOCKS; i++)
4527                 blocks[i] = ctx->stashed_inode->i_block[i];
4528         return 0;
4529 }
4530
4531 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4532                                   struct ext2_inode *inode)
4533 {
4534         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4535
4536         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4537                 return EXT2_ET_CALLBACK_NOTHANDLED;
4538         *inode = *ctx->stashed_inode;
4539         return 0;
4540 }
4541
4542 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4543                             struct ext2_inode *inode)
4544 {
4545         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4546
4547         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4548                 *ctx->stashed_inode = *inode;
4549         return EXT2_ET_CALLBACK_NOTHANDLED;
4550 }
4551
4552 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4553 {
4554         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4555
4556         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4557                 return EXT2_ET_CALLBACK_NOTHANDLED;
4558
4559         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4560                 return EXT2_ET_NO_DIRECTORY;
4561         return 0;
4562 }
4563
4564 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4565 {
4566         ext2_filsys fs = ctx->fs;
4567
4568         if (bool) {
4569                 fs->get_blocks = pass1_get_blocks;
4570                 fs->check_directory = pass1_check_directory;
4571                 fs->read_inode = pass1_read_inode;
4572                 fs->write_inode = pass1_write_inode;
4573                 ctx->stashed_ino = 0;
4574         } else {
4575                 fs->get_blocks = 0;
4576                 fs->check_directory = 0;
4577                 fs->read_inode = 0;
4578                 fs->write_inode = 0;
4579         }
4580 }
4581
4582 /*
4583  * pass1b.c --- Pass #1b of e2fsck
4584  *
4585  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4586  * only invoked if pass 1 discovered blocks which are in use by more
4587  * than one inode.
4588  *
4589  * Pass1B scans the data blocks of all the inodes again, generating a
4590  * complete list of duplicate blocks and which inodes have claimed
4591  * them.
4592  *
4593  * Pass1C does a tree-traversal of the filesystem, to determine the
4594  * parent directories of these inodes.  This step is necessary so that
4595  * e2fsck can print out the pathnames of affected inodes.
4596  *
4597  * Pass1D is a reconciliation pass.  For each inode with duplicate
4598  * blocks, the user is prompted if s/he would like to clone the file
4599  * (so that the file gets a fresh copy of the duplicated blocks) or
4600  * simply to delete the file.
4601  *
4602  */
4603
4604
4605 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4606 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4607 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4608
4609 /* Define an extension to the ext2 library's block count information */
4610 #define BLOCK_COUNT_EXTATTR     (-5)
4611
4612 struct block_el {
4613         blk_t   block;
4614         struct block_el *next;
4615 };
4616
4617 struct inode_el {
4618         ext2_ino_t      inode;
4619         struct inode_el *next;
4620 };
4621
4622 struct dup_block {
4623         int             num_bad;
4624         struct inode_el *inode_list;
4625 };
4626
4627 /*
4628  * This structure stores information about a particular inode which
4629  * is sharing blocks with other inodes.  This information is collected
4630  * to display to the user, so that the user knows what files he or she
4631  * is dealing with, when trying to decide how to resolve the conflict
4632  * of multiply-claimed blocks.
4633  */
4634 struct dup_inode {
4635         ext2_ino_t              dir;
4636         int                     num_dupblocks;
4637         struct ext2_inode       inode;
4638         struct block_el         *block_list;
4639 };
4640
4641 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4642                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4643                                 int ref_offset, void *priv_data);
4644 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4645                         struct dup_inode *dp, char *block_buf);
4646 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4647                       struct dup_inode *dp, char* block_buf);
4648 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4649
4650 static void pass1b(e2fsck_t ctx, char *block_buf);
4651 static void pass1c(e2fsck_t ctx, char *block_buf);
4652 static void pass1d(e2fsck_t ctx, char *block_buf);
4653
4654 static int dup_inode_count = 0;
4655
4656 static dict_t blk_dict, ino_dict;
4657
4658 static ext2fs_inode_bitmap inode_dup_map;
4659
4660 static int dict_int_cmp(const void *a, const void *b)
4661 {
4662         intptr_t        ia, ib;
4663
4664         ia = (intptr_t)a;
4665         ib = (intptr_t)b;
4666
4667         return (ia-ib);
4668 }
4669
4670 /*
4671  * Add a duplicate block record
4672  */
4673 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4674                      struct ext2_inode *inode)
4675 {
4676         dnode_t *n;
4677         struct dup_block        *db;
4678         struct dup_inode        *di;
4679         struct block_el         *blk_el;
4680         struct inode_el         *ino_el;
4681
4682         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4683         if (n)
4684                 db = (struct dup_block *) dnode_get(n);
4685         else {
4686                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4687                          sizeof(struct dup_block), "duplicate block header");
4688                 db->num_bad = 0;
4689                 db->inode_list = 0;
4690                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4691         }
4692         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4693                          sizeof(struct inode_el), "inode element");
4694         ino_el->inode = ino;
4695         ino_el->next = db->inode_list;
4696         db->inode_list = ino_el;
4697         db->num_bad++;
4698
4699         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4700         if (n)
4701                 di = (struct dup_inode *) dnode_get(n);
4702         else {
4703                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4704                          sizeof(struct dup_inode), "duplicate inode header");
4705                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4706                 di->num_dupblocks = 0;
4707                 di->block_list = 0;
4708                 di->inode = *inode;
4709                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4710         }
4711         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4712                          sizeof(struct block_el), "block element");
4713         blk_el->block = blk;
4714         blk_el->next = di->block_list;
4715         di->block_list = blk_el;
4716         di->num_dupblocks++;
4717 }
4718
4719 /*
4720  * Free a duplicate inode record
4721  */
4722 static void inode_dnode_free(dnode_t *node)
4723 {
4724         struct dup_inode        *di;
4725         struct block_el         *p, *next;
4726
4727         di = (struct dup_inode *) dnode_get(node);
4728         for (p = di->block_list; p; p = next) {
4729                 next = p->next;
4730                 free(p);
4731         }
4732         free(node);
4733 }
4734
4735 /*
4736  * Free a duplicate block record
4737  */
4738 static void block_dnode_free(dnode_t *node)
4739 {
4740         struct dup_block        *db;
4741         struct inode_el         *p, *next;
4742
4743         db = (struct dup_block *) dnode_get(node);
4744         for (p = db->inode_list; p; p = next) {
4745                 next = p->next;
4746                 free(p);
4747         }
4748         free(node);
4749 }
4750
4751
4752 /*
4753  * Main procedure for handling duplicate blocks
4754  */
4755 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4756 {
4757         ext2_filsys             fs = ctx->fs;
4758         struct problem_context  pctx;
4759
4760         clear_problem_context(&pctx);
4761
4762         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4763                       _("multiply claimed inode map"), &inode_dup_map);
4764         if (pctx.errcode) {
4765                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4766                 ctx->flags |= E2F_FLAG_ABORT;
4767                 return;
4768         }
4769
4770         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772         dict_set_allocator(&ino_dict, inode_dnode_free);
4773         dict_set_allocator(&blk_dict, block_dnode_free);
4774
4775         pass1b(ctx, block_buf);
4776         pass1c(ctx, block_buf);
4777         pass1d(ctx, block_buf);
4778
4779         /*
4780          * Time to free all of the accumulated data structures that we
4781          * don't need anymore.
4782          */
4783         dict_free_nodes(&ino_dict);
4784         dict_free_nodes(&blk_dict);
4785 }
4786
4787 /*
4788  * Scan the inodes looking for inodes that contain duplicate blocks.
4789  */
4790 struct process_block_struct_1b {
4791         e2fsck_t        ctx;
4792         ext2_ino_t      ino;
4793         int             dup_blocks;
4794         struct ext2_inode *inode;
4795         struct problem_context *pctx;
4796 };
4797
4798 static void pass1b(e2fsck_t ctx, char *block_buf)
4799 {
4800         ext2_filsys fs = ctx->fs;
4801         ext2_ino_t ino;
4802         struct ext2_inode inode;
4803         ext2_inode_scan scan;
4804         struct process_block_struct_1b pb;
4805         struct problem_context pctx;
4806
4807         clear_problem_context(&pctx);
4808
4809         if (!(ctx->options & E2F_OPT_PREEN))
4810                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4811         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4812                                               &scan);
4813         if (pctx.errcode) {
4814                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4815                 ctx->flags |= E2F_FLAG_ABORT;
4816                 return;
4817         }
4818         ctx->stashed_inode = &inode;
4819         pb.ctx = ctx;
4820         pb.pctx = &pctx;
4821         pctx.str = "pass1b";
4822         while (1) {
4823                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4824                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4825                         continue;
4826                 if (pctx.errcode) {
4827                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4828                         ctx->flags |= E2F_FLAG_ABORT;
4829                         return;
4830                 }
4831                 if (!ino)
4832                         break;
4833                 pctx.ino = ctx->stashed_ino = ino;
4834                 if ((ino != EXT2_BAD_INO) &&
4835                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4836                         continue;
4837
4838                 pb.ino = ino;
4839                 pb.dup_blocks = 0;
4840                 pb.inode = &inode;
4841
4842                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4843                     (ino == EXT2_BAD_INO))
4844                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4845                                      0, block_buf, process_pass1b_block, &pb);
4846                 if (inode.i_file_acl)
4847                         process_pass1b_block(fs, &inode.i_file_acl,
4848                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4849                 if (pb.dup_blocks) {
4850                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4851                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4852                             ino == EXT2_ROOT_INO)
4853                                 dup_inode_count++;
4854                 }
4855                 if (pctx.errcode)
4856                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4857         }
4858         ext2fs_close_inode_scan(scan);
4859         e2fsck_use_inode_shortcuts(ctx, 0);
4860 }
4861
4862 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4863                                 blk_t   *block_nr,
4864                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4865                                 blk_t ref_blk FSCK_ATTR((unused)),
4866                                 int ref_offset FSCK_ATTR((unused)),
4867                                 void *priv_data)
4868 {
4869         struct process_block_struct_1b *p;
4870         e2fsck_t ctx;
4871
4872         if (HOLE_BLKADDR(*block_nr))
4873                 return 0;
4874         p = (struct process_block_struct_1b *) priv_data;
4875         ctx = p->ctx;
4876
4877         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4878                 return 0;
4879
4880         /* OK, this is a duplicate block */
4881         if (p->ino != EXT2_BAD_INO) {
4882                 p->pctx->blk = *block_nr;
4883                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4884         }
4885         p->dup_blocks++;
4886         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4887
4888         add_dupe(ctx, p->ino, *block_nr, p->inode);
4889
4890         return 0;
4891 }
4892
4893 /*
4894  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4895  * is used so that we can print pathnames when prompting the user for
4896  * what to do.
4897  */
4898 struct search_dir_struct {
4899         int             count;
4900         ext2_ino_t      first_inode;
4901         ext2_ino_t      max_inode;
4902 };
4903
4904 static int search_dirent_proc(ext2_ino_t dir, int entry,
4905                               struct ext2_dir_entry *dirent,
4906                               int offset FSCK_ATTR((unused)),
4907                               int blocksize FSCK_ATTR((unused)),
4908                               char *buf FSCK_ATTR((unused)),
4909                               void *priv_data)
4910 {
4911         struct search_dir_struct *sd;
4912         struct dup_inode        *p;
4913         dnode_t                 *n;
4914
4915         sd = (struct search_dir_struct *) priv_data;
4916
4917         if (dirent->inode > sd->max_inode)
4918                 /* Should abort this inode, but not everything */
4919                 return 0;
4920
4921         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4922             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4923                 return 0;
4924
4925         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4926         if (!n)
4927                 return 0;
4928         p = (struct dup_inode *) dnode_get(n);
4929         p->dir = dir;
4930         sd->count--;
4931
4932         return sd->count ? 0 : DIRENT_ABORT;
4933 }
4934
4935
4936 static void pass1c(e2fsck_t ctx, char *block_buf)
4937 {
4938         ext2_filsys fs = ctx->fs;
4939         struct search_dir_struct sd;
4940         struct problem_context pctx;
4941
4942         clear_problem_context(&pctx);
4943
4944         if (!(ctx->options & E2F_OPT_PREEN))
4945                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4946
4947         /*
4948          * Search through all directories to translate inodes to names
4949          * (by searching for the containing directory for that inode.)
4950          */
4951         sd.count = dup_inode_count;
4952         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4953         sd.max_inode = fs->super->s_inodes_count;
4954         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4955                                   search_dirent_proc, &sd);
4956 }
4957
4958 static void pass1d(e2fsck_t ctx, char *block_buf)
4959 {
4960         ext2_filsys fs = ctx->fs;
4961         struct dup_inode        *p, *t;
4962         struct dup_block        *q;
4963         ext2_ino_t              *shared, ino;
4964         int     shared_len;
4965         int     i;
4966         int     file_ok;
4967         int     meta_data = 0;
4968         struct problem_context pctx;
4969         dnode_t *n, *m;
4970         struct block_el *s;
4971         struct inode_el *r;
4972
4973         clear_problem_context(&pctx);
4974
4975         if (!(ctx->options & E2F_OPT_PREEN))
4976                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4977         e2fsck_read_bitmaps(ctx);
4978
4979         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4980         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4981         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4982                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4983                                 "Shared inode list");
4984         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4985                 p = (struct dup_inode *) dnode_get(n);
4986                 shared_len = 0;
4987                 file_ok = 1;
4988                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4989                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4990                         continue;
4991
4992                 /*
4993                  * Find all of the inodes which share blocks with this
4994                  * one.  First we find all of the duplicate blocks
4995                  * belonging to this inode, and then search each block
4996                  * get the list of inodes, and merge them together.
4997                  */
4998                 for (s = p->block_list; s; s = s->next) {
4999                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5000                         if (!m)
5001                                 continue; /* Should never happen... */
5002                         q = (struct dup_block *) dnode_get(m);
5003                         if (q->num_bad > 1)
5004                                 file_ok = 0;
5005                         if (check_if_fs_block(ctx, s->block)) {
5006                                 file_ok = 0;
5007                                 meta_data = 1;
5008                         }
5009
5010                         /*
5011                          * Add all inodes used by this block to the
5012                          * shared[] --- which is a unique list, so
5013                          * if an inode is already in shared[], don't
5014                          * add it again.
5015                          */
5016                         for (r = q->inode_list; r; r = r->next) {
5017                                 if (r->inode == ino)
5018                                         continue;
5019                                 for (i = 0; i < shared_len; i++)
5020                                         if (shared[i] == r->inode)
5021                                                 break;
5022                                 if (i == shared_len) {
5023                                         shared[shared_len++] = r->inode;
5024                                 }
5025                         }
5026                 }
5027
5028                 /*
5029                  * Report the inode that we are working on
5030                  */
5031                 pctx.inode = &p->inode;
5032                 pctx.ino = ino;
5033                 pctx.dir = p->dir;
5034                 pctx.blkcount = p->num_dupblocks;
5035                 pctx.num = meta_data ? shared_len+1 : shared_len;
5036                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5037                 pctx.blkcount = 0;
5038                 pctx.num = 0;
5039
5040                 if (meta_data)
5041                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5042
5043                 for (i = 0; i < shared_len; i++) {
5044                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5045                         if (!m)
5046                                 continue; /* should never happen */
5047                         t = (struct dup_inode *) dnode_get(m);
5048                         /*
5049                          * Report the inode that we are sharing with
5050                          */
5051                         pctx.inode = &t->inode;
5052                         pctx.ino = shared[i];
5053                         pctx.dir = t->dir;
5054                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5055                 }
5056                 if (file_ok) {
5057                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5058                         continue;
5059                 }
5060                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5061                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5062                         if (pctx.errcode)
5063                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5064                         else
5065                                 continue;
5066                 }
5067                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5068                         delete_file(ctx, ino, p, block_buf);
5069                 else
5070                         ext2fs_unmark_valid(fs);
5071         }
5072         ext2fs_free_mem(&shared);
5073 }
5074
5075 /*
5076  * Drop the refcount on the dup_block structure, and clear the entry
5077  * in the block_dup_map if appropriate.
5078  */
5079 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5080 {
5081         p->num_bad--;
5082         if (p->num_bad <= 0 ||
5083             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5084                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5085 }
5086
5087 static int delete_file_block(ext2_filsys fs,
5088                              blk_t      *block_nr,
5089                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5090                              blk_t ref_block FSCK_ATTR((unused)),
5091                              int ref_offset FSCK_ATTR((unused)),
5092                              void *priv_data)
5093 {
5094         struct process_block_struct_1b *pb;
5095         struct dup_block *p;
5096         dnode_t *n;
5097         e2fsck_t ctx;
5098
5099         pb = (struct process_block_struct_1b *) priv_data;
5100         ctx = pb->ctx;
5101
5102         if (HOLE_BLKADDR(*block_nr))
5103                 return 0;
5104
5105         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5106                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5107                 if (n) {
5108                         p = (struct dup_block *) dnode_get(n);
5109                         decrement_badcount(ctx, *block_nr, p);
5110                 } else
5111                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5112                                 *block_nr);
5113         } else {
5114                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5115                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5116         }
5117
5118         return 0;
5119 }
5120
5121 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5122                         struct dup_inode *dp, char* block_buf)
5123 {
5124         ext2_filsys fs = ctx->fs;
5125         struct process_block_struct_1b pb;
5126         struct ext2_inode       inode;
5127         struct problem_context  pctx;
5128         unsigned int            count;
5129
5130         clear_problem_context(&pctx);
5131         pctx.ino = pb.ino = ino;
5132         pb.dup_blocks = dp->num_dupblocks;
5133         pb.ctx = ctx;
5134         pctx.str = "delete_file";
5135
5136         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5137         if (ext2fs_inode_has_valid_blocks(&inode))
5138                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5139                                                      delete_file_block, &pb);
5140         if (pctx.errcode)
5141                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5142         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5143         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5144         if (ctx->inode_bad_map)
5145                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5146         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5147
5148         /* Inode may have changed by block_iterate, so reread it */
5149         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5150         inode.i_links_count = 0;
5151         inode.i_dtime = time(NULL);
5152         if (inode.i_file_acl &&
5153             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5154                 count = 1;
5155                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5156                                                    block_buf, -1, &count);
5157                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5158                         pctx.errcode = 0;
5159                         count = 1;
5160                 }
5161                 if (pctx.errcode) {
5162                         pctx.blk = inode.i_file_acl;
5163                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5164                 }
5165                 /*
5166                  * If the count is zero, then arrange to have the
5167                  * block deleted.  If the block is in the block_dup_map,
5168                  * also call delete_file_block since it will take care
5169                  * of keeping the accounting straight.
5170                  */
5171                 if ((count == 0) ||
5172                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5173                                              inode.i_file_acl))
5174                         delete_file_block(fs, &inode.i_file_acl,
5175                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5176         }
5177         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5178 }
5179
5180 struct clone_struct {
5181         errcode_t       errcode;
5182         ext2_ino_t      dir;
5183         char    *buf;
5184         e2fsck_t ctx;
5185 };
5186
5187 static int clone_file_block(ext2_filsys fs,
5188                             blk_t       *block_nr,
5189                             e2_blkcnt_t blockcnt,
5190                             blk_t ref_block FSCK_ATTR((unused)),
5191                             int ref_offset FSCK_ATTR((unused)),
5192                             void *priv_data)
5193 {
5194         struct dup_block *p;
5195         blk_t   new_block;
5196         errcode_t       retval;
5197         struct clone_struct *cs = (struct clone_struct *) priv_data;
5198         dnode_t *n;
5199         e2fsck_t ctx;
5200
5201         ctx = cs->ctx;
5202
5203         if (HOLE_BLKADDR(*block_nr))
5204                 return 0;
5205
5206         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5207                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5208                 if (n) {
5209                         p = (struct dup_block *) dnode_get(n);
5210                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5211                                                   &new_block);
5212                         if (retval) {
5213                                 cs->errcode = retval;
5214                                 return BLOCK_ABORT;
5215                         }
5216                         if (cs->dir && (blockcnt >= 0)) {
5217                                 retval = ext2fs_set_dir_block(fs->dblist,
5218                                       cs->dir, new_block, blockcnt);
5219                                 if (retval) {
5220                                         cs->errcode = retval;
5221                                         return BLOCK_ABORT;
5222                                 }
5223                         }
5224
5225                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5226                                                      cs->buf);
5227                         if (retval) {
5228                                 cs->errcode = retval;
5229                                 return BLOCK_ABORT;
5230                         }
5231                         retval = io_channel_write_blk(fs->io, new_block, 1,
5232                                                       cs->buf);
5233                         if (retval) {
5234                                 cs->errcode = retval;
5235                                 return BLOCK_ABORT;
5236                         }
5237                         decrement_badcount(ctx, *block_nr, p);
5238                         *block_nr = new_block;
5239                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5240                                                  new_block);
5241                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5242                         return BLOCK_CHANGED;
5243                 } else
5244                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5245                                 *block_nr);
5246         }
5247         return 0;
5248 }
5249
5250 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5251                       struct dup_inode *dp, char* block_buf)
5252 {
5253         ext2_filsys fs = ctx->fs;
5254         errcode_t       retval;
5255         struct clone_struct cs;
5256         struct problem_context  pctx;
5257         blk_t           blk;
5258         dnode_t         *n;
5259         struct inode_el *ino_el;
5260         struct dup_block        *db;
5261         struct dup_inode        *di;
5262
5263         clear_problem_context(&pctx);
5264         cs.errcode = 0;
5265         cs.dir = 0;
5266         cs.ctx = ctx;
5267         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5268         if (retval)
5269                 return retval;
5270
5271         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5272                 cs.dir = ino;
5273
5274         pctx.ino = ino;
5275         pctx.str = "clone_file";
5276         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5277                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5278                                                      clone_file_block, &cs);
5279         ext2fs_mark_bb_dirty(fs);
5280         if (pctx.errcode) {
5281                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5282                 retval = pctx.errcode;
5283                 goto errout;
5284         }
5285         if (cs.errcode) {
5286                 bb_error_msg(_("returned from clone_file_block"));
5287                 retval = cs.errcode;
5288                 goto errout;
5289         }
5290         /* The inode may have changed on disk, so we have to re-read it */
5291         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5292         blk = dp->inode.i_file_acl;
5293         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5294                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5295                     BLOCK_CHANGED)) {
5296                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5297                 /*
5298                  * If we cloned the EA block, find all other inodes
5299                  * which refered to that EA block, and modify
5300                  * them to point to the new EA block.
5301                  */
5302                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5303                 db = (struct dup_block *) dnode_get(n);
5304                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5305                         if (ino_el->inode == ino)
5306                                 continue;
5307                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5308                         di = (struct dup_inode *) dnode_get(n);
5309                         if (di->inode.i_file_acl == blk) {
5310                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5311                                 e2fsck_write_inode(ctx, ino_el->inode,
5312                                            &di->inode, "clone file EA");
5313                                 decrement_badcount(ctx, blk, db);
5314                         }
5315                 }
5316         }
5317         retval = 0;
5318 errout:
5319         ext2fs_free_mem(&cs.buf);
5320         return retval;
5321 }
5322
5323 /*
5324  * This routine returns 1 if a block overlaps with one of the superblocks,
5325  * group descriptors, inode bitmaps, or block bitmaps.
5326  */
5327 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5328 {
5329         ext2_filsys fs = ctx->fs;
5330         blk_t   block;
5331         dgrp_t  i;
5332
5333         block = fs->super->s_first_data_block;
5334         for (i = 0; i < fs->group_desc_count; i++) {
5335
5336                 /* Check superblocks/block group descriptros */
5337                 if (ext2fs_bg_has_super(fs, i)) {
5338                         if (test_block >= block &&
5339                             (test_block <= block + fs->desc_blocks))
5340                                 return 1;
5341                 }
5342
5343                 /* Check the inode table */
5344                 if ((fs->group_desc[i].bg_inode_table) &&
5345                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5346                     (test_block < (fs->group_desc[i].bg_inode_table +
5347                                    fs->inode_blocks_per_group)))
5348                         return 1;
5349
5350                 /* Check the bitmap blocks */
5351                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5352                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5353                         return 1;
5354
5355                 block += fs->super->s_blocks_per_group;
5356         }
5357         return 0;
5358 }
5359 /*
5360  * pass2.c --- check directory structure
5361  *
5362  * Pass 2 of e2fsck iterates through all active directory inodes, and
5363  * applies to following tests to each directory entry in the directory
5364  * blocks in the inodes:
5365  *
5366  *      - The length of the directory entry (rec_len) should be at
5367  *              least 8 bytes, and no more than the remaining space
5368  *              left in the directory block.
5369  *      - The length of the name in the directory entry (name_len)
5370  *              should be less than (rec_len - 8).
5371  *      - The inode number in the directory entry should be within
5372  *              legal bounds.
5373  *      - The inode number should refer to a in-use inode.
5374  *      - The first entry should be '.', and its inode should be
5375  *              the inode of the directory.
5376  *      - The second entry should be '..'.
5377  *
5378  * To minimize disk seek time, the directory blocks are processed in
5379  * sorted order of block numbers.
5380  *
5381  * Pass 2 also collects the following information:
5382  *      - The inode numbers of the subdirectories for each directory.
5383  *
5384  * Pass 2 relies on the following information from previous passes:
5385  *      - The directory information collected in pass 1.
5386  *      - The inode_used_map bitmap
5387  *      - The inode_bad_map bitmap
5388  *      - The inode_dir_map bitmap
5389  *
5390  * Pass 2 frees the following data structures
5391  *      - The inode_bad_map bitmap
5392  *      - The inode_reg_map bitmap
5393  */
5394
5395 /*
5396  * Keeps track of how many times an inode is referenced.
5397  */
5398 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5399 static int check_dir_block(ext2_filsys fs,
5400                            struct ext2_db_entry *dir_blocks_info,
5401                            void *priv_data);
5402 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5403                               struct problem_context *pctx);
5404 static int update_dir_block(ext2_filsys fs,
5405                             blk_t       *block_nr,
5406                             e2_blkcnt_t blockcnt,
5407                             blk_t       ref_block,
5408                             int         ref_offset,
5409                             void        *priv_data);
5410 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5411 static int htree_depth(struct dx_dir_info *dx_dir,
5412                        struct dx_dirblock_info *dx_db);
5413 static int special_dir_block_cmp(const void *a, const void *b);
5414
5415 struct check_dir_struct {
5416         char *buf;
5417         struct problem_context  pctx;
5418         int     count, max;
5419         e2fsck_t ctx;
5420 };
5421
5422 static void e2fsck_pass2(e2fsck_t ctx)
5423 {
5424         struct ext2_super_block *sb = ctx->fs->super;
5425         struct problem_context  pctx;
5426         ext2_filsys             fs = ctx->fs;
5427         char                    *buf;
5428         struct dir_info         *dir;
5429         struct check_dir_struct cd;
5430         struct dx_dir_info      *dx_dir;
5431         struct dx_dirblock_info *dx_db, *dx_parent;
5432         int                     b;
5433         int                     i, depth;
5434         problem_t               code;
5435         int                     bad_dir;
5436
5437         clear_problem_context(&cd.pctx);
5438
5439         /* Pass 2 */
5440
5441         if (!(ctx->options & E2F_OPT_PREEN))
5442                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5443
5444         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5445                                                 0, ctx->inode_link_info,
5446                                                 &ctx->inode_count);
5447         if (cd.pctx.errcode) {
5448                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5449                 ctx->flags |= E2F_FLAG_ABORT;
5450                 return;
5451         }
5452         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5453                                               "directory scan buffer");
5454
5455         /*
5456          * Set up the parent pointer for the root directory, if
5457          * present.  (If the root directory is not present, we will
5458          * create it in pass 3.)
5459          */
5460         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5461         if (dir)
5462                 dir->parent = EXT2_ROOT_INO;
5463
5464         cd.buf = buf;
5465         cd.ctx = ctx;
5466         cd.count = 1;
5467         cd.max = ext2fs_dblist_count(fs->dblist);
5468
5469         if (ctx->progress)
5470                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5471
5472         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5473                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5474
5475         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5476                                                 &cd);
5477         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478                 return;
5479         if (cd.pctx.errcode) {
5480                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5481                 ctx->flags |= E2F_FLAG_ABORT;
5482                 return;
5483         }
5484
5485 #ifdef ENABLE_HTREE
5486         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5487                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5488                         return;
5489                 if (dx_dir->numblocks == 0)
5490                         continue;
5491                 clear_problem_context(&pctx);
5492                 bad_dir = 0;
5493                 pctx.dir = dx_dir->ino;
5494                 dx_db = dx_dir->dx_block;
5495                 if (dx_db->flags & DX_FLAG_REFERENCED)
5496                         dx_db->flags |= DX_FLAG_DUP_REF;
5497                 else
5498                         dx_db->flags |= DX_FLAG_REFERENCED;
5499                 /*
5500                  * Find all of the first and last leaf blocks, and
5501                  * update their parent's min and max hash values
5502                  */
5503                 for (b=0, dx_db = dx_dir->dx_block;
5504                      b < dx_dir->numblocks;
5505                      b++, dx_db++) {
5506                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5507                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5508                                 continue;
5509                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5510                         /*
5511                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5512                          */
5513                         if (dx_db->flags & DX_FLAG_FIRST)
5514                                 dx_parent->min_hash = dx_db->min_hash;
5515                         /*
5516                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5517                          */
5518                         if (dx_db->flags & DX_FLAG_LAST)
5519                                 dx_parent->max_hash = dx_db->max_hash;
5520                 }
5521
5522                 for (b=0, dx_db = dx_dir->dx_block;
5523                      b < dx_dir->numblocks;
5524                      b++, dx_db++) {
5525                         pctx.blkcount = b;
5526                         pctx.group = dx_db->parent;
5527                         code = 0;
5528                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5529                             (dx_db->min_hash < dx_db->node_min_hash)) {
5530                                 pctx.blk = dx_db->min_hash;
5531                                 pctx.blk2 = dx_db->node_min_hash;
5532                                 code = PR_2_HTREE_MIN_HASH;
5533                                 fix_problem(ctx, code, &pctx);
5534                                 bad_dir++;
5535                         }
5536                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5537                                 depth = htree_depth(dx_dir, dx_db);
5538                                 if (depth != dx_dir->depth) {
5539                                         code = PR_2_HTREE_BAD_DEPTH;
5540                                         fix_problem(ctx, code, &pctx);
5541                                         bad_dir++;
5542                                 }
5543                         }
5544                         /*
5545                          * This test doesn't apply for the root block
5546                          * at block #0
5547                          */
5548                         if (b &&
5549                             (dx_db->max_hash > dx_db->node_max_hash)) {
5550                                 pctx.blk = dx_db->max_hash;
5551                                 pctx.blk2 = dx_db->node_max_hash;
5552                                 code = PR_2_HTREE_MAX_HASH;
5553                                 fix_problem(ctx, code, &pctx);
5554                                 bad_dir++;
5555                         }
5556                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5557                                 code = PR_2_HTREE_NOTREF;
5558                                 fix_problem(ctx, code, &pctx);
5559                                 bad_dir++;
5560                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5561                                 code = PR_2_HTREE_DUPREF;
5562                                 fix_problem(ctx, code, &pctx);
5563                                 bad_dir++;
5564                         }
5565                         if (code == 0)
5566                                 continue;
5567                 }
5568                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5569                         clear_htree(ctx, dx_dir->ino);
5570                         dx_dir->numblocks = 0;
5571                 }
5572         }
5573 #endif
5574         ext2fs_free_mem(&buf);
5575         ext2fs_free_dblist(fs->dblist);
5576
5577         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5578         ctx->inode_bad_map = 0;
5579         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5580         ctx->inode_reg_map = 0;
5581
5582         clear_problem_context(&pctx);
5583         if (ctx->large_files) {
5584                 if (!(sb->s_feature_ro_compat &
5585                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5586                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5587                         sb->s_feature_ro_compat |=
5588                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5589                         ext2fs_mark_super_dirty(fs);
5590                 }
5591                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5592                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5593                         ext2fs_update_dynamic_rev(fs);
5594                         ext2fs_mark_super_dirty(fs);
5595                 }
5596         } else if (!ctx->large_files &&
5597             (sb->s_feature_ro_compat &
5598               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5599                 if (fs->flags & EXT2_FLAG_RW) {
5600                         sb->s_feature_ro_compat &=
5601                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5602                         ext2fs_mark_super_dirty(fs);
5603                 }
5604         }
5605 }
5606
5607 #define MAX_DEPTH 32000
5608 static int htree_depth(struct dx_dir_info *dx_dir,
5609                        struct dx_dirblock_info *dx_db)
5610 {
5611         int     depth = 0;
5612
5613         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614                 dx_db = &dx_dir->dx_block[dx_db->parent];
5615                 depth++;
5616         }
5617         return depth;
5618 }
5619
5620 static int dict_de_cmp(const void *a, const void *b)
5621 {
5622         const struct ext2_dir_entry *de_a, *de_b;
5623         int     a_len, b_len;
5624
5625         de_a = (const struct ext2_dir_entry *) a;
5626         a_len = de_a->name_len & 0xFF;
5627         de_b = (const struct ext2_dir_entry *) b;
5628         b_len = de_b->name_len & 0xFF;
5629
5630         if (a_len != b_len)
5631                 return (a_len - b_len);
5632
5633         return strncmp(de_a->name, de_b->name, a_len);
5634 }
5635
5636 /*
5637  * This is special sort function that makes sure that directory blocks
5638  * with a dirblock of zero are sorted to the beginning of the list.
5639  * This guarantees that the root node of the htree directories are
5640  * processed first, so we know what hash version to use.
5641  */
5642 static int special_dir_block_cmp(const void *a, const void *b)
5643 {
5644         const struct ext2_db_entry *db_a =
5645                 (const struct ext2_db_entry *) a;
5646         const struct ext2_db_entry *db_b =
5647                 (const struct ext2_db_entry *) b;
5648
5649         if (db_a->blockcnt && !db_b->blockcnt)
5650                 return 1;
5651
5652         if (!db_a->blockcnt && db_b->blockcnt)
5653                 return -1;
5654
5655         if (db_a->blk != db_b->blk)
5656                 return (int) (db_a->blk - db_b->blk);
5657
5658         if (db_a->ino != db_b->ino)
5659                 return (int) (db_a->ino - db_b->ino);
5660
5661         return (int) (db_a->blockcnt - db_b->blockcnt);
5662 }
5663
5664
5665 /*
5666  * Make sure the first entry in the directory is '.', and that the
5667  * directory entry is sane.
5668  */
5669 static int check_dot(e2fsck_t ctx,
5670                      struct ext2_dir_entry *dirent,
5671                      ext2_ino_t ino, struct problem_context *pctx)
5672 {
5673         struct ext2_dir_entry *nextdir;
5674         int     status = 0;
5675         int     created = 0;
5676         int     new_len;
5677         int     problem = 0;
5678
5679         if (!dirent->inode)
5680                 problem = PR_2_MISSING_DOT;
5681         else if (((dirent->name_len & 0xFF) != 1) ||
5682                  (dirent->name[0] != '.'))
5683                 problem = PR_2_1ST_NOT_DOT;
5684         else if (dirent->name[1] != '\0')
5685                 problem = PR_2_DOT_NULL_TERM;
5686
5687         if (problem) {
5688                 if (fix_problem(ctx, problem, pctx)) {
5689                         if (dirent->rec_len < 12)
5690                                 dirent->rec_len = 12;
5691                         dirent->inode = ino;
5692                         dirent->name_len = 1;
5693                         dirent->name[0] = '.';
5694                         dirent->name[1] = '\0';
5695                         status = 1;
5696                         created = 1;
5697                 }
5698         }
5699         if (dirent->inode != ino) {
5700                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701                         dirent->inode = ino;
5702                         status = 1;
5703                 }
5704         }
5705         if (dirent->rec_len > 12) {
5706                 new_len = dirent->rec_len - 12;
5707                 if (new_len > 12) {
5708                         if (created ||
5709                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710                                 nextdir = (struct ext2_dir_entry *)
5711                                         ((char *) dirent + 12);
5712                                 dirent->rec_len = 12;
5713                                 nextdir->rec_len = new_len;
5714                                 nextdir->inode = 0;
5715                                 nextdir->name_len = 0;
5716                                 status = 1;
5717                         }
5718                 }
5719         }
5720         return status;
5721 }
5722
5723 /*
5724  * Make sure the second entry in the directory is '..', and that the
5725  * directory entry is sane.  We do not check the inode number of '..'
5726  * here; this gets done in pass 3.
5727  */
5728 static int check_dotdot(e2fsck_t ctx,
5729                         struct ext2_dir_entry *dirent,
5730                         struct dir_info *dir, struct problem_context *pctx)
5731 {
5732         int             problem = 0;
5733
5734         if (!dirent->inode)
5735                 problem = PR_2_MISSING_DOT_DOT;
5736         else if (((dirent->name_len & 0xFF) != 2) ||
5737                  (dirent->name[0] != '.') ||
5738                  (dirent->name[1] != '.'))
5739                 problem = PR_2_2ND_NOT_DOT_DOT;
5740         else if (dirent->name[2] != '\0')
5741                 problem = PR_2_DOT_DOT_NULL_TERM;
5742
5743         if (problem) {
5744                 if (fix_problem(ctx, problem, pctx)) {
5745                         if (dirent->rec_len < 12)
5746                                 dirent->rec_len = 12;
5747                         /*
5748                          * Note: we don't have the parent inode just
5749                          * yet, so we will fill it in with the root
5750                          * inode.  This will get fixed in pass 3.
5751                          */
5752                         dirent->inode = EXT2_ROOT_INO;
5753                         dirent->name_len = 2;
5754                         dirent->name[0] = '.';
5755                         dirent->name[1] = '.';
5756                         dirent->name[2] = '\0';
5757                         return 1;
5758                 }
5759                 return 0;
5760         }
5761         dir->dotdot = dirent->inode;
5762         return 0;
5763 }
5764
5765 /*
5766  * Check to make sure a directory entry doesn't contain any illegal
5767  * characters.
5768  */
5769 static int check_name(e2fsck_t ctx,
5770                       struct ext2_dir_entry *dirent,
5771                       struct problem_context *pctx)
5772 {
5773         int     i;
5774         int     fixup = -1;
5775         int     ret = 0;
5776
5777         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779                         if (fixup < 0) {
5780                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5781                         }
5782                         if (fixup) {
5783                                 dirent->name[i] = '.';
5784                                 ret = 1;
5785                         }
5786                 }
5787         }
5788         return ret;
5789 }
5790
5791 /*
5792  * Check the directory filetype (if present)
5793  */
5794
5795 /*
5796  * Given a mode, return the ext2 file type
5797  */
5798 static int ext2_file_type(unsigned int mode)
5799 {
5800         if (LINUX_S_ISREG(mode))
5801                 return EXT2_FT_REG_FILE;
5802
5803         if (LINUX_S_ISDIR(mode))
5804                 return EXT2_FT_DIR;
5805
5806         if (LINUX_S_ISCHR(mode))
5807                 return EXT2_FT_CHRDEV;
5808
5809         if (LINUX_S_ISBLK(mode))
5810                 return EXT2_FT_BLKDEV;
5811
5812         if (LINUX_S_ISLNK(mode))
5813                 return EXT2_FT_SYMLINK;
5814
5815         if (LINUX_S_ISFIFO(mode))
5816                 return EXT2_FT_FIFO;
5817
5818         if (LINUX_S_ISSOCK(mode))
5819                 return EXT2_FT_SOCK;
5820
5821         return 0;
5822 }
5823
5824 static int check_filetype(e2fsck_t ctx,
5825                                    struct ext2_dir_entry *dirent,
5826                                    struct problem_context *pctx)
5827 {
5828         int     filetype = dirent->name_len >> 8;
5829         int     should_be = EXT2_FT_UNKNOWN;
5830         struct ext2_inode       inode;
5831
5832         if (!(ctx->fs->super->s_feature_incompat &
5833               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834                 if (filetype == 0 ||
5835                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836                         return 0;
5837                 dirent->name_len = dirent->name_len & 0xFF;
5838                 return 1;
5839         }
5840
5841         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842                 should_be = EXT2_FT_DIR;
5843         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844                                             dirent->inode)) {
5845                 should_be = EXT2_FT_REG_FILE;
5846         } else if (ctx->inode_bad_map &&
5847                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848                                             dirent->inode))
5849                 should_be = 0;
5850         else {
5851                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5852                                   "check_filetype");
5853                 should_be = ext2_file_type(inode.i_mode);
5854         }
5855         if (filetype == should_be)
5856                 return 0;
5857         pctx->num = should_be;
5858
5859         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860                         pctx) == 0)
5861                 return 0;
5862
5863         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864         return 1;
5865 }
5866
5867 #ifdef ENABLE_HTREE
5868 static void parse_int_node(ext2_filsys fs,
5869                            struct ext2_db_entry *db,
5870                            struct check_dir_struct *cd,
5871                            struct dx_dir_info   *dx_dir,
5872                            char *block_buf)
5873 {
5874         struct          ext2_dx_root_info  *root;
5875         struct          ext2_dx_entry *ent;
5876         struct          ext2_dx_countlimit *limit;
5877         struct dx_dirblock_info *dx_db;
5878         int             i, expect_limit, count;
5879         blk_t           blk;
5880         ext2_dirhash_t  min_hash = 0xffffffff;
5881         ext2_dirhash_t  max_hash = 0;
5882         ext2_dirhash_t  hash = 0, prev_hash;
5883
5884         if (db->blockcnt == 0) {
5885                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5886                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887         } else {
5888                 ent = (struct ext2_dx_entry *) (block_buf+8);
5889         }
5890         limit = (struct ext2_dx_countlimit *) ent;
5891
5892         count = ext2fs_le16_to_cpu(limit->count);
5893         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894                 sizeof(struct ext2_dx_entry);
5895         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898                         goto clear_and_exit;
5899         }
5900         if (count > expect_limit) {
5901                 cd->pctx.num = count;
5902                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903                         goto clear_and_exit;
5904                 count = expect_limit;
5905         }
5906
5907         for (i=0; i < count; i++) {
5908                 prev_hash = hash;
5909                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911                 /* Check to make sure the block is valid */
5912                 if (blk > (blk_t) dx_dir->numblocks) {
5913                         cd->pctx.blk = blk;
5914                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915                                         &cd->pctx))
5916                                 goto clear_and_exit;
5917                 }
5918                 if (hash < prev_hash &&
5919                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920                         goto clear_and_exit;
5921                 dx_db = &dx_dir->dx_block[blk];
5922                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5923                         dx_db->flags |= DX_FLAG_DUP_REF;
5924                 } else {
5925                         dx_db->flags |= DX_FLAG_REFERENCED;
5926                         dx_db->parent = db->blockcnt;
5927                 }
5928                 if (hash < min_hash)
5929                         min_hash = hash;
5930                 if (hash > max_hash)
5931                         max_hash = hash;
5932                 dx_db->node_min_hash = hash;
5933                 if ((i+1) < count)
5934                         dx_db->node_max_hash =
5935                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936                 else {
5937                         dx_db->node_max_hash = 0xfffffffe;
5938                         dx_db->flags |= DX_FLAG_LAST;
5939                 }
5940                 if (i == 0)
5941                         dx_db->flags |= DX_FLAG_FIRST;
5942         }
5943         dx_db = &dx_dir->dx_block[db->blockcnt];
5944         dx_db->min_hash = min_hash;
5945         dx_db->max_hash = max_hash;
5946         return;
5947
5948 clear_and_exit:
5949         clear_htree(cd->ctx, cd->pctx.ino);
5950         dx_dir->numblocks = 0;
5951 }
5952 #endif /* ENABLE_HTREE */
5953
5954 /*
5955  * Given a busted directory, try to salvage it somehow.
5956  *
5957  */
5958 static void salvage_directory(ext2_filsys fs,
5959                               struct ext2_dir_entry *dirent,
5960                               struct ext2_dir_entry *prev,
5961                               unsigned int *offset)
5962 {
5963         char    *cp = (char *) dirent;
5964         int left = fs->blocksize - *offset - dirent->rec_len;
5965         int name_len = dirent->name_len & 0xFF;
5966
5967         /*
5968          * Special case of directory entry of size 8: copy what's left
5969          * of the directory block up to cover up the invalid hole.
5970          */
5971         if ((left >= 12) && (dirent->rec_len == 8)) {
5972                 memmove(cp, cp+8, left);
5973                 memset(cp + left, 0, 8);
5974                 return;
5975         }
5976         /*
5977          * If the directory entry overruns the end of the directory
5978          * block, and the name is small enough to fit, then adjust the
5979          * record length.
5980          */
5981         if ((left < 0) &&
5982             (name_len + 8 <= dirent->rec_len + left) &&
5983             dirent->inode <= fs->super->s_inodes_count &&
5984             strnlen(dirent->name, name_len) == name_len) {
5985                 dirent->rec_len += left;
5986                 return;
5987         }
5988         /*
5989          * If the directory entry is a multiple of four, so it is
5990          * valid, let the previous directory entry absorb the invalid
5991          * one.
5992          */
5993         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994                 prev->rec_len += dirent->rec_len;
5995                 *offset += dirent->rec_len;
5996                 return;
5997         }
5998         /*
5999          * Default salvage method --- kill all of the directory
6000          * entries for the rest of the block.  We will either try to
6001          * absorb it into the previous directory entry, or create a
6002          * new empty directory entry the rest of the directory block.
6003          */
6004         if (prev) {
6005                 prev->rec_len += fs->blocksize - *offset;
6006                 *offset = fs->blocksize;
6007         } else {
6008                 dirent->rec_len = fs->blocksize - *offset;
6009                 dirent->name_len = 0;
6010                 dirent->inode = 0;
6011         }
6012 }
6013
6014 static int check_dir_block(ext2_filsys fs,
6015                            struct ext2_db_entry *db,
6016                            void *priv_data)
6017 {
6018         struct dir_info         *subdir, *dir;
6019         struct dx_dir_info      *dx_dir;
6020 #ifdef ENABLE_HTREE
6021         struct dx_dirblock_info *dx_db = NULL;
6022 #endif /* ENABLE_HTREE */
6023         struct ext2_dir_entry   *dirent, *prev;
6024         ext2_dirhash_t          hash;
6025         unsigned int            offset = 0;
6026         int                     dir_modified = 0;
6027         int                     dot_state;
6028         blk_t                   block_nr = db->blk;
6029         ext2_ino_t              ino = db->ino;
6030         __u16                   links;
6031         struct check_dir_struct *cd;
6032         char                    *buf;
6033         e2fsck_t                ctx;
6034         int                     problem;
6035         struct ext2_dx_root_info *root;
6036         struct ext2_dx_countlimit *limit;
6037         static dict_t de_dict;
6038         struct problem_context  pctx;
6039         int     dups_found = 0;
6040
6041         cd = (struct check_dir_struct *) priv_data;
6042         buf = cd->buf;
6043         ctx = cd->ctx;
6044
6045         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046                 return DIRENT_ABORT;
6047
6048         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049                 return DIRENT_ABORT;
6050
6051         /*
6052          * Make sure the inode is still in use (could have been
6053          * deleted in the duplicate/bad blocks pass.
6054          */
6055         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056                 return 0;
6057
6058         cd->pctx.ino = ino;
6059         cd->pctx.blk = block_nr;
6060         cd->pctx.blkcount = db->blockcnt;
6061         cd->pctx.ino2 = 0;
6062         cd->pctx.dirent = 0;
6063         cd->pctx.num = 0;
6064
6065         if (db->blk == 0) {
6066                 if (allocate_dir_block(ctx, db, &cd->pctx))
6067                         return 0;
6068                 block_nr = db->blk;
6069         }
6070
6071         if (db->blockcnt)
6072                 dot_state = 2;
6073         else
6074                 dot_state = 0;
6075
6076         if (ctx->dirs_to_hash &&
6077             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078                 dups_found++;
6079
6080         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083         if (cd->pctx.errcode) {
6084                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085                         ctx->flags |= E2F_FLAG_ABORT;
6086                         return DIRENT_ABORT;
6087                 }
6088                 memset(buf, 0, fs->blocksize);
6089         }
6090 #ifdef ENABLE_HTREE
6091         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092         if (dx_dir && dx_dir->numblocks) {
6093                 if (db->blockcnt >= dx_dir->numblocks) {
6094                         printf("XXX should never happen!!!\n");
6095                         abort();
6096                 }
6097                 dx_db = &dx_dir->dx_block[db->blockcnt];
6098                 dx_db->type = DX_DIRBLOCK_LEAF;
6099                 dx_db->phys = block_nr;
6100                 dx_db->min_hash = ~0;
6101                 dx_db->max_hash = 0;
6102
6103                 dirent = (struct ext2_dir_entry *) buf;
6104                 limit = (struct ext2_dx_countlimit *) (buf+8);
6105                 if (db->blockcnt == 0) {
6106                         root = (struct ext2_dx_root_info *) (buf + 24);
6107                         dx_db->type = DX_DIRBLOCK_ROOT;
6108                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109                         if ((root->reserved_zero ||
6110                              root->info_length < 8 ||
6111                              root->indirect_levels > 1) &&
6112                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113                                 clear_htree(ctx, ino);
6114                                 dx_dir->numblocks = 0;
6115                                 dx_db = 0;
6116                         }
6117                         dx_dir->hashversion = root->hash_version;
6118                         dx_dir->depth = root->indirect_levels + 1;
6119                 } else if ((dirent->inode == 0) &&
6120                            (dirent->rec_len == fs->blocksize) &&
6121                            (dirent->name_len == 0) &&
6122                            (ext2fs_le16_to_cpu(limit->limit) ==
6123                             ((fs->blocksize-8) /
6124                              sizeof(struct ext2_dx_entry))))
6125                         dx_db->type = DX_DIRBLOCK_NODE;
6126         }
6127 #endif /* ENABLE_HTREE */
6128
6129         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130         prev = 0;
6131         do {
6132                 problem = 0;
6133                 dirent = (struct ext2_dir_entry *) (buf + offset);
6134                 cd->pctx.dirent = dirent;
6135                 cd->pctx.num = offset;
6136                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6137                     (dirent->rec_len < 12) ||
6138                     ((dirent->rec_len % 4) != 0) ||
6139                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141                                 salvage_directory(fs, dirent, prev, &offset);
6142                                 dir_modified++;
6143                                 continue;
6144                         } else
6145                                 goto abort_free_dict;
6146                 }
6147                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149                                 dirent->name_len = EXT2_NAME_LEN;
6150                                 dir_modified++;
6151                         }
6152                 }
6153
6154                 if (dot_state == 0) {
6155                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6156                                 dir_modified++;
6157                 } else if (dot_state == 1) {
6158                         dir = e2fsck_get_dir_info(ctx, ino);
6159                         if (!dir) {
6160                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161                                 goto abort_free_dict;
6162                         }
6163                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164                                 dir_modified++;
6165                 } else if (dirent->inode == ino) {
6166                         problem = PR_2_LINK_DOT;
6167                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168                                 dirent->inode = 0;
6169                                 dir_modified++;
6170                                 goto next;
6171                         }
6172                 }
6173                 if (!dirent->inode)
6174                         goto next;
6175
6176                 /*
6177                  * Make sure the inode listed is a legal one.
6178                  */
6179                 if (((dirent->inode != EXT2_ROOT_INO) &&
6180                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181                     (dirent->inode > fs->super->s_inodes_count)) {
6182                         problem = PR_2_BAD_INO;
6183                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184                                                dirent->inode))) {
6185                         /*
6186                          * If the inode is unused, offer to clear it.
6187                          */
6188                         problem = PR_2_UNUSED_INODE;
6189                 } else if ((dot_state > 1) &&
6190                            ((dirent->name_len & 0xFF) == 1) &&
6191                            (dirent->name[0] == '.')) {
6192                         /*
6193                          * If there's a '.' entry in anything other
6194                          * than the first directory entry, it's a
6195                          * duplicate entry that should be removed.
6196                          */
6197                         problem = PR_2_DUP_DOT;
6198                 } else if ((dot_state > 1) &&
6199                            ((dirent->name_len & 0xFF) == 2) &&
6200                            (dirent->name[0] == '.') &&
6201                            (dirent->name[1] == '.')) {
6202                         /*
6203                          * If there's a '..' entry in anything other
6204                          * than the second directory entry, it's a
6205                          * duplicate entry that should be removed.
6206                          */
6207                         problem = PR_2_DUP_DOT_DOT;
6208                 } else if ((dot_state > 1) &&
6209                            (dirent->inode == EXT2_ROOT_INO)) {
6210                         /*
6211                          * Don't allow links to the root directory.
6212                          * We check this specially to make sure we
6213                          * catch this error case even if the root
6214                          * directory hasn't been created yet.
6215                          */
6216                         problem = PR_2_LINK_ROOT;
6217                 } else if ((dot_state > 1) &&
6218                            (dirent->name_len & 0xFF) == 0) {
6219                         /*
6220                          * Don't allow zero-length directory names.
6221                          */
6222                         problem = PR_2_NULL_NAME;
6223                 }
6224
6225                 if (problem) {
6226                         if (fix_problem(ctx, problem, &cd->pctx)) {
6227                                 dirent->inode = 0;
6228                                 dir_modified++;
6229                                 goto next;
6230                         } else {
6231                                 ext2fs_unmark_valid(fs);
6232                                 if (problem == PR_2_BAD_INO)
6233                                         goto next;
6234                         }
6235                 }
6236
6237                 /*
6238                  * If the inode was marked as having bad fields in
6239                  * pass1, process it and offer to fix/clear it.
6240                  * (We wait until now so that we can display the
6241                  * pathname to the user.)
6242                  */
6243                 if (ctx->inode_bad_map &&
6244                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245                                              dirent->inode)) {
6246                         if (e2fsck_process_bad_inode(ctx, ino,
6247                                                      dirent->inode,
6248                                                      buf + fs->blocksize)) {
6249                                 dirent->inode = 0;
6250                                 dir_modified++;
6251                                 goto next;
6252                         }
6253                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254                                 return DIRENT_ABORT;
6255                 }
6256
6257                 if (check_name(ctx, dirent, &cd->pctx))
6258                         dir_modified++;
6259
6260                 if (check_filetype(ctx, dirent, &cd->pctx))
6261                         dir_modified++;
6262
6263 #ifdef ENABLE_HTREE
6264                 if (dx_db) {
6265                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266                                        (dirent->name_len & 0xFF),
6267                                        fs->super->s_hash_seed, &hash, 0);
6268                         if (hash < dx_db->min_hash)
6269                                 dx_db->min_hash = hash;
6270                         if (hash > dx_db->max_hash)
6271                                 dx_db->max_hash = hash;
6272                 }
6273 #endif
6274
6275                 /*
6276                  * If this is a directory, then mark its parent in its
6277                  * dir_info structure.  If the parent field is already
6278                  * filled in, then this directory has more than one
6279                  * hard link.  We assume the first link is correct,
6280                  * and ask the user if he/she wants to clear this one.
6281                  */
6282                 if ((dot_state > 1) &&
6283                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284                                               dirent->inode))) {
6285                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286                         if (!subdir) {
6287                                 cd->pctx.ino = dirent->inode;
6288                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289                                 goto abort_free_dict;
6290                         }
6291                         if (subdir->parent) {
6292                                 cd->pctx.ino2 = subdir->parent;
6293                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6294                                                 &cd->pctx)) {
6295                                         dirent->inode = 0;
6296                                         dir_modified++;
6297                                         goto next;
6298                                 }
6299                                 cd->pctx.ino2 = 0;
6300                         } else
6301                                 subdir->parent = ino;
6302                 }
6303
6304                 if (dups_found) {
6305                         ;
6306                 } else if (dict_lookup(&de_dict, dirent)) {
6307                         clear_problem_context(&pctx);
6308                         pctx.ino = ino;
6309                         pctx.dirent = dirent;
6310                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311                         if (!ctx->dirs_to_hash)
6312                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313                         if (ctx->dirs_to_hash)
6314                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315                         dups_found++;
6316                 } else
6317                         dict_alloc_insert(&de_dict, dirent, dirent);
6318
6319                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320                                         &links);
6321                 if (links > 1)
6322                         ctx->fs_links_count++;
6323                 ctx->fs_total_count++;
6324         next:
6325                 prev = dirent;
6326                 offset += dirent->rec_len;
6327                 dot_state++;
6328         } while (offset < fs->blocksize);
6329 #ifdef ENABLE_HTREE
6330         if (dx_db) {
6331                 cd->pctx.dir = cd->pctx.ino;
6332                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333                     (dx_db->type == DX_DIRBLOCK_NODE))
6334                         parse_int_node(fs, db, cd, dx_dir, buf);
6335         }
6336 #endif /* ENABLE_HTREE */
6337         if (offset != fs->blocksize) {
6338                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340                         dirent->rec_len = cd->pctx.num;
6341                         dir_modified++;
6342                 }
6343         }
6344         if (dir_modified) {
6345                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346                 if (cd->pctx.errcode) {
6347                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348                                          &cd->pctx))
6349                                 goto abort_free_dict;
6350                 }
6351                 ext2fs_mark_changed(fs);
6352         }
6353         dict_free_nodes(&de_dict);
6354         return 0;
6355 abort_free_dict:
6356         dict_free_nodes(&de_dict);
6357         ctx->flags |= E2F_FLAG_ABORT;
6358         return DIRENT_ABORT;
6359 }
6360
6361 /*
6362  * This function is called to deallocate a block, and is an interator
6363  * functioned called by deallocate inode via ext2fs_iterate_block().
6364  */
6365 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367                                   blk_t ref_block FSCK_ATTR((unused)),
6368                                   int ref_offset FSCK_ATTR((unused)),
6369                                   void *priv_data)
6370 {
6371         e2fsck_t        ctx = (e2fsck_t) priv_data;
6372
6373         if (HOLE_BLKADDR(*block_nr))
6374                 return 0;
6375         if ((*block_nr < fs->super->s_first_data_block) ||
6376             (*block_nr >= fs->super->s_blocks_count))
6377                 return 0;
6378         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380         return 0;
6381 }
6382
6383 /*
6384  * This fuction deallocates an inode
6385  */
6386 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6387 {
6388         ext2_filsys fs = ctx->fs;
6389         struct ext2_inode       inode;
6390         struct problem_context  pctx;
6391         __u32                   count;
6392
6393         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395         inode.i_links_count = 0;
6396         inode.i_dtime = time(NULL);
6397         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398         clear_problem_context(&pctx);
6399         pctx.ino = ino;
6400
6401         /*
6402          * Fix up the bitmaps...
6403          */
6404         e2fsck_read_bitmaps(ctx);
6405         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407         if (ctx->inode_bad_map)
6408                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6410
6411         if (inode.i_file_acl &&
6412             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414                                                    block_buf, -1, &count);
6415                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416                         pctx.errcode = 0;
6417                         count = 1;
6418                 }
6419                 if (pctx.errcode) {
6420                         pctx.blk = inode.i_file_acl;
6421                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422                         ctx->flags |= E2F_FLAG_ABORT;
6423                         return;
6424                 }
6425                 if (count == 0) {
6426                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427                                                    inode.i_file_acl);
6428                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6429                 }
6430                 inode.i_file_acl = 0;
6431         }
6432
6433         if (!ext2fs_inode_has_valid_blocks(&inode))
6434                 return;
6435
6436         if (LINUX_S_ISREG(inode.i_mode) &&
6437             (inode.i_size_high || inode.i_size & 0x80000000UL))
6438                 ctx->large_files--;
6439
6440         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441                                             deallocate_inode_block, ctx);
6442         if (pctx.errcode) {
6443                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444                 ctx->flags |= E2F_FLAG_ABORT;
6445                 return;
6446         }
6447 }
6448
6449 /*
6450  * This fuction clears the htree flag on an inode
6451  */
6452 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6453 {
6454         struct ext2_inode       inode;
6455
6456         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459         if (ctx->dirs_to_hash)
6460                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6461 }
6462
6463
6464 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465                                     ext2_ino_t ino, char *buf)
6466 {
6467         ext2_filsys fs = ctx->fs;
6468         struct ext2_inode       inode;
6469         int                     inode_modified = 0;
6470         int                     not_fixed = 0;
6471         unsigned char           *frag, *fsize;
6472         struct problem_context  pctx;
6473         int     problem = 0;
6474
6475         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6476
6477         clear_problem_context(&pctx);
6478         pctx.ino = ino;
6479         pctx.dir = dir;
6480         pctx.inode = &inode;
6481
6482         if (inode.i_file_acl &&
6483             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485                 inode.i_file_acl = 0;
6486 #if BB_BIG_ENDIAN
6487                 /*
6488                  * This is a special kludge to deal with long symlinks
6489                  * on big endian systems.  i_blocks had already been
6490                  * decremented earlier in pass 1, but since i_file_acl
6491                  * hadn't yet been cleared, ext2fs_read_inode()
6492                  * assumed that the file was short symlink and would
6493                  * not have byte swapped i_block[0].  Hence, we have
6494                  * to byte-swap it here.
6495                  */
6496                 if (LINUX_S_ISLNK(inode.i_mode) &&
6497                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498                     (inode.i_blocks == fs->blocksize >> 9))
6499                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500 #endif
6501                 inode_modified++;
6502         } else
6503                 not_fixed++;
6504
6505         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508             !(LINUX_S_ISSOCK(inode.i_mode)))
6509                 problem = PR_2_BAD_MODE;
6510         else if (LINUX_S_ISCHR(inode.i_mode)
6511                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6512                 problem = PR_2_BAD_CHAR_DEV;
6513         else if (LINUX_S_ISBLK(inode.i_mode)
6514                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6515                 problem = PR_2_BAD_BLOCK_DEV;
6516         else if (LINUX_S_ISFIFO(inode.i_mode)
6517                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6518                 problem = PR_2_BAD_FIFO;
6519         else if (LINUX_S_ISSOCK(inode.i_mode)
6520                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6521                 problem = PR_2_BAD_SOCKET;
6522         else if (LINUX_S_ISLNK(inode.i_mode)
6523                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524                 problem = PR_2_INVALID_SYMLINK;
6525         }
6526
6527         if (problem) {
6528                 if (fix_problem(ctx, problem, &pctx)) {
6529                         deallocate_inode(ctx, ino, 0);
6530                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531                                 return 0;
6532                         return 1;
6533                 } else
6534                         not_fixed++;
6535                 problem = 0;
6536         }
6537
6538         if (inode.i_faddr) {
6539                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540                         inode.i_faddr = 0;
6541                         inode_modified++;
6542                 } else
6543                         not_fixed++;
6544         }
6545
6546         switch (fs->super->s_creator_os) {
6547             case EXT2_OS_LINUX:
6548                 frag = &inode.osd2.linux2.l_i_frag;
6549                 fsize = &inode.osd2.linux2.l_i_fsize;
6550                 break;
6551             case EXT2_OS_HURD:
6552                 frag = &inode.osd2.hurd2.h_i_frag;
6553                 fsize = &inode.osd2.hurd2.h_i_fsize;
6554                 break;
6555             case EXT2_OS_MASIX:
6556                 frag = &inode.osd2.masix2.m_i_frag;
6557                 fsize = &inode.osd2.masix2.m_i_fsize;
6558                 break;
6559             default:
6560                 frag = fsize = 0;
6561         }
6562         if (frag && *frag) {
6563                 pctx.num = *frag;
6564                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565                         *frag = 0;
6566                         inode_modified++;
6567                 } else
6568                         not_fixed++;
6569                 pctx.num = 0;
6570         }
6571         if (fsize && *fsize) {
6572                 pctx.num = *fsize;
6573                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574                         *fsize = 0;
6575                         inode_modified++;
6576                 } else
6577                         not_fixed++;
6578                 pctx.num = 0;
6579         }
6580
6581         if (inode.i_file_acl &&
6582             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585                         inode.i_file_acl = 0;
6586                         inode_modified++;
6587                 } else
6588                         not_fixed++;
6589         }
6590         if (inode.i_dir_acl &&
6591             LINUX_S_ISDIR(inode.i_mode)) {
6592                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593                         inode.i_dir_acl = 0;
6594                         inode_modified++;
6595                 } else
6596                         not_fixed++;
6597         }
6598
6599         if (inode_modified)
6600                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601         if (!not_fixed)
6602                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603         return 0;
6604 }
6605
6606
6607 /*
6608  * allocate_dir_block --- this function allocates a new directory
6609  *      block for a particular inode; this is done if a directory has
6610  *      a "hole" in it, or if a directory has a illegal block number
6611  *      that was zeroed out and now needs to be replaced.
6612  */
6613 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614                               struct problem_context *pctx)
6615 {
6616         ext2_filsys fs = ctx->fs;
6617         blk_t                   blk;
6618         char                    *block;
6619         struct ext2_inode       inode;
6620
6621         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622                 return 1;
6623
6624         /*
6625          * Read the inode and block bitmaps in; we'll be messing with
6626          * them.
6627          */
6628         e2fsck_read_bitmaps(ctx);
6629
6630         /*
6631          * First, find a free block
6632          */
6633         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634         if (pctx->errcode) {
6635                 pctx->str = "ext2fs_new_block";
6636                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637                 return 1;
6638         }
6639         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640         ext2fs_mark_block_bitmap(fs->block_map, blk);
6641         ext2fs_mark_bb_dirty(fs);
6642
6643         /*
6644          * Now let's create the actual data block for the inode
6645          */
6646         if (db->blockcnt)
6647                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648         else
6649                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650                                                      EXT2_ROOT_INO, &block);
6651
6652         if (pctx->errcode) {
6653                 pctx->str = "ext2fs_new_dir_block";
6654                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655                 return 1;
6656         }
6657
6658         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659         ext2fs_free_mem(&block);
6660         if (pctx->errcode) {
6661                 pctx->str = "ext2fs_write_dir_block";
6662                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663                 return 1;
6664         }
6665
6666         /*
6667          * Update the inode block count
6668          */
6669         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670         inode.i_blocks += fs->blocksize / 512;
6671         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6674
6675         /*
6676          * Finally, update the block pointers for the inode
6677          */
6678         db->blk = blk;
6679         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680                                       0, update_dir_block, db);
6681         if (pctx->errcode) {
6682                 pctx->str = "ext2fs_block_iterate";
6683                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684                 return 1;
6685         }
6686
6687         return 0;
6688 }
6689
6690 /*
6691  * This is a helper function for allocate_dir_block().
6692  */
6693 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694                             blk_t       *block_nr,
6695                             e2_blkcnt_t blockcnt,
6696                             blk_t ref_block FSCK_ATTR((unused)),
6697                             int ref_offset FSCK_ATTR((unused)),
6698                             void *priv_data)
6699 {
6700         struct ext2_db_entry *db;
6701
6702         db = (struct ext2_db_entry *) priv_data;
6703         if (db->blockcnt == (int) blockcnt) {
6704                 *block_nr = db->blk;
6705                 return BLOCK_CHANGED;
6706         }
6707         return 0;
6708 }
6709
6710 /*
6711  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6712  *
6713  * Pass #3 assures that all directories are connected to the
6714  * filesystem tree, using the following algorithm:
6715  *
6716  * First, the root directory is checked to make sure it exists; if
6717  * not, e2fsck will offer to create a new one.  It is then marked as
6718  * "done".
6719  *
6720  * Then, pass3 interates over all directory inodes; for each directory
6721  * it attempts to trace up the filesystem tree, using dirinfo.parent
6722  * until it reaches a directory which has been marked "done".  If it
6723  * cannot do so, then the directory must be disconnected, and e2fsck
6724  * will offer to reconnect it to /lost+found.  While it is chasing
6725  * parent pointers up the filesystem tree, if pass3 sees a directory
6726  * twice, then it has detected a filesystem loop, and it will again
6727  * offer to reconnect the directory to /lost+found in to break the
6728  * filesystem loop.
6729  *
6730  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731  * reconnect inodes to /lost+found; this subroutine is also used by
6732  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6733  * is responsible for creating /lost+found if it does not exist.
6734  *
6735  * Pass 3 frees the following data structures:
6736  *      - The dirinfo directory information cache.
6737  */
6738
6739 static void check_root(e2fsck_t ctx);
6740 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741                            struct problem_context *pctx);
6742 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6743
6744 static ext2fs_inode_bitmap inode_loop_detect;
6745 static ext2fs_inode_bitmap inode_done_map;
6746
6747 static void e2fsck_pass3(e2fsck_t ctx)
6748 {
6749         ext2_filsys fs = ctx->fs;
6750         int             i;
6751         struct problem_context  pctx;
6752         struct dir_info *dir;
6753         unsigned long maxdirs, count;
6754
6755         clear_problem_context(&pctx);
6756
6757         /* Pass 3 */
6758
6759         if (!(ctx->options & E2F_OPT_PREEN))
6760                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6761
6762         /*
6763          * Allocate some bitmaps to do loop detection.
6764          */
6765         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766                                                     &inode_done_map);
6767         if (pctx.errcode) {
6768                 pctx.num = 2;
6769                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770                 ctx->flags |= E2F_FLAG_ABORT;
6771                 goto abort_exit;
6772         }
6773         check_root(ctx);
6774         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775                 goto abort_exit;
6776
6777         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6778
6779         maxdirs = e2fsck_get_num_dirinfo(ctx);
6780         count = 1;
6781
6782         if (ctx->progress)
6783                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784                         goto abort_exit;
6785
6786         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788                         goto abort_exit;
6789                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790                         goto abort_exit;
6791                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792                         if (check_directory(ctx, dir, &pctx))
6793                                 goto abort_exit;
6794         }
6795
6796         /*
6797          * Force the creation of /lost+found if not present
6798          */
6799         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800                 e2fsck_get_lost_and_found(ctx, 1);
6801
6802         /*
6803          * If there are any directories that need to be indexed or
6804          * optimized, do it here.
6805          */
6806         e2fsck_rehash_directories(ctx);
6807
6808 abort_exit:
6809         e2fsck_free_dir_info(ctx);
6810         ext2fs_free_inode_bitmap(inode_loop_detect);
6811         inode_loop_detect = 0;
6812         ext2fs_free_inode_bitmap(inode_done_map);
6813         inode_done_map = 0;
6814 }
6815
6816 /*
6817  * This makes sure the root inode is present; if not, we ask if the
6818  * user wants us to create it.  Not creating it is a fatal error.
6819  */
6820 static void check_root(e2fsck_t ctx)
6821 {
6822         ext2_filsys fs = ctx->fs;
6823         blk_t                   blk;
6824         struct ext2_inode       inode;
6825         char *                  block;
6826         struct problem_context  pctx;
6827
6828         clear_problem_context(&pctx);
6829
6830         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6831                 /*
6832                  * If the root inode is not a directory, die here.  The
6833                  * user must have answered 'no' in pass1 when we
6834                  * offered to clear it.
6835                  */
6836                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837                                                EXT2_ROOT_INO))) {
6838                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839                         ctx->flags |= E2F_FLAG_ABORT;
6840                 }
6841                 return;
6842         }
6843
6844         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846                 ctx->flags |= E2F_FLAG_ABORT;
6847                 return;
6848         }
6849
6850         e2fsck_read_bitmaps(ctx);
6851
6852         /*
6853          * First, find a free block
6854          */
6855         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856         if (pctx.errcode) {
6857                 pctx.str = "ext2fs_new_block";
6858                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859                 ctx->flags |= E2F_FLAG_ABORT;
6860                 return;
6861         }
6862         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863         ext2fs_mark_block_bitmap(fs->block_map, blk);
6864         ext2fs_mark_bb_dirty(fs);
6865
6866         /*
6867          * Now let's create the actual data block for the inode
6868          */
6869         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870                                             &block);
6871         if (pctx.errcode) {
6872                 pctx.str = "ext2fs_new_dir_block";
6873                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874                 ctx->flags |= E2F_FLAG_ABORT;
6875                 return;
6876         }
6877
6878         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879         if (pctx.errcode) {
6880                 pctx.str = "ext2fs_write_dir_block";
6881                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882                 ctx->flags |= E2F_FLAG_ABORT;
6883                 return;
6884         }
6885         ext2fs_free_mem(&block);
6886
6887         /*
6888          * Set up the inode structure
6889          */
6890         memset(&inode, 0, sizeof(inode));
6891         inode.i_mode = 040755;
6892         inode.i_size = fs->blocksize;
6893         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6894         inode.i_links_count = 2;
6895         inode.i_blocks = fs->blocksize / 512;
6896         inode.i_block[0] = blk;
6897
6898         /*
6899          * Write out the inode.
6900          */
6901         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902         if (pctx.errcode) {
6903                 pctx.str = "ext2fs_write_inode";
6904                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905                 ctx->flags |= E2F_FLAG_ABORT;
6906                 return;
6907         }
6908
6909         /*
6910          * Miscellaneous bookkeeping...
6911          */
6912         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6915
6916         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919         ext2fs_mark_ib_dirty(fs);
6920 }
6921
6922 /*
6923  * This subroutine is responsible for making sure that a particular
6924  * directory is connected to the root; if it isn't we trace it up as
6925  * far as we can go, and then offer to connect the resulting parent to
6926  * the lost+found.  We have to do loop detection; if we ever discover
6927  * a loop, we treat that as a disconnected directory and offer to
6928  * reparent it to lost+found.
6929  *
6930  * However, loop detection is expensive, because for very large
6931  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932  * is non-trivial.  Loops in filesystems are also a rare error case,
6933  * and we shouldn't optimize for error cases.  So we try two passes of
6934  * the algorithm.  The first time, we ignore loop detection and merely
6935  * increment a counter; if the counter exceeds some extreme threshold,
6936  * then we try again with the loop detection bitmap enabled.
6937  */
6938 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939                            struct problem_context *pctx)
6940 {
6941         ext2_filsys     fs = ctx->fs;
6942         struct dir_info *p = dir;
6943         int             loop_pass = 0, parent_count = 0;
6944
6945         if (!p)
6946                 return 0;
6947
6948         while (1) {
6949                 /*
6950                  * Mark this inode as being "done"; by the time we
6951                  * return from this function, the inode we either be
6952                  * verified as being connected to the directory tree,
6953                  * or we will have offered to reconnect this to
6954                  * lost+found.
6955                  *
6956                  * If it was marked done already, then we've reached a
6957                  * parent we've already checked.
6958                  */
6959                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960                         break;
6961
6962                 /*
6963                  * If this directory doesn't have a parent, or we've
6964                  * seen the parent once already, then offer to
6965                  * reparent it to lost+found
6966                  */
6967                 if (!p->parent ||
6968                     (loop_pass &&
6969                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6970                                               p->parent)))) {
6971                         pctx->ino = p->ino;
6972                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6974                                         ext2fs_unmark_valid(fs);
6975                                 else {
6976                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
6977                                         p->parent = ctx->lost_and_found;
6978                                         fix_dotdot(ctx, p, ctx->lost_and_found);
6979                                 }
6980                         }
6981                         break;
6982                 }
6983                 p = e2fsck_get_dir_info(ctx, p->parent);
6984                 if (!p) {
6985                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986                         return 0;
6987                 }
6988                 if (loop_pass) {
6989                         ext2fs_mark_inode_bitmap(inode_loop_detect,
6990                                                  p->ino);
6991                 } else if (parent_count++ > 2048) {
6992                         /*
6993                          * If we've run into a path depth that's
6994                          * greater than 2048, try again with the inode
6995                          * loop bitmap turned on and start from the
6996                          * top.
6997                          */
6998                         loop_pass = 1;
6999                         if (inode_loop_detect)
7000                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
7001                         else {
7002                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003                                 if (pctx->errcode) {
7004                                         pctx->num = 1;
7005                                         fix_problem(ctx,
7006                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007                                         ctx->flags |= E2F_FLAG_ABORT;
7008                                         return -1;
7009                                 }
7010                         }
7011                         p = dir;
7012                 }
7013         }
7014
7015         /*
7016          * Make sure that .. and the parent directory are the same;
7017          * offer to fix it if not.
7018          */
7019         if (dir->parent != dir->dotdot) {
7020                 pctx->ino = dir->ino;
7021                 pctx->ino2 = dir->dotdot;
7022                 pctx->dir = dir->parent;
7023                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024                         fix_dotdot(ctx, dir, dir->parent);
7025         }
7026         return 0;
7027 }
7028
7029 /*
7030  * This routine gets the lost_and_found inode, making it a directory
7031  * if necessary
7032  */
7033 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7034 {
7035         ext2_filsys fs = ctx->fs;
7036         ext2_ino_t                      ino;
7037         blk_t                   blk;
7038         errcode_t               retval;
7039         struct ext2_inode       inode;
7040         char *                  block;
7041         static const char       name[] = "lost+found";
7042         struct  problem_context pctx;
7043         struct dir_info         *dirinfo;
7044
7045         if (ctx->lost_and_found)
7046                 return ctx->lost_and_found;
7047
7048         clear_problem_context(&pctx);
7049
7050         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051                                sizeof(name)-1, 0, &ino);
7052         if (retval && !fix)
7053                 return 0;
7054         if (!retval) {
7055                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056                         ctx->lost_and_found = ino;
7057                         return ino;
7058                 }
7059
7060                 /* Lost+found isn't a directory! */
7061                 if (!fix)
7062                         return 0;
7063                 pctx.ino = ino;
7064                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065                         return 0;
7066
7067                 /* OK, unlink the old /lost+found file. */
7068                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069                 if (pctx.errcode) {
7070                         pctx.str = "ext2fs_unlink";
7071                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072                         return 0;
7073                 }
7074                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7075                 if (dirinfo)
7076                         dirinfo->parent = 0;
7077                 e2fsck_adjust_inode_count(ctx, ino, -1);
7078         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079                 pctx.errcode = retval;
7080                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7081         }
7082         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083                 return 0;
7084
7085         /*
7086          * Read the inode and block bitmaps in; we'll be messing with
7087          * them.
7088          */
7089         e2fsck_read_bitmaps(ctx);
7090
7091         /*
7092          * First, find a free block
7093          */
7094         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095         if (retval) {
7096                 pctx.errcode = retval;
7097                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098                 return 0;
7099         }
7100         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101         ext2fs_block_alloc_stats(fs, blk, +1);
7102
7103         /*
7104          * Next find a free inode.
7105          */
7106         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107                                   ctx->inode_used_map, &ino);
7108         if (retval) {
7109                 pctx.errcode = retval;
7110                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111                 return 0;
7112         }
7113         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7116
7117         /*
7118          * Now let's create the actual data block for the inode
7119          */
7120         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121         if (retval) {
7122                 pctx.errcode = retval;
7123                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124                 return 0;
7125         }
7126
7127         retval = ext2fs_write_dir_block(fs, blk, block);
7128         ext2fs_free_mem(&block);
7129         if (retval) {
7130                 pctx.errcode = retval;
7131                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132                 return 0;
7133         }
7134
7135         /*
7136          * Set up the inode structure
7137          */
7138         memset(&inode, 0, sizeof(inode));
7139         inode.i_mode = 040700;
7140         inode.i_size = fs->blocksize;
7141         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7142         inode.i_links_count = 2;
7143         inode.i_blocks = fs->blocksize / 512;
7144         inode.i_block[0] = blk;
7145
7146         /*
7147          * Next, write out the inode.
7148          */
7149         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150         if (pctx.errcode) {
7151                 pctx.str = "ext2fs_write_inode";
7152                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153                 return 0;
7154         }
7155         /*
7156          * Finally, create the directory link
7157          */
7158         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159         if (pctx.errcode) {
7160                 pctx.str = "ext2fs_link";
7161                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162                 return 0;
7163         }
7164
7165         /*
7166          * Miscellaneous bookkeeping that needs to be kept straight.
7167          */
7168         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170         ext2fs_icount_store(ctx->inode_count, ino, 2);
7171         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172         ctx->lost_and_found = ino;
7173         return ino;
7174 }
7175
7176 /*
7177  * This routine will connect a file to lost+found
7178  */
7179 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7180 {
7181         ext2_filsys fs = ctx->fs;
7182         errcode_t       retval;
7183         char            name[80];
7184         struct problem_context  pctx;
7185         struct ext2_inode       inode;
7186         int             file_type = 0;
7187
7188         clear_problem_context(&pctx);
7189         pctx.ino = ino;
7190
7191         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193                         ctx->bad_lost_and_found++;
7194         }
7195         if (ctx->bad_lost_and_found) {
7196                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197                 return 1;
7198         }
7199
7200         sprintf(name, "#%u", ino);
7201         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202                 file_type = ext2_file_type(inode.i_mode);
7203         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204         if (retval == EXT2_ET_DIR_NO_SPACE) {
7205                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206                         return 1;
7207                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208                                                  1, 0);
7209                 if (retval) {
7210                         pctx.errcode = retval;
7211                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212                         return 1;
7213                 }
7214                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215                                      ino, file_type);
7216         }
7217         if (retval) {
7218                 pctx.errcode = retval;
7219                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220                 return 1;
7221         }
7222         e2fsck_adjust_inode_count(ctx, ino, 1);
7223
7224         return 0;
7225 }
7226
7227 /*
7228  * Utility routine to adjust the inode counts on an inode.
7229  */
7230 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7231 {
7232         ext2_filsys fs = ctx->fs;
7233         errcode_t               retval;
7234         struct ext2_inode       inode;
7235
7236         if (!ino)
7237                 return 0;
7238
7239         retval = ext2fs_read_inode(fs, ino, &inode);
7240         if (retval)
7241                 return retval;
7242
7243         if (adj == 1) {
7244                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245                 if (inode.i_links_count == (__u16) ~0)
7246                         return 0;
7247                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248                 inode.i_links_count++;
7249         } else if (adj == -1) {
7250                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251                 if (inode.i_links_count == 0)
7252                         return 0;
7253                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254                 inode.i_links_count--;
7255         }
7256
7257         retval = ext2fs_write_inode(fs, ino, &inode);
7258         if (retval)
7259                 return retval;
7260
7261         return 0;
7262 }
7263
7264 /*
7265  * Fix parent --- this routine fixes up the parent of a directory.
7266  */
7267 struct fix_dotdot_struct {
7268         ext2_filsys     fs;
7269         ext2_ino_t      parent;
7270         int             done;
7271         e2fsck_t        ctx;
7272 };
7273
7274 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275                            int  offset FSCK_ATTR((unused)),
7276                            int  blocksize FSCK_ATTR((unused)),
7277                            char *buf FSCK_ATTR((unused)),
7278                            void *priv_data)
7279 {
7280         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281         errcode_t       retval;
7282         struct problem_context pctx;
7283
7284         if ((dirent->name_len & 0xFF) != 2)
7285                 return 0;
7286         if (strncmp(dirent->name, "..", 2))
7287                 return 0;
7288
7289         clear_problem_context(&pctx);
7290
7291         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292         if (retval) {
7293                 pctx.errcode = retval;
7294                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7295         }
7296         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297         if (retval) {
7298                 pctx.errcode = retval;
7299                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7300         }
7301         dirent->inode = fp->parent;
7302
7303         fp->done++;
7304         return DIRENT_ABORT | DIRENT_CHANGED;
7305 }
7306
7307 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7308 {
7309         ext2_filsys fs = ctx->fs;
7310         errcode_t       retval;
7311         struct fix_dotdot_struct fp;
7312         struct problem_context pctx;
7313
7314         fp.fs = fs;
7315         fp.parent = parent;
7316         fp.done = 0;
7317         fp.ctx = ctx;
7318
7319         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320                                     0, fix_dotdot_proc, &fp);
7321         if (retval || !fp.done) {
7322                 clear_problem_context(&pctx);
7323                 pctx.ino = dir->ino;
7324                 pctx.errcode = retval;
7325                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326                             PR_3_FIX_PARENT_NOFIND, &pctx);
7327                 ext2fs_unmark_valid(fs);
7328         }
7329         dir->dotdot = parent;
7330 }
7331
7332 /*
7333  * These routines are responsible for expanding a /lost+found if it is
7334  * too small.
7335  */
7336
7337 struct expand_dir_struct {
7338         int                     num;
7339         int                     guaranteed_size;
7340         int                     newblocks;
7341         int                     last_block;
7342         errcode_t               err;
7343         e2fsck_t                ctx;
7344 };
7345
7346 static int expand_dir_proc(ext2_filsys fs,
7347                            blk_t        *blocknr,
7348                            e2_blkcnt_t  blockcnt,
7349                            blk_t ref_block FSCK_ATTR((unused)),
7350                            int ref_offset FSCK_ATTR((unused)),
7351                            void *priv_data)
7352 {
7353         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354         blk_t   new_blk;
7355         static blk_t    last_blk = 0;
7356         char            *block;
7357         errcode_t       retval;
7358         e2fsck_t        ctx;
7359
7360         ctx = es->ctx;
7361
7362         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363                 return BLOCK_ABORT;
7364
7365         if (blockcnt > 0)
7366                 es->last_block = blockcnt;
7367         if (*blocknr) {
7368                 last_blk = *blocknr;
7369                 return 0;
7370         }
7371         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372                                   &new_blk);
7373         if (retval) {
7374                 es->err = retval;
7375                 return BLOCK_ABORT;
7376         }
7377         if (blockcnt > 0) {
7378                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379                 if (retval) {
7380                         es->err = retval;
7381                         return BLOCK_ABORT;
7382                 }
7383                 es->num--;
7384                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7385         } else {
7386                 retval = ext2fs_get_mem(fs->blocksize, &block);
7387                 if (retval) {
7388                         es->err = retval;
7389                         return BLOCK_ABORT;
7390                 }
7391                 memset(block, 0, fs->blocksize);
7392                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7393         }
7394         if (retval) {
7395                 es->err = retval;
7396                 return BLOCK_ABORT;
7397         }
7398         ext2fs_free_mem(&block);
7399         *blocknr = new_blk;
7400         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401         ext2fs_block_alloc_stats(fs, new_blk, +1);
7402         es->newblocks++;
7403
7404         if (es->num == 0)
7405                 return (BLOCK_CHANGED | BLOCK_ABORT);
7406         else
7407                 return BLOCK_CHANGED;
7408 }
7409
7410 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411                                   int num, int guaranteed_size)
7412 {
7413         ext2_filsys fs = ctx->fs;
7414         errcode_t       retval;
7415         struct expand_dir_struct es;
7416         struct ext2_inode       inode;
7417
7418         if (!(fs->flags & EXT2_FLAG_RW))
7419                 return EXT2_ET_RO_FILSYS;
7420
7421         /*
7422          * Read the inode and block bitmaps in; we'll be messing with
7423          * them.
7424          */
7425         e2fsck_read_bitmaps(ctx);
7426
7427         retval = ext2fs_check_directory(fs, dir);
7428         if (retval)
7429                 return retval;
7430
7431         es.num = num;
7432         es.guaranteed_size = guaranteed_size;
7433         es.last_block = 0;
7434         es.err = 0;
7435         es.newblocks = 0;
7436         es.ctx = ctx;
7437
7438         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439                                        0, expand_dir_proc, &es);
7440
7441         if (es.err)
7442                 return es.err;
7443
7444         /*
7445          * Update the size and block count fields in the inode.
7446          */
7447         retval = ext2fs_read_inode(fs, dir, &inode);
7448         if (retval)
7449                 return retval;
7450
7451         inode.i_size = (es.last_block + 1) * fs->blocksize;
7452         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7453
7454         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7455
7456         return 0;
7457 }
7458
7459 /*
7460  * pass4.c -- pass #4 of e2fsck: Check reference counts
7461  *
7462  * Pass 4 frees the following data structures:
7463  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7464  */
7465
7466 /*
7467  * This routine is called when an inode is not connected to the
7468  * directory tree.
7469  *
7470  * This subroutine returns 1 then the caller shouldn't bother with the
7471  * rest of the pass 4 tests.
7472  */
7473 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7474 {
7475         ext2_filsys fs = ctx->fs;
7476         struct ext2_inode       inode;
7477         struct problem_context  pctx;
7478
7479         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480         clear_problem_context(&pctx);
7481         pctx.ino = i;
7482         pctx.inode = &inode;
7483
7484         /*
7485          * Offer to delete any zero-length files that does not have
7486          * blocks.  If there is an EA block, it might have useful
7487          * information, so we won't prompt to delete it, but let it be
7488          * reconnected to lost+found.
7489          */
7490         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491                                 LINUX_S_ISDIR(inode.i_mode))) {
7492                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494                         inode.i_links_count = 0;
7495                         inode.i_dtime = time(NULL);
7496                         e2fsck_write_inode(ctx, i, &inode,
7497                                            "disconnect_inode");
7498                         /*
7499                          * Fix up the bitmaps...
7500                          */
7501                         e2fsck_read_bitmaps(ctx);
7502                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504                         ext2fs_inode_alloc_stats2(fs, i, -1,
7505                                                   LINUX_S_ISDIR(inode.i_mode));
7506                         return 0;
7507                 }
7508         }
7509
7510         /*
7511          * Prompt to reconnect.
7512          */
7513         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514                 if (e2fsck_reconnect_file(ctx, i))
7515                         ext2fs_unmark_valid(fs);
7516         } else {
7517                 /*
7518                  * If we don't attach the inode, then skip the
7519                  * i_links_test since there's no point in trying to
7520                  * force i_links_count to zero.
7521                  */
7522                 ext2fs_unmark_valid(fs);
7523                 return 1;
7524         }
7525         return 0;
7526 }
7527
7528
7529 static void e2fsck_pass4(e2fsck_t ctx)
7530 {
7531         ext2_filsys fs = ctx->fs;
7532         ext2_ino_t      i;
7533         struct ext2_inode       inode;
7534         struct problem_context  pctx;
7535         __u16   link_count, link_counted;
7536         char    *buf = NULL;
7537         int     group, maxgroup;
7538
7539         /* Pass 4 */
7540
7541         clear_problem_context(&pctx);
7542
7543         if (!(ctx->options & E2F_OPT_PREEN))
7544                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7545
7546         group = 0;
7547         maxgroup = fs->group_desc_count;
7548         if (ctx->progress)
7549                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550                         return;
7551
7552         for (i=1; i <= fs->super->s_inodes_count; i++) {
7553                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554                         return;
7555                 if ((i % fs->super->s_inodes_per_group) == 0) {
7556                         group++;
7557                         if (ctx->progress)
7558                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7559                                         return;
7560                 }
7561                 if (i == EXT2_BAD_INO ||
7562                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563                         continue;
7564                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565                     (ctx->inode_imagic_map &&
7566                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567                         continue;
7568                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570                 if (link_counted == 0) {
7571                         if (!buf)
7572                                 buf = e2fsck_allocate_memory(ctx,
7573                                      fs->blocksize, "bad_inode buffer");
7574                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575                                 continue;
7576                         if (disconnect_inode(ctx, i))
7577                                 continue;
7578                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7579                                             &link_count);
7580                         ext2fs_icount_fetch(ctx->inode_count, i,
7581                                             &link_counted);
7582                 }
7583                 if (link_counted != link_count) {
7584                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7585                         pctx.ino = i;
7586                         pctx.inode = &inode;
7587                         if (link_count != inode.i_links_count) {
7588                                 pctx.num = link_count;
7589                                 fix_problem(ctx,
7590                                             PR_4_INCONSISTENT_COUNT, &pctx);
7591                         }
7592                         pctx.num = link_counted;
7593                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594                                 inode.i_links_count = link_counted;
7595                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7596                         }
7597                 }
7598         }
7599         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602         ctx->inode_imagic_map = 0;
7603         ext2fs_free_mem(&buf);
7604 }
7605
7606 /*
7607  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7608  */
7609
7610 #define NO_BLK ((blk_t) -1)
7611
7612 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613                             struct problem_context *pctx)
7614 {
7615         switch (problem) {
7616         case PR_5_BLOCK_UNUSED:
7617                 if (pctx->blk == pctx->blk2)
7618                         pctx->blk2 = 0;
7619                 else
7620                         problem = PR_5_BLOCK_RANGE_UNUSED;
7621                 break;
7622         case PR_5_BLOCK_USED:
7623                 if (pctx->blk == pctx->blk2)
7624                         pctx->blk2 = 0;
7625                 else
7626                         problem = PR_5_BLOCK_RANGE_USED;
7627                 break;
7628         case PR_5_INODE_UNUSED:
7629                 if (pctx->ino == pctx->ino2)
7630                         pctx->ino2 = 0;
7631                 else
7632                         problem = PR_5_INODE_RANGE_UNUSED;
7633                 break;
7634         case PR_5_INODE_USED:
7635                 if (pctx->ino == pctx->ino2)
7636                         pctx->ino2 = 0;
7637                 else
7638                         problem = PR_5_INODE_RANGE_USED;
7639                 break;
7640         }
7641         fix_problem(ctx, problem, pctx);
7642         pctx->blk = pctx->blk2 = NO_BLK;
7643         pctx->ino = pctx->ino2 = 0;
7644 }
7645
7646 static void check_block_bitmaps(e2fsck_t ctx)
7647 {
7648         ext2_filsys fs = ctx->fs;
7649         blk_t   i;
7650         int     *free_array;
7651         int     group = 0;
7652         unsigned int    blocks = 0;
7653         unsigned int    free_blocks = 0;
7654         int     group_free = 0;
7655         int     actual, bitmap;
7656         struct problem_context  pctx;
7657         int     problem, save_problem, fixit, had_problem;
7658         errcode_t       retval;
7659
7660         clear_problem_context(&pctx);
7661         free_array = (int *) e2fsck_allocate_memory(ctx,
7662             fs->group_desc_count * sizeof(int), "free block count array");
7663
7664         if ((fs->super->s_first_data_block <
7665              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666             (fs->super->s_blocks_count-1 >
7667              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668                 pctx.num = 1;
7669                 pctx.blk = fs->super->s_first_data_block;
7670                 pctx.blk2 = fs->super->s_blocks_count -1;
7671                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7674
7675                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676                 return;
7677         }
7678
7679         if ((fs->super->s_first_data_block <
7680              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681             (fs->super->s_blocks_count-1 >
7682              ext2fs_get_block_bitmap_end(fs->block_map))) {
7683                 pctx.num = 2;
7684                 pctx.blk = fs->super->s_first_data_block;
7685                 pctx.blk2 = fs->super->s_blocks_count -1;
7686                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7689
7690                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691                 return;
7692         }
7693
7694 redo_counts:
7695         had_problem = 0;
7696         save_problem = 0;
7697         pctx.blk = pctx.blk2 = NO_BLK;
7698         for (i = fs->super->s_first_data_block;
7699              i < fs->super->s_blocks_count;
7700              i++) {
7701                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7703
7704                 if (actual == bitmap)
7705                         goto do_counts;
7706
7707                 if (!actual && bitmap) {
7708                         /*
7709                          * Block not used, but marked in use in the bitmap.
7710                          */
7711                         problem = PR_5_BLOCK_UNUSED;
7712                 } else {
7713                         /*
7714                          * Block used, but not marked in use in the bitmap.
7715                          */
7716                         problem = PR_5_BLOCK_USED;
7717                 }
7718                 if (pctx.blk == NO_BLK) {
7719                         pctx.blk = pctx.blk2 = i;
7720                         save_problem = problem;
7721                 } else {
7722                         if ((problem == save_problem) &&
7723                             (pctx.blk2 == i-1))
7724                                 pctx.blk2++;
7725                         else {
7726                                 print_bitmap_problem(ctx, save_problem, &pctx);
7727                                 pctx.blk = pctx.blk2 = i;
7728                                 save_problem = problem;
7729                         }
7730                 }
7731                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732                 had_problem++;
7733
7734         do_counts:
7735                 if (!bitmap) {
7736                         group_free++;
7737                         free_blocks++;
7738                 }
7739                 blocks ++;
7740                 if ((blocks == fs->super->s_blocks_per_group) ||
7741                     (i == fs->super->s_blocks_count-1)) {
7742                         free_array[group] = group_free;
7743                         group ++;
7744                         blocks = 0;
7745                         group_free = 0;
7746                         if (ctx->progress)
7747                                 if ((ctx->progress)(ctx, 5, group,
7748                                                     fs->group_desc_count*2))
7749                                         return;
7750                 }
7751         }
7752         if (pctx.blk != NO_BLK)
7753                 print_bitmap_problem(ctx, save_problem, &pctx);
7754         if (had_problem)
7755                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756         else
7757                 fixit = -1;
7758         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7759
7760         if (fixit == 1) {
7761                 ext2fs_free_block_bitmap(fs->block_map);
7762                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763                                                   &fs->block_map);
7764                 if (retval) {
7765                         clear_problem_context(&pctx);
7766                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767                         ctx->flags |= E2F_FLAG_ABORT;
7768                         return;
7769                 }
7770                 ext2fs_set_bitmap_padding(fs->block_map);
7771                 ext2fs_mark_bb_dirty(fs);
7772
7773                 /* Redo the counts */
7774                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776                 goto redo_counts;
7777         } else if (fixit == 0)
7778                 ext2fs_unmark_valid(fs);
7779
7780         for (i = 0; i < fs->group_desc_count; i++) {
7781                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782                         pctx.group = i;
7783                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784                         pctx.blk2 = free_array[i];
7785
7786                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787                                         &pctx)) {
7788                                 fs->group_desc[i].bg_free_blocks_count =
7789                                         free_array[i];
7790                                 ext2fs_mark_super_dirty(fs);
7791                         } else
7792                                 ext2fs_unmark_valid(fs);
7793                 }
7794         }
7795         if (free_blocks != fs->super->s_free_blocks_count) {
7796                 pctx.group = 0;
7797                 pctx.blk = fs->super->s_free_blocks_count;
7798                 pctx.blk2 = free_blocks;
7799
7800                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801                         fs->super->s_free_blocks_count = free_blocks;
7802                         ext2fs_mark_super_dirty(fs);
7803                 } else
7804                         ext2fs_unmark_valid(fs);
7805         }
7806         ext2fs_free_mem(&free_array);
7807 }
7808
7809 static void check_inode_bitmaps(e2fsck_t ctx)
7810 {
7811         ext2_filsys fs = ctx->fs;
7812         ext2_ino_t      i;
7813         unsigned int    free_inodes = 0;
7814         int             group_free = 0;
7815         int             dirs_count = 0;
7816         int             group = 0;
7817         unsigned int    inodes = 0;
7818         int             *free_array;
7819         int             *dir_array;
7820         int             actual, bitmap;
7821         errcode_t       retval;
7822         struct problem_context  pctx;
7823         int             problem, save_problem, fixit, had_problem;
7824
7825         clear_problem_context(&pctx);
7826         free_array = (int *) e2fsck_allocate_memory(ctx,
7827             fs->group_desc_count * sizeof(int), "free inode count array");
7828
7829         dir_array = (int *) e2fsck_allocate_memory(ctx,
7830            fs->group_desc_count * sizeof(int), "directory count array");
7831
7832         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833             (fs->super->s_inodes_count >
7834              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835                 pctx.num = 3;
7836                 pctx.blk = 1;
7837                 pctx.blk2 = fs->super->s_inodes_count;
7838                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843                 return;
7844         }
7845         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846             (fs->super->s_inodes_count >
7847              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848                 pctx.num = 4;
7849                 pctx.blk = 1;
7850                 pctx.blk2 = fs->super->s_inodes_count;
7851                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7854
7855                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856                 return;
7857         }
7858
7859 redo_counts:
7860         had_problem = 0;
7861         save_problem = 0;
7862         pctx.ino = pctx.ino2 = 0;
7863         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7866
7867                 if (actual == bitmap)
7868                         goto do_counts;
7869
7870                 if (!actual && bitmap) {
7871                         /*
7872                          * Inode wasn't used, but marked in bitmap
7873                          */
7874                         problem = PR_5_INODE_UNUSED;
7875                 } else /* if (actual && !bitmap) */ {
7876                         /*
7877                          * Inode used, but not in bitmap
7878                          */
7879                         problem = PR_5_INODE_USED;
7880                 }
7881                 if (pctx.ino == 0) {
7882                         pctx.ino = pctx.ino2 = i;
7883                         save_problem = problem;
7884                 } else {
7885                         if ((problem == save_problem) &&
7886                             (pctx.ino2 == i-1))
7887                                 pctx.ino2++;
7888                         else {
7889                                 print_bitmap_problem(ctx, save_problem, &pctx);
7890                                 pctx.ino = pctx.ino2 = i;
7891                                 save_problem = problem;
7892                         }
7893                 }
7894                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895                 had_problem++;
7896
7897 do_counts:
7898                 if (!bitmap) {
7899                         group_free++;
7900                         free_inodes++;
7901                 } else {
7902                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903                                 dirs_count++;
7904                 }
7905                 inodes++;
7906                 if ((inodes == fs->super->s_inodes_per_group) ||
7907                     (i == fs->super->s_inodes_count)) {
7908                         free_array[group] = group_free;
7909                         dir_array[group] = dirs_count;
7910                         group ++;
7911                         inodes = 0;
7912                         group_free = 0;
7913                         dirs_count = 0;
7914                         if (ctx->progress)
7915                                 if ((ctx->progress)(ctx, 5,
7916                                             group + fs->group_desc_count,
7917                                             fs->group_desc_count*2))
7918                                         return;
7919                 }
7920         }
7921         if (pctx.ino)
7922                 print_bitmap_problem(ctx, save_problem, &pctx);
7923
7924         if (had_problem)
7925                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926         else
7927                 fixit = -1;
7928         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7929
7930         if (fixit == 1) {
7931                 ext2fs_free_inode_bitmap(fs->inode_map);
7932                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933                                                   &fs->inode_map);
7934                 if (retval) {
7935                         clear_problem_context(&pctx);
7936                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937                         ctx->flags |= E2F_FLAG_ABORT;
7938                         return;
7939                 }
7940                 ext2fs_set_bitmap_padding(fs->inode_map);
7941                 ext2fs_mark_ib_dirty(fs);
7942
7943                 /* redo counts */
7944                 inodes = 0; free_inodes = 0; group_free = 0;
7945                 dirs_count = 0; group = 0;
7946                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948                 goto redo_counts;
7949         } else if (fixit == 0)
7950                 ext2fs_unmark_valid(fs);
7951
7952         for (i = 0; i < fs->group_desc_count; i++) {
7953                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954                         pctx.group = i;
7955                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956                         pctx.ino2 = free_array[i];
7957                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958                                         &pctx)) {
7959                                 fs->group_desc[i].bg_free_inodes_count =
7960                                         free_array[i];
7961                                 ext2fs_mark_super_dirty(fs);
7962                         } else
7963                                 ext2fs_unmark_valid(fs);
7964                 }
7965                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966                         pctx.group = i;
7967                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968                         pctx.ino2 = dir_array[i];
7969
7970                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971                                         &pctx)) {
7972                                 fs->group_desc[i].bg_used_dirs_count =
7973                                         dir_array[i];
7974                                 ext2fs_mark_super_dirty(fs);
7975                         } else
7976                                 ext2fs_unmark_valid(fs);
7977                 }
7978         }
7979         if (free_inodes != fs->super->s_free_inodes_count) {
7980                 pctx.group = -1;
7981                 pctx.ino = fs->super->s_free_inodes_count;
7982                 pctx.ino2 = free_inodes;
7983
7984                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985                         fs->super->s_free_inodes_count = free_inodes;
7986                         ext2fs_mark_super_dirty(fs);
7987                 } else
7988                         ext2fs_unmark_valid(fs);
7989         }
7990         ext2fs_free_mem(&free_array);
7991         ext2fs_free_mem(&dir_array);
7992 }
7993
7994 static void check_inode_end(e2fsck_t ctx)
7995 {
7996         ext2_filsys fs = ctx->fs;
7997         ext2_ino_t      end, save_inodes_count, i;
7998         struct problem_context  pctx;
7999
8000         clear_problem_context(&pctx);
8001
8002         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004                                                      &save_inodes_count);
8005         if (pctx.errcode) {
8006                 pctx.num = 1;
8007                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009                 return;
8010         }
8011         if (save_inodes_count == end)
8012                 return;
8013
8014         for (i = save_inodes_count + 1; i <= end; i++) {
8015                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017                                 for (i = save_inodes_count + 1; i <= end; i++)
8018                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8019                                                                  i);
8020                                 ext2fs_mark_ib_dirty(fs);
8021                         } else
8022                                 ext2fs_unmark_valid(fs);
8023                         break;
8024                 }
8025         }
8026
8027         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028                                                      save_inodes_count, 0);
8029         if (pctx.errcode) {
8030                 pctx.num = 2;
8031                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033                 return;
8034         }
8035 }
8036
8037 static void check_block_end(e2fsck_t ctx)
8038 {
8039         ext2_filsys fs = ctx->fs;
8040         blk_t   end, save_blocks_count, i;
8041         struct problem_context  pctx;
8042
8043         clear_problem_context(&pctx);
8044
8045         end = fs->block_map->start +
8046                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048                                                      &save_blocks_count);
8049         if (pctx.errcode) {
8050                 pctx.num = 3;
8051                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053                 return;
8054         }
8055         if (save_blocks_count == end)
8056                 return;
8057
8058         for (i = save_blocks_count + 1; i <= end; i++) {
8059                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061                                 for (i = save_blocks_count + 1; i <= end; i++)
8062                                         ext2fs_mark_block_bitmap(fs->block_map,
8063                                                                  i);
8064                                 ext2fs_mark_bb_dirty(fs);
8065                         } else
8066                                 ext2fs_unmark_valid(fs);
8067                         break;
8068                 }
8069         }
8070
8071         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072                                                      save_blocks_count, 0);
8073         if (pctx.errcode) {
8074                 pctx.num = 4;
8075                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077                 return;
8078         }
8079 }
8080
8081 static void e2fsck_pass5(e2fsck_t ctx)
8082 {
8083         struct problem_context  pctx;
8084
8085         /* Pass 5 */
8086
8087         clear_problem_context(&pctx);
8088
8089         if (!(ctx->options & E2F_OPT_PREEN))
8090                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8091
8092         if (ctx->progress)
8093                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094                         return;
8095
8096         e2fsck_read_bitmaps(ctx);
8097
8098         check_block_bitmaps(ctx);
8099         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100                 return;
8101         check_inode_bitmaps(ctx);
8102         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103                 return;
8104         check_inode_end(ctx);
8105         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106                 return;
8107         check_block_end(ctx);
8108         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109                 return;
8110
8111         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112         ctx->inode_used_map = 0;
8113         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114         ctx->inode_dir_map = 0;
8115         ext2fs_free_block_bitmap(ctx->block_found_map);
8116         ctx->block_found_map = 0;
8117 }
8118
8119 /*
8120  * problem.c --- report filesystem problems to the user
8121  */
8122
8123 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8124 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8125 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8126 #define PR_MSG_ONLY     0x000008 /* Print message only */
8127
8128 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8129
8130 #define PR_FATAL        0x001000 /* Fatal error */
8131 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8132                                  /* ask another */
8133 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8134 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8135 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8136 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8137 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8138
8139
8140 #define PROMPT_NONE     0
8141 #define PROMPT_FIX      1
8142 #define PROMPT_CLEAR    2
8143 #define PROMPT_RELOCATE 3
8144 #define PROMPT_ALLOCATE 4
8145 #define PROMPT_EXPAND   5
8146 #define PROMPT_CONNECT  6
8147 #define PROMPT_CREATE   7
8148 #define PROMPT_SALVAGE  8
8149 #define PROMPT_TRUNCATE 9
8150 #define PROMPT_CLEAR_INODE 10
8151 #define PROMPT_ABORT    11
8152 #define PROMPT_SPLIT    12
8153 #define PROMPT_CONTINUE 13
8154 #define PROMPT_CLONE    14
8155 #define PROMPT_DELETE   15
8156 #define PROMPT_SUPPRESS 16
8157 #define PROMPT_UNLINK   17
8158 #define PROMPT_CLEAR_HTREE 18
8159 #define PROMPT_RECREATE 19
8160 #define PROMPT_NULL     20
8161
8162 struct e2fsck_problem {
8163         problem_t       e2p_code;
8164         const char *    e2p_description;
8165         char            prompt;
8166         int             flags;
8167         problem_t       second_code;
8168 };
8169
8170 struct latch_descr {
8171         int             latch_code;
8172         problem_t       question;
8173         problem_t       end_message;
8174         int             flags;
8175 };
8176
8177 /*
8178  * These are the prompts which are used to ask the user if they want
8179  * to fix a problem.
8180  */
8181 static const char *const prompt[] = {
8182         N_("(no prompt)"),      /* 0 */
8183         N_("Fix"),              /* 1 */
8184         N_("Clear"),            /* 2 */
8185         N_("Relocate"),         /* 3 */
8186         N_("Allocate"),         /* 4 */
8187         N_("Expand"),           /* 5 */
8188         N_("Connect to /lost+found"), /* 6 */
8189         N_("Create"),           /* 7 */
8190         N_("Salvage"),          /* 8 */
8191         N_("Truncate"),         /* 9 */
8192         N_("Clear inode"),      /* 10 */
8193         N_("Abort"),            /* 11 */
8194         N_("Split"),            /* 12 */
8195         N_("Continue"),         /* 13 */
8196         N_("Clone multiply-claimed blocks"), /* 14 */
8197         N_("Delete file"),      /* 15 */
8198         N_("Suppress messages"),/* 16 */
8199         N_("Unlink"),           /* 17 */
8200         N_("Clear HTree index"),/* 18 */
8201         N_("Recreate"),         /* 19 */
8202         "",                     /* 20 */
8203 };
8204
8205 /*
8206  * These messages are printed when we are preen mode and we will be
8207  * automatically fixing the problem.
8208  */
8209 static const char *const preen_msg[] = {
8210         N_("(NONE)"),           /* 0 */
8211         N_("FIXED"),            /* 1 */
8212         N_("CLEARED"),          /* 2 */
8213         N_("RELOCATED"),        /* 3 */
8214         N_("ALLOCATED"),        /* 4 */
8215         N_("EXPANDED"),         /* 5 */
8216         N_("RECONNECTED"),      /* 6 */
8217         N_("CREATED"),          /* 7 */
8218         N_("SALVAGED"),         /* 8 */
8219         N_("TRUNCATED"),        /* 9 */
8220         N_("INODE CLEARED"),    /* 10 */
8221         N_("ABORTED"),          /* 11 */
8222         N_("SPLIT"),            /* 12 */
8223         N_("CONTINUING"),       /* 13 */
8224         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225         N_("FILE DELETED"),     /* 15 */
8226         N_("SUPPRESSED"),       /* 16 */
8227         N_("UNLINKED"),         /* 17 */
8228         N_("HTREE INDEX CLEARED"),/* 18 */
8229         N_("WILL RECREATE"),    /* 19 */
8230         "",                     /* 20 */
8231 };
8232
8233 static const struct e2fsck_problem problem_table[] = {
8234
8235         /* Pre-Pass 1 errors */
8236
8237         /* Block bitmap not in group */
8238         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8239           PROMPT_RELOCATE, PR_LATCH_RELOC },
8240
8241         /* Inode bitmap not in group */
8242         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8243           PROMPT_RELOCATE, PR_LATCH_RELOC },
8244
8245         /* Inode table not in group */
8246         { PR_0_ITABLE_NOT_GROUP,
8247           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8248           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249           PROMPT_RELOCATE, PR_LATCH_RELOC },
8250
8251         /* Superblock corrupt */
8252         { PR_0_SB_CORRUPT,
8253           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254           "@f.  If the @v is valid and it really contains an ext2\n"
8255           "@f (and not swap or ufs or something else), then the @S\n"
8256           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257           "    e2fsck -b %S <@v>\n\n"),
8258           PROMPT_NONE, PR_FATAL },
8259
8260         /* Filesystem size is wrong */
8261         { PR_0_FS_SIZE_WRONG,
8262           N_("The @f size (according to the @S) is %b @bs\n"
8263           "The physical size of the @v is %c @bs\n"
8264           "Either the @S or the partition table is likely to be corrupt!\n"),
8265           PROMPT_ABORT, 0 },
8266
8267         /* Fragments not supported */
8268         { PR_0_NO_FRAGMENTS,
8269           N_("@S @b_size = %b, fragsize = %c.\n"
8270           "This version of e2fsck does not support fragment sizes different\n"
8271           "from the @b size.\n"),
8272           PROMPT_NONE, PR_FATAL },
8273
8274           /* Bad blocks_per_group */
8275         { PR_0_BLOCKS_PER_GROUP,
8276           N_("@S @bs_per_group = %b, should have been %c\n"),
8277           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8278
8279         /* Bad first_data_block */
8280         { PR_0_FIRST_DATA_BLOCK,
8281           N_("@S first_data_@b = %b, should have been %c\n"),
8282           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8283
8284         /* Adding UUID to filesystem */
8285         { PR_0_ADD_UUID,
8286           N_("@f did not have a UUID; generating one.\n\n"),
8287           PROMPT_NONE, 0 },
8288
8289         /* Relocate hint */
8290         { PR_0_RELOCATE_HINT,
8291           N_("Note: if several inode or block bitmap blocks or part\n"
8292           "of the inode table require relocation, you may wish to try\n"
8293           "running e2fsck with the '-b %S' option first.  The problem\n"
8294           "may lie only with the primary block group descriptors, and\n"
8295           "the backup block group descriptors may be OK.\n\n"),
8296           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8297
8298         /* Miscellaneous superblock corruption */
8299         { PR_0_MISC_CORRUPT_SUPER,
8300           N_("Corruption found in @S.  (%s = %N).\n"),
8301           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8302
8303         /* Error determing physical device size of filesystem */
8304         { PR_0_GETSIZE_ERROR,
8305           N_("Error determining size of the physical @v: %m\n"),
8306           PROMPT_NONE, PR_FATAL },
8307
8308         /* Inode count in superblock is incorrect */
8309         { PR_0_INODE_COUNT_WRONG,
8310           N_("@i count in @S is %i, @s %j.\n"),
8311           PROMPT_FIX, 0 },
8312
8313         { PR_0_HURD_CLEAR_FILETYPE,
8314           N_("The Hurd does not support the filetype feature.\n"),
8315           PROMPT_CLEAR, 0 },
8316
8317         /* Journal inode is invalid */
8318         { PR_0_JOURNAL_BAD_INODE,
8319           N_("@S has an @n ext3 @j (@i %i).\n"),
8320           PROMPT_CLEAR, PR_PREEN_OK },
8321
8322         /* The external journal has (unsupported) multiple filesystems */
8323         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324           N_("External @j has multiple @f users (unsupported).\n"),
8325           PROMPT_NONE, PR_FATAL },
8326
8327         /* Can't find external journal */
8328         { PR_0_CANT_FIND_JOURNAL,
8329           N_("Can't find external @j\n"),
8330           PROMPT_NONE, PR_FATAL },
8331
8332         /* External journal has bad superblock */
8333         { PR_0_EXT_JOURNAL_BAD_SUPER,
8334           N_("External @j has bad @S\n"),
8335           PROMPT_NONE, PR_FATAL },
8336
8337         /* Superblock has a bad journal UUID */
8338         { PR_0_JOURNAL_BAD_UUID,
8339           N_("External @j does not support this @f\n"),
8340           PROMPT_NONE, PR_FATAL },
8341
8342         /* Journal has an unknown superblock type */
8343         { PR_0_JOURNAL_UNSUPP_SUPER,
8344           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345              "It is likely that your copy of e2fsck is old and/or doesn't "
8346              "support this @j format.\n"
8347              "It is also possible the @j @S is corrupt.\n"),
8348           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8349
8350         /* Journal superblock is corrupt */
8351         { PR_0_JOURNAL_BAD_SUPER,
8352           N_("Ext3 @j @S is corrupt.\n"),
8353           PROMPT_FIX, PR_PREEN_OK },
8354
8355         /* Superblock flag should be cleared */
8356         { PR_0_JOURNAL_HAS_JOURNAL,
8357           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358           PROMPT_CLEAR, PR_PREEN_OK },
8359
8360         /* Superblock flag is incorrect */
8361         { PR_0_JOURNAL_RECOVER_SET,
8362           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363           PROMPT_CLEAR, PR_PREEN_OK },
8364
8365         /* Journal has data, but recovery flag is clear */
8366         { PR_0_JOURNAL_RECOVERY_CLEAR,
8367           N_("ext3 recovery flag is clear, but @j has data.\n"),
8368           PROMPT_NONE, 0 },
8369
8370         /* Ask if we should clear the journal */
8371         { PR_0_JOURNAL_RESET_JOURNAL,
8372           N_("Clear @j"),
8373           PROMPT_NULL, PR_PREEN_NOMSG },
8374
8375         /* Ask if we should run the journal anyway */
8376         { PR_0_JOURNAL_RUN,
8377           N_("Run @j anyway"),
8378           PROMPT_NULL, 0 },
8379
8380         /* Run the journal by default */
8381         { PR_0_JOURNAL_RUN_DEFAULT,
8382           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383           PROMPT_NONE, 0 },
8384
8385         /* Clearing orphan inode */
8386         { PR_0_ORPHAN_CLEAR_INODE,
8387           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388           PROMPT_NONE, 0 },
8389
8390         /* Illegal block found in orphaned inode */
8391         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393           PROMPT_NONE, 0 },
8394
8395         /* Already cleared block found in orphaned inode */
8396         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398           PROMPT_NONE, 0 },
8399
8400         /* Illegal orphan inode in superblock */
8401         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402           N_("@I @o @i %i in @S.\n"),
8403           PROMPT_NONE, 0 },
8404
8405         /* Illegal inode in orphaned inode list */
8406         { PR_0_ORPHAN_ILLEGAL_INODE,
8407           N_("@I @i %i in @o @i list.\n"),
8408           PROMPT_NONE, 0 },
8409
8410         /* Filesystem revision is 0, but feature flags are set */
8411         { PR_0_FS_REV_LEVEL,
8412           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8413           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8414
8415         /* Journal superblock has an unknown read-only feature flag set */
8416         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418           PROMPT_ABORT, 0 },
8419
8420         /* Journal superblock has an unknown incompatible feature flag set */
8421         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423           PROMPT_ABORT, 0 },
8424
8425         /* Journal has unsupported version number */
8426         { PR_0_JOURNAL_UNSUPP_VERSION,
8427           N_("@j version not supported by this e2fsck.\n"),
8428           PROMPT_ABORT, 0 },
8429
8430         /* Moving journal to hidden file */
8431         { PR_0_MOVE_JOURNAL,
8432           N_("Moving @j from /%s to hidden @i.\n\n"),
8433           PROMPT_NONE, 0 },
8434
8435         /* Error moving journal to hidden file */
8436         { PR_0_ERR_MOVE_JOURNAL,
8437           N_("Error moving @j: %m\n\n"),
8438           PROMPT_NONE, 0 },
8439
8440         /* Clearing V2 journal superblock */
8441         { PR_0_CLEAR_V2_JOURNAL,
8442           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443              "Clearing fields beyond the V1 @j @S...\n\n"),
8444           PROMPT_NONE, 0 },
8445
8446         /* Backup journal inode blocks */
8447         { PR_0_BACKUP_JNL,
8448           N_("Backing up @j @i @b information.\n\n"),
8449           PROMPT_NONE, 0 },
8450
8451         /* Reserved blocks w/o resize_inode */
8452         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454              "is %N; @s zero.  "),
8455           PROMPT_FIX, 0 },
8456
8457         /* Resize_inode not enabled, but resize inode is non-zero */
8458         { PR_0_CLEAR_RESIZE_INODE,
8459           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8460           PROMPT_CLEAR, 0 },
8461
8462         /* Resize inode invalid */
8463         { PR_0_RESIZE_INODE_INVALID,
8464           N_("Resize @i not valid.  "),
8465           PROMPT_RECREATE, 0 },
8466
8467         /* Pass 1 errors */
8468
8469         /* Pass 1: Checking inodes, blocks, and sizes */
8470         { PR_1_PASS_HEADER,
8471           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472           PROMPT_NONE, 0 },
8473
8474         /* Root directory is not an inode */
8475         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8476           PROMPT_CLEAR, 0 },
8477
8478         /* Root directory has dtime set */
8479         { PR_1_ROOT_DTIME,
8480           N_("@r has dtime set (probably due to old mke2fs).  "),
8481           PROMPT_FIX, PR_PREEN_OK },
8482
8483         /* Reserved inode has bad mode */
8484         { PR_1_RESERVED_BAD_MODE,
8485           N_("Reserved @i %i (%Q) has @n mode.  "),
8486           PROMPT_CLEAR, PR_PREEN_OK },
8487
8488         /* Deleted inode has zero dtime */
8489         { PR_1_ZERO_DTIME,
8490           N_("@D @i %i has zero dtime.  "),
8491           PROMPT_FIX, PR_PREEN_OK },
8492
8493         /* Inode in use, but dtime set */
8494         { PR_1_SET_DTIME,
8495           N_("@i %i is in use, but has dtime set.  "),
8496           PROMPT_FIX, PR_PREEN_OK },
8497
8498         /* Zero-length directory */
8499         { PR_1_ZERO_LENGTH_DIR,
8500           N_("@i %i is a @z @d.  "),
8501           PROMPT_CLEAR, PR_PREEN_OK },
8502
8503         /* Block bitmap conflicts with some other fs block */
8504         { PR_1_BB_CONFLICT,
8505           N_("@g %g's @b @B at %b @C.\n"),
8506           PROMPT_RELOCATE, 0 },
8507
8508         /* Inode bitmap conflicts with some other fs block */
8509         { PR_1_IB_CONFLICT,
8510           N_("@g %g's @i @B at %b @C.\n"),
8511           PROMPT_RELOCATE, 0 },
8512
8513         /* Inode table conflicts with some other fs block */
8514         { PR_1_ITABLE_CONFLICT,
8515           N_("@g %g's @i table at %b @C.\n"),
8516           PROMPT_RELOCATE, 0 },
8517
8518         /* Block bitmap is on a bad block */
8519         { PR_1_BB_BAD_BLOCK,
8520           N_("@g %g's @b @B (%b) is bad.  "),
8521           PROMPT_RELOCATE, 0 },
8522
8523         /* Inode bitmap is on a bad block */
8524         { PR_1_IB_BAD_BLOCK,
8525           N_("@g %g's @i @B (%b) is bad.  "),
8526           PROMPT_RELOCATE, 0 },
8527
8528         /* Inode has incorrect i_size */
8529         { PR_1_BAD_I_SIZE,
8530           N_("@i %i, i_size is %Is, @s %N.  "),
8531           PROMPT_FIX, PR_PREEN_OK },
8532
8533         /* Inode has incorrect i_blocks */
8534         { PR_1_BAD_I_BLOCKS,
8535           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8536           PROMPT_FIX, PR_PREEN_OK },
8537
8538         /* Illegal blocknumber in inode */
8539         { PR_1_ILLEGAL_BLOCK_NUM,
8540           N_("@I @b #%B (%b) in @i %i.  "),
8541           PROMPT_CLEAR, PR_LATCH_BLOCK },
8542
8543         /* Block number overlaps fs metadata */
8544         { PR_1_BLOCK_OVERLAPS_METADATA,
8545           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8546           PROMPT_CLEAR, PR_LATCH_BLOCK },
8547
8548         /* Inode has illegal blocks (latch question) */
8549         { PR_1_INODE_BLOCK_LATCH,
8550           N_("@i %i has illegal @b(s).  "),
8551           PROMPT_CLEAR, 0 },
8552
8553         /* Too many bad blocks in inode */
8554         { PR_1_TOO_MANY_BAD_BLOCKS,
8555           N_("Too many illegal @bs in @i %i.\n"),
8556           PROMPT_CLEAR_INODE, PR_NO_OK },
8557
8558         /* Illegal block number in bad block inode */
8559         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560           N_("@I @b #%B (%b) in bad @b @i.  "),
8561           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8562
8563         /* Bad block inode has illegal blocks (latch question) */
8564         { PR_1_INODE_BBLOCK_LATCH,
8565           N_("Bad @b @i has illegal @b(s).  "),
8566           PROMPT_CLEAR, 0 },
8567
8568         /* Duplicate or bad blocks in use! */
8569         { PR_1_DUP_BLOCKS_PREENSTOP,
8570           N_("Duplicate or bad @b in use!\n"),
8571           PROMPT_NONE, 0 },
8572
8573         /* Bad block used as bad block indirect block */
8574         { PR_1_BBINODE_BAD_METABLOCK,
8575           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8576           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8577
8578         /* Inconsistency can't be fixed prompt */
8579         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8581              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582              "in the @f.\n"),
8583           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8584
8585         /* Bad primary block */
8586         { PR_1_BAD_PRIMARY_BLOCK,
8587           N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8589
8590         /* Bad primary block prompt */
8591         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592           N_("You can remove this @b from the bad @b list and hope\n"
8593              "that the @b is really OK.  But there are no guarantees.\n\n"),
8594           PROMPT_CLEAR, PR_PREEN_NOMSG },
8595
8596         /* Bad primary superblock */
8597         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598           N_("The primary @S (%b) is on the bad @b list.\n"),
8599           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8600
8601         /* Bad primary block group descriptors */
8602         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603           N_("Block %b in the primary @g descriptors "
8604           "is on the bad @b list\n"),
8605           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8606
8607         /* Bad superblock in group */
8608         { PR_1_BAD_SUPERBLOCK,
8609           N_("Warning: Group %g's @S (%b) is bad.\n"),
8610           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8611
8612         /* Bad block group descriptors in group */
8613         { PR_1_BAD_GROUP_DESCRIPTORS,
8614           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615           "@b (%b).\n"),
8616           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8617
8618         /* Block claimed for no reason */
8619         { PR_1_PROGERR_CLAIMED_BLOCK,
8620           N_("Programming error?  @b #%b claimed for no reason in "
8621           "process_bad_@b.\n"),
8622           PROMPT_NONE, PR_PREEN_OK },
8623
8624         /* Error allocating blocks for relocating metadata */
8625         { PR_1_RELOC_BLOCK_ALLOCATE,
8626           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627           PROMPT_NONE, PR_PREEN_OK },
8628
8629         /* Error allocating block buffer during relocation process */
8630         { PR_1_RELOC_MEMORY_ALLOCATE,
8631           N_("@A @b buffer for relocating %s\n"),
8632           PROMPT_NONE, PR_PREEN_OK },
8633
8634         /* Relocating metadata group information from X to Y */
8635         { PR_1_RELOC_FROM_TO,
8636           N_("Relocating @g %g's %s from %b to %c...\n"),
8637           PROMPT_NONE, PR_PREEN_OK },
8638
8639         /* Relocating metatdata group information to X */
8640         { PR_1_RELOC_TO,
8641           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642           PROMPT_NONE, PR_PREEN_OK },
8643
8644         /* Block read error during relocation process */
8645         { PR_1_RELOC_READ_ERR,
8646           N_("Warning: could not read @b %b of %s: %m\n"),
8647           PROMPT_NONE, PR_PREEN_OK },
8648
8649         /* Block write error during relocation process */
8650         { PR_1_RELOC_WRITE_ERR,
8651           N_("Warning: could not write @b %b for %s: %m\n"),
8652           PROMPT_NONE, PR_PREEN_OK },
8653
8654         /* Error allocating inode bitmap */
8655         { PR_1_ALLOCATE_IBITMAP_ERROR,
8656           N_("@A @i @B (%N): %m\n"),
8657           PROMPT_NONE, PR_FATAL },
8658
8659         /* Error allocating block bitmap */
8660         { PR_1_ALLOCATE_BBITMAP_ERROR,
8661           N_("@A @b @B (%N): %m\n"),
8662           PROMPT_NONE, PR_FATAL },
8663
8664         /* Error allocating icount structure */
8665         { PR_1_ALLOCATE_ICOUNT,
8666           N_("@A icount link information: %m\n"),
8667           PROMPT_NONE, PR_FATAL },
8668
8669         /* Error allocating dbcount */
8670         { PR_1_ALLOCATE_DBCOUNT,
8671           N_("@A @d @b array: %m\n"),
8672           PROMPT_NONE, PR_FATAL },
8673
8674         /* Error while scanning inodes */
8675         { PR_1_ISCAN_ERROR,
8676           N_("Error while scanning @is (%i): %m\n"),
8677           PROMPT_NONE, PR_FATAL },
8678
8679         /* Error while iterating over blocks */
8680         { PR_1_BLOCK_ITERATE,
8681           N_("Error while iterating over @bs in @i %i: %m\n"),
8682           PROMPT_NONE, PR_FATAL },
8683
8684         /* Error while storing inode count information */
8685         { PR_1_ICOUNT_STORE,
8686           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687           PROMPT_NONE, PR_FATAL },
8688
8689         /* Error while storing directory block information */
8690         { PR_1_ADD_DBLOCK,
8691           N_("Error storing @d @b information "
8692           "(@i=%i, @b=%b, num=%N): %m\n"),
8693           PROMPT_NONE, PR_FATAL },
8694
8695         /* Error while reading inode (for clearing) */
8696         { PR_1_READ_INODE,
8697           N_("Error reading @i %i: %m\n"),
8698           PROMPT_NONE, PR_FATAL },
8699
8700         /* Suppress messages prompt */
8701         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8702
8703         /* Imagic flag set on an inode when filesystem doesn't support it */
8704         { PR_1_SET_IMAGIC,
8705           N_("@i %i has imagic flag set.  "),
8706           PROMPT_CLEAR, 0 },
8707
8708         /* Immutable flag set on a device or socket inode */
8709         { PR_1_SET_IMMUTABLE,
8710           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711              "or append-only flag set.  "),
8712           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8713
8714         /* Compression flag set on an inode when filesystem doesn't support it */
8715         { PR_1_COMPR_SET,
8716           N_("@i %i has @cion flag set on @f without @cion support.  "),
8717           PROMPT_CLEAR, 0 },
8718
8719         /* Non-zero size for device, fifo or socket inode */
8720         { PR_1_SET_NONZSIZE,
8721           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8722           PROMPT_FIX, PR_PREEN_OK },
8723
8724         /* Filesystem revision is 0, but feature flags are set */
8725         { PR_1_FS_REV_LEVEL,
8726           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8727           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8728
8729         /* Journal inode is not in use, but contains data */
8730         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731           N_("@j @i is not in use, but contains data.  "),
8732           PROMPT_CLEAR, PR_PREEN_OK },
8733
8734         /* Journal has bad mode */
8735         { PR_1_JOURNAL_BAD_MODE,
8736           N_("@j is not regular file.  "),
8737           PROMPT_FIX, PR_PREEN_OK },
8738
8739         /* Deal with inodes that were part of orphan linked list */
8740         { PR_1_LOW_DTIME,
8741           N_("@i %i was part of the @o @i list.  "),
8742           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8743
8744         /* Deal with inodes that were part of corrupted orphan linked
8745            list (latch question) */
8746         { PR_1_ORPHAN_LIST_REFUGEES,
8747           N_("@is that were part of a corrupted orphan linked list found.  "),
8748           PROMPT_FIX, 0 },
8749
8750         /* Error allocating refcount structure */
8751         { PR_1_ALLOCATE_REFCOUNT,
8752           N_("@A refcount structure (%N): %m\n"),
8753           PROMPT_NONE, PR_FATAL },
8754
8755         /* Error reading extended attribute block */
8756         { PR_1_READ_EA_BLOCK,
8757           N_("Error reading @a @b %b for @i %i.  "),
8758           PROMPT_CLEAR, 0 },
8759
8760         /* Invalid extended attribute block */
8761         { PR_1_BAD_EA_BLOCK,
8762           N_("@i %i has a bad @a @b %b.  "),
8763           PROMPT_CLEAR, 0 },
8764
8765         /* Error reading Extended Attribute block while fixing refcount */
8766         { PR_1_EXTATTR_READ_ABORT,
8767           N_("Error reading @a @b %b (%m).  "),
8768           PROMPT_ABORT, 0 },
8769
8770         /* Extended attribute reference count incorrect */
8771         { PR_1_EXTATTR_REFCOUNT,
8772           N_("@a @b %b has reference count %B, @s %N.  "),
8773           PROMPT_FIX, 0 },
8774
8775         /* Error writing Extended Attribute block while fixing refcount */
8776         { PR_1_EXTATTR_WRITE,
8777           N_("Error writing @a @b %b (%m).  "),
8778           PROMPT_ABORT, 0 },
8779
8780         /* Multiple EA blocks not supported */
8781         { PR_1_EA_MULTI_BLOCK,
8782           N_("@a @b %b has h_@bs > 1.  "),
8783           PROMPT_CLEAR, 0},
8784
8785         /* Error allocating EA region allocation structure */
8786         { PR_1_EA_ALLOC_REGION,
8787           N_("@A @a @b %b.  "),
8788           PROMPT_ABORT, 0},
8789
8790         /* Error EA allocation collision */
8791         { PR_1_EA_ALLOC_COLLISION,
8792           N_("@a @b %b is corrupt (allocation collision).  "),
8793           PROMPT_CLEAR, 0},
8794
8795         /* Bad extended attribute name */
8796         { PR_1_EA_BAD_NAME,
8797           N_("@a @b %b is corrupt (@n name).  "),
8798           PROMPT_CLEAR, 0},
8799
8800         /* Bad extended attribute value */
8801         { PR_1_EA_BAD_VALUE,
8802           N_("@a @b %b is corrupt (@n value).  "),
8803           PROMPT_CLEAR, 0},
8804
8805         /* Inode too big (latch question) */
8806         { PR_1_INODE_TOOBIG,
8807           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8808
8809         /* Directory too big */
8810         { PR_1_TOOBIG_DIR,
8811           N_("@b #%B (%b) causes @d to be too big.  "),
8812           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8813
8814         /* Regular file too big */
8815         { PR_1_TOOBIG_REG,
8816           N_("@b #%B (%b) causes file to be too big.  "),
8817           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8818
8819         /* Symlink too big */
8820         { PR_1_TOOBIG_SYMLINK,
8821           N_("@b #%B (%b) causes symlink to be too big.  "),
8822           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8823
8824         /* INDEX_FL flag set on a non-HTREE filesystem */
8825         { PR_1_HTREE_SET,
8826           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8828
8829         /* INDEX_FL flag set on a non-directory */
8830         { PR_1_HTREE_NODIR,
8831           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8833
8834         /* Invalid root node in HTREE directory */
8835         { PR_1_HTREE_BADROOT,
8836           N_("@h %i has an @n root node.\n"),
8837           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8838
8839         /* Unsupported hash version in HTREE directory */
8840         { PR_1_HTREE_HASHV,
8841           N_("@h %i has an unsupported hash version (%N)\n"),
8842           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8843
8844         /* Incompatible flag in HTREE root node */
8845         { PR_1_HTREE_INCOMPAT,
8846           N_("@h %i uses an incompatible htree root node flag.\n"),
8847           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8848
8849         /* HTREE too deep */
8850         { PR_1_HTREE_DEPTH,
8851           N_("@h %i has a tree depth (%N) which is too big\n"),
8852           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853
8854         /* Bad block has indirect block that conflicts with filesystem block */
8855         { PR_1_BB_FS_BLOCK,
8856           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857              "@f metadata.  "),
8858           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8859
8860         /* Resize inode failed */
8861         { PR_1_RESIZE_INODE_CREATE,
8862           N_("Resize @i (re)creation failed: %m."),
8863           PROMPT_ABORT, 0 },
8864
8865         /* invalid inode->i_extra_isize */
8866         { PR_1_EXTRA_ISIZE,
8867           N_("@i %i has a extra size (%IS) which is @n\n"),
8868           PROMPT_FIX, PR_PREEN_OK },
8869
8870         /* invalid ea entry->e_name_len */
8871         { PR_1_ATTR_NAME_LEN,
8872           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873           PROMPT_CLEAR, PR_PREEN_OK },
8874
8875         /* invalid ea entry->e_value_size */
8876         { PR_1_ATTR_VALUE_SIZE,
8877           N_("@a in @i %i has a value size (%N) which is @n\n"),
8878           PROMPT_CLEAR, PR_PREEN_OK },
8879
8880         /* invalid ea entry->e_value_offs */
8881         { PR_1_ATTR_VALUE_OFFSET,
8882           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883           PROMPT_CLEAR, PR_PREEN_OK },
8884
8885         /* invalid ea entry->e_value_block */
8886         { PR_1_ATTR_VALUE_BLOCK,
8887           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888           PROMPT_CLEAR, PR_PREEN_OK },
8889
8890         /* invalid ea entry->e_hash */
8891         { PR_1_ATTR_HASH,
8892           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893           PROMPT_CLEAR, PR_PREEN_OK },
8894
8895         /* Pass 1b errors */
8896
8897         /* Pass 1B: Rescan for duplicate/bad blocks */
8898         { PR_1B_PASS_HEADER,
8899           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900           "Pass 1B: Rescanning for @m @bs\n"),
8901           PROMPT_NONE, 0 },
8902
8903         /* Duplicate/bad block(s) header */
8904         { PR_1B_DUP_BLOCK_HEADER,
8905           N_("@m @b(s) in @i %i:"),
8906           PROMPT_NONE, 0 },
8907
8908         /* Duplicate/bad block(s) in inode */
8909         { PR_1B_DUP_BLOCK,
8910           " %b",
8911           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8912
8913         /* Duplicate/bad block(s) end */
8914         { PR_1B_DUP_BLOCK_END,
8915           "\n",
8916           PROMPT_NONE, PR_PREEN_NOHDR },
8917
8918         /* Error while scanning inodes */
8919         { PR_1B_ISCAN_ERROR,
8920           N_("Error while scanning inodes (%i): %m\n"),
8921           PROMPT_NONE, PR_FATAL },
8922
8923         /* Error allocating inode bitmap */
8924         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925           N_("@A @i @B (@i_dup_map): %m\n"),
8926           PROMPT_NONE, PR_FATAL },
8927
8928         /* Error while iterating over blocks */
8929         { PR_1B_BLOCK_ITERATE,
8930           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931           PROMPT_NONE, 0 },
8932
8933         /* Error adjusting EA refcount */
8934         { PR_1B_ADJ_EA_REFCOUNT,
8935           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936           PROMPT_NONE, 0 },
8937
8938
8939         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940         { PR_1C_PASS_HEADER,
8941           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942           PROMPT_NONE, 0 },
8943
8944
8945         /* Pass 1D: Reconciling multiply-claimed blocks */
8946         { PR_1D_PASS_HEADER,
8947           N_("Pass 1D: Reconciling @m @bs\n"),
8948           PROMPT_NONE, 0 },
8949
8950         /* File has duplicate blocks */
8951         { PR_1D_DUP_FILE,
8952           N_("File %Q (@i #%i, mod time %IM)\n"
8953           "  has %B @m @b(s), shared with %N file(s):\n"),
8954           PROMPT_NONE, 0 },
8955
8956         /* List of files sharing duplicate blocks */
8957         { PR_1D_DUP_FILE_LIST,
8958           N_("\t%Q (@i #%i, mod time %IM)\n"),
8959           PROMPT_NONE, 0 },
8960
8961         /* File sharing blocks with filesystem metadata  */
8962         { PR_1D_SHARE_METADATA,
8963           N_("\t<@f metadata>\n"),
8964           PROMPT_NONE, 0 },
8965
8966         /* Report of how many duplicate/bad inodes */
8967         { PR_1D_NUM_DUP_INODES,
8968           N_("(There are %N @is containing @m @bs.)\n\n"),
8969           PROMPT_NONE, 0 },
8970
8971         /* Duplicated blocks already reassigned or cloned. */
8972         { PR_1D_DUP_BLOCKS_DEALT,
8973           N_("@m @bs already reassigned or cloned.\n\n"),
8974           PROMPT_NONE, 0 },
8975
8976         /* Clone duplicate/bad blocks? */
8977         { PR_1D_CLONE_QUESTION,
8978           "", PROMPT_CLONE, PR_NO_OK },
8979
8980         /* Delete file? */
8981         { PR_1D_DELETE_QUESTION,
8982           "", PROMPT_DELETE, 0 },
8983
8984         /* Couldn't clone file (error) */
8985         { PR_1D_CLONE_ERROR,
8986           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8987
8988         /* Pass 2 errors */
8989
8990         /* Pass 2: Checking directory structure */
8991         { PR_2_PASS_HEADER,
8992           N_("Pass 2: Checking @d structure\n"),
8993           PROMPT_NONE, 0 },
8994
8995         /* Bad inode number for '.' */
8996         { PR_2_BAD_INODE_DOT,
8997           N_("@n @i number for '.' in @d @i %i.\n"),
8998           PROMPT_FIX, 0 },
8999
9000         /* Directory entry has bad inode number */
9001         { PR_2_BAD_INO,
9002           N_("@E has @n @i #: %Di.\n"),
9003           PROMPT_CLEAR, 0 },
9004
9005         /* Directory entry has deleted or unused inode */
9006         { PR_2_UNUSED_INODE,
9007           N_("@E has @D/unused @i %Di.  "),
9008           PROMPT_CLEAR, PR_PREEN_OK },
9009
9010         /* Directry entry is link to '.' */
9011         { PR_2_LINK_DOT,
9012           N_("@E @L to '.'  "),
9013           PROMPT_CLEAR, 0 },
9014
9015         /* Directory entry points to inode now located in a bad block */
9016         { PR_2_BB_INODE,
9017           N_("@E points to @i (%Di) located in a bad @b.\n"),
9018           PROMPT_CLEAR, 0 },
9019
9020         /* Directory entry contains a link to a directory */
9021         { PR_2_LINK_DIR,
9022           N_("@E @L to @d %P (%Di).\n"),
9023           PROMPT_CLEAR, 0 },
9024
9025         /* Directory entry contains a link to the root directry */
9026         { PR_2_LINK_ROOT,
9027           N_("@E @L to the @r.\n"),
9028           PROMPT_CLEAR, 0 },
9029
9030         /* Directory entry has illegal characters in its name */
9031         { PR_2_BAD_NAME,
9032           N_("@E has illegal characters in its name.\n"),
9033           PROMPT_FIX, 0 },
9034
9035         /* Missing '.' in directory inode */
9036         { PR_2_MISSING_DOT,
9037           N_("Missing '.' in @d @i %i.\n"),
9038           PROMPT_FIX, 0 },
9039
9040         /* Missing '..' in directory inode */
9041         { PR_2_MISSING_DOT_DOT,
9042           N_("Missing '..' in @d @i %i.\n"),
9043           PROMPT_FIX, 0 },
9044
9045         /* First entry in directory inode doesn't contain '.' */
9046         { PR_2_1ST_NOT_DOT,
9047           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048           PROMPT_FIX, 0 },
9049
9050         /* Second entry in directory inode doesn't contain '..' */
9051         { PR_2_2ND_NOT_DOT_DOT,
9052           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053           PROMPT_FIX, 0 },
9054
9055         /* i_faddr should be zero */
9056         { PR_2_FADDR_ZERO,
9057           N_("i_faddr @F %IF, @s zero.\n"),
9058           PROMPT_CLEAR, 0 },
9059
9060         /* i_file_acl should be zero */
9061         { PR_2_FILE_ACL_ZERO,
9062           N_("i_file_acl @F %If, @s zero.\n"),
9063           PROMPT_CLEAR, 0 },
9064
9065         /* i_dir_acl should be zero */
9066         { PR_2_DIR_ACL_ZERO,
9067           N_("i_dir_acl @F %Id, @s zero.\n"),
9068           PROMPT_CLEAR, 0 },
9069
9070         /* i_frag should be zero */
9071         { PR_2_FRAG_ZERO,
9072           N_("i_frag @F %N, @s zero.\n"),
9073           PROMPT_CLEAR, 0 },
9074
9075         /* i_fsize should be zero */
9076         { PR_2_FSIZE_ZERO,
9077           N_("i_fsize @F %N, @s zero.\n"),
9078           PROMPT_CLEAR, 0 },
9079
9080         /* inode has bad mode */
9081         { PR_2_BAD_MODE,
9082           N_("@i %i (%Q) has @n mode (%Im).\n"),
9083           PROMPT_CLEAR, 0 },
9084
9085         /* directory corrupted */
9086         { PR_2_DIR_CORRUPTED,
9087           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088           PROMPT_SALVAGE, 0 },
9089
9090         /* filename too long */
9091         { PR_2_FILENAME_LONG,
9092           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093           PROMPT_TRUNCATE, 0 },
9094
9095         /* Directory inode has a missing block (hole) */
9096         { PR_2_DIRECTORY_HOLE,
9097           N_("@d @i %i has an unallocated @b #%B.  "),
9098           PROMPT_ALLOCATE, 0 },
9099
9100         /* '.' is not NULL terminated */
9101         { PR_2_DOT_NULL_TERM,
9102           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103           PROMPT_FIX, 0 },
9104
9105         /* '..' is not NULL terminated */
9106         { PR_2_DOT_DOT_NULL_TERM,
9107           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108           PROMPT_FIX, 0 },
9109
9110         /* Illegal character device inode */
9111         { PR_2_BAD_CHAR_DEV,
9112           N_("@i %i (%Q) is an @I character @v.\n"),
9113           PROMPT_CLEAR, 0 },
9114
9115         /* Illegal block device inode */
9116         { PR_2_BAD_BLOCK_DEV,
9117           N_("@i %i (%Q) is an @I @b @v.\n"),
9118           PROMPT_CLEAR, 0 },
9119
9120         /* Duplicate '.' entry */
9121         { PR_2_DUP_DOT,
9122           N_("@E is duplicate '.' @e.\n"),
9123           PROMPT_FIX, 0 },
9124
9125         /* Duplicate '..' entry */
9126         { PR_2_DUP_DOT_DOT,
9127           N_("@E is duplicate '..' @e.\n"),
9128           PROMPT_FIX, 0 },
9129
9130         /* Internal error: couldn't find dir_info */
9131         { PR_2_NO_DIRINFO,
9132           N_("Internal error: cannot find dir_info for %i.\n"),
9133           PROMPT_NONE, PR_FATAL },
9134
9135         /* Final rec_len is wrong */
9136         { PR_2_FINAL_RECLEN,
9137           N_("@E has rec_len of %Dr, @s %N.\n"),
9138           PROMPT_FIX, 0 },
9139
9140         /* Error allocating icount structure */
9141         { PR_2_ALLOCATE_ICOUNT,
9142           N_("@A icount structure: %m\n"),
9143           PROMPT_NONE, PR_FATAL },
9144
9145         /* Error iterating over directory blocks */
9146         { PR_2_DBLIST_ITERATE,
9147           N_("Error iterating over @d @bs: %m\n"),
9148           PROMPT_NONE, PR_FATAL },
9149
9150         /* Error reading directory block */
9151         { PR_2_READ_DIRBLOCK,
9152           N_("Error reading @d @b %b (@i %i): %m\n"),
9153           PROMPT_CONTINUE, 0 },
9154
9155         /* Error writing directory block */
9156         { PR_2_WRITE_DIRBLOCK,
9157           N_("Error writing @d @b %b (@i %i): %m\n"),
9158           PROMPT_CONTINUE, 0 },
9159
9160         /* Error allocating new directory block */
9161         { PR_2_ALLOC_DIRBOCK,
9162           N_("@A new @d @b for @i %i (%s): %m\n"),
9163           PROMPT_NONE, 0 },
9164
9165         /* Error deallocating inode */
9166         { PR_2_DEALLOC_INODE,
9167           N_("Error deallocating @i %i: %m\n"),
9168           PROMPT_NONE, PR_FATAL },
9169
9170         /* Directory entry for '.' is big.  Split? */
9171         { PR_2_SPLIT_DOT,
9172           N_("@d @e for '.' is big.  "),
9173           PROMPT_SPLIT, PR_NO_OK },
9174
9175         /* Illegal FIFO inode */
9176         { PR_2_BAD_FIFO,
9177           N_("@i %i (%Q) is an @I FIFO.\n"),
9178           PROMPT_CLEAR, 0 },
9179
9180         /* Illegal socket inode */
9181         { PR_2_BAD_SOCKET,
9182           N_("@i %i (%Q) is an @I socket.\n"),
9183           PROMPT_CLEAR, 0 },
9184
9185         /* Directory filetype not set */
9186         { PR_2_SET_FILETYPE,
9187           N_("Setting filetype for @E to %N.\n"),
9188           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9189
9190         /* Directory filetype incorrect */
9191         { PR_2_BAD_FILETYPE,
9192           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193           PROMPT_FIX, 0 },
9194
9195         /* Directory filetype set on filesystem */
9196         { PR_2_CLEAR_FILETYPE,
9197           N_("@E has filetype set.\n"),
9198           PROMPT_CLEAR, PR_PREEN_OK },
9199
9200         /* Directory filename is null */
9201         { PR_2_NULL_NAME,
9202           N_("@E has a @z name.\n"),
9203           PROMPT_CLEAR, 0 },
9204
9205         /* Invalid symlink */
9206         { PR_2_INVALID_SYMLINK,
9207           N_("Symlink %Q (@i #%i) is @n.\n"),
9208           PROMPT_CLEAR, 0 },
9209
9210         /* i_file_acl (extended attribute block) is bad */
9211         { PR_2_FILE_ACL_BAD,
9212           N_("@a @b @F @n (%If).\n"),
9213           PROMPT_CLEAR, 0 },
9214
9215         /* Filesystem contains large files, but has no such flag in sb */
9216         { PR_2_FEATURE_LARGE_FILES,
9217           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218           PROMPT_FIX, 0 },
9219
9220         /* Node in HTREE directory not referenced */
9221         { PR_2_HTREE_NOTREF,
9222           N_("@p @h %d: node (%B) not referenced\n"),
9223           PROMPT_NONE, 0 },
9224
9225         /* Node in HTREE directory referenced twice */
9226         { PR_2_HTREE_DUPREF,
9227           N_("@p @h %d: node (%B) referenced twice\n"),
9228           PROMPT_NONE, 0 },
9229
9230         /* Node in HTREE directory has bad min hash */
9231         { PR_2_HTREE_MIN_HASH,
9232           N_("@p @h %d: node (%B) has bad min hash\n"),
9233           PROMPT_NONE, 0 },
9234
9235         /* Node in HTREE directory has bad max hash */
9236         { PR_2_HTREE_MAX_HASH,
9237           N_("@p @h %d: node (%B) has bad max hash\n"),
9238           PROMPT_NONE, 0 },
9239
9240         /* Clear invalid HTREE directory */
9241         { PR_2_HTREE_CLEAR,
9242           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9243
9244         /* Bad block in htree interior node */
9245         { PR_2_HTREE_BADBLK,
9246           N_("@p @h %d (%q): bad @b number %b.\n"),
9247           PROMPT_CLEAR_HTREE, 0 },
9248
9249         /* Error adjusting EA refcount */
9250         { PR_2_ADJ_EA_REFCOUNT,
9251           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252           PROMPT_NONE, PR_FATAL },
9253
9254         /* Invalid HTREE root node */
9255         { PR_2_HTREE_BAD_ROOT,
9256           N_("@p @h %d: root node is @n\n"),
9257           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9258
9259         /* Invalid HTREE limit */
9260         { PR_2_HTREE_BAD_LIMIT,
9261           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9263
9264         /* Invalid HTREE count */
9265         { PR_2_HTREE_BAD_COUNT,
9266           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9268
9269         /* HTREE interior node has out-of-order hashes in table */
9270         { PR_2_HTREE_HASH_ORDER,
9271           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9273
9274         /* Node in HTREE directory has invalid depth */
9275         { PR_2_HTREE_BAD_DEPTH,
9276           N_("@p @h %d: node (%B) has @n depth\n"),
9277           PROMPT_NONE, 0 },
9278
9279         /* Duplicate directory entry found */
9280         { PR_2_DUPLICATE_DIRENT,
9281           N_("Duplicate @E found.  "),
9282           PROMPT_CLEAR, 0 },
9283
9284         /* Non-unique filename found */
9285         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286           N_("@E has a non-unique filename.\nRename to %s"),
9287           PROMPT_NULL, 0 },
9288
9289         /* Duplicate directory entry found */
9290         { PR_2_REPORT_DUP_DIRENT,
9291           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292           PROMPT_NONE, 0 },
9293
9294         /* Pass 3 errors */
9295
9296         /* Pass 3: Checking directory connectivity */
9297         { PR_3_PASS_HEADER,
9298           N_("Pass 3: Checking @d connectivity\n"),
9299           PROMPT_NONE, 0 },
9300
9301         /* Root inode not allocated */
9302         { PR_3_NO_ROOT_INODE,
9303           N_("@r not allocated.  "),
9304           PROMPT_ALLOCATE, 0 },
9305
9306         /* No room in lost+found */
9307         { PR_3_EXPAND_LF_DIR,
9308           N_("No room in @l @d.  "),
9309           PROMPT_EXPAND, 0 },
9310
9311         /* Unconnected directory inode */
9312         { PR_3_UNCONNECTED_DIR,
9313           N_("Unconnected @d @i %i (%p)\n"),
9314           PROMPT_CONNECT, 0 },
9315
9316         /* /lost+found not found */
9317         { PR_3_NO_LF_DIR,
9318           N_("/@l not found.  "),
9319           PROMPT_CREATE, PR_PREEN_OK },
9320
9321         /* .. entry is incorrect */
9322         { PR_3_BAD_DOT_DOT,
9323           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324           PROMPT_FIX, 0 },
9325
9326         /* Bad or non-existent /lost+found.  Cannot reconnect */
9327         { PR_3_NO_LPF,
9328           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9329           PROMPT_NONE, 0 },
9330
9331         /* Could not expand /lost+found */
9332         { PR_3_CANT_EXPAND_LPF,
9333           N_("Could not expand /@l: %m\n"),
9334           PROMPT_NONE, 0 },
9335
9336         /* Could not reconnect inode */
9337         { PR_3_CANT_RECONNECT,
9338           N_("Could not reconnect %i: %m\n"),
9339           PROMPT_NONE, 0 },
9340
9341         /* Error while trying to find /lost+found */
9342         { PR_3_ERR_FIND_LPF,
9343           N_("Error while trying to find /@l: %m\n"),
9344           PROMPT_NONE, 0 },
9345
9346         /* Error in ext2fs_new_block while creating /lost+found */
9347         { PR_3_ERR_LPF_NEW_BLOCK,
9348           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349           PROMPT_NONE, 0 },
9350
9351         /* Error in ext2fs_new_inode while creating /lost+found */
9352         { PR_3_ERR_LPF_NEW_INODE,
9353           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354           PROMPT_NONE, 0 },
9355
9356         /* Error in ext2fs_new_dir_block while creating /lost+found */
9357         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359           PROMPT_NONE, 0 },
9360
9361         /* Error while writing directory block for /lost+found */
9362         { PR_3_ERR_LPF_WRITE_BLOCK,
9363           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364           PROMPT_NONE, 0 },
9365
9366         /* Error while adjusting inode count */
9367         { PR_3_ADJUST_INODE,
9368           N_("Error while adjusting @i count on @i %i\n"),
9369           PROMPT_NONE, 0 },
9370
9371         /* Couldn't fix parent directory -- error */
9372         { PR_3_FIX_PARENT_ERR,
9373           N_("Couldn't fix parent of @i %i: %m\n\n"),
9374           PROMPT_NONE, 0 },
9375
9376         /* Couldn't fix parent directory -- couldn't find it */
9377         { PR_3_FIX_PARENT_NOFIND,
9378           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379           PROMPT_NONE, 0 },
9380
9381         /* Error allocating inode bitmap */
9382         { PR_3_ALLOCATE_IBITMAP_ERROR,
9383           N_("@A @i @B (%N): %m\n"),
9384           PROMPT_NONE, PR_FATAL },
9385
9386         /* Error creating root directory */
9387         { PR_3_CREATE_ROOT_ERROR,
9388           N_("Error creating root @d (%s): %m\n"),
9389           PROMPT_NONE, PR_FATAL },
9390
9391         /* Error creating lost and found directory */
9392         { PR_3_CREATE_LPF_ERROR,
9393           N_("Error creating /@l @d (%s): %m\n"),
9394           PROMPT_NONE, PR_FATAL },
9395
9396         /* Root inode is not directory; aborting */
9397         { PR_3_ROOT_NOT_DIR_ABORT,
9398           N_("@r is not a @d; aborting.\n"),
9399           PROMPT_NONE, PR_FATAL },
9400
9401         /* Cannot proceed without a root inode. */
9402         { PR_3_NO_ROOT_INODE_ABORT,
9403           N_("can't proceed without a @r.\n"),
9404           PROMPT_NONE, PR_FATAL },
9405
9406         /* Internal error: couldn't find dir_info */
9407         { PR_3_NO_DIRINFO,
9408           N_("Internal error: cannot find dir_info for %i.\n"),
9409           PROMPT_NONE, PR_FATAL },
9410
9411         /* Lost+found not a directory */
9412         { PR_3_LPF_NOTDIR,
9413           N_("/@l is not a @d (ino=%i)\n"),
9414           PROMPT_UNLINK, 0 },
9415
9416         /* Pass 3A Directory Optimization       */
9417
9418         /* Pass 3A: Optimizing directories */
9419         { PR_3A_PASS_HEADER,
9420           N_("Pass 3A: Optimizing directories\n"),
9421           PROMPT_NONE, PR_PREEN_NOMSG },
9422
9423         /* Error iterating over directories */
9424         { PR_3A_OPTIMIZE_ITER,
9425           N_("Failed to create dirs_to_hash iterator: %m"),
9426           PROMPT_NONE, 0 },
9427
9428         /* Error rehash directory */
9429         { PR_3A_OPTIMIZE_DIR_ERR,
9430           N_("Failed to optimize directory %q (%d): %m"),
9431           PROMPT_NONE, 0 },
9432
9433         /* Rehashing dir header */
9434         { PR_3A_OPTIMIZE_DIR_HEADER,
9435           N_("Optimizing directories: "),
9436           PROMPT_NONE, PR_MSG_ONLY },
9437
9438         /* Rehashing directory %d */
9439         { PR_3A_OPTIMIZE_DIR,
9440           " %d",
9441           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9442
9443         /* Rehashing dir end */
9444         { PR_3A_OPTIMIZE_DIR_END,
9445           "\n",
9446           PROMPT_NONE, PR_PREEN_NOHDR },
9447
9448         /* Pass 4 errors */
9449
9450         /* Pass 4: Checking reference counts */
9451         { PR_4_PASS_HEADER,
9452           N_("Pass 4: Checking reference counts\n"),
9453           PROMPT_NONE, 0 },
9454
9455         /* Unattached zero-length inode */
9456         { PR_4_ZERO_LEN_INODE,
9457           N_("@u @z @i %i.  "),
9458           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9459
9460         /* Unattached inode */
9461         { PR_4_UNATTACHED_INODE,
9462           N_("@u @i %i\n"),
9463           PROMPT_CONNECT, 0 },
9464
9465         /* Inode ref count wrong */
9466         { PR_4_BAD_REF_COUNT,
9467           N_("@i %i ref count is %Il, @s %N.  "),
9468           PROMPT_FIX, PR_PREEN_OK },
9469
9470         { PR_4_INCONSISTENT_COUNT,
9471           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9474           "They @s the same!\n"),
9475           PROMPT_NONE, 0 },
9476
9477         /* Pass 5 errors */
9478
9479         /* Pass 5: Checking group summary information */
9480         { PR_5_PASS_HEADER,
9481           N_("Pass 5: Checking @g summary information\n"),
9482           PROMPT_NONE, 0 },
9483
9484         /* Padding at end of inode bitmap is not set. */
9485         { PR_5_INODE_BMAP_PADDING,
9486           N_("Padding at end of @i @B is not set. "),
9487           PROMPT_FIX, PR_PREEN_OK },
9488
9489         /* Padding at end of block bitmap is not set. */
9490         { PR_5_BLOCK_BMAP_PADDING,
9491           N_("Padding at end of @b @B is not set. "),
9492           PROMPT_FIX, PR_PREEN_OK },
9493
9494         /* Block bitmap differences header */
9495         { PR_5_BLOCK_BITMAP_HEADER,
9496           N_("@b @B differences: "),
9497           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9498
9499         /* Block not used, but marked in bitmap */
9500         { PR_5_BLOCK_UNUSED,
9501           " -%b",
9502           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9503
9504         /* Block used, but not marked used in bitmap */
9505         { PR_5_BLOCK_USED,
9506           " +%b",
9507           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9508
9509         /* Block bitmap differences end */
9510         { PR_5_BLOCK_BITMAP_END,
9511           "\n",
9512           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9513
9514         /* Inode bitmap differences header */
9515         { PR_5_INODE_BITMAP_HEADER,
9516           N_("@i @B differences: "),
9517           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9518
9519         /* Inode not used, but marked in bitmap */
9520         { PR_5_INODE_UNUSED,
9521           " -%i",
9522           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9523
9524         /* Inode used, but not marked used in bitmap */
9525         { PR_5_INODE_USED,
9526           " +%i",
9527           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528
9529         /* Inode bitmap differences end */
9530         { PR_5_INODE_BITMAP_END,
9531           "\n",
9532           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9533
9534         /* Free inodes count for group wrong */
9535         { PR_5_FREE_INODE_COUNT_GROUP,
9536           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538
9539         /* Directories count for group wrong */
9540         { PR_5_FREE_DIR_COUNT_GROUP,
9541           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9543
9544         /* Free inodes count wrong */
9545         { PR_5_FREE_INODE_COUNT,
9546           N_("Free @is count wrong (%i, counted=%j).\n"),
9547           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9548
9549         /* Free blocks count for group wrong */
9550         { PR_5_FREE_BLOCK_COUNT_GROUP,
9551           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9553
9554         /* Free blocks count wrong */
9555         { PR_5_FREE_BLOCK_COUNT,
9556           N_("Free @bs count wrong (%b, counted=%c).\n"),
9557           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558
9559         /* Programming error: bitmap endpoints don't match */
9560         { PR_5_BMAP_ENDPOINTS,
9561           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562           "match calculated @B endpoints (%i, %j)\n"),
9563           PROMPT_NONE, PR_FATAL },
9564
9565         /* Internal error: fudging end of bitmap */
9566         { PR_5_FUDGE_BITMAP_ERROR,
9567           N_("Internal error: fudging end of bitmap (%N)\n"),
9568           PROMPT_NONE, PR_FATAL },
9569
9570         /* Error copying in replacement inode bitmap */
9571         { PR_5_COPY_IBITMAP_ERROR,
9572           N_("Error copying in replacement @i @B: %m\n"),
9573           PROMPT_NONE, PR_FATAL },
9574
9575         /* Error copying in replacement block bitmap */
9576         { PR_5_COPY_BBITMAP_ERROR,
9577           N_("Error copying in replacement @b @B: %m\n"),
9578           PROMPT_NONE, PR_FATAL },
9579
9580         /* Block range not used, but marked in bitmap */
9581         { PR_5_BLOCK_RANGE_UNUSED,
9582           " -(%b--%c)",
9583           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9584
9585         /* Block range used, but not marked used in bitmap */
9586         { PR_5_BLOCK_RANGE_USED,
9587           " +(%b--%c)",
9588           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9589
9590         /* Inode range not used, but marked in bitmap */
9591         { PR_5_INODE_RANGE_UNUSED,
9592           " -(%i--%j)",
9593           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9594
9595         /* Inode range used, but not marked used in bitmap */
9596         { PR_5_INODE_RANGE_USED,
9597           " +(%i--%j)",
9598           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9599
9600         { 0 }
9601 };
9602
9603 /*
9604  * This is the latch flags register.  It allows several problems to be
9605  * "latched" together.  This means that the user has to answer but one
9606  * question for the set of problems, and all of the associated
9607  * problems will be either fixed or not fixed.
9608  */
9609 static struct latch_descr pr_latch_info[] = {
9610         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619         { -1, 0, 0 },
9620 };
9621
9622 static const struct e2fsck_problem *find_problem(problem_t code)
9623 {
9624         int     i;
9625
9626         for (i=0; problem_table[i].e2p_code; i++) {
9627                 if (problem_table[i].e2p_code == code)
9628                         return &problem_table[i];
9629         }
9630         return 0;
9631 }
9632
9633 static struct latch_descr *find_latch(int code)
9634 {
9635         int     i;
9636
9637         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638                 if (pr_latch_info[i].latch_code == code)
9639                         return &pr_latch_info[i];
9640         }
9641         return 0;
9642 }
9643
9644 int end_problem_latch(e2fsck_t ctx, int mask)
9645 {
9646         struct latch_descr *ldesc;
9647         struct problem_context pctx;
9648         int answer = -1;
9649
9650         ldesc = find_latch(mask);
9651         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652                 clear_problem_context(&pctx);
9653                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9654         }
9655         ldesc->flags &= ~(PRL_VARIABLE);
9656         return answer;
9657 }
9658
9659 int set_latch_flags(int mask, int setflags, int clearflags)
9660 {
9661         struct latch_descr *ldesc;
9662
9663         ldesc = find_latch(mask);
9664         if (!ldesc)
9665                 return -1;
9666         ldesc->flags |= setflags;
9667         ldesc->flags &= ~clearflags;
9668         return 0;
9669 }
9670
9671 void clear_problem_context(struct problem_context *ctx)
9672 {
9673         memset(ctx, 0, sizeof(struct problem_context));
9674         ctx->blkcount = -1;
9675         ctx->group = -1;
9676 }
9677
9678 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9679 {
9680         ext2_filsys fs = ctx->fs;
9681         const struct e2fsck_problem *ptr;
9682         struct latch_descr *ldesc = NULL;
9683         const char *message;
9684         int             def_yn, answer, ans;
9685         int             print_answer = 0;
9686         int             suppress = 0;
9687
9688         ptr = find_problem(code);
9689         if (!ptr) {
9690                 printf(_("Unhandled error code (0x%x)!\n"), code);
9691                 return 0;
9692         }
9693         def_yn = 1;
9694         if ((ptr->flags & PR_NO_DEFAULT) ||
9695             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696             (ctx->options & E2F_OPT_NO))
9697                 def_yn= 0;
9698
9699         /*
9700          * Do special latch processing.  This is where we ask the
9701          * latch question, if it exists
9702          */
9703         if (ptr->flags & PR_LATCH_MASK) {
9704                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706                         ans = fix_problem(ctx, ldesc->question, pctx);
9707                         if (ans == 1)
9708                                 ldesc->flags |= PRL_YES;
9709                         if (ans == 0)
9710                                 ldesc->flags |= PRL_NO;
9711                         ldesc->flags |= PRL_LATCHED;
9712                 }
9713                 if (ldesc->flags & PRL_SUPPRESS)
9714                         suppress++;
9715         }
9716         if ((ptr->flags & PR_PREEN_NOMSG) &&
9717             (ctx->options & E2F_OPT_PREEN))
9718                 suppress++;
9719         if ((ptr->flags & PR_NO_NOMSG) &&
9720             (ctx->options & E2F_OPT_NO))
9721                 suppress++;
9722         if (!suppress) {
9723                 message = ptr->e2p_description;
9724                 if ((ctx->options & E2F_OPT_PREEN) &&
9725                     !(ptr->flags & PR_PREEN_NOHDR)) {
9726                         printf("%s: ", ctx->device_name ?
9727                                ctx->device_name : ctx->filesystem_name);
9728                 }
9729                 if (*message)
9730                         print_e2fsck_message(ctx, _(message), pctx, 1);
9731         }
9732         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733                 preenhalt(ctx);
9734
9735         if (ptr->flags & PR_FATAL)
9736                 bb_error_msg_and_die(0);
9737
9738         if (ptr->prompt == PROMPT_NONE) {
9739                 if (ptr->flags & PR_NOCOLLATE)
9740                         answer = -1;
9741                 else
9742                         answer = def_yn;
9743         } else {
9744                 if (ctx->options & E2F_OPT_PREEN) {
9745                         answer = def_yn;
9746                         if (!(ptr->flags & PR_PREEN_NOMSG))
9747                                 print_answer = 1;
9748                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9749                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9750                         if (!suppress)
9751                                 print_answer = 1;
9752                         if (ldesc->flags & PRL_YES)
9753                                 answer = 1;
9754                         else
9755                                 answer = 0;
9756                 } else
9757                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758                 if (!answer && !(ptr->flags & PR_NO_OK))
9759                         ext2fs_unmark_valid(fs);
9760
9761                 if (print_answer)
9762                         printf("%s.\n", answer ?
9763                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9764         }
9765
9766         if ((ptr->prompt == PROMPT_ABORT) && answer)
9767                 bb_error_msg_and_die(0);
9768
9769         if (ptr->flags & PR_AFTER_CODE)
9770                 answer = fix_problem(ctx, ptr->second_code, pctx);
9771
9772         return answer;
9773 }
9774
9775 /*
9776  * linux/fs/recovery.c
9777  *
9778  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9779  */
9780
9781 /*
9782  * Maintain information about the progress of the recovery job, so that
9783  * the different passes can carry information between them.
9784  */
9785 struct recovery_info
9786 {
9787         tid_t           start_transaction;
9788         tid_t           end_transaction;
9789
9790         int             nr_replays;
9791         int             nr_revokes;
9792         int             nr_revoke_hits;
9793 };
9794
9795 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9796 static int do_one_pass(journal_t *journal,
9797                                 struct recovery_info *info, enum passtype pass);
9798 static int scan_revoke_records(journal_t *, struct buffer_head *,
9799                                 tid_t, struct recovery_info *);
9800
9801 /*
9802  * Read a block from the journal
9803  */
9804
9805 static int jread(struct buffer_head **bhp, journal_t *journal,
9806                  unsigned int offset)
9807 {
9808         int err;
9809         unsigned long blocknr;
9810         struct buffer_head *bh;
9811
9812         *bhp = NULL;
9813
9814         err = journal_bmap(journal, offset, &blocknr);
9815
9816         if (err) {
9817                 printf("JBD: bad block at offset %u\n", offset);
9818                 return err;
9819         }
9820
9821         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9822         if (!bh)
9823                 return -ENOMEM;
9824
9825         if (!buffer_uptodate(bh)) {
9826                 /* If this is a brand new buffer, start readahead.
9827                    Otherwise, we assume we are already reading it.  */
9828                 if (!buffer_req(bh))
9829                         do_readahead(journal, offset);
9830                 wait_on_buffer(bh);
9831         }
9832
9833         if (!buffer_uptodate(bh)) {
9834                 printf("JBD: Failed to read block at offset %u\n", offset);
9835                 brelse(bh);
9836                 return -EIO;
9837         }
9838
9839         *bhp = bh;
9840         return 0;
9841 }
9842
9843
9844 /*
9845  * Count the number of in-use tags in a journal descriptor block.
9846  */
9847
9848 static int count_tags(struct buffer_head *bh, int size)
9849 {
9850         char *                  tagp;
9851         journal_block_tag_t *   tag;
9852         int                     nr = 0;
9853
9854         tagp = &bh->b_data[sizeof(journal_header_t)];
9855
9856         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9857                 tag = (journal_block_tag_t *) tagp;
9858
9859                 nr++;
9860                 tagp += sizeof(journal_block_tag_t);
9861                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9862                         tagp += 16;
9863
9864                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9865                         break;
9866         }
9867
9868         return nr;
9869 }
9870
9871
9872 /* Make sure we wrap around the log correctly! */
9873 #define wrap(journal, var)                                            \
9874 do {                                                                \
9875         if (var >= (journal)->j_last)                                   \
9876                 var -= ((journal)->j_last - (journal)->j_first);        \
9877 } while (0)
9878
9879 /**
9880  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9881  * @journal: the journal to recover
9882  *
9883  * The primary function for recovering the log contents when mounting a
9884  * journaled device.
9885  *
9886  * Recovery is done in three passes.  In the first pass, we look for the
9887  * end of the log.  In the second, we assemble the list of revoke
9888  * blocks.  In the third and final pass, we replay any un-revoked blocks
9889  * in the log.
9890  */
9891 int journal_recover(journal_t *journal)
9892 {
9893         int                     err;
9894         journal_superblock_t *  sb;
9895
9896         struct recovery_info    info;
9897
9898         memset(&info, 0, sizeof(info));
9899         sb = journal->j_superblock;
9900
9901         /*
9902          * The journal superblock's s_start field (the current log head)
9903          * is always zero if, and only if, the journal was cleanly
9904          * unmounted.
9905          */
9906
9907         if (!sb->s_start) {
9908                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9909                 return 0;
9910         }
9911
9912         err = do_one_pass(journal, &info, PASS_SCAN);
9913         if (!err)
9914                 err = do_one_pass(journal, &info, PASS_REVOKE);
9915         if (!err)
9916                 err = do_one_pass(journal, &info, PASS_REPLAY);
9917
9918         /* Restart the log at the next transaction ID, thus invalidating
9919          * any existing commit records in the log. */
9920         journal->j_transaction_sequence = ++info.end_transaction;
9921
9922         journal_clear_revoke(journal);
9923         sync_blockdev(journal->j_fs_dev);
9924         return err;
9925 }
9926
9927 static int do_one_pass(journal_t *journal,
9928                         struct recovery_info *info, enum passtype pass)
9929 {
9930         unsigned int            first_commit_ID, next_commit_ID;
9931         unsigned long           next_log_block;
9932         int                     err, success = 0;
9933         journal_superblock_t *  sb;
9934         journal_header_t *      tmp;
9935         struct buffer_head *    bh;
9936         unsigned int            sequence;
9937         int                     blocktype;
9938
9939         /* Precompute the maximum metadata descriptors in a descriptor block */
9940         int                     MAX_BLOCKS_PER_DESC;
9941         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9942                                / sizeof(journal_block_tag_t));
9943
9944         /*
9945          * First thing is to establish what we expect to find in the log
9946          * (in terms of transaction IDs), and where (in terms of log
9947          * block offsets): query the superblock.
9948          */
9949
9950         sb = journal->j_superblock;
9951         next_commit_ID = ntohl(sb->s_sequence);
9952         next_log_block = ntohl(sb->s_start);
9953
9954         first_commit_ID = next_commit_ID;
9955         if (pass == PASS_SCAN)
9956                 info->start_transaction = first_commit_ID;
9957
9958         /*
9959          * Now we walk through the log, transaction by transaction,
9960          * making sure that each transaction has a commit block in the
9961          * expected place.  Each complete transaction gets replayed back
9962          * into the main filesystem.
9963          */
9964
9965         while (1) {
9966                 int                     flags;
9967                 char *                  tagp;
9968                 journal_block_tag_t *   tag;
9969                 struct buffer_head *    obh;
9970                 struct buffer_head *    nbh;
9971
9972                 /* If we already know where to stop the log traversal,
9973                  * check right now that we haven't gone past the end of
9974                  * the log. */
9975
9976                 if (pass != PASS_SCAN)
9977                         if (tid_geq(next_commit_ID, info->end_transaction))
9978                                 break;
9979
9980                 /* Skip over each chunk of the transaction looking
9981                  * either the next descriptor block or the final commit
9982                  * record. */
9983
9984                 err = jread(&bh, journal, next_log_block);
9985                 if (err)
9986                         goto failed;
9987
9988                 next_log_block++;
9989                 wrap(journal, next_log_block);
9990
9991                 /* What kind of buffer is it?
9992                  *
9993                  * If it is a descriptor block, check that it has the
9994                  * expected sequence number.  Otherwise, we're all done
9995                  * here. */
9996
9997                 tmp = (journal_header_t *)bh->b_data;
9998
9999                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10000                         brelse(bh);
10001                         break;
10002                 }
10003
10004                 blocktype = ntohl(tmp->h_blocktype);
10005                 sequence = ntohl(tmp->h_sequence);
10006
10007                 if (sequence != next_commit_ID) {
10008                         brelse(bh);
10009                         break;
10010                 }
10011
10012                 /* OK, we have a valid descriptor block which matches
10013                  * all of the sequence number checks.  What are we going
10014                  * to do with it?  That depends on the pass... */
10015
10016                 switch (blocktype) {
10017                 case JFS_DESCRIPTOR_BLOCK:
10018                         /* If it is a valid descriptor block, replay it
10019                          * in pass REPLAY; otherwise, just skip over the
10020                          * blocks it describes. */
10021                         if (pass != PASS_REPLAY) {
10022                                 next_log_block +=
10023                                         count_tags(bh, journal->j_blocksize);
10024                                 wrap(journal, next_log_block);
10025                                 brelse(bh);
10026                                 continue;
10027                         }
10028
10029                         /* A descriptor block: we can now write all of
10030                          * the data blocks.  Yay, useful work is finally
10031                          * getting done here! */
10032
10033                         tagp = &bh->b_data[sizeof(journal_header_t)];
10034                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10035                                <= journal->j_blocksize) {
10036                                 unsigned long io_block;
10037
10038                                 tag = (journal_block_tag_t *) tagp;
10039                                 flags = ntohl(tag->t_flags);
10040
10041                                 io_block = next_log_block++;
10042                                 wrap(journal, next_log_block);
10043                                 err = jread(&obh, journal, io_block);
10044                                 if (err) {
10045                                         /* Recover what we can, but
10046                                          * report failure at the end. */
10047                                         success = err;
10048                                         printf("JBD: IO error %d recovering "
10049                                                 "block %ld in log\n",
10050                                                 err, io_block);
10051                                 } else {
10052                                         unsigned long blocknr;
10053
10054                                         blocknr = ntohl(tag->t_blocknr);
10055
10056                                         /* If the block has been
10057                                          * revoked, then we're all done
10058                                          * here. */
10059                                         if (journal_test_revoke
10060                                             (journal, blocknr,
10061                                              next_commit_ID)) {
10062                                                 brelse(obh);
10063                                                 ++info->nr_revoke_hits;
10064                                                 goto skip_write;
10065                                         }
10066
10067                                         /* Find a buffer for the new
10068                                          * data being restored */
10069                                         nbh = getblk(journal->j_fs_dev,
10070                                                        blocknr,
10071                                                      journal->j_blocksize);
10072                                         if (nbh == NULL) {
10073                                                 printf("JBD: Out of memory "
10074                                                        "during recovery.\n");
10075                                                 err = -ENOMEM;
10076                                                 brelse(bh);
10077                                                 brelse(obh);
10078                                                 goto failed;
10079                                         }
10080
10081                                         lock_buffer(nbh);
10082                                         memcpy(nbh->b_data, obh->b_data,
10083                                                         journal->j_blocksize);
10084                                         if (flags & JFS_FLAG_ESCAPE) {
10085                                                 *((unsigned int *)bh->b_data) =
10086                                                         htonl(JFS_MAGIC_NUMBER);
10087                                         }
10088
10089                                         mark_buffer_uptodate(nbh, 1);
10090                                         mark_buffer_dirty(nbh);
10091                                         ++info->nr_replays;
10092                                         /* ll_rw_block(WRITE, 1, &nbh); */
10093                                         unlock_buffer(nbh);
10094                                         brelse(obh);
10095                                         brelse(nbh);
10096                                 }
10097
10098                         skip_write:
10099                                 tagp += sizeof(journal_block_tag_t);
10100                                 if (!(flags & JFS_FLAG_SAME_UUID))
10101                                         tagp += 16;
10102
10103                                 if (flags & JFS_FLAG_LAST_TAG)
10104                                         break;
10105                         }
10106
10107                         brelse(bh);
10108                         continue;
10109
10110                 case JFS_COMMIT_BLOCK:
10111                         /* Found an expected commit block: not much to
10112                          * do other than move on to the next sequence
10113                          * number. */
10114                         brelse(bh);
10115                         next_commit_ID++;
10116                         continue;
10117
10118                 case JFS_REVOKE_BLOCK:
10119                         /* If we aren't in the REVOKE pass, then we can
10120                          * just skip over this block. */
10121                         if (pass != PASS_REVOKE) {
10122                                 brelse(bh);
10123                                 continue;
10124                         }
10125
10126                         err = scan_revoke_records(journal, bh,
10127                                                   next_commit_ID, info);
10128                         brelse(bh);
10129                         if (err)
10130                                 goto failed;
10131                         continue;
10132
10133                 default:
10134                         goto done;
10135                 }
10136         }
10137
10138  done:
10139         /*
10140          * We broke out of the log scan loop: either we came to the
10141          * known end of the log or we found an unexpected block in the
10142          * log.  If the latter happened, then we know that the "current"
10143          * transaction marks the end of the valid log.
10144          */
10145
10146         if (pass == PASS_SCAN)
10147                 info->end_transaction = next_commit_ID;
10148         else {
10149                 /* It's really bad news if different passes end up at
10150                  * different places (but possible due to IO errors). */
10151                 if (info->end_transaction != next_commit_ID) {
10152                         printf("JBD: recovery pass %d ended at "
10153                                 "transaction %u, expected %u\n",
10154                                 pass, next_commit_ID, info->end_transaction);
10155                         if (!success)
10156                                 success = -EIO;
10157                 }
10158         }
10159
10160         return success;
10161
10162  failed:
10163         return err;
10164 }
10165
10166
10167 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10168
10169 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10170                                tid_t sequence, struct recovery_info *info)
10171 {
10172         journal_revoke_header_t *header;
10173         int offset, max;
10174
10175         header = (journal_revoke_header_t *) bh->b_data;
10176         offset = sizeof(journal_revoke_header_t);
10177         max = ntohl(header->r_count);
10178
10179         while (offset < max) {
10180                 unsigned long blocknr;
10181                 int err;
10182
10183                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10184                 offset += 4;
10185                 err = journal_set_revoke(journal, blocknr, sequence);
10186                 if (err)
10187                         return err;
10188                 ++info->nr_revokes;
10189         }
10190         return 0;
10191 }
10192
10193
10194 /*
10195  * rehash.c --- rebuild hash tree directories
10196  *
10197  * This algorithm is designed for simplicity of implementation and to
10198  * pack the directory as much as possible.  It however requires twice
10199  * as much memory as the size of the directory.  The maximum size
10200  * directory supported using a 4k blocksize is roughly a gigabyte, and
10201  * so there may very well be problems with machines that don't have
10202  * virtual memory, and obscenely large directories.
10203  *
10204  * An alternate algorithm which is much more disk intensive could be
10205  * written, and probably will need to be written in the future.  The
10206  * design goals of such an algorithm are: (a) use (roughly) constant
10207  * amounts of memory, no matter how large the directory, (b) the
10208  * directory must be safe at all times, even if e2fsck is interrupted
10209  * in the middle, (c) we must use minimal amounts of extra disk
10210  * blocks.  This pretty much requires an incremental approach, where
10211  * we are reading from one part of the directory, and inserting into
10212  * the front half.  So the algorithm will have to keep track of a
10213  * moving block boundary between the new tree and the old tree, and
10214  * files will need to be moved from the old directory and inserted
10215  * into the new tree.  If the new directory requires space which isn't
10216  * yet available, blocks from the beginning part of the old directory
10217  * may need to be moved to the end of the directory to make room for
10218  * the new tree:
10219  *
10220  *    --------------------------------------------------------
10221  *    |  new tree   |        | old tree                      |
10222  *    --------------------------------------------------------
10223  *                  ^ ptr    ^ptr
10224  *                tail new   head old
10225  *
10226  * This is going to be a pain in the tuckus to implement, and will
10227  * require a lot more disk accesses.  So I'm going to skip it for now;
10228  * it's only really going to be an issue for really, really big
10229  * filesystems (when we reach the level of tens of millions of files
10230  * in a single directory).  It will probably be easier to simply
10231  * require that e2fsck use VM first.
10232  */
10233
10234 struct fill_dir_struct {
10235         char *buf;
10236         struct ext2_inode *inode;
10237         int err;
10238         e2fsck_t ctx;
10239         struct hash_entry *harray;
10240         int max_array, num_array;
10241         int dir_size;
10242         int compress;
10243         ino_t parent;
10244 };
10245
10246 struct hash_entry {
10247         ext2_dirhash_t  hash;
10248         ext2_dirhash_t  minor_hash;
10249         struct ext2_dir_entry   *dir;
10250 };
10251
10252 struct out_dir {
10253         int             num;
10254         int             max;
10255         char            *buf;
10256         ext2_dirhash_t  *hashes;
10257 };
10258
10259 static int fill_dir_block(ext2_filsys fs,
10260                           blk_t *block_nr,
10261                           e2_blkcnt_t blockcnt,
10262                           blk_t ref_block FSCK_ATTR((unused)),
10263                           int ref_offset FSCK_ATTR((unused)),
10264                           void *priv_data)
10265 {
10266         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10267         struct hash_entry       *new_array, *ent;
10268         struct ext2_dir_entry   *dirent;
10269         char                    *dir;
10270         unsigned int            offset, dir_offset;
10271
10272         if (blockcnt < 0)
10273                 return 0;
10274
10275         offset = blockcnt * fs->blocksize;
10276         if (offset + fs->blocksize > fd->inode->i_size) {
10277                 fd->err = EXT2_ET_DIR_CORRUPTED;
10278                 return BLOCK_ABORT;
10279         }
10280         dir = (fd->buf+offset);
10281         if (HOLE_BLKADDR(*block_nr)) {
10282                 memset(dir, 0, fs->blocksize);
10283                 dirent = (struct ext2_dir_entry *) dir;
10284                 dirent->rec_len = fs->blocksize;
10285         } else {
10286                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10287                 if (fd->err)
10288                         return BLOCK_ABORT;
10289         }
10290         /* While the directory block is "hot", index it. */
10291         dir_offset = 0;
10292         while (dir_offset < fs->blocksize) {
10293                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10294                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10295                     (dirent->rec_len < 8) ||
10296                     ((dirent->rec_len % 4) != 0) ||
10297                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10298                         fd->err = EXT2_ET_DIR_CORRUPTED;
10299                         return BLOCK_ABORT;
10300                 }
10301                 dir_offset += dirent->rec_len;
10302                 if (dirent->inode == 0)
10303                         continue;
10304                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10305                     (dirent->name[0] == '.'))
10306                         continue;
10307                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10308                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10309                         fd->parent = dirent->inode;
10310                         continue;
10311                 }
10312                 if (fd->num_array >= fd->max_array) {
10313                         new_array = xrealloc(fd->harray,
10314                             sizeof(struct hash_entry) * (fd->max_array+500));
10315                         fd->harray = new_array;
10316                         fd->max_array += 500;
10317                 }
10318                 ent = fd->harray + fd->num_array++;
10319                 ent->dir = dirent;
10320                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10321                 if (fd->compress)
10322                         ent->hash = ent->minor_hash = 0;
10323                 else {
10324                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10325                                                  dirent->name,
10326                                                  dirent->name_len & 0xFF,
10327                                                  fs->super->s_hash_seed,
10328                                                  &ent->hash, &ent->minor_hash);
10329                         if (fd->err)
10330                                 return BLOCK_ABORT;
10331                 }
10332         }
10333
10334         return 0;
10335 }
10336
10337 /* Used for sorting the hash entry */
10338 static int name_cmp(const void *a, const void *b)
10339 {
10340         const struct hash_entry *he_a = (const struct hash_entry *) a;
10341         const struct hash_entry *he_b = (const struct hash_entry *) b;
10342         int     ret;
10343         int     min_len;
10344
10345         min_len = he_a->dir->name_len;
10346         if (min_len > he_b->dir->name_len)
10347                 min_len = he_b->dir->name_len;
10348
10349         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10350         if (ret == 0) {
10351                 if (he_a->dir->name_len > he_b->dir->name_len)
10352                         ret = 1;
10353                 else if (he_a->dir->name_len < he_b->dir->name_len)
10354                         ret = -1;
10355                 else
10356                         ret = he_b->dir->inode - he_a->dir->inode;
10357         }
10358         return ret;
10359 }
10360
10361 /* Used for sorting the hash entry */
10362 static int hash_cmp(const void *a, const void *b)
10363 {
10364         const struct hash_entry *he_a = (const struct hash_entry *) a;
10365         const struct hash_entry *he_b = (const struct hash_entry *) b;
10366         int     ret;
10367
10368         if (he_a->hash > he_b->hash)
10369                 ret = 1;
10370         else if (he_a->hash < he_b->hash)
10371                 ret = -1;
10372         else {
10373                 if (he_a->minor_hash > he_b->minor_hash)
10374                         ret = 1;
10375                 else if (he_a->minor_hash < he_b->minor_hash)
10376                         ret = -1;
10377                 else
10378                         ret = name_cmp(a, b);
10379         }
10380         return ret;
10381 }
10382
10383 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10384                                 int blocks)
10385 {
10386         void                    *new_mem;
10387
10388         if (outdir->max) {
10389                 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10390                 outdir->buf = new_mem;
10391                 new_mem = xrealloc(outdir->hashes,
10392                                   blocks * sizeof(ext2_dirhash_t));
10393                 outdir->hashes = new_mem;
10394         } else {
10395                 outdir->buf = xmalloc(blocks * fs->blocksize);
10396                 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10397                 outdir->num = 0;
10398         }
10399         outdir->max = blocks;
10400         return 0;
10401 }
10402
10403 static void free_out_dir(struct out_dir *outdir)
10404 {
10405         free(outdir->buf);
10406         free(outdir->hashes);
10407         outdir->max = 0;
10408         outdir->num =0;
10409 }
10410
10411 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10412                          char ** ret)
10413 {
10414         errcode_t       retval;
10415
10416         if (outdir->num >= outdir->max) {
10417                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10418                 if (retval)
10419                         return retval;
10420         }
10421         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10422         memset(*ret, 0, fs->blocksize);
10423         return 0;
10424 }
10425
10426 /*
10427  * This function is used to make a unique filename.  We do this by
10428  * appending ~0, and then incrementing the number.  However, we cannot
10429  * expand the length of the filename beyond the padding available in
10430  * the directory entry.
10431  */
10432 static void mutate_name(char *str, __u16 *len)
10433 {
10434         int     i;
10435         __u16   l = *len & 0xFF, h = *len & 0xff00;
10436
10437         /*
10438          * First check to see if it looks the name has been mutated
10439          * already
10440          */
10441         for (i = l-1; i > 0; i--) {
10442                 if (!isdigit(str[i]))
10443                         break;
10444         }
10445         if ((i == l-1) || (str[i] != '~')) {
10446                 if (((l-1) & 3) < 2)
10447                         l += 2;
10448                 else
10449                         l = (l+3) & ~3;
10450                 str[l-2] = '~';
10451                 str[l-1] = '0';
10452                 *len = l | h;
10453                 return;
10454         }
10455         for (i = l-1; i >= 0; i--) {
10456                 if (isdigit(str[i])) {
10457                         if (str[i] == '9')
10458                                 str[i] = '0';
10459                         else {
10460                                 str[i]++;
10461                                 return;
10462                         }
10463                         continue;
10464                 }
10465                 if (i == 1) {
10466                         if (str[0] == 'z')
10467                                 str[0] = 'A';
10468                         else if (str[0] == 'Z') {
10469                                 str[0] = '~';
10470                                 str[1] = '0';
10471                         } else
10472                                 str[0]++;
10473                 } else if (i > 0) {
10474                         str[i] = '1';
10475                         str[i-1] = '~';
10476                 } else {
10477                         if (str[0] == '~')
10478                                 str[0] = 'a';
10479                         else
10480                                 str[0]++;
10481                 }
10482                 break;
10483         }
10484 }
10485
10486 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10487                                     ext2_ino_t ino,
10488                                     struct fill_dir_struct *fd)
10489 {
10490         struct problem_context  pctx;
10491         struct hash_entry       *ent, *prev;
10492         int                     i, j;
10493         int                     fixed = 0;
10494         char                    new_name[256];
10495         __u16                   new_len;
10496
10497         clear_problem_context(&pctx);
10498         pctx.ino = ino;
10499
10500         for (i=1; i < fd->num_array; i++) {
10501                 ent = fd->harray + i;
10502                 prev = ent - 1;
10503                 if (!ent->dir->inode ||
10504                     ((ent->dir->name_len & 0xFF) !=
10505                      (prev->dir->name_len & 0xFF)) ||
10506                     (strncmp(ent->dir->name, prev->dir->name,
10507                              ent->dir->name_len & 0xFF)))
10508                         continue;
10509                 pctx.dirent = ent->dir;
10510                 if ((ent->dir->inode == prev->dir->inode) &&
10511                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10512                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10513                         ent->dir->inode = 0;
10514                         fixed++;
10515                         continue;
10516                 }
10517                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10518                 new_len = ent->dir->name_len;
10519                 mutate_name(new_name, &new_len);
10520                 for (j=0; j < fd->num_array; j++) {
10521                         if ((i==j) ||
10522                             ((ent->dir->name_len & 0xFF) !=
10523                              (fd->harray[j].dir->name_len & 0xFF)) ||
10524                             (strncmp(new_name, fd->harray[j].dir->name,
10525                                      new_len & 0xFF)))
10526                                 continue;
10527                         mutate_name(new_name, &new_len);
10528
10529                         j = -1;
10530                 }
10531                 new_name[new_len & 0xFF] = 0;
10532                 pctx.str = new_name;
10533                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10534                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10535                         ent->dir->name_len = new_len;
10536                         ext2fs_dirhash(fs->super->s_def_hash_version,
10537                                        ent->dir->name,
10538                                        ent->dir->name_len & 0xFF,
10539                                        fs->super->s_hash_seed,
10540                                        &ent->hash, &ent->minor_hash);
10541                         fixed++;
10542                 }
10543         }
10544         return fixed;
10545 }
10546
10547
10548 static errcode_t copy_dir_entries(ext2_filsys fs,
10549                                   struct fill_dir_struct *fd,
10550                                   struct out_dir *outdir)
10551 {
10552         errcode_t               retval;
10553         char                    *block_start;
10554         struct hash_entry       *ent;
10555         struct ext2_dir_entry   *dirent;
10556         int                     i, rec_len, left;
10557         ext2_dirhash_t          prev_hash;
10558         int                     offset;
10559
10560         outdir->max = 0;
10561         retval = alloc_size_dir(fs, outdir,
10562                                 (fd->dir_size / fs->blocksize) + 2);
10563         if (retval)
10564                 return retval;
10565         outdir->num = fd->compress ? 0 : 1;
10566         offset = 0;
10567         outdir->hashes[0] = 0;
10568         prev_hash = 1;
10569         if ((retval = get_next_block(fs, outdir, &block_start)))
10570                 return retval;
10571         dirent = (struct ext2_dir_entry *) block_start;
10572         left = fs->blocksize;
10573         for (i=0; i < fd->num_array; i++) {
10574                 ent = fd->harray + i;
10575                 if (ent->dir->inode == 0)
10576                         continue;
10577                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10578                 if (rec_len > left) {
10579                         if (left)
10580                                 dirent->rec_len += left;
10581                         if ((retval = get_next_block(fs, outdir,
10582                                                       &block_start)))
10583                                 return retval;
10584                         offset = 0;
10585                 }
10586                 left = fs->blocksize - offset;
10587                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10588                 if (offset == 0) {
10589                         if (ent->hash == prev_hash)
10590                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10591                         else
10592                                 outdir->hashes[outdir->num-1] = ent->hash;
10593                 }
10594                 dirent->inode = ent->dir->inode;
10595                 dirent->name_len = ent->dir->name_len;
10596                 dirent->rec_len = rec_len;
10597                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10598                 offset += rec_len;
10599                 left -= rec_len;
10600                 if (left < 12) {
10601                         dirent->rec_len += left;
10602                         offset += left;
10603                         left = 0;
10604                 }
10605                 prev_hash = ent->hash;
10606         }
10607         if (left)
10608                 dirent->rec_len += left;
10609
10610         return 0;
10611 }
10612
10613
10614 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10615                                     ext2_ino_t ino, ext2_ino_t parent)
10616 {
10617         struct ext2_dir_entry           *dir;
10618         struct ext2_dx_root_info        *root;
10619         struct ext2_dx_countlimit       *limits;
10620         int                             filetype = 0;
10621
10622         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10623                 filetype = EXT2_FT_DIR << 8;
10624
10625         memset(buf, 0, fs->blocksize);
10626         dir = (struct ext2_dir_entry *) buf;
10627         dir->inode = ino;
10628         dir->name[0] = '.';
10629         dir->name_len = 1 | filetype;
10630         dir->rec_len = 12;
10631         dir = (struct ext2_dir_entry *) (buf + 12);
10632         dir->inode = parent;
10633         dir->name[0] = '.';
10634         dir->name[1] = '.';
10635         dir->name_len = 2 | filetype;
10636         dir->rec_len = fs->blocksize - 12;
10637
10638         root = (struct ext2_dx_root_info *) (buf+24);
10639         root->reserved_zero = 0;
10640         root->hash_version = fs->super->s_def_hash_version;
10641         root->info_length = 8;
10642         root->indirect_levels = 0;
10643         root->unused_flags = 0;
10644
10645         limits = (struct ext2_dx_countlimit *) (buf+32);
10646         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10647         limits->count = 0;
10648
10649         return root;
10650 }
10651
10652
10653 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10654 {
10655         struct ext2_dir_entry           *dir;
10656         struct ext2_dx_countlimit       *limits;
10657
10658         memset(buf, 0, fs->blocksize);
10659         dir = (struct ext2_dir_entry *) buf;
10660         dir->inode = 0;
10661         dir->rec_len = fs->blocksize;
10662
10663         limits = (struct ext2_dx_countlimit *) (buf+8);
10664         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10665         limits->count = 0;
10666
10667         return (struct ext2_dx_entry *) limits;
10668 }
10669
10670 /*
10671  * This function takes the leaf nodes which have been written in
10672  * outdir, and populates the root node and any necessary interior nodes.
10673  */
10674 static errcode_t calculate_tree(ext2_filsys fs,
10675                                 struct out_dir *outdir,
10676                                 ext2_ino_t ino,
10677                                 ext2_ino_t parent)
10678 {
10679         struct ext2_dx_root_info        *root_info;
10680         struct ext2_dx_entry            *root, *dx_ent = NULL;
10681         struct ext2_dx_countlimit       *root_limit, *limit;
10682         errcode_t                       retval;
10683         char                            * block_start;
10684         int                             i, c1, c2, nblks;
10685         int                             limit_offset, root_offset;
10686
10687         root_info = set_root_node(fs, outdir->buf, ino, parent);
10688         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10689                 root_info->info_length;
10690         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10691         c1 = root_limit->limit;
10692         nblks = outdir->num;
10693
10694         /* Write out the pointer blocks */
10695         if (nblks-1 <= c1) {
10696                 /* Just write out the root block, and we're done */
10697                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10698                 for (i=1; i < nblks; i++) {
10699                         root->block = ext2fs_cpu_to_le32(i);
10700                         if (i != 1)
10701                                 root->hash =
10702                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10703                         root++;
10704                         c1--;
10705                 }
10706         } else {
10707                 c2 = 0;
10708                 limit = 0;
10709                 root_info->indirect_levels = 1;
10710                 for (i=1; i < nblks; i++) {
10711                         if (c1 == 0)
10712                                 return ENOSPC;
10713                         if (c2 == 0) {
10714                                 if (limit)
10715                                         limit->limit = limit->count =
10716                 ext2fs_cpu_to_le16(limit->limit);
10717                                 root = (struct ext2_dx_entry *)
10718                                         (outdir->buf + root_offset);
10719                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10720                                 if (i != 1)
10721                                         root->hash =
10722                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10723                                 if ((retval =  get_next_block(fs, outdir,
10724                                                               &block_start)))
10725                                         return retval;
10726                                 dx_ent = set_int_node(fs, block_start);
10727                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10728                                 c2 = limit->limit;
10729                                 root_offset += sizeof(struct ext2_dx_entry);
10730                                 c1--;
10731                         }
10732                         dx_ent->block = ext2fs_cpu_to_le32(i);
10733                         if (c2 != limit->limit)
10734                                 dx_ent->hash =
10735                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10736                         dx_ent++;
10737                         c2--;
10738                 }
10739                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10740                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10741         }
10742         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10743         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10744         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10745
10746         return 0;
10747 }
10748
10749 struct write_dir_struct {
10750         struct out_dir *outdir;
10751         errcode_t       err;
10752         e2fsck_t        ctx;
10753         int             cleared;
10754 };
10755
10756 /*
10757  * Helper function which writes out a directory block.
10758  */
10759 static int write_dir_block(ext2_filsys fs,
10760                            blk_t        *block_nr,
10761                            e2_blkcnt_t blockcnt,
10762                            blk_t ref_block FSCK_ATTR((unused)),
10763                            int ref_offset FSCK_ATTR((unused)),
10764                            void *priv_data)
10765 {
10766         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10767         blk_t   blk;
10768         char    *dir;
10769
10770         if (*block_nr == 0)
10771                 return 0;
10772         if (blockcnt >= wd->outdir->num) {
10773                 e2fsck_read_bitmaps(wd->ctx);
10774                 blk = *block_nr;
10775                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10776                 ext2fs_block_alloc_stats(fs, blk, -1);
10777                 *block_nr = 0;
10778                 wd->cleared++;
10779                 return BLOCK_CHANGED;
10780         }
10781         if (blockcnt < 0)
10782                 return 0;
10783
10784         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10785         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10786         if (wd->err)
10787                 return BLOCK_ABORT;
10788         return 0;
10789 }
10790
10791 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10792                                  struct out_dir *outdir,
10793                                  ext2_ino_t ino, int compress)
10794 {
10795         struct write_dir_struct wd;
10796         errcode_t       retval;
10797         struct ext2_inode       inode;
10798
10799         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10800         if (retval)
10801                 return retval;
10802
10803         wd.outdir = outdir;
10804         wd.err = 0;
10805         wd.ctx = ctx;
10806         wd.cleared = 0;
10807
10808         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10809                                        write_dir_block, &wd);
10810         if (retval)
10811                 return retval;
10812         if (wd.err)
10813                 return wd.err;
10814
10815         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10816         if (compress)
10817                 inode.i_flags &= ~EXT2_INDEX_FL;
10818         else
10819                 inode.i_flags |= EXT2_INDEX_FL;
10820         inode.i_size = outdir->num * fs->blocksize;
10821         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10822         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10823
10824         return 0;
10825 }
10826
10827 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10828 {
10829         ext2_filsys             fs = ctx->fs;
10830         errcode_t               retval;
10831         struct ext2_inode       inode;
10832         char                    *dir_buf = NULL;
10833         struct fill_dir_struct  fd;
10834         struct out_dir          outdir;
10835
10836         outdir.max = outdir.num = 0;
10837         outdir.buf = 0;
10838         outdir.hashes = 0;
10839         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10840
10841         retval = ENOMEM;
10842         fd.harray = 0;
10843         dir_buf = xmalloc(inode.i_size);
10844
10845         fd.max_array = inode.i_size / 32;
10846         fd.num_array = 0;
10847         fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10848
10849         fd.ctx = ctx;
10850         fd.buf = dir_buf;
10851         fd.inode = &inode;
10852         fd.err = 0;
10853         fd.dir_size = 0;
10854         fd.compress = 0;
10855         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10856             (inode.i_size / fs->blocksize) < 2)
10857                 fd.compress = 1;
10858         fd.parent = 0;
10859
10860         /* Read in the entire directory into memory */
10861         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10862                                        fill_dir_block, &fd);
10863         if (fd.err) {
10864                 retval = fd.err;
10865                 goto errout;
10866         }
10867
10868         /* Sort the list */
10869 resort:
10870         if (fd.compress)
10871                 qsort(fd.harray+2, fd.num_array-2,
10872                       sizeof(struct hash_entry), name_cmp);
10873         else
10874                 qsort(fd.harray, fd.num_array,
10875                       sizeof(struct hash_entry), hash_cmp);
10876
10877         /*
10878          * Look for duplicates
10879          */
10880         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10881                 goto resort;
10882
10883         if (ctx->options & E2F_OPT_NO) {
10884                 retval = 0;
10885                 goto errout;
10886         }
10887
10888         /*
10889          * Copy the directory entries.  In a htree directory these
10890          * will become the leaf nodes.
10891          */
10892         retval = copy_dir_entries(fs, &fd, &outdir);
10893         if (retval)
10894                 goto errout;
10895
10896         free(dir_buf); dir_buf = 0;
10897
10898         if (!fd.compress) {
10899                 /* Calculate the interior nodes */
10900                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10901                 if (retval)
10902                         goto errout;
10903         }
10904
10905         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10906
10907 errout:
10908         free(dir_buf);
10909         free(fd.harray);
10910
10911         free_out_dir(&outdir);
10912         return retval;
10913 }
10914
10915 void e2fsck_rehash_directories(e2fsck_t ctx)
10916 {
10917         struct problem_context  pctx;
10918         struct dir_info         *dir;
10919         ext2_u32_iterate        iter;
10920         ext2_ino_t              ino;
10921         errcode_t               retval;
10922         int                     i, cur, max, all_dirs, dir_index, first = 1;
10923
10924         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10925
10926         if (!ctx->dirs_to_hash && !all_dirs)
10927                 return;
10928
10929         e2fsck_get_lost_and_found(ctx, 0);
10930
10931         clear_problem_context(&pctx);
10932
10933         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10934         cur = 0;
10935         if (all_dirs) {
10936                 i = 0;
10937                 max = e2fsck_get_num_dirinfo(ctx);
10938         } else {
10939                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10940                                                        &iter);
10941                 if (retval) {
10942                         pctx.errcode = retval;
10943                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10944                         return;
10945                 }
10946                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10947         }
10948         while (1) {
10949                 if (all_dirs) {
10950                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10951                                 break;
10952                         ino = dir->ino;
10953                 } else {
10954                         if (!ext2fs_u32_list_iterate(iter, &ino))
10955                                 break;
10956                 }
10957                 if (ino == ctx->lost_and_found)
10958                         continue;
10959                 pctx.dir = ino;
10960                 if (first) {
10961                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10962                         first = 0;
10963                 }
10964                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10965                 if (pctx.errcode) {
10966                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10967                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10968                 }
10969                 if (ctx->progress && !ctx->progress_fd)
10970                         e2fsck_simple_progress(ctx, "Rebuilding directory",
10971                                100.0 * (float) (++cur) / (float) max, ino);
10972         }
10973         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10974         if (!all_dirs)
10975                 ext2fs_u32_list_iterate_end(iter);
10976
10977         ext2fs_u32_list_free(ctx->dirs_to_hash);
10978         ctx->dirs_to_hash = 0;
10979 }
10980
10981 /*
10982  * linux/fs/revoke.c
10983  *
10984  * Journal revoke routines for the generic filesystem journaling code;
10985  * part of the ext2fs journaling system.
10986  *
10987  * Revoke is the mechanism used to prevent old log records for deleted
10988  * metadata from being replayed on top of newer data using the same
10989  * blocks.  The revoke mechanism is used in two separate places:
10990  *
10991  * + Commit: during commit we write the entire list of the current
10992  *   transaction's revoked blocks to the journal
10993  *
10994  * + Recovery: during recovery we record the transaction ID of all
10995  *   revoked blocks.  If there are multiple revoke records in the log
10996  *   for a single block, only the last one counts, and if there is a log
10997  *   entry for a block beyond the last revoke, then that log entry still
10998  *   gets replayed.
10999  *
11000  * We can get interactions between revokes and new log data within a
11001  * single transaction:
11002  *
11003  * Block is revoked and then journaled:
11004  *   The desired end result is the journaling of the new block, so we
11005  *   cancel the revoke before the transaction commits.
11006  *
11007  * Block is journaled and then revoked:
11008  *   The revoke must take precedence over the write of the block, so we
11009  *   need either to cancel the journal entry or to write the revoke
11010  *   later in the log than the log block.  In this case, we choose the
11011  *   latter: journaling a block cancels any revoke record for that block
11012  *   in the current transaction, so any revoke for that block in the
11013  *   transaction must have happened after the block was journaled and so
11014  *   the revoke must take precedence.
11015  *
11016  * Block is revoked and then written as data:
11017  *   The data write is allowed to succeed, but the revoke is _not_
11018  *   cancelled.  We still need to prevent old log records from
11019  *   overwriting the new data.  We don't even need to clear the revoke
11020  *   bit here.
11021  *
11022  * Revoke information on buffers is a tri-state value:
11023  *
11024  * RevokeValid clear:   no cached revoke status, need to look it up
11025  * RevokeValid set, Revoked clear:
11026  *                      buffer has not been revoked, and cancel_revoke
11027  *                      need do nothing.
11028  * RevokeValid set, Revoked set:
11029  *                      buffer has been revoked.
11030  */
11031
11032 static kmem_cache_t *revoke_record_cache;
11033 static kmem_cache_t *revoke_table_cache;
11034
11035 /* Each revoke record represents one single revoked block.  During
11036    journal replay, this involves recording the transaction ID of the
11037    last transaction to revoke this block. */
11038
11039 struct jbd_revoke_record_s
11040 {
11041         struct list_head  hash;
11042         tid_t             sequence;     /* Used for recovery only */
11043         unsigned long     blocknr;
11044 };
11045
11046
11047 /* The revoke table is just a simple hash table of revoke records. */
11048 struct jbd_revoke_table_s
11049 {
11050         /* It is conceivable that we might want a larger hash table
11051          * for recovery.  Must be a power of two. */
11052         int               hash_size;
11053         int               hash_shift;
11054         struct list_head *hash_table;
11055 };
11056
11057
11058 /* Utility functions to maintain the revoke table */
11059
11060 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11061 static int hash(journal_t *journal, unsigned long block)
11062 {
11063         struct jbd_revoke_table_s *table = journal->j_revoke;
11064         int hash_shift = table->hash_shift;
11065
11066         return ((block << (hash_shift - 6)) ^
11067                 (block >> 13) ^
11068                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11069 }
11070
11071 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11072                               tid_t seq)
11073 {
11074         struct list_head *hash_list;
11075         struct jbd_revoke_record_s *record;
11076
11077         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11078         if (!record)
11079                 goto oom;
11080
11081         record->sequence = seq;
11082         record->blocknr = blocknr;
11083         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11084         list_add(&record->hash, hash_list);
11085         return 0;
11086
11087 oom:
11088         return -ENOMEM;
11089 }
11090
11091 /* Find a revoke record in the journal's hash table. */
11092
11093 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11094                                                       unsigned long blocknr)
11095 {
11096         struct list_head *hash_list;
11097         struct jbd_revoke_record_s *record;
11098
11099         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11100
11101         record = (struct jbd_revoke_record_s *) hash_list->next;
11102         while (&(record->hash) != hash_list) {
11103                 if (record->blocknr == blocknr)
11104                         return record;
11105                 record = (struct jbd_revoke_record_s *) record->hash.next;
11106         }
11107         return NULL;
11108 }
11109
11110 int journal_init_revoke_caches(void)
11111 {
11112         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11113         if (revoke_record_cache == 0)
11114                 return -ENOMEM;
11115
11116         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11117         if (revoke_table_cache == 0) {
11118                 do_cache_destroy(revoke_record_cache);
11119                 revoke_record_cache = NULL;
11120                 return -ENOMEM;
11121         }
11122         return 0;
11123 }
11124
11125 void journal_destroy_revoke_caches(void)
11126 {
11127         do_cache_destroy(revoke_record_cache);
11128         revoke_record_cache = 0;
11129         do_cache_destroy(revoke_table_cache);
11130         revoke_table_cache = 0;
11131 }
11132
11133 /* Initialise the revoke table for a given journal to a given size. */
11134
11135 int journal_init_revoke(journal_t *journal, int hash_size)
11136 {
11137         int shift, tmp;
11138
11139         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11140         if (!journal->j_revoke)
11141                 return -ENOMEM;
11142
11143         /* Check that the hash_size is a power of two */
11144         journal->j_revoke->hash_size = hash_size;
11145
11146         shift = 0;
11147         tmp = hash_size;
11148         while ((tmp >>= 1UL) != 0UL)
11149                 shift++;
11150         journal->j_revoke->hash_shift = shift;
11151
11152         journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11153
11154         for (tmp = 0; tmp < hash_size; tmp++)
11155                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11156
11157         return 0;
11158 }
11159
11160 /* Destoy a journal's revoke table.  The table must already be empty! */
11161
11162 void journal_destroy_revoke(journal_t *journal)
11163 {
11164         struct jbd_revoke_table_s *table;
11165         struct list_head *hash_list;
11166         int i;
11167
11168         table = journal->j_revoke;
11169         if (!table)
11170                 return;
11171
11172         for (i=0; i<table->hash_size; i++) {
11173                 hash_list = &table->hash_table[i];
11174         }
11175
11176         free(table->hash_table);
11177         free(table);
11178         journal->j_revoke = NULL;
11179 }
11180
11181 /*
11182  * Revoke support for recovery.
11183  *
11184  * Recovery needs to be able to:
11185  *
11186  *  record all revoke records, including the tid of the latest instance
11187  *  of each revoke in the journal
11188  *
11189  *  check whether a given block in a given transaction should be replayed
11190  *  (ie. has not been revoked by a revoke record in that or a subsequent
11191  *  transaction)
11192  *
11193  *  empty the revoke table after recovery.
11194  */
11195
11196 /*
11197  * First, setting revoke records.  We create a new revoke record for
11198  * every block ever revoked in the log as we scan it for recovery, and
11199  * we update the existing records if we find multiple revokes for a
11200  * single block.
11201  */
11202
11203 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11204                        tid_t sequence)
11205 {
11206         struct jbd_revoke_record_s *record;
11207
11208         record = find_revoke_record(journal, blocknr);
11209         if (record) {
11210                 /* If we have multiple occurences, only record the
11211                  * latest sequence number in the hashed record */
11212                 if (tid_gt(sequence, record->sequence))
11213                         record->sequence = sequence;
11214                 return 0;
11215         }
11216         return insert_revoke_hash(journal, blocknr, sequence);
11217 }
11218
11219 /*
11220  * Test revoke records.  For a given block referenced in the log, has
11221  * that block been revoked?  A revoke record with a given transaction
11222  * sequence number revokes all blocks in that transaction and earlier
11223  * ones, but later transactions still need replayed.
11224  */
11225
11226 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11227                         tid_t sequence)
11228 {
11229         struct jbd_revoke_record_s *record;
11230
11231         record = find_revoke_record(journal, blocknr);
11232         if (!record)
11233                 return 0;
11234         if (tid_gt(sequence, record->sequence))
11235                 return 0;
11236         return 1;
11237 }
11238
11239 /*
11240  * Finally, once recovery is over, we need to clear the revoke table so
11241  * that it can be reused by the running filesystem.
11242  */
11243
11244 void journal_clear_revoke(journal_t *journal)
11245 {
11246         int i;
11247         struct list_head *hash_list;
11248         struct jbd_revoke_record_s *record;
11249         struct jbd_revoke_table_s *revoke_var;
11250
11251         revoke_var = journal->j_revoke;
11252
11253         for (i = 0; i < revoke_var->hash_size; i++) {
11254                 hash_list = &revoke_var->hash_table[i];
11255                 while (!list_empty(hash_list)) {
11256                         record = (struct jbd_revoke_record_s*) hash_list->next;
11257                         list_del(&record->hash);
11258                         free(record);
11259                 }
11260         }
11261 }
11262
11263 /*
11264  * e2fsck.c - superblock checks
11265  */
11266
11267 #define MIN_CHECK 1
11268 #define MAX_CHECK 2
11269
11270 static void check_super_value(e2fsck_t ctx, const char *descr,
11271                               unsigned long value, int flags,
11272                               unsigned long min_val, unsigned long max_val)
11273 {
11274         struct          problem_context pctx;
11275
11276         if (((flags & MIN_CHECK) && (value < min_val)) ||
11277             ((flags & MAX_CHECK) && (value > max_val))) {
11278                 clear_problem_context(&pctx);
11279                 pctx.num = value;
11280                 pctx.str = descr;
11281                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11282                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11283         }
11284 }
11285
11286 /*
11287  * This routine may get stubbed out in special compilations of the
11288  * e2fsck code..
11289  */
11290 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11291 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11292 {
11293         return (ext2fs_get_device_size(ctx->filesystem_name,
11294                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11295                                        &ctx->num_blocks));
11296 }
11297 #endif
11298
11299 /*
11300  * helper function to release an inode
11301  */
11302 struct process_block_struct {
11303         e2fsck_t        ctx;
11304         char            *buf;
11305         struct problem_context *pctx;
11306         int             truncating;
11307         int             truncate_offset;
11308         e2_blkcnt_t     truncate_block;
11309         int             truncated_blocks;
11310         int             abort;
11311         errcode_t       errcode;
11312 };
11313
11314 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11315                                e2_blkcnt_t blockcnt,
11316                                blk_t    ref_blk FSCK_ATTR((unused)),
11317                                int      ref_offset FSCK_ATTR((unused)),
11318                                void *priv_data)
11319 {
11320         struct process_block_struct *pb;
11321         e2fsck_t                ctx;
11322         struct problem_context  *pctx;
11323         blk_t                   blk = *block_nr;
11324         int                     retval = 0;
11325
11326         pb = (struct process_block_struct *) priv_data;
11327         ctx = pb->ctx;
11328         pctx = pb->pctx;
11329
11330         pctx->blk = blk;
11331         pctx->blkcount = blockcnt;
11332
11333         if (HOLE_BLKADDR(blk))
11334                 return 0;
11335
11336         if ((blk < fs->super->s_first_data_block) ||
11337             (blk >= fs->super->s_blocks_count)) {
11338                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11339  return_abort:
11340                 pb->abort = 1;
11341                 return BLOCK_ABORT;
11342         }
11343
11344         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11345                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11346                 goto return_abort;
11347         }
11348
11349         /*
11350          * If we are deleting an orphan, then we leave the fields alone.
11351          * If we are truncating an orphan, then update the inode fields
11352          * and clean up any partial block data.
11353          */
11354         if (pb->truncating) {
11355                 /*
11356                  * We only remove indirect blocks if they are
11357                  * completely empty.
11358                  */
11359                 if (blockcnt < 0) {
11360                         int     i, limit;
11361                         blk_t   *bp;
11362
11363                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11364                                                         pb->buf);
11365                         if (pb->errcode)
11366                                 goto return_abort;
11367
11368                         limit = fs->blocksize >> 2;
11369                         for (i = 0, bp = (blk_t *) pb->buf;
11370                              i < limit;  i++, bp++)
11371                                 if (*bp)
11372                                         return 0;
11373                 }
11374                 /*
11375                  * We don't remove direct blocks until we've reached
11376                  * the truncation block.
11377                  */
11378                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11379                         return 0;
11380                 /*
11381                  * If part of the last block needs truncating, we do
11382                  * it here.
11383                  */
11384                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11385                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11386                                                         pb->buf);
11387                         if (pb->errcode)
11388                                 goto return_abort;
11389                         memset(pb->buf + pb->truncate_offset, 0,
11390                                fs->blocksize - pb->truncate_offset);
11391                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11392                                                          pb->buf);
11393                         if (pb->errcode)
11394                                 goto return_abort;
11395                 }
11396                 pb->truncated_blocks++;
11397                 *block_nr = 0;
11398                 retval |= BLOCK_CHANGED;
11399         }
11400
11401         ext2fs_block_alloc_stats(fs, blk, -1);
11402         return retval;
11403 }
11404
11405 /*
11406  * This function releases an inode.  Returns 1 if an inconsistency was
11407  * found.  If the inode has a link count, then it is being truncated and
11408  * not deleted.
11409  */
11410 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11411                                 struct ext2_inode *inode, char *block_buf,
11412                                 struct problem_context *pctx)
11413 {
11414         struct process_block_struct     pb;
11415         ext2_filsys                     fs = ctx->fs;
11416         errcode_t                       retval;
11417         __u32                           count;
11418
11419         if (!ext2fs_inode_has_valid_blocks(inode))
11420                 return 0;
11421
11422         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11423         pb.ctx = ctx;
11424         pb.abort = 0;
11425         pb.errcode = 0;
11426         pb.pctx = pctx;
11427         if (inode->i_links_count) {
11428                 pb.truncating = 1;
11429                 pb.truncate_block = (e2_blkcnt_t)
11430                         ((((long long)inode->i_size_high << 32) +
11431                           inode->i_size + fs->blocksize - 1) /
11432                          fs->blocksize);
11433                 pb.truncate_offset = inode->i_size % fs->blocksize;
11434         } else {
11435                 pb.truncating = 0;
11436                 pb.truncate_block = 0;
11437                 pb.truncate_offset = 0;
11438         }
11439         pb.truncated_blocks = 0;
11440         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11441                                       block_buf, release_inode_block, &pb);
11442         if (retval) {
11443                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11444                         ino);
11445                 return 1;
11446         }
11447         if (pb.abort)
11448                 return 1;
11449
11450         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11451         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11452
11453         if (pb.truncated_blocks)
11454                 inode->i_blocks -= pb.truncated_blocks *
11455                         (fs->blocksize / 512);
11456
11457         if (inode->i_file_acl) {
11458                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11459                                                    block_buf, -1, &count);
11460                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11461                         retval = 0;
11462                         count = 1;
11463                 }
11464                 if (retval) {
11465                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11466                                 ino);
11467                         return 1;
11468                 }
11469                 if (count == 0)
11470                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11471                 inode->i_file_acl = 0;
11472         }
11473         return 0;
11474 }
11475
11476 /*
11477  * This function releases all of the orphan inodes.  It returns 1 if
11478  * it hit some error, and 0 on success.
11479  */
11480 static int release_orphan_inodes(e2fsck_t ctx)
11481 {
11482         ext2_filsys fs = ctx->fs;
11483         ext2_ino_t      ino, next_ino;
11484         struct ext2_inode inode;
11485         struct problem_context pctx;
11486         char *block_buf;
11487
11488         if ((ino = fs->super->s_last_orphan) == 0)
11489                 return 0;
11490
11491         /*
11492          * Win or lose, we won't be using the head of the orphan inode
11493          * list again.
11494          */
11495         fs->super->s_last_orphan = 0;
11496         ext2fs_mark_super_dirty(fs);
11497
11498         /*
11499          * If the filesystem contains errors, don't run the orphan
11500          * list, since the orphan list can't be trusted; and we're
11501          * going to be running a full e2fsck run anyway...
11502          */
11503         if (fs->super->s_state & EXT2_ERROR_FS)
11504                 return 0;
11505
11506         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11507             (ino > fs->super->s_inodes_count)) {
11508                 clear_problem_context(&pctx);
11509                 pctx.ino = ino;
11510                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11511                 return 1;
11512         }
11513
11514         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11515                                                     "block iterate buffer");
11516         e2fsck_read_bitmaps(ctx);
11517
11518         while (ino) {
11519                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11520                 clear_problem_context(&pctx);
11521                 pctx.ino = ino;
11522                 pctx.inode = &inode;
11523                 pctx.str = inode.i_links_count ? _("Truncating") :
11524                         _("Clearing");
11525
11526                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11527
11528                 next_ino = inode.i_dtime;
11529                 if (next_ino &&
11530                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11531                      (next_ino > fs->super->s_inodes_count))) {
11532                         pctx.ino = next_ino;
11533                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11534                         goto return_abort;
11535                 }
11536
11537                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11538                         goto return_abort;
11539
11540                 if (!inode.i_links_count) {
11541                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11542                                                   LINUX_S_ISDIR(inode.i_mode));
11543                         inode.i_dtime = time(NULL);
11544                 } else {
11545                         inode.i_dtime = 0;
11546                 }
11547                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11548                 ino = next_ino;
11549         }
11550         ext2fs_free_mem(&block_buf);
11551         return 0;
11552  return_abort:
11553         ext2fs_free_mem(&block_buf);
11554         return 1;
11555 }
11556
11557 /*
11558  * Check the resize inode to make sure it is sane.  We check both for
11559  * the case where on-line resizing is not enabled (in which case the
11560  * resize inode should be cleared) as well as the case where on-line
11561  * resizing is enabled.
11562  */
11563 static void check_resize_inode(e2fsck_t ctx)
11564 {
11565         ext2_filsys fs = ctx->fs;
11566         struct ext2_inode inode;
11567         struct problem_context  pctx;
11568         int             i, j, gdt_off, ind_off;
11569         blk_t           blk, pblk, expect;
11570         __u32           *dind_buf = NULL, *ind_buf;
11571         errcode_t       retval;
11572
11573         clear_problem_context(&pctx);
11574
11575         /*
11576          * If the resize inode feature isn't set, then
11577          * s_reserved_gdt_blocks must be zero.
11578          */
11579         if (!(fs->super->s_feature_compat &
11580               EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11581                 if (fs->super->s_reserved_gdt_blocks) {
11582                         pctx.num = fs->super->s_reserved_gdt_blocks;
11583                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11584                                         &pctx)) {
11585                                 fs->super->s_reserved_gdt_blocks = 0;
11586                                 ext2fs_mark_super_dirty(fs);
11587                         }
11588                 }
11589         }
11590
11591         /* Read the resize inode */
11592         pctx.ino = EXT2_RESIZE_INO;
11593         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11594         if (retval) {
11595                 if (fs->super->s_feature_compat &
11596                     EXT2_FEATURE_COMPAT_RESIZE_INO)
11597                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11598                 return;
11599         }
11600
11601         /*
11602          * If the resize inode feature isn't set, check to make sure
11603          * the resize inode is cleared; then we're done.
11604          */
11605         if (!(fs->super->s_feature_compat &
11606               EXT2_FEATURE_COMPAT_RESIZE_INO)) {
11607                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11608                         if (inode.i_block[i])
11609                                 break;
11610                 }
11611                 if ((i < EXT2_N_BLOCKS) &&
11612                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11613                         memset(&inode, 0, sizeof(inode));
11614                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11615                                            "clear_resize");
11616                 }
11617                 return;
11618         }
11619
11620         /*
11621          * The resize inode feature is enabled; check to make sure the
11622          * only block in use is the double indirect block
11623          */
11624         blk = inode.i_block[EXT2_DIND_BLOCK];
11625         for (i=0; i < EXT2_N_BLOCKS; i++) {
11626                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11627                         break;
11628         }
11629         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11630             !(inode.i_mode & LINUX_S_IFREG) ||
11631             (blk < fs->super->s_first_data_block ||
11632              blk >= fs->super->s_blocks_count)) {
11633  resize_inode_invalid:
11634                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11635                         memset(&inode, 0, sizeof(inode));
11636                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11637                                            "clear_resize");
11638                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11639                 }
11640                 if (!(ctx->options & E2F_OPT_READONLY)) {
11641                         fs->super->s_state &= ~EXT2_VALID_FS;
11642                         ext2fs_mark_super_dirty(fs);
11643                 }
11644                 goto cleanup;
11645         }
11646         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11647                                                     "resize dind buffer");
11648         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11649
11650         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11651         if (retval)
11652                 goto resize_inode_invalid;
11653
11654         gdt_off = fs->desc_blocks;
11655         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11656         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11657              i++, gdt_off++, pblk++) {
11658                 gdt_off %= fs->blocksize/4;
11659                 if (dind_buf[gdt_off] != pblk)
11660                         goto resize_inode_invalid;
11661                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11662                 if (retval)
11663                         goto resize_inode_invalid;
11664                 ind_off = 0;
11665                 for (j = 1; j < fs->group_desc_count; j++) {
11666                         if (!ext2fs_bg_has_super(fs, j))
11667                                 continue;
11668                         expect = pblk + (j * fs->super->s_blocks_per_group);
11669                         if (ind_buf[ind_off] != expect)
11670                                 goto resize_inode_invalid;
11671                         ind_off++;
11672                 }
11673         }
11674
11675  cleanup:
11676         ext2fs_free_mem(&dind_buf);
11677 }
11678
11679 static void check_super_block(e2fsck_t ctx)
11680 {
11681         ext2_filsys fs = ctx->fs;
11682         blk_t   first_block, last_block;
11683         struct ext2_super_block *sb = fs->super;
11684         struct ext2_group_desc *gd;
11685         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11686         blk_t   bpg_max;
11687         int     inodes_per_block;
11688         int     ipg_max;
11689         int     inode_size;
11690         dgrp_t  i;
11691         blk_t   should_be;
11692         struct problem_context  pctx;
11693         __u32   free_blocks = 0, free_inodes = 0;
11694
11695         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11696         ipg_max = inodes_per_block * (blocks_per_group - 4);
11697         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11698                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11699         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11700         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11701                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11702
11703         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11704                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11705         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11706                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11707         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11708                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11709
11710         clear_problem_context(&pctx);
11711
11712         /*
11713          * Verify the super block constants...
11714          */
11715         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11716                           MIN_CHECK, 1, 0);
11717         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11718                           MIN_CHECK, 1, 0);
11719         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11720                           MAX_CHECK, 0, sb->s_blocks_count);
11721         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11722                           MIN_CHECK | MAX_CHECK, 0,
11723                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11724         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11725                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11726         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11727                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11728                           bpg_max);
11729         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11730                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11731         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11732                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11733         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11734                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11735         check_super_value(ctx, "reserved_gdt_blocks",
11736                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11737                           fs->blocksize/4);
11738         inode_size = EXT2_INODE_SIZE(sb);
11739         check_super_value(ctx, "inode_size",
11740                           inode_size, MIN_CHECK | MAX_CHECK,
11741                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11742         if (inode_size & (inode_size - 1)) {
11743                 pctx.num = inode_size;
11744                 pctx.str = "inode_size";
11745                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11746                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11747                 return;
11748         }
11749
11750         if (!ctx->num_blocks) {
11751                 pctx.errcode = e2fsck_get_device_size(ctx);
11752                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11753                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11754                         ctx->flags |= E2F_FLAG_ABORT;
11755                         return;
11756                 }
11757                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11758                     (ctx->num_blocks < sb->s_blocks_count)) {
11759                         pctx.blk = sb->s_blocks_count;
11760                         pctx.blk2 = ctx->num_blocks;
11761                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11762                                 ctx->flags |= E2F_FLAG_ABORT;
11763                                 return;
11764                         }
11765                 }
11766         }
11767
11768         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11769                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11770                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11771                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11772                 ctx->flags |= E2F_FLAG_ABORT;
11773                 return;
11774         }
11775
11776         should_be = sb->s_frags_per_group >>
11777                 (sb->s_log_block_size - sb->s_log_frag_size);
11778         if (sb->s_blocks_per_group != should_be) {
11779                 pctx.blk = sb->s_blocks_per_group;
11780                 pctx.blk2 = should_be;
11781                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11782                 ctx->flags |= E2F_FLAG_ABORT;
11783                 return;
11784         }
11785
11786         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11787         if (sb->s_first_data_block != should_be) {
11788                 pctx.blk = sb->s_first_data_block;
11789                 pctx.blk2 = should_be;
11790                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11791                 ctx->flags |= E2F_FLAG_ABORT;
11792                 return;
11793         }
11794
11795         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11796         if (sb->s_inodes_count != should_be) {
11797                 pctx.ino = sb->s_inodes_count;
11798                 pctx.ino2 = should_be;
11799                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11800                         sb->s_inodes_count = should_be;
11801                         ext2fs_mark_super_dirty(fs);
11802                 }
11803         }
11804
11805         /*
11806          * Verify the group descriptors....
11807          */
11808         first_block =  sb->s_first_data_block;
11809         last_block = first_block + blocks_per_group;
11810
11811         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11812                 pctx.group = i;
11813
11814                 if (i == fs->group_desc_count - 1)
11815                         last_block = sb->s_blocks_count;
11816                 if ((gd->bg_block_bitmap < first_block) ||
11817                     (gd->bg_block_bitmap >= last_block)) {
11818                         pctx.blk = gd->bg_block_bitmap;
11819                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11820                                 gd->bg_block_bitmap = 0;
11821                 }
11822                 if (gd->bg_block_bitmap == 0) {
11823                         ctx->invalid_block_bitmap_flag[i]++;
11824                         ctx->invalid_bitmaps++;
11825                 }
11826                 if ((gd->bg_inode_bitmap < first_block) ||
11827                     (gd->bg_inode_bitmap >= last_block)) {
11828                         pctx.blk = gd->bg_inode_bitmap;
11829                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11830                                 gd->bg_inode_bitmap = 0;
11831                 }
11832                 if (gd->bg_inode_bitmap == 0) {
11833                         ctx->invalid_inode_bitmap_flag[i]++;
11834                         ctx->invalid_bitmaps++;
11835                 }
11836                 if ((gd->bg_inode_table < first_block) ||
11837                     ((gd->bg_inode_table +
11838                       fs->inode_blocks_per_group - 1) >= last_block)) {
11839                         pctx.blk = gd->bg_inode_table;
11840                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11841                                 gd->bg_inode_table = 0;
11842                 }
11843                 if (gd->bg_inode_table == 0) {
11844                         ctx->invalid_inode_table_flag[i]++;
11845                         ctx->invalid_bitmaps++;
11846                 }
11847                 free_blocks += gd->bg_free_blocks_count;
11848                 free_inodes += gd->bg_free_inodes_count;
11849                 first_block += sb->s_blocks_per_group;
11850                 last_block += sb->s_blocks_per_group;
11851
11852                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11853                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11854                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11855                         ext2fs_unmark_valid(fs);
11856         }
11857
11858         /*
11859          * Update the global counts from the block group counts.  This
11860          * is needed for an experimental patch which eliminates
11861          * locking the entire filesystem when allocating blocks or
11862          * inodes; if the filesystem is not unmounted cleanly, the
11863          * global counts may not be accurate.
11864          */
11865         if ((free_blocks != sb->s_free_blocks_count) ||
11866             (free_inodes != sb->s_free_inodes_count)) {
11867                 if (ctx->options & E2F_OPT_READONLY)
11868                         ext2fs_unmark_valid(fs);
11869                 else {
11870                         sb->s_free_blocks_count = free_blocks;
11871                         sb->s_free_inodes_count = free_inodes;
11872                         ext2fs_mark_super_dirty(fs);
11873                 }
11874         }
11875
11876         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11877             (sb->s_free_inodes_count > sb->s_inodes_count))
11878                 ext2fs_unmark_valid(fs);
11879
11880
11881         /*
11882          * If we have invalid bitmaps, set the error state of the
11883          * filesystem.
11884          */
11885         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11886                 sb->s_state &= ~EXT2_VALID_FS;
11887                 ext2fs_mark_super_dirty(fs);
11888         }
11889
11890         clear_problem_context(&pctx);
11891
11892         /*
11893          * If the UUID field isn't assigned, assign it.
11894          */
11895         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11896                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11897                         uuid_generate(sb->s_uuid);
11898                         ext2fs_mark_super_dirty(fs);
11899                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11900                 }
11901         }
11902
11903         /* FIXME - HURD support?
11904          * For the Hurd, check to see if the filetype option is set,
11905          * since it doesn't support it.
11906          */
11907         if (!(ctx->options & E2F_OPT_READONLY) &&
11908             fs->super->s_creator_os == EXT2_OS_HURD &&
11909             (fs->super->s_feature_incompat &
11910              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11911                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11912                         fs->super->s_feature_incompat &=
11913                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11914                         ext2fs_mark_super_dirty(fs);
11915                 }
11916         }
11917
11918         /*
11919          * If we have any of the compatibility flags set, we need to have a
11920          * revision 1 filesystem.  Most kernels will not check the flags on
11921          * a rev 0 filesystem and we may have corruption issues because of
11922          * the incompatible changes to the filesystem.
11923          */
11924         if (!(ctx->options & E2F_OPT_READONLY) &&
11925             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11926             (fs->super->s_feature_compat ||
11927              fs->super->s_feature_ro_compat ||
11928              fs->super->s_feature_incompat) &&
11929             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11930                 ext2fs_update_dynamic_rev(fs);
11931                 ext2fs_mark_super_dirty(fs);
11932         }
11933
11934         check_resize_inode(ctx);
11935
11936         /*
11937          * Clean up any orphan inodes, if present.
11938          */
11939         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11940                 fs->super->s_state &= ~EXT2_VALID_FS;
11941                 ext2fs_mark_super_dirty(fs);
11942         }
11943
11944         /*
11945          * Move the ext3 journal file, if necessary.
11946          */
11947         e2fsck_move_ext3_journal(ctx);
11948 }
11949
11950 /*
11951  * swapfs.c --- byte-swap an ext2 filesystem
11952  */
11953
11954 #ifdef ENABLE_SWAPFS
11955
11956 struct swap_block_struct {
11957         ext2_ino_t      ino;
11958         int             isdir;
11959         errcode_t       errcode;
11960         char            *dir_buf;
11961         struct ext2_inode *inode;
11962 };
11963
11964 /*
11965  * This is a helper function for block_iterate.  We mark all of the
11966  * indirect and direct blocks as changed, so that block_iterate will
11967  * write them out.
11968  */
11969 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11970                       void *priv_data)
11971 {
11972         errcode_t       retval;
11973
11974         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11975
11976         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11977                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11978                 if (retval) {
11979                         sb->errcode = retval;
11980                         return BLOCK_ABORT;
11981                 }
11982                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11983                 if (retval) {
11984                         sb->errcode = retval;
11985                         return BLOCK_ABORT;
11986                 }
11987         }
11988         if (blockcnt >= 0) {
11989                 if (blockcnt < EXT2_NDIR_BLOCKS)
11990                         return 0;
11991                 return BLOCK_CHANGED;
11992         }
11993         if (blockcnt == BLOCK_COUNT_IND) {
11994                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11995                         return 0;
11996                 return BLOCK_CHANGED;
11997         }
11998         if (blockcnt == BLOCK_COUNT_DIND) {
11999                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12000                         return 0;
12001                 return BLOCK_CHANGED;
12002         }
12003         if (blockcnt == BLOCK_COUNT_TIND) {
12004                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12005                         return 0;
12006                 return BLOCK_CHANGED;
12007         }
12008         return BLOCK_CHANGED;
12009 }
12010
12011 /*
12012  * This function is responsible for byte-swapping all of the indirect,
12013  * block pointers.  It is also responsible for byte-swapping directories.
12014  */
12015 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12016                               struct ext2_inode *inode)
12017 {
12018         errcode_t                       retval;
12019         struct swap_block_struct        sb;
12020
12021         sb.ino = ino;
12022         sb.inode = inode;
12023         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12024         sb.errcode = 0;
12025         sb.isdir = 0;
12026         if (LINUX_S_ISDIR(inode->i_mode))
12027                 sb.isdir = 1;
12028
12029         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12030                                       swap_block, &sb);
12031         if (retval) {
12032                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12033                 ctx->flags |= E2F_FLAG_ABORT;
12034                 return;
12035         }
12036         if (sb.errcode) {
12037                 bb_error_msg(_("while calling iterator function"));
12038                 ctx->flags |= E2F_FLAG_ABORT;
12039                 return;
12040         }
12041 }
12042
12043 static void swap_inodes(e2fsck_t ctx)
12044 {
12045         ext2_filsys fs = ctx->fs;
12046         dgrp_t                  group;
12047         unsigned int            i;
12048         ext2_ino_t              ino = 1;
12049         char                    *buf, *block_buf;
12050         errcode_t               retval;
12051         struct ext2_inode *     inode;
12052
12053         e2fsck_use_inode_shortcuts(ctx, 1);
12054
12055         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12056                                 &buf);
12057         if (retval) {
12058                 bb_error_msg(_("while allocating inode buffer"));
12059                 ctx->flags |= E2F_FLAG_ABORT;
12060                 return;
12061         }
12062         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12063                                                     "block interate buffer");
12064         for (group = 0; group < fs->group_desc_count; group++) {
12065                 retval = io_channel_read_blk(fs->io,
12066                       fs->group_desc[group].bg_inode_table,
12067                       fs->inode_blocks_per_group, buf);
12068                 if (retval) {
12069                         bb_error_msg(_("while reading inode table (group %d)"),
12070                                 group);
12071                         ctx->flags |= E2F_FLAG_ABORT;
12072                         return;
12073                 }
12074                 inode = (struct ext2_inode *) buf;
12075                 for (i=0; i < fs->super->s_inodes_per_group;
12076                      i++, ino++, inode++) {
12077                         ctx->stashed_ino = ino;
12078                         ctx->stashed_inode = inode;
12079
12080                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12081                                 ext2fs_swap_inode(fs, inode, inode, 0);
12082
12083                         /*
12084                          * Skip deleted files.
12085                          */
12086                         if (inode->i_links_count == 0)
12087                                 continue;
12088
12089                         if (LINUX_S_ISDIR(inode->i_mode) ||
12090                             ((inode->i_block[EXT2_IND_BLOCK] ||
12091                               inode->i_block[EXT2_DIND_BLOCK] ||
12092                               inode->i_block[EXT2_TIND_BLOCK]) &&
12093                              ext2fs_inode_has_valid_blocks(inode)))
12094                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12095
12096                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12097                                 return;
12098
12099                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12100                                 ext2fs_swap_inode(fs, inode, inode, 1);
12101                 }
12102                 retval = io_channel_write_blk(fs->io,
12103                       fs->group_desc[group].bg_inode_table,
12104                       fs->inode_blocks_per_group, buf);
12105                 if (retval) {
12106                         bb_error_msg(_("while writing inode table (group %d)"),
12107                                 group);
12108                         ctx->flags |= E2F_FLAG_ABORT;
12109                         return;
12110                 }
12111         }
12112         ext2fs_free_mem(&buf);
12113         ext2fs_free_mem(&block_buf);
12114         e2fsck_use_inode_shortcuts(ctx, 0);
12115         ext2fs_flush_icache(fs);
12116 }
12117
12118 #if defined(__powerpc__) && BB_BIG_ENDIAN
12119 /*
12120  * On the PowerPC, the big-endian variant of the ext2 filesystem
12121  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12122  * of each word.  Thus a bitmap with only bit 0 set would be, as
12123  * a string of bytes, 00 00 00 01 00 ...
12124  * To cope with this, we byte-reverse each word of a bitmap if
12125  * we have a big-endian filesystem, that is, if we are *not*
12126  * byte-swapping other word-sized numbers.
12127  */
12128 #define EXT2_BIG_ENDIAN_BITMAPS
12129 #endif
12130
12131 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12132 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12133 {
12134         __u32 *p = (__u32 *) bmap->bitmap;
12135         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12136
12137         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12138                 *p = ext2fs_swab32(*p);
12139 }
12140 #endif
12141
12142
12143 #ifdef ENABLE_SWAPFS
12144 static void swap_filesys(e2fsck_t ctx)
12145 {
12146         ext2_filsys fs = ctx->fs;
12147         if (!(ctx->options & E2F_OPT_PREEN))
12148                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12149
12150         /* Byte swap */
12151
12152         if (fs->super->s_mnt_count) {
12153                 fprintf(stderr, _("%s: the filesystem must be freshly "
12154                         "checked using fsck\n"
12155                         "and not mounted before trying to "
12156                         "byte-swap it.\n"), ctx->device_name);
12157                 ctx->flags |= E2F_FLAG_ABORT;
12158                 return;
12159         }
12160         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12161                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12162                                EXT2_FLAG_SWAP_BYTES_WRITE);
12163                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12164         } else {
12165                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12166                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12167         }
12168         swap_inodes(ctx);
12169         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12170                 return;
12171         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12172                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12173         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12174                        EXT2_FLAG_SWAP_BYTES_WRITE);
12175
12176 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12177         e2fsck_read_bitmaps(ctx);
12178         ext2fs_swap_bitmap(fs->inode_map);
12179         ext2fs_swap_bitmap(fs->block_map);
12180         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12181 #endif
12182         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12183         ext2fs_flush(fs);
12184         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12185 }
12186 #endif  /* ENABLE_SWAPFS */
12187
12188 #endif
12189
12190 /*
12191  * util.c --- miscellaneous utilities
12192  */
12193
12194
12195 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12196                              const char *description)
12197 {
12198         return xzalloc(size);
12199 }
12200
12201 static char *string_copy(const char *str, int len)
12202 {
12203         char    *ret;
12204
12205         if (!str)
12206                 return NULL;
12207         if (!len)
12208                 len = strlen(str);
12209         ret = xmalloc(len+1);
12210         strncpy(ret, str, len);
12211         ret[len] = 0;
12212         return ret;
12213 }
12214
12215 #ifndef HAVE_CONIO_H
12216 static int read_a_char(void)
12217 {
12218         char    c;
12219         int     r;
12220         int     fail = 0;
12221
12222         while (1) {
12223                 if (e2fsck_global_ctx &&
12224                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12225                         return 3;
12226                 }
12227                 r = read(0, &c, 1);
12228                 if (r == 1)
12229                         return c;
12230                 if (fail++ > 100)
12231                         break;
12232         }
12233         return EOF;
12234 }
12235 #endif
12236
12237 static int ask_yn(const char * string, int def)
12238 {
12239         int             c;
12240         const char      *defstr;
12241         static const char short_yes[] = "yY";
12242         static const char short_no[] = "nN";
12243
12244 #ifdef HAVE_TERMIOS_H
12245         struct termios  termios, tmp;
12246
12247         tcgetattr (0, &termios);
12248         tmp = termios;
12249         tmp.c_lflag &= ~(ICANON | ECHO);
12250         tmp.c_cc[VMIN] = 1;
12251         tmp.c_cc[VTIME] = 0;
12252         tcsetattr_stdin_TCSANOW(&tmp);
12253 #endif
12254
12255         if (def == 1)
12256                 defstr = "<y>";
12257         else if (def == 0)
12258                 defstr = "<n>";
12259         else
12260                 defstr = " (y/n)";
12261         printf("%s%s? ", string, defstr);
12262         while (1) {
12263                 fflush (stdout);
12264                 if ((c = read_a_char()) == EOF)
12265                         break;
12266                 if (c == 3) {
12267 #ifdef HAVE_TERMIOS_H
12268                         tcsetattr_stdin_TCSANOW(&termios);
12269 #endif
12270                         if (e2fsck_global_ctx &&
12271                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12272                                 puts("\n");
12273                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12274                         }
12275                         puts(_("cancelled!\n"));
12276                         return 0;
12277                 }
12278                 if (strchr(short_yes, (char) c)) {
12279                         def = 1;
12280                         break;
12281                 }
12282                 else if (strchr(short_no, (char) c)) {
12283                         def = 0;
12284                         break;
12285                 }
12286                 else if ((c == ' ' || c == '\n') && (def != -1))
12287                         break;
12288         }
12289         if (def)
12290                 puts("yes\n");
12291         else
12292                 puts ("no\n");
12293 #ifdef HAVE_TERMIOS_H
12294         tcsetattr_stdin_TCSANOW(&termios);
12295 #endif
12296         return def;
12297 }
12298
12299 int ask (e2fsck_t ctx, const char * string, int def)
12300 {
12301         if (ctx->options & E2F_OPT_NO) {
12302                 printf(_("%s? no\n\n"), string);
12303                 return 0;
12304         }
12305         if (ctx->options & E2F_OPT_YES) {
12306                 printf(_("%s? yes\n\n"), string);
12307                 return 1;
12308         }
12309         if (ctx->options & E2F_OPT_PREEN) {
12310                 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12311                 return def;
12312         }
12313         return ask_yn(string, def);
12314 }
12315
12316 void e2fsck_read_bitmaps(e2fsck_t ctx)
12317 {
12318         ext2_filsys fs = ctx->fs;
12319         errcode_t       retval;
12320
12321         if (ctx->invalid_bitmaps) {
12322                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12323                         ctx->device_name);
12324                 bb_error_msg_and_die(0);
12325         }
12326
12327         ehandler_operation(_("reading inode and block bitmaps"));
12328         retval = ext2fs_read_bitmaps(fs);
12329         ehandler_operation(0);
12330         if (retval) {
12331                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12332                         ctx->device_name);
12333                 bb_error_msg_and_die(0);
12334         }
12335 }
12336
12337 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12338 {
12339         ext2_filsys fs = ctx->fs;
12340         errcode_t       retval;
12341
12342         if (ext2fs_test_bb_dirty(fs)) {
12343                 ehandler_operation(_("writing block bitmaps"));
12344                 retval = ext2fs_write_block_bitmap(fs);
12345                 ehandler_operation(0);
12346                 if (retval) {
12347                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12348                                 ctx->device_name);
12349                         bb_error_msg_and_die(0);
12350                 }
12351         }
12352
12353         if (ext2fs_test_ib_dirty(fs)) {
12354                 ehandler_operation(_("writing inode bitmaps"));
12355                 retval = ext2fs_write_inode_bitmap(fs);
12356                 ehandler_operation(0);
12357                 if (retval) {
12358                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12359                                 ctx->device_name);
12360                         bb_error_msg_and_die(0);
12361                 }
12362         }
12363 }
12364
12365 void preenhalt(e2fsck_t ctx)
12366 {
12367         ext2_filsys fs = ctx->fs;
12368
12369         if (!(ctx->options & E2F_OPT_PREEN))
12370                 return;
12371         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12372                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12373                ctx->device_name);
12374         if (fs != NULL) {
12375                 fs->super->s_state |= EXT2_ERROR_FS;
12376                 ext2fs_mark_super_dirty(fs);
12377                 ext2fs_close(fs);
12378         }
12379         exit(EXIT_UNCORRECTED);
12380 }
12381
12382 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12383                               struct ext2_inode * inode, const char *proc)
12384 {
12385         int retval;
12386
12387         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12388         if (retval) {
12389                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12390                 bb_error_msg_and_die(0);
12391         }
12392 }
12393
12394 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12395                                struct ext2_inode * inode, int bufsize,
12396                                const char *proc)
12397 {
12398         int retval;
12399
12400         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12401         if (retval) {
12402                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12403                 bb_error_msg_and_die(0);
12404         }
12405 }
12406
12407 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12408                                struct ext2_inode * inode, const char *proc)
12409 {
12410         int retval;
12411
12412         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12413         if (retval) {
12414                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12415                 bb_error_msg_and_die(0);
12416         }
12417 }
12418
12419 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12420                    io_manager manager)
12421 {
12422         struct ext2_super_block *sb;
12423         io_channel              io = NULL;
12424         void                    *buf = NULL;
12425         int                     blocksize;
12426         blk_t                   superblock, ret_sb = 8193;
12427
12428         if (fs && fs->super) {
12429                 ret_sb = (fs->super->s_blocks_per_group +
12430                           fs->super->s_first_data_block);
12431                 if (ctx) {
12432                         ctx->superblock = ret_sb;
12433                         ctx->blocksize = fs->blocksize;
12434                 }
12435                 return ret_sb;
12436         }
12437
12438         if (ctx) {
12439                 if (ctx->blocksize) {
12440                         ret_sb = ctx->blocksize * 8;
12441                         if (ctx->blocksize == 1024)
12442                                 ret_sb++;
12443                         ctx->superblock = ret_sb;
12444                         return ret_sb;
12445                 }
12446                 ctx->superblock = ret_sb;
12447                 ctx->blocksize = 1024;
12448         }
12449
12450         if (!name || !manager)
12451                 goto cleanup;
12452
12453         if (manager->open(name, 0, &io) != 0)
12454                 goto cleanup;
12455
12456         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12457                 goto cleanup;
12458         sb = (struct ext2_super_block *) buf;
12459
12460         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12461              blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12462                 superblock = blocksize*8;
12463                 if (blocksize == 1024)
12464                         superblock++;
12465                 io_channel_set_blksize(io, blocksize);
12466                 if (io_channel_read_blk(io, superblock,
12467                                         -SUPERBLOCK_SIZE, buf))
12468                         continue;
12469 #if BB_BIG_ENDIAN
12470                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12471                         ext2fs_swap_super(sb);
12472 #endif
12473                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12474                         ret_sb = superblock;
12475                         if (ctx) {
12476                                 ctx->superblock = superblock;
12477                                 ctx->blocksize = blocksize;
12478                         }
12479                         break;
12480                 }
12481         }
12482
12483 cleanup:
12484         if (io)
12485                 io_channel_close(io);
12486         ext2fs_free_mem(&buf);
12487         return ret_sb;
12488 }
12489
12490
12491 /*
12492  * This function runs through the e2fsck passes and calls them all,
12493  * returning restart, abort, or cancel as necessary...
12494  */
12495 typedef void (*pass_t)(e2fsck_t ctx);
12496
12497 static const pass_t e2fsck_passes[] = {
12498         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12499         e2fsck_pass5, 0 };
12500
12501 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12502
12503 static int e2fsck_run(e2fsck_t ctx)
12504 {
12505         int     i;
12506         pass_t  e2fsck_pass;
12507
12508         if (setjmp(ctx->abort_loc)) {
12509                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12510                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12511         }
12512         ctx->flags |= E2F_FLAG_SETJMP_OK;
12513
12514         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12515                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12516                         break;
12517                 e2fsck_pass(ctx);
12518                 if (ctx->progress)
12519                         (void) (ctx->progress)(ctx, 0, 0, 0);
12520         }
12521         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12522
12523         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12524                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12525         return 0;
12526 }
12527
12528
12529 /*
12530  * unix.c - The unix-specific code for e2fsck
12531  */
12532
12533
12534 /* Command line options */
12535 static int swapfs;
12536 #ifdef ENABLE_SWAPFS
12537 static int normalize_swapfs;
12538 #endif
12539 static int cflag;               /* check disk */
12540 static int show_version_only;
12541 static int verbose;
12542
12543 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12544
12545 static void show_stats(e2fsck_t ctx)
12546 {
12547         ext2_filsys fs = ctx->fs;
12548         int inodes, inodes_used, blocks, blocks_used;
12549         int dir_links;
12550         int num_files, num_links;
12551         int frag_percent;
12552
12553         dir_links = 2 * ctx->fs_directory_count - 1;
12554         num_files = ctx->fs_total_count - dir_links;
12555         num_links = ctx->fs_links_count - dir_links;
12556         inodes = fs->super->s_inodes_count;
12557         inodes_used = (fs->super->s_inodes_count -
12558                        fs->super->s_free_inodes_count);
12559         blocks = fs->super->s_blocks_count;
12560         blocks_used = (fs->super->s_blocks_count -
12561                        fs->super->s_free_blocks_count);
12562
12563         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12564         frag_percent = (frag_percent + 5) / 10;
12565
12566         if (!verbose) {
12567                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12568                        ctx->device_name, inodes_used, inodes,
12569                        frag_percent / 10, frag_percent % 10,
12570                        blocks_used, blocks);
12571                 return;
12572         }
12573         printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12574                 100 * inodes_used / inodes);
12575         printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12576                 P_E2("", "s", ctx->fs_fragmented),
12577                 frag_percent / 10, frag_percent % 10);
12578         printf(_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12579                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12580         printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12581                 (int) ((long long) 100 * blocks_used / blocks));
12582         printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12583         printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12584         printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12585         printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12586         printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12587         printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12588         printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12589         printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12590         printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12591         printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12592         printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12593 }
12594
12595 static void check_mount(e2fsck_t ctx)
12596 {
12597         errcode_t       retval;
12598         int             cont;
12599
12600         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12601                                          &ctx->mount_flags);
12602         if (retval) {
12603                 bb_error_msg(_("while determining whether %s is mounted"),
12604                         ctx->filesystem_name);
12605                 return;
12606         }
12607
12608         /*
12609          * If the filesystem isn't mounted, or it's the root filesystem
12610          * and it's mounted read-only, then everything's fine.
12611          */
12612         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12613             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12614              (ctx->mount_flags & EXT2_MF_READONLY)))
12615                 return;
12616
12617         if (ctx->options & E2F_OPT_READONLY) {
12618                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12619                 return;
12620         }
12621
12622         printf(_("%s is mounted.  "), ctx->filesystem_name);
12623         if (!ctx->interactive)
12624                 bb_error_msg_and_die(_("can't continue, aborting"));
12625         printf(_("\n\n\007\007\007\007WARNING!!!  "
12626                "Running e2fsck on a mounted filesystem may cause\n"
12627                "SEVERE filesystem damage.\007\007\007\n\n"));
12628         cont = ask_yn(_("Do you really want to continue"), -1);
12629         if (!cont) {
12630                 printf(_("check aborted.\n"));
12631                 exit(0);
12632         }
12633 }
12634
12635 static int is_on_batt(void)
12636 {
12637         FILE    *f;
12638         DIR     *d;
12639         char    tmp[80], tmp2[80], fname[80];
12640         unsigned int    acflag;
12641         struct dirent*  de;
12642
12643         f = fopen_for_read("/proc/apm");
12644         if (f) {
12645                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12646                         acflag = 1;
12647                 fclose(f);
12648                 return (acflag != 1);
12649         }
12650         d = opendir("/proc/acpi/ac_adapter");
12651         if (d) {
12652                 while ((de=readdir(d)) != NULL) {
12653                         if (!strncmp(".", de->d_name, 1))
12654                                 continue;
12655                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12656                                  de->d_name);
12657                         f = fopen_for_read(fname);
12658                         if (!f)
12659                                 continue;
12660                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12661                                 tmp[0] = 0;
12662                         fclose(f);
12663                         if (strncmp(tmp, "off-line", 8) == 0) {
12664                                 closedir(d);
12665                                 return 1;
12666                         }
12667                 }
12668                 closedir(d);
12669         }
12670         return 0;
12671 }
12672
12673 /*
12674  * This routine checks to see if a filesystem can be skipped; if so,
12675  * it will exit with EXIT_OK.  Under some conditions it will print a
12676  * message explaining why a check is being forced.
12677  */
12678 static void check_if_skip(e2fsck_t ctx)
12679 {
12680         ext2_filsys fs = ctx->fs;
12681         const char *reason = NULL;
12682         unsigned int reason_arg = 0;
12683         long next_check;
12684         int batt = is_on_batt();
12685         time_t now = time(NULL);
12686
12687         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12688                 return;
12689
12690         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12691             !ext2fs_test_valid(fs))
12692                 reason = _(" contains a file system with errors");
12693         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12694                 reason = _(" was not cleanly unmounted");
12695         else if ((fs->super->s_max_mnt_count > 0) &&
12696                  (fs->super->s_mnt_count >=
12697                   (unsigned) fs->super->s_max_mnt_count)) {
12698                 reason = _(" has been mounted %u times without being checked");
12699                 reason_arg = fs->super->s_mnt_count;
12700                 if (batt && (fs->super->s_mnt_count <
12701                              (unsigned) fs->super->s_max_mnt_count*2))
12702                         reason = 0;
12703         } else if (fs->super->s_checkinterval &&
12704                    ((now - fs->super->s_lastcheck) >=
12705                     fs->super->s_checkinterval)) {
12706                 reason = _(" has gone %u days without being checked");
12707                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12708                 if (batt && ((now - fs->super->s_lastcheck) <
12709                              fs->super->s_checkinterval*2))
12710                         reason = 0;
12711         }
12712         if (reason) {
12713                 fputs(ctx->device_name, stdout);
12714                 printf(reason, reason_arg);
12715                 fputs(_(", check forced.\n"), stdout);
12716                 return;
12717         }
12718         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12719                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12720                fs->super->s_inodes_count,
12721                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12722                fs->super->s_blocks_count);
12723         next_check = 100000;
12724         if (fs->super->s_max_mnt_count > 0) {
12725                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12726                 if (next_check <= 0)
12727                         next_check = 1;
12728         }
12729         if (fs->super->s_checkinterval &&
12730             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12731                 next_check = 1;
12732         if (next_check <= 5) {
12733                 if (next_check == 1)
12734                         fputs(_(" (check after next mount)"), stdout);
12735                 else
12736                         printf(_(" (check in %ld mounts)"), next_check);
12737         }
12738         bb_putchar('\n');
12739         ext2fs_close(fs);
12740         ctx->fs = NULL;
12741         e2fsck_free_context(ctx);
12742         exit(EXIT_OK);
12743 }
12744
12745 /*
12746  * For completion notice
12747  */
12748 struct percent_tbl {
12749         int     max_pass;
12750         int     table[32];
12751 };
12752 static const struct percent_tbl e2fsck_tbl = {
12753         5, { 0, 70, 90, 92,  95, 100 }
12754 };
12755
12756 static char bar[128], spaces[128];
12757
12758 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12759                           int max)
12760 {
12761         float   percent;
12762
12763         if (pass <= 0)
12764                 return 0.0;
12765         if (pass > tbl->max_pass || max == 0)
12766                 return 100.0;
12767         percent = ((float) curr) / ((float) max);
12768         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12769                 + tbl->table[pass-1]);
12770 }
12771
12772 void e2fsck_clear_progbar(e2fsck_t ctx)
12773 {
12774         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12775                 return;
12776
12777         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12778                ctx->stop_meta);
12779         fflush(stdout);
12780         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12781 }
12782
12783 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12784                            unsigned int dpynum)
12785 {
12786         static const char spinner[] = "\\|/-";
12787         int     i;
12788         unsigned int    tick;
12789         struct timeval  tv;
12790         int dpywidth;
12791         int fixed_percent;
12792
12793         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12794                 return 0;
12795
12796         /*
12797          * Calculate the new progress position.  If the
12798          * percentage hasn't changed, then we skip out right
12799          * away.
12800          */
12801         fixed_percent = (int) ((10 * percent) + 0.5);
12802         if (ctx->progress_last_percent == fixed_percent)
12803                 return 0;
12804         ctx->progress_last_percent = fixed_percent;
12805
12806         /*
12807          * If we've already updated the spinner once within
12808          * the last 1/8th of a second, no point doing it
12809          * again.
12810          */
12811         gettimeofday(&tv, NULL);
12812         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12813         if ((tick == ctx->progress_last_time) &&
12814             (fixed_percent != 0) && (fixed_percent != 1000))
12815                 return 0;
12816         ctx->progress_last_time = tick;
12817
12818         /*
12819          * Advance the spinner, and note that the progress bar
12820          * will be on the screen
12821          */
12822         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12823         ctx->flags |= E2F_FLAG_PROG_BAR;
12824
12825         dpywidth = 66 - strlen(label);
12826         dpywidth = 8 * (dpywidth / 8);
12827         if (dpynum)
12828                 dpywidth -= 8;
12829
12830         i = ((percent * dpywidth) + 50) / 100;
12831         printf("%s%s: |%s%s", ctx->start_meta, label,
12832                bar + (sizeof(bar) - (i+1)),
12833                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12834         if (fixed_percent == 1000)
12835                 bb_putchar('|');
12836         else
12837                 bb_putchar(spinner[ctx->progress_pos & 3]);
12838         printf(" %4.1f%%  ", percent);
12839         if (dpynum)
12840                 printf("%u\r", dpynum);
12841         else
12842                 fputs(" \r", stdout);
12843         fputs(ctx->stop_meta, stdout);
12844
12845         if (fixed_percent == 1000)
12846                 e2fsck_clear_progbar(ctx);
12847         fflush(stdout);
12848
12849         return 0;
12850 }
12851
12852 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12853                                   unsigned long cur, unsigned long max)
12854 {
12855         char buf[80];
12856         float percent;
12857
12858         if (pass == 0)
12859                 return 0;
12860
12861         if (ctx->progress_fd) {
12862                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12863                 xwrite_str(ctx->progress_fd, buf);
12864         } else {
12865                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12866                 e2fsck_simple_progress(ctx, ctx->device_name,
12867                                        percent, 0);
12868         }
12869         return 0;
12870 }
12871
12872 static void reserve_stdio_fds(void)
12873 {
12874         int     fd;
12875
12876         while (1) {
12877                 fd = open(bb_dev_null, O_RDWR);
12878                 if (fd > 2)
12879                         break;
12880                 if (fd < 0) {
12881                         fprintf(stderr, _("ERROR: Cannot open "
12882                                 "/dev/null (%s)\n"),
12883                                 strerror(errno));
12884                         break;
12885                 }
12886         }
12887         close(fd);
12888 }
12889
12890 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12891 {
12892         e2fsck_t ctx = e2fsck_global_ctx;
12893
12894         if (!ctx)
12895                 return;
12896
12897         ctx->progress = e2fsck_update_progress;
12898         ctx->progress_fd = 0;
12899 }
12900
12901 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12902 {
12903         e2fsck_t ctx = e2fsck_global_ctx;
12904
12905         if (!ctx)
12906                 return;
12907
12908         e2fsck_clear_progbar(ctx);
12909         ctx->progress = 0;
12910 }
12911
12912 static void signal_cancel(int sig FSCK_ATTR((unused)))
12913 {
12914         e2fsck_t ctx = e2fsck_global_ctx;
12915
12916         if (!ctx)
12917                 exit(FSCK_CANCELED);
12918
12919         ctx->flags |= E2F_FLAG_CANCEL;
12920 }
12921
12922 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12923 {
12924         char    *buf, *token, *next, *p, *arg;
12925         int     ea_ver;
12926         int     extended_usage = 0;
12927
12928         buf = string_copy(opts, 0);
12929         for (token = buf; token && *token; token = next) {
12930                 p = strchr(token, ',');
12931                 next = 0;
12932                 if (p) {
12933                         *p = 0;
12934                         next = p+1;
12935                 }
12936                 arg = strchr(token, '=');
12937                 if (arg) {
12938                         *arg = 0;
12939                         arg++;
12940                 }
12941                 if (strcmp(token, "ea_ver") == 0) {
12942                         if (!arg) {
12943                                 extended_usage++;
12944                                 continue;
12945                         }
12946                         ea_ver = strtoul(arg, &p, 0);
12947                         if (*p ||
12948                             ((ea_ver != 1) && (ea_ver != 2))) {
12949                                 fprintf(stderr,
12950                                         _("Invalid EA version.\n"));
12951                                 extended_usage++;
12952                                 continue;
12953                         }
12954                         ctx->ext_attr_ver = ea_ver;
12955                 } else {
12956                         fprintf(stderr, _("Unknown extended option: %s\n"),
12957                                 token);
12958                         extended_usage++;
12959                 }
12960         }
12961         if (extended_usage) {
12962                 bb_error_msg_and_die(
12963                         "Extended options are separated by commas, "
12964                         "and may take an argument which\n"
12965                         "is set off by an equals ('=') sign.  "
12966                         "Valid extended options are:\n"
12967                         "\tea_ver=<ea_version (1 or 2)>\n\n");
12968         }
12969 }
12970
12971
12972 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12973 {
12974         int             flush = 0;
12975         int             c, fd;
12976         e2fsck_t        ctx;
12977         errcode_t       retval;
12978         struct sigaction        sa;
12979         char            *extended_opts = NULL;
12980
12981         retval = e2fsck_allocate_context(&ctx);
12982         if (retval)
12983                 return retval;
12984
12985         *ret_ctx = ctx;
12986
12987         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12988         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12989         if (isatty(0) && isatty(1)) {
12990                 ctx->interactive = 1;
12991         } else {
12992                 ctx->start_meta[0] = '\001';
12993                 ctx->stop_meta[0] = '\002';
12994         }
12995         memset(bar, '=', sizeof(bar)-1);
12996         memset(spaces, ' ', sizeof(spaces)-1);
12997         blkid_get_cache(&ctx->blkid, NULL);
12998
12999         if (argc && *argv)
13000                 ctx->program_name = *argv;
13001         else
13002                 ctx->program_name = "e2fsck";
13003         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13004                 switch (c) {
13005                 case 'C':
13006                         ctx->progress = e2fsck_update_progress;
13007                         ctx->progress_fd = atoi(optarg);
13008                         if (!ctx->progress_fd)
13009                                 break;
13010                         /* Validate the file descriptor to avoid disasters */
13011                         fd = dup(ctx->progress_fd);
13012                         if (fd < 0) {
13013                                 fprintf(stderr,
13014                                 _("Error validating file descriptor %d: %s\n"),
13015                                         ctx->progress_fd,
13016                                         error_message(errno));
13017                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13018                         } else
13019                                 close(fd);
13020                         break;
13021                 case 'D':
13022                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13023                         break;
13024                 case 'E':
13025                         extended_opts = optarg;
13026                         break;
13027                 case 'p':
13028                 case 'a':
13029                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13030                         conflict_opt:
13031                                 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13032                         }
13033                         ctx->options |= E2F_OPT_PREEN;
13034                         break;
13035                 case 'n':
13036                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13037                                 goto conflict_opt;
13038                         ctx->options |= E2F_OPT_NO;
13039                         break;
13040                 case 'y':
13041                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13042                                 goto conflict_opt;
13043                         ctx->options |= E2F_OPT_YES;
13044                         break;
13045                 case 't':
13046                         /* FIXME - This needs to go away in a future path - will change binary */
13047                         fprintf(stderr, _("The -t option is not "
13048                                 "supported on this version of e2fsck.\n"));
13049                         break;
13050                 case 'c':
13051                         if (cflag++)
13052                                 ctx->options |= E2F_OPT_WRITECHECK;
13053                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13054                         break;
13055                 case 'r':
13056                         /* What we do by default, anyway! */
13057                         break;
13058                 case 'b':
13059                         ctx->use_superblock = atoi(optarg);
13060                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13061                         break;
13062                 case 'B':
13063                         ctx->blocksize = atoi(optarg);
13064                         break;
13065                 case 'I':
13066                         ctx->inode_buffer_blocks = atoi(optarg);
13067                         break;
13068                 case 'j':
13069                         ctx->journal_name = string_copy(optarg, 0);
13070                         break;
13071                 case 'P':
13072                         ctx->process_inode_size = atoi(optarg);
13073                         break;
13074                 case 'd':
13075                         ctx->options |= E2F_OPT_DEBUG;
13076                         break;
13077                 case 'f':
13078                         ctx->options |= E2F_OPT_FORCE;
13079                         break;
13080                 case 'F':
13081                         flush = 1;
13082                         break;
13083                 case 'v':
13084                         verbose = 1;
13085                         break;
13086                 case 'V':
13087                         show_version_only = 1;
13088                         break;
13089                 case 'N':
13090                         ctx->device_name = optarg;
13091                         break;
13092 #ifdef ENABLE_SWAPFS
13093                 case 's':
13094                         normalize_swapfs = 1;
13095                 case 'S':
13096                         swapfs = 1;
13097                         break;
13098 #else
13099                 case 's':
13100                 case 'S':
13101                         fprintf(stderr, _("Byte-swapping filesystems "
13102                                           "not compiled in this version "
13103                                           "of e2fsck\n"));
13104                         exit(1);
13105 #endif
13106                 default:
13107                         bb_show_usage();
13108                 }
13109         if (show_version_only)
13110                 return 0;
13111         if (optind != argc - 1)
13112                 bb_show_usage();
13113         if ((ctx->options & E2F_OPT_NO) &&
13114             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13115                 ctx->options |= E2F_OPT_READONLY;
13116         ctx->io_options = strchr(argv[optind], '?');
13117         if (ctx->io_options)
13118                 *ctx->io_options++ = 0;
13119         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13120         if (!ctx->filesystem_name) {
13121                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13122                 bb_error_msg_and_die(0);
13123         }
13124         if (extended_opts)
13125                 parse_extended_opts(ctx, extended_opts);
13126
13127         if (flush) {
13128                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13129                 if (fd < 0) {
13130                         bb_error_msg(_("while opening %s for flushing"),
13131                                 ctx->filesystem_name);
13132                         bb_error_msg_and_die(0);
13133                 }
13134                 if ((retval = ext2fs_sync_device(fd, 1))) {
13135                         bb_error_msg(_("while trying to flush %s"),
13136                                 ctx->filesystem_name);
13137                         bb_error_msg_and_die(0);
13138                 }
13139                 close(fd);
13140         }
13141 #ifdef ENABLE_SWAPFS
13142         if (swapfs && cflag) {
13143                         fprintf(stderr, _("Incompatible options not "
13144                                           "allowed when byte-swapping.\n"));
13145                         exit(EXIT_USAGE);
13146         }
13147 #endif
13148         /*
13149          * Set up signal action
13150          */
13151         memset(&sa, 0, sizeof(struct sigaction));
13152         sa.sa_handler = signal_cancel;
13153         sigaction(SIGINT, &sa, 0);
13154         sigaction(SIGTERM, &sa, 0);
13155 #ifdef SA_RESTART
13156         sa.sa_flags = SA_RESTART;
13157 #endif
13158         e2fsck_global_ctx = ctx;
13159         sa.sa_handler = signal_progress_on;
13160         sigaction(SIGUSR1, &sa, 0);
13161         sa.sa_handler = signal_progress_off;
13162         sigaction(SIGUSR2, &sa, 0);
13163
13164         /* Update our PATH to include /sbin if we need to run badblocks  */
13165         if (cflag)
13166                 e2fs_set_sbin_path();
13167         return 0;
13168 }
13169
13170 static const char my_ver_string[] = E2FSPROGS_VERSION;
13171 static const char my_ver_date[] = E2FSPROGS_DATE;
13172
13173 int e2fsck_main (int argc, char **argv);
13174 int e2fsck_main (int argc, char **argv)
13175 {
13176         errcode_t       retval;
13177         int             exit_value = EXIT_OK;
13178         ext2_filsys     fs = 0;
13179         io_manager      io_ptr;
13180         struct ext2_super_block *sb;
13181         const char      *lib_ver_date;
13182         int             my_ver, lib_ver;
13183         e2fsck_t        ctx;
13184         struct problem_context pctx;
13185         int flags, run_result;
13186
13187         clear_problem_context(&pctx);
13188
13189         my_ver = ext2fs_parse_version_string(my_ver_string);
13190         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13191         if (my_ver > lib_ver) {
13192                 fprintf( stderr, _("Error: ext2fs library version "
13193                         "out of date!\n"));
13194                 show_version_only++;
13195         }
13196
13197         retval = PRS(argc, argv, &ctx);
13198         if (retval) {
13199                 bb_error_msg(_("while trying to initialize program"));
13200                 exit(EXIT_ERROR);
13201         }
13202         reserve_stdio_fds();
13203
13204         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13205                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13206                          my_ver_date);
13207
13208         if (show_version_only) {
13209                 fprintf(stderr, _("\tUsing %s, %s\n"),
13210                         error_message(EXT2_ET_BASE), lib_ver_date);
13211                 exit(EXIT_OK);
13212         }
13213
13214         check_mount(ctx);
13215
13216         if (!(ctx->options & E2F_OPT_PREEN) &&
13217             !(ctx->options & E2F_OPT_NO) &&
13218             !(ctx->options & E2F_OPT_YES)) {
13219                 if (!ctx->interactive)
13220                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13221         }
13222         ctx->superblock = ctx->use_superblock;
13223 restart:
13224 #ifdef CONFIG_TESTIO_DEBUG
13225         io_ptr = test_io_manager;
13226         test_io_backing_manager = unix_io_manager;
13227 #else
13228         io_ptr = unix_io_manager;
13229 #endif
13230         flags = 0;
13231         if ((ctx->options & E2F_OPT_READONLY) == 0)
13232                 flags |= EXT2_FLAG_RW;
13233
13234         if (ctx->superblock && ctx->blocksize) {
13235                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13236                                       flags, ctx->superblock, ctx->blocksize,
13237                                       io_ptr, &fs);
13238         } else if (ctx->superblock) {
13239                 int blocksize;
13240                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13241                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13242                         retval = ext2fs_open2(ctx->filesystem_name,
13243                                               ctx->io_options, flags,
13244                                               ctx->superblock, blocksize,
13245                                               io_ptr, &fs);
13246                         if (!retval)
13247                                 break;
13248                 }
13249         } else
13250                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13251                                       flags, 0, 0, io_ptr, &fs);
13252         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13253             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13254             ((retval == EXT2_ET_BAD_MAGIC) ||
13255              ((retval == 0) && ext2fs_check_desc(fs)))) {
13256                 if (!fs || (fs->group_desc_count > 1)) {
13257                         printf(_("%s trying backup blocks...\n"),
13258                                retval ? _("Couldn't find ext2 superblock,") :
13259                                _("Group descriptors look bad..."));
13260                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13261                         if (fs)
13262                                 ext2fs_close(fs);
13263                         goto restart;
13264                 }
13265         }
13266         if (retval) {
13267                 bb_error_msg(_("while trying to open %s"),
13268                         ctx->filesystem_name);
13269                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13270                         printf(_("The filesystem revision is apparently "
13271                                "too high for this version of e2fsck.\n"
13272                                "(Or the filesystem superblock "
13273                                "is corrupt)\n\n"));
13274                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13275                 } else if (retval == EXT2_ET_SHORT_READ)
13276                         printf(_("Could this be a zero-length partition?\n"));
13277                 else if ((retval == EPERM) || (retval == EACCES))
13278                         printf(_("You must have %s access to the "
13279                                "filesystem or be root\n"),
13280                                (ctx->options & E2F_OPT_READONLY) ?
13281                                "r/o" : "r/w");
13282                 else if (retval == ENXIO)
13283                         printf(_("Possibly non-existent or swap device?\n"));
13284 #ifdef EROFS
13285                 else if (retval == EROFS)
13286                         printf(_("Disk write-protected; use the -n option "
13287                                "to do a read-only\n"
13288                                "check of the device.\n"));
13289 #endif
13290                 else
13291                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13292                 bb_error_msg_and_die(0);
13293         }
13294         ctx->fs = fs;
13295         fs->priv_data = ctx;
13296         sb = fs->super;
13297         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13298                 bb_error_msg(_("while trying to open %s"),
13299                         ctx->filesystem_name);
13300         get_newer:
13301                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13302         }
13303
13304         /*
13305          * Set the device name, which is used whenever we print error
13306          * or informational messages to the user.
13307          */
13308         if (ctx->device_name == 0 &&
13309             (sb->s_volume_name[0] != 0)) {
13310                 ctx->device_name = string_copy(sb->s_volume_name,
13311                                                sizeof(sb->s_volume_name));
13312         }
13313         if (ctx->device_name == 0)
13314                 ctx->device_name = ctx->filesystem_name;
13315
13316         /*
13317          * Make sure the ext3 superblock fields are consistent.
13318          */
13319         retval = e2fsck_check_ext3_journal(ctx);
13320         if (retval) {
13321                 bb_error_msg(_("while checking ext3 journal for %s"),
13322                         ctx->device_name);
13323                 bb_error_msg_and_die(0);
13324         }
13325
13326         /*
13327          * Check to see if we need to do ext3-style recovery.  If so,
13328          * do it, and then restart the fsck.
13329          */
13330         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13331                 if (ctx->options & E2F_OPT_READONLY) {
13332                         printf(_("Warning: skipping journal recovery "
13333                                  "because doing a read-only filesystem "
13334                                  "check.\n"));
13335                         io_channel_flush(ctx->fs->io);
13336                 } else {
13337                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13338                                 /*
13339                                  * Whoops, we attempted to run the
13340                                  * journal twice.  This should never
13341                                  * happen, unless the hardware or
13342                                  * device driver is being bogus.
13343                                  */
13344                                 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13345                                 bb_error_msg_and_die(0);
13346                         }
13347                         retval = e2fsck_run_ext3_journal(ctx);
13348                         if (retval) {
13349                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13350                                         ctx->device_name);
13351                                 bb_error_msg_and_die(0);
13352                         }
13353                         ext2fs_close(ctx->fs);
13354                         ctx->fs = 0;
13355                         ctx->flags |= E2F_FLAG_RESTARTED;
13356                         goto restart;
13357                 }
13358         }
13359
13360         /*
13361          * Check for compatibility with the feature sets.  We need to
13362          * be more stringent than ext2fs_open().
13363          */
13364         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13365             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13366                 bb_error_msg("(%s)", ctx->device_name);
13367                 goto get_newer;
13368         }
13369         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13370                 bb_error_msg("(%s)", ctx->device_name);
13371                 goto get_newer;
13372         }
13373 #ifdef ENABLE_COMPRESSION
13374         /* FIXME - do we support this at all? */
13375         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13376                 bb_error_msg(_("warning: compression support is experimental"));
13377 #endif
13378 #ifndef ENABLE_HTREE
13379         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13380                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13381                           "but filesystem %s has HTREE directories."),
13382                         ctx->device_name);
13383                 goto get_newer;
13384         }
13385 #endif
13386
13387         /*
13388          * If the user specified a specific superblock, presumably the
13389          * master superblock has been trashed.  So we mark the
13390          * superblock as dirty, so it can be written out.
13391          */
13392         if (ctx->superblock &&
13393             !(ctx->options & E2F_OPT_READONLY))
13394                 ext2fs_mark_super_dirty(fs);
13395
13396         /*
13397          * We only update the master superblock because (a) paranoia;
13398          * we don't want to corrupt the backup superblocks, and (b) we
13399          * don't need to update the mount count and last checked
13400          * fields in the backup superblock (the kernel doesn't
13401          * update the backup superblocks anyway).
13402          */
13403         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13404
13405         ehandler_init(fs->io);
13406
13407         if (ctx->superblock)
13408                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13409         ext2fs_mark_valid(fs);
13410         check_super_block(ctx);
13411         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13412                 bb_error_msg_and_die(0);
13413         check_if_skip(ctx);
13414         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13415                 bb_error_msg_and_die(0);
13416 #ifdef ENABLE_SWAPFS
13417
13418 #ifdef WORDS_BIGENDIAN
13419 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13420 #else
13421 #define NATIVE_FLAG 0
13422 #endif
13423
13424
13425         if (normalize_swapfs) {
13426                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13427                         fprintf(stderr, _("%s: Filesystem byte order "
13428                                 "already normalized.\n"), ctx->device_name);
13429                         bb_error_msg_and_die(0);
13430                 }
13431         }
13432         if (swapfs) {
13433                 swap_filesys(ctx);
13434                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13435                         bb_error_msg_and_die(0);
13436         }
13437 #endif
13438
13439         /*
13440          * Mark the system as valid, 'til proven otherwise
13441          */
13442         ext2fs_mark_valid(fs);
13443
13444         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13445         if (retval) {
13446                 bb_error_msg(_("while reading bad blocks inode"));
13447                 preenhalt(ctx);
13448                 printf(_("This doesn't bode well,"
13449                          " but we'll try to go on...\n"));
13450         }
13451
13452         run_result = e2fsck_run(ctx);
13453         e2fsck_clear_progbar(ctx);
13454         if (run_result == E2F_FLAG_RESTART) {
13455                 printf(_("Restarting e2fsck from the beginning...\n"));
13456                 retval = e2fsck_reset_context(ctx);
13457                 if (retval) {
13458                         bb_error_msg(_("while resetting context"));
13459                         bb_error_msg_and_die(0);
13460                 }
13461                 ext2fs_close(fs);
13462                 goto restart;
13463         }
13464         if (run_result & E2F_FLAG_CANCEL) {
13465                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13466                        ctx->device_name : ctx->filesystem_name);
13467                 exit_value |= FSCK_CANCELED;
13468         }
13469         if (run_result & E2F_FLAG_ABORT)
13470                 bb_error_msg_and_die(_("aborted"));
13471
13472         /* Cleanup */
13473         if (ext2fs_test_changed(fs)) {
13474                 exit_value |= EXIT_NONDESTRUCT;
13475                 if (!(ctx->options & E2F_OPT_PREEN))
13476                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13477                                ctx->device_name);
13478                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13479                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13480                                ctx->device_name);
13481                         exit_value |= EXIT_DESTRUCT;
13482                 }
13483         }
13484         if (!ext2fs_test_valid(fs)) {
13485                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13486                          "errors **********\n\n"), ctx->device_name);
13487                 exit_value |= EXIT_UNCORRECTED;
13488                 exit_value &= ~EXIT_NONDESTRUCT;
13489         }
13490         if (exit_value & FSCK_CANCELED)
13491                 exit_value &= ~EXIT_NONDESTRUCT;
13492         else {
13493                 show_stats(ctx);
13494                 if (!(ctx->options & E2F_OPT_READONLY)) {
13495                         if (ext2fs_test_valid(fs)) {
13496                                 if (!(sb->s_state & EXT2_VALID_FS))
13497                                         exit_value |= EXIT_NONDESTRUCT;
13498                                 sb->s_state = EXT2_VALID_FS;
13499                         } else
13500                                 sb->s_state &= ~EXT2_VALID_FS;
13501                         sb->s_mnt_count = 0;
13502                         sb->s_lastcheck = time(NULL);
13503                         ext2fs_mark_super_dirty(fs);
13504                 }
13505         }
13506
13507         e2fsck_write_bitmaps(ctx);
13508
13509         ext2fs_close(fs);
13510         ctx->fs = NULL;
13511         free(ctx->filesystem_name);
13512         free(ctx->journal_name);
13513         e2fsck_free_context(ctx);
13514
13515         return exit_value;
13516 }