7384bc45376dfc7c3adcb446a6e6f0a3c92e2b60
[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 tarball for details.
30  */
31
32 #ifndef _GNU_SOURCE
33 #define _GNU_SOURCE 1 /* get strnlen() */
34 #endif
35
36 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
37
38 #define _(x) x
39 #define N_(x) x
40
41 /*
42  * Procedure declarations
43  */
44
45 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
46
47 /* pass1.c */
48 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
49
50 /* pass2.c */
51 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
52                                     ext2_ino_t ino, char *buf);
53
54 /* pass3.c */
55 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
56 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
57                                          int num, int gauranteed_size);
58 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
59 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
60                                            int adj);
61
62 /* rehash.c */
63 static void e2fsck_rehash_directories(e2fsck_t ctx);
64
65 /* util.c */
66 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
67                                     const char *description);
68 static int ask(e2fsck_t ctx, const char * string, int def);
69 static void e2fsck_read_bitmaps(e2fsck_t ctx);
70 static void preenhalt(e2fsck_t ctx);
71 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
72                               struct ext2_inode * inode, const char * proc);
73 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
74                                struct ext2_inode * inode, const char * proc);
75 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
76                            const char *name, io_manager manager);
77
78 /* unix.c */
79 static void e2fsck_clear_progbar(e2fsck_t ctx);
80 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
81                                   float percent, unsigned int dpynum);
82
83
84 /*
85  * problem.h --- e2fsck problem error codes
86  */
87
88 typedef __u32 problem_t;
89
90 struct problem_context {
91         errcode_t       errcode;
92         ext2_ino_t      ino, ino2, dir;
93         struct ext2_inode *inode;
94         struct ext2_dir_entry *dirent;
95         blk_t           blk, blk2;
96         e2_blkcnt_t     blkcount;
97         int             group;
98         __u64           num;
99         const char      *str;
100 };
101
102
103 /*
104  * Function declarations
105  */
106 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
107 static int end_problem_latch(e2fsck_t ctx, int mask);
108 static int set_latch_flags(int mask, int setflags, int clearflags);
109 static void clear_problem_context(struct problem_context *ctx);
110
111 /*
112  * Dictionary Abstract Data Type
113  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
114  *
115  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
116  * kazlib_1_20
117  */
118
119 #ifndef DICT_H
120 #define DICT_H
121
122 /*
123  * Blurb for inclusion into C++ translation units
124  */
125
126 typedef unsigned long dictcount_t;
127 #define DICTCOUNT_T_MAX ULONG_MAX
128
129 /*
130  * The dictionary is implemented as a red-black tree
131  */
132
133 typedef enum { dnode_red, dnode_black } dnode_color_t;
134
135 typedef struct dnode_t {
136         struct dnode_t *dict_left;
137         struct dnode_t *dict_right;
138         struct dnode_t *dict_parent;
139         dnode_color_t dict_color;
140         const void *dict_key;
141         void *dict_data;
142 } dnode_t;
143
144 typedef int (*dict_comp_t)(const void *, const void *);
145 typedef void (*dnode_free_t)(dnode_t *);
146
147 typedef struct dict_t {
148         dnode_t dict_nilnode;
149         dictcount_t dict_nodecount;
150         dictcount_t dict_maxcount;
151         dict_comp_t dict_compare;
152         dnode_free_t dict_freenode;
153         int dict_dupes;
154 } dict_t;
155
156 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
157
158 typedef struct dict_load_t {
159         dict_t *dict_dictptr;
160         dnode_t dict_nilnode;
161 } dict_load_t;
162
163 #define dict_count(D) ((D)->dict_nodecount)
164 #define dnode_get(N) ((N)->dict_data)
165 #define dnode_getkey(N) ((N)->dict_key)
166
167 #endif
168
169 /*
170  * Compatibility header file for e2fsck which should be included
171  * instead of linux/jfs.h
172  *
173  * Copyright (C) 2000 Stephen C. Tweedie
174  */
175
176 /*
177  * Pull in the definition of the e2fsck context structure
178  */
179
180 struct buffer_head {
181         char            b_data[8192];
182         e2fsck_t        b_ctx;
183         io_channel      b_io;
184         int             b_size;
185         blk_t           b_blocknr;
186         int             b_dirty;
187         int             b_uptodate;
188         int             b_err;
189 };
190
191
192 #define K_DEV_FS        1
193 #define K_DEV_JOURNAL   2
194
195 #define lock_buffer(bh) do {} while (0)
196 #define unlock_buffer(bh) do {} while (0)
197 #define buffer_req(bh) 1
198 #define do_readahead(journal, start) do {} while (0)
199
200 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
201
202 typedef struct {
203         int     object_length;
204 } kmem_cache_t;
205
206 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
207
208 /*
209  * We use the standard libext2fs portability tricks for inline
210  * functions.
211  */
212
213 static kmem_cache_t * do_cache_create(int len)
214 {
215         kmem_cache_t *new_cache;
216
217         new_cache = xmalloc(sizeof(*new_cache));
218         new_cache->object_length = len;
219         return new_cache;
220 }
221
222 static void do_cache_destroy(kmem_cache_t *cache)
223 {
224         free(cache);
225 }
226
227
228 /*
229  * Dictionary Abstract Data Type
230  */
231
232
233 /*
234  * These macros provide short convenient names for structure members,
235  * which are embellished with dict_ prefixes so that they are
236  * properly confined to the documented namespace. It's legal for a
237  * program which uses dict to define, for instance, a macro called ``parent''.
238  * Such a macro would interfere with the dnode_t struct definition.
239  * In general, highly portable and reusable C modules which expose their
240  * structures need to confine structure member names to well-defined spaces.
241  * The resulting identifiers aren't necessarily convenient to use, nor
242  * readable, in the implementation, however!
243  */
244
245 #define left dict_left
246 #define right dict_right
247 #define parent dict_parent
248 #define color dict_color
249 #define key dict_key
250 #define data dict_data
251
252 #define nilnode dict_nilnode
253 #define maxcount dict_maxcount
254 #define compare dict_compare
255 #define dupes dict_dupes
256
257 #define dict_root(D) ((D)->nilnode.left)
258 #define dict_nil(D) (&(D)->nilnode)
259
260 static void dnode_free(dnode_t *node);
261
262 /*
263  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
264  * its right child C are rearranged so that the P instead becomes the left
265  * child of C.   The left subtree of C is inherited as the new right subtree
266  * for P.  The ordering of the keys within the tree is thus preserved.
267  */
268
269 static void rotate_left(dnode_t *upper)
270 {
271         dnode_t *lower, *lowleft, *upparent;
272
273         lower = upper->right;
274         upper->right = lowleft = lower->left;
275         lowleft->parent = upper;
276
277         lower->parent = upparent = upper->parent;
278
279         /* don't need to check for root node here because root->parent is
280            the sentinel nil node, and root->parent->left points back to root */
281
282         if (upper == upparent->left) {
283                 upparent->left = lower;
284         } else {
285                 assert (upper == upparent->right);
286                 upparent->right = lower;
287         }
288
289         lower->left = upper;
290         upper->parent = lower;
291 }
292
293 /*
294  * This operation is the ``mirror'' image of rotate_left. It is
295  * the same procedure, but with left and right interchanged.
296  */
297
298 static void rotate_right(dnode_t *upper)
299 {
300         dnode_t *lower, *lowright, *upparent;
301
302         lower = upper->left;
303         upper->left = lowright = lower->right;
304         lowright->parent = upper;
305
306         lower->parent = upparent = upper->parent;
307
308         if (upper == upparent->right) {
309                 upparent->right = lower;
310         } else {
311                 assert (upper == upparent->left);
312                 upparent->left = lower;
313         }
314
315         lower->right = upper;
316         upper->parent = lower;
317 }
318
319 /*
320  * Do a postorder traversal of the tree rooted at the specified
321  * node and free everything under it.  Used by dict_free().
322  */
323
324 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
325 {
326         if (node == nil)
327                 return;
328         free_nodes(dict, node->left, nil);
329         free_nodes(dict, node->right, nil);
330         dict->dict_freenode(node);
331 }
332
333 /*
334  * Verify that the tree contains the given node. This is done by
335  * traversing all of the nodes and comparing their pointers to the
336  * given pointer. Returns 1 if the node is found, otherwise
337  * returns zero. It is intended for debugging purposes.
338  */
339
340 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
341 {
342         if (root != nil) {
343                 return root == node
344                         || verify_dict_has_node(nil, root->left, node)
345                         || verify_dict_has_node(nil, root->right, node);
346         }
347         return 0;
348 }
349
350
351 /*
352  * Select a different set of node allocator routines.
353  */
354
355 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
356 {
357         assert(dict_count(dict) == 0);
358         dict->dict_freenode = fr;
359 }
360
361 /*
362  * Free all the nodes in the dictionary by using the dictionary's
363  * installed free routine. The dictionary is emptied.
364  */
365
366 static void dict_free_nodes(dict_t *dict)
367 {
368         dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
369         free_nodes(dict, root, nil);
370         dict->dict_nodecount = 0;
371         dict->nilnode.left = &dict->nilnode;
372         dict->nilnode.right = &dict->nilnode;
373 }
374
375 /*
376  * Initialize a user-supplied dictionary object.
377  */
378
379 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
380 {
381         dict->compare = comp;
382         dict->dict_freenode = dnode_free;
383         dict->dict_nodecount = 0;
384         dict->maxcount = maxcount;
385         dict->nilnode.left = &dict->nilnode;
386         dict->nilnode.right = &dict->nilnode;
387         dict->nilnode.parent = &dict->nilnode;
388         dict->nilnode.color = dnode_black;
389         dict->dupes = 0;
390         return dict;
391 }
392
393 /*
394  * Locate a node in the dictionary having the given key.
395  * If the node is not found, a null a pointer is returned (rather than
396  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
397  * located node is returned.
398  */
399
400 static dnode_t *dict_lookup(dict_t *dict, const void *key)
401 {
402         dnode_t *root = dict_root(dict);
403         dnode_t *nil = dict_nil(dict);
404         dnode_t *saved;
405         int result;
406
407         /* simple binary search adapted for trees that contain duplicate keys */
408
409         while (root != nil) {
410                 result = dict->compare(key, root->key);
411                 if (result < 0)
412                         root = root->left;
413                 else if (result > 0)
414                         root = root->right;
415                 else {
416                         if (!dict->dupes) { /* no duplicates, return match          */
417                                 return root;
418                         } else {            /* could be dupes, find leftmost one    */
419                                 do {
420                                         saved = root;
421                                         root = root->left;
422                                         while (root != nil && dict->compare(key, root->key))
423                                                 root = root->right;
424                                 } while (root != nil);
425                                 return saved;
426                         }
427                 }
428         }
429
430         return NULL;
431 }
432
433 /*
434  * Insert a node into the dictionary. The node should have been
435  * initialized with a data field. All other fields are ignored.
436  * The behavior is undefined if the user attempts to insert into
437  * a dictionary that is already full (for which the dict_isfull()
438  * function returns true).
439  */
440
441 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
442 {
443         dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
444         dnode_t *parent = nil, *uncle, *grandpa;
445         int result = -1;
446
447         node->key = key;
448
449         /* basic binary tree insert */
450
451         while (where != nil) {
452                 parent = where;
453                 result = dict->compare(key, where->key);
454                 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
455                 assert(dict->dupes || result != 0);
456                 if (result < 0)
457                         where = where->left;
458                 else
459                         where = where->right;
460         }
461
462         assert(where == nil);
463
464         if (result < 0)
465                 parent->left = node;
466         else
467                 parent->right = node;
468
469         node->parent = parent;
470         node->left = nil;
471         node->right = nil;
472
473         dict->dict_nodecount++;
474
475         /* red black adjustments */
476
477         node->color = dnode_red;
478
479         while (parent->color == dnode_red) {
480                 grandpa = parent->parent;
481                 if (parent == grandpa->left) {
482                         uncle = grandpa->right;
483                         if (uncle->color == dnode_red) {    /* red parent, red uncle */
484                                 parent->color = dnode_black;
485                                 uncle->color = dnode_black;
486                                 grandpa->color = dnode_red;
487                                 node = grandpa;
488                                 parent = grandpa->parent;
489                         } else {                            /* red parent, black uncle */
490                                 if (node == parent->right) {
491                                         rotate_left(parent);
492                                         parent = node;
493                                         assert (grandpa == parent->parent);
494                                         /* rotation between parent and child preserves grandpa */
495                                 }
496                                 parent->color = dnode_black;
497                                 grandpa->color = dnode_red;
498                                 rotate_right(grandpa);
499                                 break;
500                         }
501                 } else {        /* symmetric cases: parent == parent->parent->right */
502                         uncle = grandpa->left;
503                         if (uncle->color == dnode_red) {
504                                 parent->color = dnode_black;
505                                 uncle->color = dnode_black;
506                                 grandpa->color = dnode_red;
507                                 node = grandpa;
508                                 parent = grandpa->parent;
509                         } else {
510                                 if (node == parent->left) {
511                                         rotate_right(parent);
512                                         parent = node;
513                                         assert (grandpa == parent->parent);
514                                 }
515                                 parent->color = dnode_black;
516                                 grandpa->color = dnode_red;
517                                 rotate_left(grandpa);
518                                 break;
519                         }
520                 }
521         }
522
523         dict_root(dict)->color = dnode_black;
524
525 }
526
527 /*
528  * Allocate a node using the dictionary's allocator routine, give it
529  * the data item.
530  */
531
532 static dnode_t *dnode_init(dnode_t *dnode, void *data)
533 {
534         dnode->data = data;
535         dnode->parent = NULL;
536         dnode->left = NULL;
537         dnode->right = NULL;
538         return dnode;
539 }
540
541 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
542 {
543         dnode_t *node = xmalloc(sizeof(dnode_t));
544
545         dnode_init(node, data);
546         dict_insert(dict, node, key);
547         return 1;
548 }
549
550 /*
551  * Return the node with the lowest (leftmost) key. If the dictionary is empty
552  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
553  */
554
555 static dnode_t *dict_first(dict_t *dict)
556 {
557         dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
558
559         if (root != nil)
560                 while ((left = root->left) != nil)
561                         root = left;
562
563         return (root == nil) ? NULL : root;
564 }
565
566 /*
567  * Return the given node's successor node---the node which has the
568  * next key in the the left to right ordering. If the node has
569  * no successor, a null pointer is returned rather than a pointer to
570  * the nil node.
571  */
572
573 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
574 {
575         dnode_t *nil = dict_nil(dict), *parent, *left;
576
577         if (curr->right != nil) {
578                 curr = curr->right;
579                 while ((left = curr->left) != nil)
580                         curr = left;
581                 return curr;
582         }
583
584         parent = curr->parent;
585
586         while (parent != nil && curr == parent->right) {
587                 curr = parent;
588                 parent = curr->parent;
589         }
590
591         return (parent == nil) ? NULL : parent;
592 }
593
594
595 static void dnode_free(dnode_t *node)
596 {
597         free(node);
598 }
599
600
601 #undef left
602 #undef right
603 #undef parent
604 #undef color
605 #undef key
606 #undef data
607
608 #undef nilnode
609 #undef maxcount
610 #undef compare
611 #undef dupes
612
613
614 /*
615  * dirinfo.c --- maintains the directory information table for e2fsck.
616  */
617
618 /*
619  * This subroutine is called during pass1 to create a directory info
620  * entry.  During pass1, the passed-in parent is 0; it will get filled
621  * in during pass2.
622  */
623 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
624 {
625         struct dir_info *dir;
626         int             i, j;
627         ext2_ino_t      num_dirs;
628         errcode_t       retval;
629         unsigned long   old_size;
630
631         if (!ctx->dir_info) {
632                 ctx->dir_info_count = 0;
633                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
634                 if (retval)
635                         num_dirs = 1024;        /* Guess */
636                 ctx->dir_info_size = num_dirs + 10;
637                 ctx->dir_info  = (struct dir_info *)
638                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
639                                                * sizeof (struct dir_info),
640                                                "directory map");
641         }
642
643         if (ctx->dir_info_count >= ctx->dir_info_size) {
644                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
645                 ctx->dir_info_size += 10;
646                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
647                                            sizeof(struct dir_info),
648                                            &ctx->dir_info);
649                 if (retval) {
650                         ctx->dir_info_size -= 10;
651                         return;
652                 }
653         }
654
655         /*
656          * Normally, add_dir_info is called with each inode in
657          * sequential order; but once in a while (like when pass 3
658          * needs to recreate the root directory or lost+found
659          * directory) it is called out of order.  In those cases, we
660          * need to move the dir_info entries down to make room, since
661          * the dir_info array needs to be sorted by inode number for
662          * get_dir_info()'s sake.
663          */
664         if (ctx->dir_info_count &&
665             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
666                 for (i = ctx->dir_info_count-1; i > 0; i--)
667                         if (ctx->dir_info[i-1].ino < ino)
668                                 break;
669                 dir = &ctx->dir_info[i];
670                 if (dir->ino != ino)
671                         for (j = ctx->dir_info_count++; j > i; j--)
672                                 ctx->dir_info[j] = ctx->dir_info[j-1];
673         } else
674                 dir = &ctx->dir_info[ctx->dir_info_count++];
675
676         dir->ino = ino;
677         dir->dotdot = parent;
678         dir->parent = parent;
679 }
680
681 /*
682  * get_dir_info() --- given an inode number, try to find the directory
683  * information entry for it.
684  */
685 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
686 {
687         int     low, high, mid;
688
689         low = 0;
690         high = ctx->dir_info_count-1;
691         if (!ctx->dir_info)
692                 return 0;
693         if (ino == ctx->dir_info[low].ino)
694                 return &ctx->dir_info[low];
695         if  (ino == ctx->dir_info[high].ino)
696                 return &ctx->dir_info[high];
697
698         while (low < high) {
699                 mid = (low+high)/2;
700                 if (mid == low || mid == high)
701                         break;
702                 if (ino == ctx->dir_info[mid].ino)
703                         return &ctx->dir_info[mid];
704                 if (ino < ctx->dir_info[mid].ino)
705                         high = mid;
706                 else
707                         low = mid;
708         }
709         return 0;
710 }
711
712 /*
713  * Free the dir_info structure when it isn't needed any more.
714  */
715 static void e2fsck_free_dir_info(e2fsck_t ctx)
716 {
717         ext2fs_free_mem(&ctx->dir_info);
718         ctx->dir_info_size = 0;
719         ctx->dir_info_count = 0;
720 }
721
722 /*
723  * Return the count of number of directories in the dir_info structure
724  */
725 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
726 {
727         return ctx->dir_info_count;
728 }
729
730 /*
731  * A simple interator function
732  */
733 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
734 {
735         if (*control >= ctx->dir_info_count)
736                 return 0;
737
738         return ctx->dir_info + (*control)++;
739 }
740
741 /*
742  * dirinfo.c --- maintains the directory information table for e2fsck.
743  *
744  */
745
746 #ifdef ENABLE_HTREE
747
748 /*
749  * This subroutine is called during pass1 to create a directory info
750  * entry.  During pass1, the passed-in parent is 0; it will get filled
751  * in during pass2.
752  */
753 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
754 {
755         struct dx_dir_info *dir;
756         int             i, j;
757         errcode_t       retval;
758         unsigned long   old_size;
759
760         if (!ctx->dx_dir_info) {
761                 ctx->dx_dir_info_count = 0;
762                 ctx->dx_dir_info_size = 100; /* Guess */
763                 ctx->dx_dir_info  = (struct dx_dir_info *)
764                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
765                                                * sizeof (struct dx_dir_info),
766                                                "directory map");
767         }
768
769         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
770                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
771                 ctx->dx_dir_info_size += 10;
772                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
773                                            sizeof(struct dx_dir_info),
774                                            &ctx->dx_dir_info);
775                 if (retval) {
776                         ctx->dx_dir_info_size -= 10;
777                         return;
778                 }
779         }
780
781         /*
782          * Normally, add_dx_dir_info is called with each inode in
783          * sequential order; but once in a while (like when pass 3
784          * needs to recreate the root directory or lost+found
785          * directory) it is called out of order.  In those cases, we
786          * need to move the dx_dir_info entries down to make room, since
787          * the dx_dir_info array needs to be sorted by inode number for
788          * get_dx_dir_info()'s sake.
789          */
790         if (ctx->dx_dir_info_count &&
791             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
792                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
793                         if (ctx->dx_dir_info[i-1].ino < ino)
794                                 break;
795                 dir = &ctx->dx_dir_info[i];
796                 if (dir->ino != ino)
797                         for (j = ctx->dx_dir_info_count++; j > i; j--)
798                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
799         } else
800                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
801
802         dir->ino = ino;
803         dir->numblocks = num_blocks;
804         dir->hashversion = 0;
805         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
806                                        * sizeof (struct dx_dirblock_info),
807                                        "dx_block info array");
808
809 }
810
811 /*
812  * get_dx_dir_info() --- given an inode number, try to find the directory
813  * information entry for it.
814  */
815 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
816 {
817         int     low, high, mid;
818
819         low = 0;
820         high = ctx->dx_dir_info_count-1;
821         if (!ctx->dx_dir_info)
822                 return 0;
823         if (ino == ctx->dx_dir_info[low].ino)
824                 return &ctx->dx_dir_info[low];
825         if  (ino == ctx->dx_dir_info[high].ino)
826                 return &ctx->dx_dir_info[high];
827
828         while (low < high) {
829                 mid = (low+high)/2;
830                 if (mid == low || mid == high)
831                         break;
832                 if (ino == ctx->dx_dir_info[mid].ino)
833                         return &ctx->dx_dir_info[mid];
834                 if (ino < ctx->dx_dir_info[mid].ino)
835                         high = mid;
836                 else
837                         low = mid;
838         }
839         return 0;
840 }
841
842 /*
843  * Free the dx_dir_info structure when it isn't needed any more.
844  */
845 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
846 {
847         int     i;
848         struct dx_dir_info *dir;
849
850         if (ctx->dx_dir_info) {
851                 dir = ctx->dx_dir_info;
852                 for (i=0; i < ctx->dx_dir_info_count; i++) {
853                         ext2fs_free_mem(&dir->dx_block);
854                 }
855                 ext2fs_free_mem(&ctx->dx_dir_info);
856         }
857         ctx->dx_dir_info_size = 0;
858         ctx->dx_dir_info_count = 0;
859 }
860
861 /*
862  * A simple interator function
863  */
864 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
865 {
866         if (*control >= ctx->dx_dir_info_count)
867                 return 0;
868
869         return ctx->dx_dir_info + (*control)++;
870 }
871
872 #endif /* ENABLE_HTREE */
873 /*
874  * e2fsck.c - a consistency checker for the new extended file system.
875  *
876  */
877
878 /*
879  * This function allocates an e2fsck context
880  */
881 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
882 {
883         e2fsck_t        context;
884         errcode_t       retval;
885
886         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
887         if (retval)
888                 return retval;
889
890         memset(context, 0, sizeof(struct e2fsck_struct));
891
892         context->process_inode_size = 256;
893         context->ext_attr_ver = 2;
894
895         *ret = context;
896         return 0;
897 }
898
899 struct ea_refcount_el {
900         blk_t   ea_blk;
901         int     ea_count;
902 };
903
904 struct ea_refcount {
905         blk_t           count;
906         blk_t           size;
907         blk_t           cursor;
908         struct ea_refcount_el   *list;
909 };
910
911 static void ea_refcount_free(ext2_refcount_t refcount)
912 {
913         if (!refcount)
914                 return;
915
916         ext2fs_free_mem(&refcount->list);
917         ext2fs_free_mem(&refcount);
918 }
919
920 /*
921  * This function resets an e2fsck context; it is called when e2fsck
922  * needs to be restarted.
923  */
924 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
925 {
926         ctx->flags = 0;
927         ctx->lost_and_found = 0;
928         ctx->bad_lost_and_found = 0;
929         ext2fs_free_inode_bitmap(ctx->inode_used_map);
930         ctx->inode_used_map = 0;
931         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
932         ctx->inode_dir_map = 0;
933         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
934         ctx->inode_reg_map = 0;
935         ext2fs_free_block_bitmap(ctx->block_found_map);
936         ctx->block_found_map = 0;
937         ext2fs_free_icount(ctx->inode_link_info);
938         ctx->inode_link_info = 0;
939         if (ctx->journal_io) {
940                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
941                         io_channel_close(ctx->journal_io);
942                 ctx->journal_io = 0;
943         }
944         if (ctx->fs) {
945                 ext2fs_free_dblist(ctx->fs->dblist);
946                 ctx->fs->dblist = 0;
947         }
948         e2fsck_free_dir_info(ctx);
949 #ifdef ENABLE_HTREE
950         e2fsck_free_dx_dir_info(ctx);
951 #endif
952         ea_refcount_free(ctx->refcount);
953         ctx->refcount = 0;
954         ea_refcount_free(ctx->refcount_extra);
955         ctx->refcount_extra = 0;
956         ext2fs_free_block_bitmap(ctx->block_dup_map);
957         ctx->block_dup_map = 0;
958         ext2fs_free_block_bitmap(ctx->block_ea_map);
959         ctx->block_ea_map = 0;
960         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
961         ctx->inode_bad_map = 0;
962         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
963         ctx->inode_imagic_map = 0;
964         ext2fs_u32_list_free(ctx->dirs_to_hash);
965         ctx->dirs_to_hash = 0;
966
967         /*
968          * Clear the array of invalid meta-data flags
969          */
970         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
971         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
972         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
973
974         /* Clear statistic counters */
975         ctx->fs_directory_count = 0;
976         ctx->fs_regular_count = 0;
977         ctx->fs_blockdev_count = 0;
978         ctx->fs_chardev_count = 0;
979         ctx->fs_links_count = 0;
980         ctx->fs_symlinks_count = 0;
981         ctx->fs_fast_symlinks_count = 0;
982         ctx->fs_fifo_count = 0;
983         ctx->fs_total_count = 0;
984         ctx->fs_sockets_count = 0;
985         ctx->fs_ind_count = 0;
986         ctx->fs_dind_count = 0;
987         ctx->fs_tind_count = 0;
988         ctx->fs_fragmented = 0;
989         ctx->large_files = 0;
990
991         /* Reset the superblock to the user's requested value */
992         ctx->superblock = ctx->use_superblock;
993
994         return 0;
995 }
996
997 static void e2fsck_free_context(e2fsck_t ctx)
998 {
999         if (!ctx)
1000                 return;
1001
1002         e2fsck_reset_context(ctx);
1003         if (ctx->blkid)
1004                 blkid_put_cache(ctx->blkid);
1005
1006         ext2fs_free_mem(&ctx);
1007 }
1008
1009 /*
1010  * ea_refcount.c
1011  */
1012
1013 /*
1014  * The strategy we use for keeping track of EA refcounts is as
1015  * follows.  We keep a sorted array of first EA blocks and its
1016  * reference counts.  Once the refcount has dropped to zero, it is
1017  * removed from the array to save memory space.  Once the EA block is
1018  * checked, its bit is set in the block_ea_map bitmap.
1019  */
1020
1021
1022 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1023 {
1024         ext2_refcount_t refcount;
1025         errcode_t       retval;
1026         size_t          bytes;
1027
1028         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1029         if (retval)
1030                 return retval;
1031         memset(refcount, 0, sizeof(struct ea_refcount));
1032
1033         if (!size)
1034                 size = 500;
1035         refcount->size = size;
1036         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1037 #ifdef DEBUG
1038         printf("Refcount allocated %d entries, %d bytes.\n",
1039                refcount->size, bytes);
1040 #endif
1041         retval = ext2fs_get_mem(bytes, &refcount->list);
1042         if (retval)
1043                 goto errout;
1044         memset(refcount->list, 0, bytes);
1045
1046         refcount->count = 0;
1047         refcount->cursor = 0;
1048
1049         *ret = refcount;
1050         return 0;
1051
1052 errout:
1053         ea_refcount_free(refcount);
1054         return retval;
1055 }
1056
1057 /*
1058  * collapse_refcount() --- go through the refcount array, and get rid
1059  * of any count == zero entries
1060  */
1061 static void refcount_collapse(ext2_refcount_t refcount)
1062 {
1063         unsigned int    i, j;
1064         struct ea_refcount_el   *list;
1065
1066         list = refcount->list;
1067         for (i = 0, j = 0; i < refcount->count; i++) {
1068                 if (list[i].ea_count) {
1069                         if (i != j)
1070                                 list[j] = list[i];
1071                         j++;
1072                 }
1073         }
1074 #if defined(DEBUG) || defined(TEST_PROGRAM)
1075         printf("Refcount_collapse: size was %d, now %d\n",
1076                refcount->count, j);
1077 #endif
1078         refcount->count = j;
1079 }
1080
1081
1082 /*
1083  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1084  *      specified position.
1085  */
1086 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1087                                                  blk_t blk, int pos)
1088 {
1089         struct ea_refcount_el   *el;
1090         errcode_t               retval;
1091         blk_t                   new_size = 0;
1092         int                     num;
1093
1094         if (refcount->count >= refcount->size) {
1095                 new_size = refcount->size + 100;
1096 #ifdef DEBUG
1097                 printf("Reallocating refcount %d entries...\n", new_size);
1098 #endif
1099                 retval = ext2fs_resize_mem((size_t) refcount->size *
1100                                            sizeof(struct ea_refcount_el),
1101                                            (size_t) new_size *
1102                                            sizeof(struct ea_refcount_el),
1103                                            &refcount->list);
1104                 if (retval)
1105                         return 0;
1106                 refcount->size = new_size;
1107         }
1108         num = (int) refcount->count - pos;
1109         if (num < 0)
1110                 return 0;       /* should never happen */
1111         if (num) {
1112                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1113                         sizeof(struct ea_refcount_el) * num);
1114         }
1115         refcount->count++;
1116         el = &refcount->list[pos];
1117         el->ea_count = 0;
1118         el->ea_blk = blk;
1119         return el;
1120 }
1121
1122
1123 /*
1124  * get_refcount_el() --- given an block number, try to find refcount
1125  *      information in the sorted list.  If the create flag is set,
1126  *      and we can't find an entry, create one in the sorted list.
1127  */
1128 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1129                                               blk_t blk, int create)
1130 {
1131         float   range;
1132         int     low, high, mid;
1133         blk_t   lowval, highval;
1134
1135         if (!refcount || !refcount->list)
1136                 return 0;
1137 retry:
1138         low = 0;
1139         high = (int) refcount->count-1;
1140         if (create && ((refcount->count == 0) ||
1141                        (blk > refcount->list[high].ea_blk))) {
1142                 if (refcount->count >= refcount->size)
1143                         refcount_collapse(refcount);
1144
1145                 return insert_refcount_el(refcount, blk,
1146                                           (unsigned) refcount->count);
1147         }
1148         if (refcount->count == 0)
1149                 return 0;
1150
1151         if (refcount->cursor >= refcount->count)
1152                 refcount->cursor = 0;
1153         if (blk == refcount->list[refcount->cursor].ea_blk)
1154                 return &refcount->list[refcount->cursor++];
1155 #ifdef DEBUG
1156         printf("Non-cursor get_refcount_el: %u\n", blk);
1157 #endif
1158         while (low <= high) {
1159                 if (low == high)
1160                         mid = low;
1161                 else {
1162                         /* Interpolate for efficiency */
1163                         lowval = refcount->list[low].ea_blk;
1164                         highval = refcount->list[high].ea_blk;
1165
1166                         if (blk < lowval)
1167                                 range = 0;
1168                         else if (blk > highval)
1169                                 range = 1;
1170                         else
1171                                 range = ((float) (blk - lowval)) /
1172                                         (highval - lowval);
1173                         mid = low + ((int) (range * (high-low)));
1174                 }
1175
1176                 if (blk == refcount->list[mid].ea_blk) {
1177                         refcount->cursor = mid+1;
1178                         return &refcount->list[mid];
1179                 }
1180                 if (blk < refcount->list[mid].ea_blk)
1181                         high = mid-1;
1182                 else
1183                         low = mid+1;
1184         }
1185         /*
1186          * If we need to create a new entry, it should be right at
1187          * low (where high will be left at low-1).
1188          */
1189         if (create) {
1190                 if (refcount->count >= refcount->size) {
1191                         refcount_collapse(refcount);
1192                         if (refcount->count < refcount->size)
1193                                 goto retry;
1194                 }
1195                 return insert_refcount_el(refcount, blk, low);
1196         }
1197         return 0;
1198 }
1199
1200 static errcode_t
1201 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1202 {
1203         struct ea_refcount_el   *el;
1204
1205         el = get_refcount_el(refcount, blk, 1);
1206         if (!el)
1207                 return EXT2_ET_NO_MEMORY;
1208         el->ea_count++;
1209
1210         if (ret)
1211                 *ret = el->ea_count;
1212         return 0;
1213 }
1214
1215 static errcode_t
1216 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1217 {
1218         struct ea_refcount_el   *el;
1219
1220         el = get_refcount_el(refcount, blk, 0);
1221         if (!el || el->ea_count == 0)
1222                 return EXT2_ET_INVALID_ARGUMENT;
1223
1224         el->ea_count--;
1225
1226         if (ret)
1227                 *ret = el->ea_count;
1228         return 0;
1229 }
1230
1231 static errcode_t
1232 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1233 {
1234         struct ea_refcount_el   *el;
1235
1236         /*
1237          * Get the refcount element
1238          */
1239         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1240         if (!el)
1241                 return count ? EXT2_ET_NO_MEMORY : 0;
1242         el->ea_count = count;
1243         return 0;
1244 }
1245
1246 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1247 {
1248         refcount->cursor = 0;
1249 }
1250
1251
1252 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1253 {
1254         struct ea_refcount_el   *list;
1255
1256         while (1) {
1257                 if (refcount->cursor >= refcount->count)
1258                         return 0;
1259                 list = refcount->list;
1260                 if (list[refcount->cursor].ea_count) {
1261                         if (ret)
1262                                 *ret = list[refcount->cursor].ea_count;
1263                         return list[refcount->cursor++].ea_blk;
1264                 }
1265                 refcount->cursor++;
1266         }
1267 }
1268
1269
1270 /*
1271  * ehandler.c --- handle bad block errors which come up during the
1272  *      course of an e2fsck session.
1273  */
1274
1275
1276 static const char *operation;
1277
1278 static errcode_t
1279 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1280                          void *data, size_t size FSCK_ATTR((unused)),
1281                          int actual FSCK_ATTR((unused)), errcode_t error)
1282 {
1283         int     i;
1284         char    *p;
1285         ext2_filsys fs = (ext2_filsys) channel->app_data;
1286         e2fsck_t ctx;
1287
1288         ctx = (e2fsck_t) fs->priv_data;
1289
1290         /*
1291          * If more than one block was read, try reading each block
1292          * separately.  We could use the actual bytes read to figure
1293          * out where to start, but we don't bother.
1294          */
1295         if (count > 1) {
1296                 p = (char *) data;
1297                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1298                         error = io_channel_read_blk(channel, block,
1299                                                     1, p);
1300                         if (error)
1301                                 return error;
1302                 }
1303                 return 0;
1304         }
1305         if (operation)
1306                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1307                        error_message(error), operation);
1308         else
1309                 printf(_("Error reading block %lu (%s).  "), block,
1310                        error_message(error));
1311         preenhalt(ctx);
1312         if (ask(ctx, _("Ignore error"), 1)) {
1313                 if (ask(ctx, _("Force rewrite"), 1))
1314                         io_channel_write_blk(channel, block, 1, data);
1315                 return 0;
1316         }
1317
1318         return error;
1319 }
1320
1321 static errcode_t
1322 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1323                         const void *data, size_t size FSCK_ATTR((unused)),
1324                         int actual FSCK_ATTR((unused)), errcode_t error)
1325 {
1326         int             i;
1327         const char      *p;
1328         ext2_filsys fs = (ext2_filsys) channel->app_data;
1329         e2fsck_t ctx;
1330
1331         ctx = (e2fsck_t) fs->priv_data;
1332
1333         /*
1334          * If more than one block was written, try writing each block
1335          * separately.  We could use the actual bytes read to figure
1336          * out where to start, but we don't bother.
1337          */
1338         if (count > 1) {
1339                 p = (const char *) data;
1340                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1341                         error = io_channel_write_blk(channel, block,
1342                                                      1, p);
1343                         if (error)
1344                                 return error;
1345                 }
1346                 return 0;
1347         }
1348
1349         if (operation)
1350                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1351                        error_message(error), operation);
1352         else
1353                 printf(_("Error writing block %lu (%s).  "), block,
1354                        error_message(error));
1355         preenhalt(ctx);
1356         if (ask(ctx, _("Ignore error"), 1))
1357                 return 0;
1358
1359         return error;
1360 }
1361
1362 static const char *ehandler_operation(const char *op)
1363 {
1364         const char *ret = operation;
1365
1366         operation = op;
1367         return ret;
1368 }
1369
1370 static void ehandler_init(io_channel channel)
1371 {
1372         channel->read_error = e2fsck_handle_read_error;
1373         channel->write_error = e2fsck_handle_write_error;
1374 }
1375
1376 /*
1377  * journal.c --- code for handling the "ext3" journal
1378  *
1379  * Copyright (C) 2000 Andreas Dilger
1380  * Copyright (C) 2000 Theodore Ts'o
1381  *
1382  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1383  * Copyright (C) 1999 Red Hat Software
1384  *
1385  * This file may be redistributed under the terms of the
1386  * GNU General Public License version 2 or at your discretion
1387  * any later version.
1388  */
1389
1390 /*
1391  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1392  * This creates a larger static binary, and a smaller binary using
1393  * shared libraries.  It's also probably slightly less CPU-efficient,
1394  * which is why it's not on by default.  But, it's a good way of
1395  * testing the functions in inode_io.c and fileio.c.
1396  */
1397 #undef USE_INODE_IO
1398
1399 /* Kernel compatibility functions for handling the journal.  These allow us
1400  * to use the recovery.c file virtually unchanged from the kernel, so we
1401  * don't have to do much to keep kernel and user recovery in sync.
1402  */
1403 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1404 {
1405 #ifdef USE_INODE_IO
1406         *phys = block;
1407         return 0;
1408 #else
1409         struct inode    *inode = journal->j_inode;
1410         errcode_t       retval;
1411         blk_t           pblk;
1412
1413         if (!inode) {
1414                 *phys = block;
1415                 return 0;
1416         }
1417
1418         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1419                             &inode->i_ext2, NULL, 0, block, &pblk);
1420         *phys = pblk;
1421         return retval;
1422 #endif
1423 }
1424
1425 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1426 {
1427         struct buffer_head *bh;
1428
1429         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1430         if (!bh)
1431                 return NULL;
1432
1433         bh->b_ctx = kdev->k_ctx;
1434         if (kdev->k_dev == K_DEV_FS)
1435                 bh->b_io = kdev->k_ctx->fs->io;
1436         else
1437                 bh->b_io = kdev->k_ctx->journal_io;
1438         bh->b_size = blocksize;
1439         bh->b_blocknr = blocknr;
1440
1441         return bh;
1442 }
1443
1444 static void sync_blockdev(kdev_t kdev)
1445 {
1446         io_channel      io;
1447
1448         if (kdev->k_dev == K_DEV_FS)
1449                 io = kdev->k_ctx->fs->io;
1450         else
1451                 io = kdev->k_ctx->journal_io;
1452
1453         io_channel_flush(io);
1454 }
1455
1456 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1457 {
1458         int retval;
1459         struct buffer_head *bh;
1460
1461         for (; nr > 0; --nr) {
1462                 bh = *bhp++;
1463                 if (rw == READ && !bh->b_uptodate) {
1464                         retval = io_channel_read_blk(bh->b_io,
1465                                                      bh->b_blocknr,
1466                                                      1, bh->b_data);
1467                         if (retval) {
1468                                 bb_error_msg("while reading block %lu",
1469                                         (unsigned long) bh->b_blocknr);
1470                                 bh->b_err = retval;
1471                                 continue;
1472                         }
1473                         bh->b_uptodate = 1;
1474                 } else if (rw == WRITE && bh->b_dirty) {
1475                         retval = io_channel_write_blk(bh->b_io,
1476                                                       bh->b_blocknr,
1477                                                       1, bh->b_data);
1478                         if (retval) {
1479                                 bb_error_msg("while writing block %lu",
1480                                         (unsigned long) bh->b_blocknr);
1481                                 bh->b_err = retval;
1482                                 continue;
1483                         }
1484                         bh->b_dirty = 0;
1485                         bh->b_uptodate = 1;
1486                 }
1487         }
1488 }
1489
1490 static void mark_buffer_dirty(struct buffer_head *bh)
1491 {
1492         bh->b_dirty = 1;
1493 }
1494
1495 static inline void mark_buffer_clean(struct buffer_head * bh)
1496 {
1497         bh->b_dirty = 0;
1498 }
1499
1500 static void brelse(struct buffer_head *bh)
1501 {
1502         if (bh->b_dirty)
1503                 ll_rw_block(WRITE, 1, &bh);
1504         ext2fs_free_mem(&bh);
1505 }
1506
1507 static int buffer_uptodate(struct buffer_head *bh)
1508 {
1509         return bh->b_uptodate;
1510 }
1511
1512 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1513 {
1514         bh->b_uptodate = val;
1515 }
1516
1517 static void wait_on_buffer(struct buffer_head *bh)
1518 {
1519         if (!bh->b_uptodate)
1520                 ll_rw_block(READ, 1, &bh);
1521 }
1522
1523
1524 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1525 {
1526         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1527
1528         /* if we had an error doing journal recovery, we need a full fsck */
1529         if (error)
1530                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1531         ext2fs_mark_super_dirty(ctx->fs);
1532 }
1533
1534 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1535 {
1536         struct ext2_super_block *sb = ctx->fs->super;
1537         struct ext2_super_block jsuper;
1538         struct problem_context  pctx;
1539         struct buffer_head      *bh;
1540         struct inode            *j_inode = NULL;
1541         struct kdev_s           *dev_fs = NULL, *dev_journal;
1542         const char              *journal_name = NULL;
1543         journal_t               *journal = NULL;
1544         errcode_t               retval = 0;
1545         io_manager              io_ptr = 0;
1546         unsigned long           start = 0;
1547         blk_t                   blk;
1548         int                     ext_journal = 0;
1549         int                     tried_backup_jnl = 0;
1550         int                     i;
1551
1552         clear_problem_context(&pctx);
1553
1554         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1555         if (!journal) {
1556                 return EXT2_ET_NO_MEMORY;
1557         }
1558
1559         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1560         if (!dev_fs) {
1561                 retval = EXT2_ET_NO_MEMORY;
1562                 goto errout;
1563         }
1564         dev_journal = dev_fs+1;
1565
1566         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1567         dev_fs->k_dev = K_DEV_FS;
1568         dev_journal->k_dev = K_DEV_JOURNAL;
1569
1570         journal->j_dev = dev_journal;
1571         journal->j_fs_dev = dev_fs;
1572         journal->j_inode = NULL;
1573         journal->j_blocksize = ctx->fs->blocksize;
1574
1575         if (uuid_is_null(sb->s_journal_uuid)) {
1576                 if (!sb->s_journal_inum)
1577                         return EXT2_ET_BAD_INODE_NUM;
1578                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1579                                                  "journal inode");
1580                 if (!j_inode) {
1581                         retval = EXT2_ET_NO_MEMORY;
1582                         goto errout;
1583                 }
1584
1585                 j_inode->i_ctx = ctx;
1586                 j_inode->i_ino = sb->s_journal_inum;
1587
1588                 if ((retval = ext2fs_read_inode(ctx->fs,
1589                                                 sb->s_journal_inum,
1590                                                 &j_inode->i_ext2))) {
1591                 try_backup_journal:
1592                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1593                             tried_backup_jnl)
1594                                 goto errout;
1595                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1596                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1597                                EXT2_N_BLOCKS*4);
1598                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1599                         j_inode->i_ext2.i_links_count = 1;
1600                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1601                         tried_backup_jnl++;
1602                 }
1603                 if (!j_inode->i_ext2.i_links_count ||
1604                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1605                         retval = EXT2_ET_NO_JOURNAL;
1606                         goto try_backup_journal;
1607                 }
1608                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1609                     JFS_MIN_JOURNAL_BLOCKS) {
1610                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1611                         goto try_backup_journal;
1612                 }
1613                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1614                         blk = j_inode->i_ext2.i_block[i];
1615                         if (!blk) {
1616                                 if (i < EXT2_NDIR_BLOCKS) {
1617                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1618                                         goto try_backup_journal;
1619                                 }
1620                                 continue;
1621                         }
1622                         if (blk < sb->s_first_data_block ||
1623                             blk >= sb->s_blocks_count) {
1624                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1625                                 goto try_backup_journal;
1626                         }
1627                 }
1628                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1629
1630 #ifdef USE_INODE_IO
1631                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1632                                                  &j_inode->i_ext2,
1633                                                  &journal_name);
1634                 if (retval)
1635                         goto errout;
1636
1637                 io_ptr = inode_io_manager;
1638 #else
1639                 journal->j_inode = j_inode;
1640                 ctx->journal_io = ctx->fs->io;
1641                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1642                         goto errout;
1643 #endif
1644         } else {
1645                 ext_journal = 1;
1646                 if (!ctx->journal_name) {
1647                         char uuid[37];
1648
1649                         uuid_unparse(sb->s_journal_uuid, uuid);
1650                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1651                                                               "UUID", uuid);
1652                         if (!ctx->journal_name)
1653                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1654                 }
1655                 journal_name = ctx->journal_name;
1656
1657                 if (!journal_name) {
1658                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1659                         return EXT2_ET_LOAD_EXT_JOURNAL;
1660                 }
1661
1662                 io_ptr = unix_io_manager;
1663         }
1664
1665 #ifndef USE_INODE_IO
1666         if (ext_journal)
1667 #endif
1668                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1669                                       &ctx->journal_io);
1670         if (retval)
1671                 goto errout;
1672
1673         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1674
1675         if (ext_journal) {
1676                 if (ctx->fs->blocksize == 1024)
1677                         start = 1;
1678                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1679                 if (!bh) {
1680                         retval = EXT2_ET_NO_MEMORY;
1681                         goto errout;
1682                 }
1683                 ll_rw_block(READ, 1, &bh);
1684                 if ((retval = bh->b_err) != 0)
1685                         goto errout;
1686                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1687                        sizeof(jsuper));
1688                 brelse(bh);
1689 #if BB_BIG_ENDIAN
1690                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1691                         ext2fs_swap_super(&jsuper);
1692 #endif
1693                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1694                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1695                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1696                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1697                         goto errout;
1698                 }
1699                 /* Make sure the journal UUID is correct */
1700                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1701                            sizeof(jsuper.s_uuid))) {
1702                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1703                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1704                         goto errout;
1705                 }
1706
1707                 journal->j_maxlen = jsuper.s_blocks_count;
1708                 start++;
1709         }
1710
1711         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1712                 retval = EXT2_ET_NO_MEMORY;
1713                 goto errout;
1714         }
1715
1716         journal->j_sb_buffer = bh;
1717         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1718
1719 #ifdef USE_INODE_IO
1720         ext2fs_free_mem(&j_inode);
1721 #endif
1722
1723         *ret_journal = journal;
1724         return 0;
1725
1726 errout:
1727         ext2fs_free_mem(&dev_fs);
1728         ext2fs_free_mem(&j_inode);
1729         ext2fs_free_mem(&journal);
1730         return retval;
1731
1732 }
1733
1734 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1735                                               struct problem_context *pctx)
1736 {
1737         struct ext2_super_block *sb = ctx->fs->super;
1738         int recover = ctx->fs->super->s_feature_incompat &
1739                 EXT3_FEATURE_INCOMPAT_RECOVER;
1740         int has_journal = ctx->fs->super->s_feature_compat &
1741                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1742
1743         if (has_journal || sb->s_journal_inum) {
1744                 /* The journal inode is bogus, remove and force full fsck */
1745                 pctx->ino = sb->s_journal_inum;
1746                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1747                         if (has_journal && sb->s_journal_inum)
1748                                 printf("*** ext3 journal has been deleted - "
1749                                        "filesystem is now ext2 only ***\n\n");
1750                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1751                         sb->s_journal_inum = 0;
1752                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1753                         e2fsck_clear_recover(ctx, 1);
1754                         return 0;
1755                 }
1756                 return EXT2_ET_BAD_INODE_NUM;
1757         } else if (recover) {
1758                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1759                         e2fsck_clear_recover(ctx, 1);
1760                         return 0;
1761                 }
1762                 return EXT2_ET_UNSUPP_FEATURE;
1763         }
1764         return 0;
1765 }
1766
1767 #define V1_SB_SIZE      0x0024
1768 static void clear_v2_journal_fields(journal_t *journal)
1769 {
1770         e2fsck_t ctx = journal->j_dev->k_ctx;
1771         struct problem_context pctx;
1772
1773         clear_problem_context(&pctx);
1774
1775         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1776                 return;
1777
1778         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1779                ctx->fs->blocksize-V1_SB_SIZE);
1780         mark_buffer_dirty(journal->j_sb_buffer);
1781 }
1782
1783
1784 static errcode_t e2fsck_journal_load(journal_t *journal)
1785 {
1786         e2fsck_t ctx = journal->j_dev->k_ctx;
1787         journal_superblock_t *jsb;
1788         struct buffer_head *jbh = journal->j_sb_buffer;
1789         struct problem_context pctx;
1790
1791         clear_problem_context(&pctx);
1792
1793         ll_rw_block(READ, 1, &jbh);
1794         if (jbh->b_err) {
1795                 bb_error_msg(_("reading journal superblock"));
1796                 return jbh->b_err;
1797         }
1798
1799         jsb = journal->j_superblock;
1800         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1801         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1802                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1803
1804         switch (ntohl(jsb->s_header.h_blocktype)) {
1805         case JFS_SUPERBLOCK_V1:
1806                 journal->j_format_version = 1;
1807                 if (jsb->s_feature_compat ||
1808                     jsb->s_feature_incompat ||
1809                     jsb->s_feature_ro_compat ||
1810                     jsb->s_nr_users)
1811                         clear_v2_journal_fields(journal);
1812                 break;
1813
1814         case JFS_SUPERBLOCK_V2:
1815                 journal->j_format_version = 2;
1816                 if (ntohl(jsb->s_nr_users) > 1 &&
1817                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1818                         clear_v2_journal_fields(journal);
1819                 if (ntohl(jsb->s_nr_users) > 1) {
1820                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1821                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1822                 }
1823                 break;
1824
1825         /*
1826          * These should never appear in a journal super block, so if
1827          * they do, the journal is badly corrupted.
1828          */
1829         case JFS_DESCRIPTOR_BLOCK:
1830         case JFS_COMMIT_BLOCK:
1831         case JFS_REVOKE_BLOCK:
1832                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1833
1834         /* If we don't understand the superblock major type, but there
1835          * is a magic number, then it is likely to be a new format we
1836          * just don't understand, so leave it alone. */
1837         default:
1838                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1839         }
1840
1841         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1842                 return EXT2_ET_UNSUPP_FEATURE;
1843
1844         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1845                 return EXT2_ET_RO_UNSUPP_FEATURE;
1846
1847         /* We have now checked whether we know enough about the journal
1848          * format to be able to proceed safely, so any other checks that
1849          * fail we should attempt to recover from. */
1850         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1851                 bb_error_msg(_("%s: no valid journal superblock found"),
1852                         ctx->device_name);
1853                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1854         }
1855
1856         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1857                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1858         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1859                 bb_error_msg(_("%s: journal too short"),
1860                         ctx->device_name);
1861                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1862         }
1863
1864         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1865         journal->j_transaction_sequence = journal->j_tail_sequence;
1866         journal->j_tail = ntohl(jsb->s_start);
1867         journal->j_first = ntohl(jsb->s_first);
1868         journal->j_last = ntohl(jsb->s_maxlen);
1869
1870         return 0;
1871 }
1872
1873 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1874                                        journal_t *journal)
1875 {
1876         char *p;
1877         union {
1878                 uuid_t uuid;
1879                 __u32 val[4];
1880         } u;
1881         __u32 new_seq = 0;
1882         int i;
1883
1884         /* Leave a valid existing V1 superblock signature alone.
1885          * Anything unrecognizable we overwrite with a new V2
1886          * signature. */
1887
1888         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1889             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1890                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1891                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1892         }
1893
1894         /* Zero out everything else beyond the superblock header */
1895
1896         p = ((char *) jsb) + sizeof(journal_header_t);
1897         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1898
1899         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1900         jsb->s_maxlen = htonl(journal->j_maxlen);
1901         jsb->s_first = htonl(1);
1902
1903         /* Initialize the journal sequence number so that there is "no"
1904          * chance we will find old "valid" transactions in the journal.
1905          * This avoids the need to zero the whole journal (slow to do,
1906          * and risky when we are just recovering the filesystem).
1907          */
1908         uuid_generate(u.uuid);
1909         for (i = 0; i < 4; i ++)
1910                 new_seq ^= u.val[i];
1911         jsb->s_sequence = htonl(new_seq);
1912
1913         mark_buffer_dirty(journal->j_sb_buffer);
1914         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1915 }
1916
1917 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1918                                                   journal_t *journal,
1919                                                   struct problem_context *pctx)
1920 {
1921         struct ext2_super_block *sb = ctx->fs->super;
1922         int recover = ctx->fs->super->s_feature_incompat &
1923                 EXT3_FEATURE_INCOMPAT_RECOVER;
1924
1925         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1926                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1927                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1928                                                    journal);
1929                         journal->j_transaction_sequence = 1;
1930                         e2fsck_clear_recover(ctx, recover);
1931                         return 0;
1932                 }
1933                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1934         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1935                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1936
1937         return 0;
1938 }
1939
1940 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1941                                    int reset, int drop)
1942 {
1943         journal_superblock_t *jsb;
1944
1945         if (drop)
1946                 mark_buffer_clean(journal->j_sb_buffer);
1947         else if (!(ctx->options & E2F_OPT_READONLY)) {
1948                 jsb = journal->j_superblock;
1949                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1950                 if (reset)
1951                         jsb->s_start = 0; /* this marks the journal as empty */
1952                 mark_buffer_dirty(journal->j_sb_buffer);
1953         }
1954         brelse(journal->j_sb_buffer);
1955
1956         if (ctx->journal_io) {
1957                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1958                         io_channel_close(ctx->journal_io);
1959                 ctx->journal_io = 0;
1960         }
1961
1962 #ifndef USE_INODE_IO
1963         ext2fs_free_mem(&journal->j_inode);
1964 #endif
1965         ext2fs_free_mem(&journal->j_fs_dev);
1966         ext2fs_free_mem(&journal);
1967 }
1968
1969 /*
1970  * This function makes sure that the superblock fields regarding the
1971  * journal are consistent.
1972  */
1973 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1974 {
1975         struct ext2_super_block *sb = ctx->fs->super;
1976         journal_t *journal;
1977         int recover = ctx->fs->super->s_feature_incompat &
1978                 EXT3_FEATURE_INCOMPAT_RECOVER;
1979         struct problem_context pctx;
1980         problem_t problem;
1981         int reset = 0, force_fsck = 0;
1982         int retval;
1983
1984         /* If we don't have any journal features, don't do anything more */
1985         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1986             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1987             uuid_is_null(sb->s_journal_uuid))
1988                 return 0;
1989
1990         clear_problem_context(&pctx);
1991         pctx.num = sb->s_journal_inum;
1992
1993         retval = e2fsck_get_journal(ctx, &journal);
1994         if (retval) {
1995                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1996                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1997                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1998                     (retval == EXT2_ET_NO_JOURNAL))
1999                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2000                 return retval;
2001         }
2002
2003         retval = e2fsck_journal_load(journal);
2004         if (retval) {
2005                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2006                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2007                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2008                                   &pctx))) ||
2009                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2010                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2011                                   &pctx))) ||
2012                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2013                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2014                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2015                                                                   &pctx);
2016                 e2fsck_journal_release(ctx, journal, 0, 1);
2017                 return retval;
2018         }
2019
2020         /*
2021          * We want to make the flags consistent here.  We will not leave with
2022          * needs_recovery set but has_journal clear.  We can't get in a loop
2023          * with -y, -n, or -p, only if a user isn't making up their mind.
2024          */
2025 no_has_journal:
2026         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2027                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2028                 pctx.str = "inode";
2029                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2030                         if (recover &&
2031                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2032                                 goto no_has_journal;
2033                         /*
2034                          * Need a full fsck if we are releasing a
2035                          * journal stored on a reserved inode.
2036                          */
2037                         force_fsck = recover ||
2038                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2039                         /* Clear all of the journal fields */
2040                         sb->s_journal_inum = 0;
2041                         sb->s_journal_dev = 0;
2042                         memset(sb->s_journal_uuid, 0,
2043                                sizeof(sb->s_journal_uuid));
2044                         e2fsck_clear_recover(ctx, force_fsck);
2045                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2046                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2047                         ext2fs_mark_super_dirty(ctx->fs);
2048                 }
2049         }
2050
2051         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2052             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2053             journal->j_superblock->s_start != 0) {
2054                 /* Print status information */
2055                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2056                 if (ctx->superblock)
2057                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2058                 else
2059                         problem = PR_0_JOURNAL_RUN;
2060                 if (fix_problem(ctx, problem, &pctx)) {
2061                         ctx->options |= E2F_OPT_FORCE;
2062                         sb->s_feature_incompat |=
2063                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2064                         ext2fs_mark_super_dirty(ctx->fs);
2065                 } else if (fix_problem(ctx,
2066                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2067                         reset = 1;
2068                         sb->s_state &= ~EXT2_VALID_FS;
2069                         ext2fs_mark_super_dirty(ctx->fs);
2070                 }
2071                 /*
2072                  * If the user answers no to the above question, we
2073                  * ignore the fact that journal apparently has data;
2074                  * accidentally replaying over valid data would be far
2075                  * worse than skipping a questionable recovery.
2076                  *
2077                  * XXX should we abort with a fatal error here?  What
2078                  * will the ext3 kernel code do if a filesystem with
2079                  * !NEEDS_RECOVERY but with a non-zero
2080                  * journal->j_superblock->s_start is mounted?
2081                  */
2082         }
2083
2084         e2fsck_journal_release(ctx, journal, reset, 0);
2085         return retval;
2086 }
2087
2088 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2089 {
2090         journal_t *journal;
2091         int retval;
2092
2093         journal_init_revoke_caches();
2094         retval = e2fsck_get_journal(ctx, &journal);
2095         if (retval)
2096                 return retval;
2097
2098         retval = e2fsck_journal_load(journal);
2099         if (retval)
2100                 goto errout;
2101
2102         retval = journal_init_revoke(journal, 1024);
2103         if (retval)
2104                 goto errout;
2105
2106         retval = -journal_recover(journal);
2107         if (retval)
2108                 goto errout;
2109
2110         if (journal->j_superblock->s_errno) {
2111                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2112                 ext2fs_mark_super_dirty(ctx->fs);
2113                 journal->j_superblock->s_errno = 0;
2114                 mark_buffer_dirty(journal->j_sb_buffer);
2115         }
2116
2117 errout:
2118         journal_destroy_revoke(journal);
2119         journal_destroy_revoke_caches();
2120         e2fsck_journal_release(ctx, journal, 1, 0);
2121         return retval;
2122 }
2123
2124 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2125 {
2126         io_manager io_ptr = ctx->fs->io->manager;
2127         int blocksize = ctx->fs->blocksize;
2128         errcode_t       retval, recover_retval;
2129
2130         printf(_("%s: recovering journal\n"), ctx->device_name);
2131         if (ctx->options & E2F_OPT_READONLY) {
2132                 printf(_("%s: won't do journal recovery while read-only\n"),
2133                        ctx->device_name);
2134                 return EXT2_ET_FILE_RO;
2135         }
2136
2137         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2138                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2139
2140         recover_retval = recover_ext3_journal(ctx);
2141
2142         /*
2143          * Reload the filesystem context to get up-to-date data from disk
2144          * because journal recovery will change the filesystem under us.
2145          */
2146         ext2fs_close(ctx->fs);
2147         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2148                              ctx->superblock, blocksize, io_ptr,
2149                              &ctx->fs);
2150
2151         if (retval) {
2152                 bb_error_msg(_("while trying to re-open %s"),
2153                         ctx->device_name);
2154                 bb_error_msg_and_die(0);
2155         }
2156         ctx->fs->priv_data = ctx;
2157
2158         /* Set the superblock flags */
2159         e2fsck_clear_recover(ctx, recover_retval);
2160         return recover_retval;
2161 }
2162
2163 /*
2164  * This function will move the journal inode from a visible file in
2165  * the filesystem directory hierarchy to the reserved inode if necessary.
2166  */
2167 static const char *const journal_names[] = {
2168         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2169
2170 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2171 {
2172         struct ext2_super_block *sb = ctx->fs->super;
2173         struct problem_context  pctx;
2174         struct ext2_inode       inode;
2175         ext2_filsys             fs = ctx->fs;
2176         ext2_ino_t              ino;
2177         errcode_t               retval;
2178         const char *const *    cpp;
2179         int                     group, mount_flags;
2180
2181         clear_problem_context(&pctx);
2182
2183         /*
2184          * If the filesystem is opened read-only, or there is no
2185          * journal, then do nothing.
2186          */
2187         if ((ctx->options & E2F_OPT_READONLY) ||
2188             (sb->s_journal_inum == 0) ||
2189             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2190                 return;
2191
2192         /*
2193          * Read in the journal inode
2194          */
2195         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2196                 return;
2197
2198         /*
2199          * If it's necessary to backup the journal inode, do so.
2200          */
2201         if ((sb->s_jnl_backup_type == 0) ||
2202             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2203              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2204                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2205                         memcpy(sb->s_jnl_blocks, inode.i_block,
2206                                EXT2_N_BLOCKS*4);
2207                         sb->s_jnl_blocks[16] = inode.i_size;
2208                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2209                         ext2fs_mark_super_dirty(fs);
2210                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2211                 }
2212         }
2213
2214         /*
2215          * If the journal is already the hidden inode, then do nothing
2216          */
2217         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2218                 return;
2219
2220         /*
2221          * The journal inode had better have only one link and not be readable.
2222          */
2223         if (inode.i_links_count != 1)
2224                 return;
2225
2226         /*
2227          * If the filesystem is mounted, or we can't tell whether
2228          * or not it's mounted, do nothing.
2229          */
2230         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2231         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2232                 return;
2233
2234         /*
2235          * If we can't find the name of the journal inode, then do
2236          * nothing.
2237          */
2238         for (cpp = journal_names; *cpp; cpp++) {
2239                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2240                                        strlen(*cpp), 0, &ino);
2241                 if ((retval == 0) && (ino == sb->s_journal_inum))
2242                         break;
2243         }
2244         if (*cpp == 0)
2245                 return;
2246
2247         /* We need the inode bitmap to be loaded */
2248         retval = ext2fs_read_bitmaps(fs);
2249         if (retval)
2250                 return;
2251
2252         pctx.str = *cpp;
2253         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2254                 return;
2255
2256         /*
2257          * OK, we've done all the checks, let's actually move the
2258          * journal inode.  Errors at this point mean we need to force
2259          * an ext2 filesystem check.
2260          */
2261         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2262                 goto err_out;
2263         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2264                 goto err_out;
2265         sb->s_journal_inum = EXT2_JOURNAL_INO;
2266         ext2fs_mark_super_dirty(fs);
2267         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2268         inode.i_links_count = 0;
2269         inode.i_dtime = time(NULL);
2270         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2271                 goto err_out;
2272
2273         group = ext2fs_group_of_ino(fs, ino);
2274         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2275         ext2fs_mark_ib_dirty(fs);
2276         fs->group_desc[group].bg_free_inodes_count++;
2277         fs->super->s_free_inodes_count++;
2278         return;
2279
2280 err_out:
2281         pctx.errcode = retval;
2282         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2283         fs->super->s_state &= ~EXT2_VALID_FS;
2284         ext2fs_mark_super_dirty(fs);
2285 }
2286
2287 /*
2288  * message.c --- print e2fsck messages (with compression)
2289  *
2290  * print_e2fsck_message() prints a message to the user, using
2291  * compression techniques and expansions of abbreviations.
2292  *
2293  * The following % expansions are supported:
2294  *
2295  *      %b      <blk>                   block number
2296  *      %B      <blkcount>              integer
2297  *      %c      <blk2>                  block number
2298  *      %Di     <dirent>->ino           inode number
2299  *      %Dn     <dirent>->name          string
2300  *      %Dr     <dirent>->rec_len
2301  *      %Dl     <dirent>->name_len
2302  *      %Dt     <dirent>->filetype
2303  *      %d      <dir>                   inode number
2304  *      %g      <group>                 integer
2305  *      %i      <ino>                   inode number
2306  *      %Is     <inode> -> i_size
2307  *      %IS     <inode> -> i_extra_isize
2308  *      %Ib     <inode> -> i_blocks
2309  *      %Il     <inode> -> i_links_count
2310  *      %Im     <inode> -> i_mode
2311  *      %IM     <inode> -> i_mtime
2312  *      %IF     <inode> -> i_faddr
2313  *      %If     <inode> -> i_file_acl
2314  *      %Id     <inode> -> i_dir_acl
2315  *      %Iu     <inode> -> i_uid
2316  *      %Ig     <inode> -> i_gid
2317  *      %j      <ino2>                  inode number
2318  *      %m      <com_err error message>
2319  *      %N      <num>
2320  *      %p      ext2fs_get_pathname of directory <ino>
2321  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2322  *                      the containing directory.  (If dirent is NULL
2323  *                      then return the pathname of directory <ino2>)
2324  *      %q      ext2fs_get_pathname of directory <dir>
2325  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2326  *                      the containing directory.
2327  *      %s      <str>                   miscellaneous string
2328  *      %S      backup superblock
2329  *      %X      <num> hexadecimal format
2330  *
2331  * The following '@' expansions are supported:
2332  *
2333  *      @a      extended attribute
2334  *      @A      error allocating
2335  *      @b      block
2336  *      @B      bitmap
2337  *      @c      compress
2338  *      @C      conflicts with some other fs block
2339  *      @D      deleted
2340  *      @d      directory
2341  *      @e      entry
2342  *      @E      Entry '%Dn' in %p (%i)
2343  *      @f      filesystem
2344  *      @F      for @i %i (%Q) is
2345  *      @g      group
2346  *      @h      HTREE directory inode
2347  *      @i      inode
2348  *      @I      illegal
2349  *      @j      journal
2350  *      @l      lost+found
2351  *      @L      is a link
2352  *      @m      multiply-claimed
2353  *      @n      invalid
2354  *      @o      orphaned
2355  *      @p      problem in
2356  *      @r      root inode
2357  *      @s      should be
2358  *      @S      superblock
2359  *      @u      unattached
2360  *      @v      device
2361  *      @z      zero-length
2362  */
2363
2364
2365 /*
2366  * This structure defines the abbreviations used by the text strings
2367  * below.  The first character in the string is the index letter.  An
2368  * abbreviation of the form '@<i>' is expanded by looking up the index
2369  * letter <i> in the table below.
2370  */
2371 static const char *const abbrevs[] = {
2372         N_("aextended attribute"),
2373         N_("Aerror allocating"),
2374         N_("bblock"),
2375         N_("Bbitmap"),
2376         N_("ccompress"),
2377         N_("Cconflicts with some other fs @b"),
2378         N_("iinode"),
2379         N_("Iillegal"),
2380         N_("jjournal"),
2381         N_("Ddeleted"),
2382         N_("ddirectory"),
2383         N_("eentry"),
2384         N_("E@e '%Dn' in %p (%i)"),
2385         N_("ffilesystem"),
2386         N_("Ffor @i %i (%Q) is"),
2387         N_("ggroup"),
2388         N_("hHTREE @d @i"),
2389         N_("llost+found"),
2390         N_("Lis a link"),
2391         N_("mmultiply-claimed"),
2392         N_("ninvalid"),
2393         N_("oorphaned"),
2394         N_("pproblem in"),
2395         N_("rroot @i"),
2396         N_("sshould be"),
2397         N_("Ssuper@b"),
2398         N_("uunattached"),
2399         N_("vdevice"),
2400         N_("zzero-length"),
2401         "@@",
2402         0
2403         };
2404
2405 /*
2406  * Give more user friendly names to the "special" inodes.
2407  */
2408 #define num_special_inodes      11
2409 static const char *const special_inode_name[] =
2410 {
2411         N_("<The NULL inode>"),                 /* 0 */
2412         N_("<The bad blocks inode>"),           /* 1 */
2413         "/",                                    /* 2 */
2414         N_("<The ACL index inode>"),            /* 3 */
2415         N_("<The ACL data inode>"),             /* 4 */
2416         N_("<The boot loader inode>"),          /* 5 */
2417         N_("<The undelete directory inode>"),   /* 6 */
2418         N_("<The group descriptor inode>"),     /* 7 */
2419         N_("<The journal inode>"),              /* 8 */
2420         N_("<Reserved inode 9>"),               /* 9 */
2421         N_("<Reserved inode 10>"),              /* 10 */
2422 };
2423
2424 /*
2425  * This function does "safe" printing.  It will convert non-printable
2426  * ASCII characters using '^' and M- notation.
2427  */
2428 static void safe_print(const char *cp, int len)
2429 {
2430         unsigned char   ch;
2431
2432         if (len < 0)
2433                 len = strlen(cp);
2434
2435         while (len--) {
2436                 ch = *cp++;
2437                 if (ch > 128) {
2438                         fputs("M-", stdout);
2439                         ch -= 128;
2440                 }
2441                 if ((ch < 32) || (ch == 0x7f)) {
2442                         bb_putchar('^');
2443                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2444                 }
2445                 bb_putchar(ch);
2446         }
2447 }
2448
2449
2450 /*
2451  * This function prints a pathname, using the ext2fs_get_pathname
2452  * function
2453  */
2454 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2455 {
2456         errcode_t       retval;
2457         char            *path;
2458
2459         if (!dir && (ino < num_special_inodes)) {
2460                 fputs(_(special_inode_name[ino]), stdout);
2461                 return;
2462         }
2463
2464         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2465         if (retval)
2466                 fputs("???", stdout);
2467         else {
2468                 safe_print(path, -1);
2469                 ext2fs_free_mem(&path);
2470         }
2471 }
2472
2473 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2474                           struct problem_context *pctx, int first);
2475 /*
2476  * This function handles the '@' expansion.  We allow recursive
2477  * expansion; an @ expression can contain further '@' and '%'
2478  * expressions.
2479  */
2480 static void expand_at_expression(e2fsck_t ctx, char ch,
2481                                           struct problem_context *pctx,
2482                                           int *first)
2483 {
2484         const char *const *cpp;
2485         const char *str;
2486
2487         /* Search for the abbreviation */
2488         for (cpp = abbrevs; *cpp; cpp++) {
2489                 if (ch == *cpp[0])
2490                         break;
2491         }
2492         if (*cpp) {
2493                 str = _(*cpp) + 1;
2494                 if (*first && islower(*str)) {
2495                         *first = 0;
2496                         bb_putchar(toupper(*str++));
2497                 }
2498                 print_e2fsck_message(ctx, str, pctx, *first);
2499         } else
2500                 printf("@%c", ch);
2501 }
2502
2503 /*
2504  * This function expands '%IX' expressions
2505  */
2506 static void expand_inode_expression(char ch,
2507                                              struct problem_context *ctx)
2508 {
2509         struct ext2_inode       *inode;
2510         struct ext2_inode_large *large_inode;
2511         char *                  time_str;
2512         time_t                  t;
2513         int                     do_gmt = -1;
2514
2515         if (!ctx || !ctx->inode)
2516                 goto no_inode;
2517
2518         inode = ctx->inode;
2519         large_inode = (struct ext2_inode_large *) inode;
2520
2521         switch (ch) {
2522         case 's':
2523                 if (LINUX_S_ISDIR(inode->i_mode))
2524                         printf("%u", inode->i_size);
2525                 else {
2526                         printf("%"PRIu64, (inode->i_size |
2527                                         ((uint64_t) inode->i_size_high << 32)));
2528                 }
2529                 break;
2530         case 'S':
2531                 printf("%u", large_inode->i_extra_isize);
2532                 break;
2533         case 'b':
2534                 printf("%u", inode->i_blocks);
2535                 break;
2536         case 'l':
2537                 printf("%d", inode->i_links_count);
2538                 break;
2539         case 'm':
2540                 printf("0%o", inode->i_mode);
2541                 break;
2542         case 'M':
2543                 /* The diet libc doesn't respect the TZ environemnt variable */
2544                 if (do_gmt == -1) {
2545                         time_str = getenv("TZ");
2546                         if (!time_str)
2547                                 time_str = "";
2548                         do_gmt = !strcmp(time_str, "GMT");
2549                 }
2550                 t = inode->i_mtime;
2551                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2552                 printf("%.24s", time_str);
2553                 break;
2554         case 'F':
2555                 printf("%u", inode->i_faddr);
2556                 break;
2557         case 'f':
2558                 printf("%u", inode->i_file_acl);
2559                 break;
2560         case 'd':
2561                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2562                               inode->i_dir_acl : 0));
2563                 break;
2564         case 'u':
2565                 printf("%d", (inode->i_uid |
2566                               (inode->osd2.linux2.l_i_uid_high << 16)));
2567                 break;
2568         case 'g':
2569                 printf("%d", (inode->i_gid |
2570                               (inode->osd2.linux2.l_i_gid_high << 16)));
2571                 break;
2572         default:
2573         no_inode:
2574                 printf("%%I%c", ch);
2575                 break;
2576         }
2577 }
2578
2579 /*
2580  * This function expands '%dX' expressions
2581  */
2582 static void expand_dirent_expression(char ch,
2583                                               struct problem_context *ctx)
2584 {
2585         struct ext2_dir_entry   *dirent;
2586         int     len;
2587
2588         if (!ctx || !ctx->dirent)
2589                 goto no_dirent;
2590
2591         dirent = ctx->dirent;
2592
2593         switch (ch) {
2594         case 'i':
2595                 printf("%u", dirent->inode);
2596                 break;
2597         case 'n':
2598                 len = dirent->name_len & 0xFF;
2599                 if (len > EXT2_NAME_LEN)
2600                         len = EXT2_NAME_LEN;
2601                 if (len > dirent->rec_len)
2602                         len = dirent->rec_len;
2603                 safe_print(dirent->name, len);
2604                 break;
2605         case 'r':
2606                 printf("%u", dirent->rec_len);
2607                 break;
2608         case 'l':
2609                 printf("%u", dirent->name_len & 0xFF);
2610                 break;
2611         case 't':
2612                 printf("%u", dirent->name_len >> 8);
2613                 break;
2614         default:
2615         no_dirent:
2616                 printf("%%D%c", ch);
2617                 break;
2618         }
2619 }
2620
2621 static void expand_percent_expression(ext2_filsys fs, char ch,
2622                                                struct problem_context *ctx)
2623 {
2624         if (!ctx)
2625                 goto no_context;
2626
2627         switch (ch) {
2628         case '%':
2629                 bb_putchar('%');
2630                 break;
2631         case 'b':
2632                 printf("%u", ctx->blk);
2633                 break;
2634         case 'B':
2635                 printf("%"PRIi64, ctx->blkcount);
2636                 break;
2637         case 'c':
2638                 printf("%u", ctx->blk2);
2639                 break;
2640         case 'd':
2641                 printf("%u", ctx->dir);
2642                 break;
2643         case 'g':
2644                 printf("%d", ctx->group);
2645                 break;
2646         case 'i':
2647                 printf("%u", ctx->ino);
2648                 break;
2649         case 'j':
2650                 printf("%u", ctx->ino2);
2651                 break;
2652         case 'm':
2653                 fputs(error_message(ctx->errcode), stdout);
2654                 break;
2655         case 'N':
2656                 printf("%"PRIi64, ctx->num);
2657                 break;
2658         case 'p':
2659                 print_pathname(fs, ctx->ino, 0);
2660                 break;
2661         case 'P':
2662                 print_pathname(fs, ctx->ino2,
2663                                ctx->dirent ? ctx->dirent->inode : 0);
2664                 break;
2665         case 'q':
2666                 print_pathname(fs, ctx->dir, 0);
2667                 break;
2668         case 'Q':
2669                 print_pathname(fs, ctx->dir, ctx->ino);
2670                 break;
2671         case 'S':
2672                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2673                 break;
2674         case 's':
2675                 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2676                 break;
2677         case 'X':
2678                 printf("0x%"PRIi64, ctx->num);
2679                 break;
2680         default:
2681         no_context:
2682                 printf("%%%c", ch);
2683                 break;
2684         }
2685 }
2686
2687
2688 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2689                           struct problem_context *pctx, int first)
2690 {
2691         ext2_filsys fs = ctx->fs;
2692         const char *    cp;
2693         int             i;
2694
2695         e2fsck_clear_progbar(ctx);
2696         for (cp = msg; *cp; cp++) {
2697                 if (cp[0] == '@') {
2698                         cp++;
2699                         expand_at_expression(ctx, *cp, pctx, &first);
2700                 } else if (cp[0] == '%' && cp[1] == 'I') {
2701                         cp += 2;
2702                         expand_inode_expression(*cp, pctx);
2703                 } else if (cp[0] == '%' && cp[1] == 'D') {
2704                         cp += 2;
2705                         expand_dirent_expression(*cp, pctx);
2706                 } else if ((cp[0] == '%')) {
2707                         cp++;
2708                         expand_percent_expression(fs, *cp, pctx);
2709                 } else {
2710                         for (i=0; cp[i]; i++)
2711                                 if ((cp[i] == '@') || cp[i] == '%')
2712                                         break;
2713                         printf("%.*s", i, cp);
2714                         cp += i-1;
2715                 }
2716                 first = 0;
2717         }
2718 }
2719
2720
2721 /*
2722  * region.c --- code which manages allocations within a region.
2723  */
2724
2725 struct region_el {
2726         region_addr_t   start;
2727         region_addr_t   end;
2728         struct region_el *next;
2729 };
2730
2731 struct region_struct {
2732         region_addr_t   min;
2733         region_addr_t   max;
2734         struct region_el *allocated;
2735 };
2736
2737 static region_t region_create(region_addr_t min, region_addr_t max)
2738 {
2739         region_t        region;
2740
2741         region = xzalloc(sizeof(struct region_struct));
2742         region->min = min;
2743         region->max = max;
2744         return region;
2745 }
2746
2747 static void region_free(region_t region)
2748 {
2749         struct region_el        *r, *next;
2750
2751         for (r = region->allocated; r; r = next) {
2752                 next = r->next;
2753                 free(r);
2754         }
2755         memset(region, 0, sizeof(struct region_struct));
2756         free(region);
2757 }
2758
2759 static int region_allocate(region_t region, region_addr_t start, int n)
2760 {
2761         struct region_el        *r, *new_region, *prev, *next;
2762         region_addr_t end;
2763
2764         end = start+n;
2765         if ((start < region->min) || (end > region->max))
2766                 return -1;
2767         if (n == 0)
2768                 return 1;
2769
2770         /*
2771          * Search through the linked list.  If we find that it
2772          * conflicts witih something that's already allocated, return
2773          * 1; if we can find an existing region which we can grow, do
2774          * so.  Otherwise, stop when we find the appropriate place
2775          * insert a new region element into the linked list.
2776          */
2777         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2778                 if (((start >= r->start) && (start < r->end)) ||
2779                     ((end > r->start) && (end <= r->end)) ||
2780                     ((start <= r->start) && (end >= r->end)))
2781                         return 1;
2782                 if (end == r->start) {
2783                         r->start = start;
2784                         return 0;
2785                 }
2786                 if (start == r->end) {
2787                         if ((next = r->next)) {
2788                                 if (end > next->start)
2789                                         return 1;
2790                                 if (end == next->start) {
2791                                         r->end = next->end;
2792                                         r->next = next->next;
2793                                         free(next);
2794                                         return 0;
2795                                 }
2796                         }
2797                         r->end = end;
2798                         return 0;
2799                 }
2800                 if (start < r->start)
2801                         break;
2802         }
2803         /*
2804          * Insert a new region element structure into the linked list
2805          */
2806         new_region = xmalloc(sizeof(struct region_el));
2807         new_region->start = start;
2808         new_region->end = start + n;
2809         new_region->next = r;
2810         if (prev)
2811                 prev->next = new_region;
2812         else
2813                 region->allocated = new_region;
2814         return 0;
2815 }
2816
2817 /*
2818  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2819  *
2820  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2821  * and applies the following tests to each inode:
2822  *
2823  *      - The mode field of the inode must be legal.
2824  *      - The size and block count fields of the inode are correct.
2825  *      - A data block must not be used by another inode
2826  *
2827  * Pass 1 also gathers the collects the following information:
2828  *
2829  *      - A bitmap of which inodes are in use.          (inode_used_map)
2830  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2831  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2832  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2833  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2834  *      - A bitmap of which blocks are in use.          (block_found_map)
2835  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2836  *      - The data blocks of the directory inodes.      (dir_map)
2837  *
2838  * Pass 1 is designed to stash away enough information so that the
2839  * other passes should not need to read in the inode information
2840  * during the normal course of a filesystem check.  (Althogh if an
2841  * inconsistency is detected, other passes may need to read in an
2842  * inode to fix it.)
2843  *
2844  * Note that pass 1B will be invoked if there are any duplicate blocks
2845  * found.
2846  */
2847
2848
2849 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2850                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2851                          int ref_offset, void *priv_data);
2852 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2853                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2854                              int ref_offset, void *priv_data);
2855 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2856                          char *block_buf);
2857 static void mark_table_blocks(e2fsck_t ctx);
2858 static void alloc_imagic_map(e2fsck_t ctx);
2859 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2860 static void handle_fs_bad_blocks(e2fsck_t ctx);
2861 static void process_inodes(e2fsck_t ctx, char *block_buf);
2862 static int process_inode_cmp(const void *a, const void *b);
2863 static errcode_t scan_callback(ext2_filsys fs,
2864                                   dgrp_t group, void * priv_data);
2865 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2866                                     char *block_buf, int adjust_sign);
2867 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2868
2869 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2870                                struct ext2_inode * inode, int bufsize,
2871                                const char *proc);
2872
2873 struct process_block_struct_1 {
2874         ext2_ino_t      ino;
2875         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2876                                 fragmented:1, compressed:1, bbcheck:1;
2877         blk_t           num_blocks;
2878         blk_t           max_blocks;
2879         e2_blkcnt_t     last_block;
2880         int             num_illegal_blocks;
2881         blk_t           previous_block;
2882         struct ext2_inode *inode;
2883         struct problem_context *pctx;
2884         ext2fs_block_bitmap fs_meta_blocks;
2885         e2fsck_t        ctx;
2886 };
2887
2888 struct process_inode_block {
2889         ext2_ino_t ino;
2890         struct ext2_inode inode;
2891 };
2892
2893 struct scan_callback_struct {
2894         e2fsck_t        ctx;
2895         char            *block_buf;
2896 };
2897
2898 /*
2899  * For the inodes to process list.
2900  */
2901 static struct process_inode_block *inodes_to_process;
2902 static int process_inode_count;
2903
2904 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2905                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2906
2907 /*
2908  * Free all memory allocated by pass1 in preparation for restarting
2909  * things.
2910  */
2911 static void unwind_pass1(void)
2912 {
2913         ext2fs_free_mem(&inodes_to_process);
2914 }
2915
2916 /*
2917  * Check to make sure a device inode is real.  Returns 1 if the device
2918  * checks out, 0 if not.
2919  *
2920  * Note: this routine is now also used to check FIFO's and Sockets,
2921  * since they have the same requirement; the i_block fields should be
2922  * zero.
2923  */
2924 static int
2925 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2926 {
2927         int     i;
2928
2929         /*
2930          * If i_blocks is non-zero, or the index flag is set, then
2931          * this is a bogus device/fifo/socket
2932          */
2933         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2934             (inode->i_flags & EXT2_INDEX_FL))
2935                 return 0;
2936
2937         /*
2938          * We should be able to do the test below all the time, but
2939          * because the kernel doesn't forcibly clear the device
2940          * inode's additional i_block fields, there are some rare
2941          * occasions when a legitimate device inode will have non-zero
2942          * additional i_block fields.  So for now, we only complain
2943          * when the immutable flag is set, which should never happen
2944          * for devices.  (And that's when the problem is caused, since
2945          * you can't set or clear immutable flags for devices.)  Once
2946          * the kernel has been fixed we can change this...
2947          */
2948         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2949                 for (i=4; i < EXT2_N_BLOCKS; i++)
2950                         if (inode->i_block[i])
2951                                 return 0;
2952         }
2953         return 1;
2954 }
2955
2956 /*
2957  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2958  * checks out, 0 if not.
2959  */
2960 static int
2961 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2962 {
2963         unsigned int len;
2964         int i;
2965         blk_t   blocks;
2966
2967         if ((inode->i_size_high || inode->i_size == 0) ||
2968             (inode->i_flags & EXT2_INDEX_FL))
2969                 return 0;
2970
2971         blocks = ext2fs_inode_data_blocks(fs, inode);
2972         if (blocks) {
2973                 if ((inode->i_size >= fs->blocksize) ||
2974                     (blocks != fs->blocksize >> 9) ||
2975                     (inode->i_block[0] < fs->super->s_first_data_block) ||
2976                     (inode->i_block[0] >= fs->super->s_blocks_count))
2977                         return 0;
2978
2979                 for (i = 1; i < EXT2_N_BLOCKS; i++)
2980                         if (inode->i_block[i])
2981                                 return 0;
2982
2983                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2984                         return 0;
2985
2986                 len = strnlen(buf, fs->blocksize);
2987                 if (len == fs->blocksize)
2988                         return 0;
2989         } else {
2990                 if (inode->i_size >= sizeof(inode->i_block))
2991                         return 0;
2992
2993                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2994                 if (len == sizeof(inode->i_block))
2995                         return 0;
2996         }
2997         if (len != inode->i_size)
2998                 return 0;
2999         return 1;
3000 }
3001
3002 /*
3003  * If the immutable (or append-only) flag is set on the inode, offer
3004  * to clear it.
3005  */
3006 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3007 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3008 {
3009         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3010                 return;
3011
3012         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3013                 return;
3014
3015         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3016         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3017 }
3018
3019 /*
3020  * If device, fifo or socket, check size is zero -- if not offer to
3021  * clear it
3022  */
3023 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3024 {
3025         struct ext2_inode *inode = pctx->inode;
3026
3027         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3028                 return;
3029
3030         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3031                 return;
3032
3033         inode->i_size = 0;
3034         inode->i_size_high = 0;
3035         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3036 }
3037
3038 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3039 {
3040         struct ext2_super_block *sb = ctx->fs->super;
3041         struct ext2_inode_large *inode;
3042         struct ext2_ext_attr_entry *entry;
3043         char *start, *end;
3044         int storage_size, remain, offs;
3045         int problem = 0;
3046
3047         inode = (struct ext2_inode_large *) pctx->inode;
3048         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3049                 inode->i_extra_isize;
3050         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3051                 inode->i_extra_isize + sizeof(__u32);
3052         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3053         entry = (struct ext2_ext_attr_entry *) start;
3054
3055         /* scan all entry's headers first */
3056
3057         /* take finish entry 0UL into account */
3058         remain = storage_size - sizeof(__u32);
3059         offs = end - start;
3060
3061         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3062
3063                 /* header eats this space */
3064                 remain -= sizeof(struct ext2_ext_attr_entry);
3065
3066                 /* is attribute name valid? */
3067                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3068                         pctx->num = entry->e_name_len;
3069                         problem = PR_1_ATTR_NAME_LEN;
3070                         goto fix;
3071                 }
3072
3073                 /* attribute len eats this space */
3074                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3075
3076                 /* check value size */
3077                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3078                         pctx->num = entry->e_value_size;
3079                         problem = PR_1_ATTR_VALUE_SIZE;
3080                         goto fix;
3081                 }
3082
3083                 /* check value placement */
3084                 if (entry->e_value_offs +
3085                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3086                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3087                         pctx->num = entry->e_value_offs;
3088                         problem = PR_1_ATTR_VALUE_OFFSET;
3089                         goto fix;
3090                 }
3091
3092                 /* e_value_block must be 0 in inode's ea */
3093                 if (entry->e_value_block != 0) {
3094                         pctx->num = entry->e_value_block;
3095                         problem = PR_1_ATTR_VALUE_BLOCK;
3096                         goto fix;
3097                 }
3098
3099                 /* e_hash must be 0 in inode's ea */
3100                 if (entry->e_hash != 0) {
3101                         pctx->num = entry->e_hash;
3102                         problem = PR_1_ATTR_HASH;
3103                         goto fix;
3104                 }
3105
3106                 remain -= entry->e_value_size;
3107                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3108
3109                 entry = EXT2_EXT_ATTR_NEXT(entry);
3110         }
3111 fix:
3112         /*
3113          * it seems like a corruption. it's very unlikely we could repair
3114          * EA(s) in automatic fashion -bzzz
3115          */
3116         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3117                 return;
3118
3119         /* simple remove all possible EA(s) */
3120         *((__u32 *)start) = 0UL;
3121         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3122                                 EXT2_INODE_SIZE(sb), "pass1");
3123 }
3124
3125 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3126 {
3127         struct ext2_super_block *sb = ctx->fs->super;
3128         struct ext2_inode_large *inode;
3129         __u32 *eamagic;
3130         int min, max;
3131
3132         inode = (struct ext2_inode_large *) pctx->inode;
3133         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3134                 /* this isn't large inode. so, nothing to check */
3135                 return;
3136         }
3137
3138         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3139         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3140         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3141         /*
3142          * For now we will allow i_extra_isize to be 0, but really
3143          * implementations should never allow i_extra_isize to be 0
3144          */
3145         if (inode->i_extra_isize &&
3146             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3147                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3148                         return;
3149                 inode->i_extra_isize = min;
3150                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3151                                         EXT2_INODE_SIZE(sb), "pass1");
3152                 return;
3153         }
3154
3155         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3156                         inode->i_extra_isize);
3157         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3158                 /* it seems inode has an extended attribute(s) in body */
3159                 check_ea_in_inode(ctx, pctx);
3160         }
3161 }
3162
3163 static void e2fsck_pass1(e2fsck_t ctx)
3164 {
3165         int     i;
3166         __u64   max_sizes;
3167         ext2_filsys fs = ctx->fs;
3168         ext2_ino_t      ino;
3169         struct ext2_inode *inode;
3170         ext2_inode_scan scan;
3171         char            *block_buf;
3172         unsigned char   frag, fsize;
3173         struct          problem_context pctx;
3174         struct          scan_callback_struct scan_struct;
3175         struct ext2_super_block *sb = ctx->fs->super;
3176         int             imagic_fs;
3177         int             busted_fs_time = 0;
3178         int             inode_size;
3179
3180         clear_problem_context(&pctx);
3181
3182         if (!(ctx->options & E2F_OPT_PREEN))
3183                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3184
3185         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3186             !(ctx->options & E2F_OPT_NO)) {
3187                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3188                         ctx->dirs_to_hash = 0;
3189         }
3190
3191         /* Pass 1 */
3192
3193 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3194
3195         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3196                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3197                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3198                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3199                 max_sizes = (max_sizes * (1UL << i)) - 1;
3200                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3201         }
3202 #undef EXT2_BPP
3203
3204         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3205
3206         /*
3207          * Allocate bitmaps structures
3208          */
3209         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3210                                               &ctx->inode_used_map);
3211         if (pctx.errcode) {
3212                 pctx.num = 1;
3213                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3214                 ctx->flags |= E2F_FLAG_ABORT;
3215                 return;
3216         }
3217         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3218                                 _("directory inode map"), &ctx->inode_dir_map);
3219         if (pctx.errcode) {
3220                 pctx.num = 2;
3221                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3222                 ctx->flags |= E2F_FLAG_ABORT;
3223                 return;
3224         }
3225         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3226                         _("regular file inode map"), &ctx->inode_reg_map);
3227         if (pctx.errcode) {
3228                 pctx.num = 6;
3229                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3230                 ctx->flags |= E2F_FLAG_ABORT;
3231                 return;
3232         }
3233         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3234                                               &ctx->block_found_map);
3235         if (pctx.errcode) {
3236                 pctx.num = 1;
3237                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3238                 ctx->flags |= E2F_FLAG_ABORT;
3239                 return;
3240         }
3241         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3242                                              &ctx->inode_link_info);
3243         if (pctx.errcode) {
3244                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3245                 ctx->flags |= E2F_FLAG_ABORT;
3246                 return;
3247         }
3248         inode_size = EXT2_INODE_SIZE(fs->super);
3249         inode = (struct ext2_inode *)
3250                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3251
3252         inodes_to_process = (struct process_inode_block *)
3253                 e2fsck_allocate_memory(ctx,
3254                                        (ctx->process_inode_size *
3255                                         sizeof(struct process_inode_block)),
3256                                        "array of inodes to process");
3257         process_inode_count = 0;
3258
3259         pctx.errcode = ext2fs_init_dblist(fs, 0);
3260         if (pctx.errcode) {
3261                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3262                 ctx->flags |= E2F_FLAG_ABORT;
3263                 return;
3264         }
3265
3266         /*
3267          * If the last orphan field is set, clear it, since the pass1
3268          * processing will automatically find and clear the orphans.
3269          * In the future, we may want to try using the last_orphan
3270          * linked list ourselves, but for now, we clear it so that the
3271          * ext3 mount code won't get confused.
3272          */
3273         if (!(ctx->options & E2F_OPT_READONLY)) {
3274                 if (fs->super->s_last_orphan) {
3275                         fs->super->s_last_orphan = 0;
3276                         ext2fs_mark_super_dirty(fs);
3277                 }
3278         }
3279
3280         mark_table_blocks(ctx);
3281         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3282                                                     "block interate buffer");
3283         e2fsck_use_inode_shortcuts(ctx, 1);
3284         ehandler_operation(_("doing inode scan"));
3285         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3286                                               &scan);
3287         if (pctx.errcode) {
3288                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3289                 ctx->flags |= E2F_FLAG_ABORT;
3290                 return;
3291         }
3292         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3293         ctx->stashed_inode = inode;
3294         scan_struct.ctx = ctx;
3295         scan_struct.block_buf = block_buf;
3296         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3297         if (ctx->progress)
3298                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3299                         return;
3300         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3301             (fs->super->s_mtime < fs->super->s_inodes_count))
3302                 busted_fs_time = 1;
3303
3304         while (1) {
3305                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3306                                                           inode, inode_size);
3307                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3308                         return;
3309                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3310                         continue;
3311                 }
3312                 if (pctx.errcode) {
3313                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3314                         ctx->flags |= E2F_FLAG_ABORT;
3315                         return;
3316                 }
3317                 if (!ino)
3318                         break;
3319                 pctx.ino = ino;
3320                 pctx.inode = inode;
3321                 ctx->stashed_ino = ino;
3322                 if (inode->i_links_count) {
3323                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3324                                            ino, inode->i_links_count);
3325                         if (pctx.errcode) {
3326                                 pctx.num = inode->i_links_count;
3327                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3328                                 ctx->flags |= E2F_FLAG_ABORT;
3329                                 return;
3330                         }
3331                 }
3332                 if (ino == EXT2_BAD_INO) {
3333                         struct process_block_struct_1 pb;
3334
3335                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3336                                                           &pb.fs_meta_blocks);
3337                         if (pctx.errcode) {
3338                                 pctx.num = 4;
3339                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3340                                 ctx->flags |= E2F_FLAG_ABORT;
3341                                 return;
3342                         }
3343                         pb.ino = EXT2_BAD_INO;
3344                         pb.num_blocks = pb.last_block = 0;
3345                         pb.num_illegal_blocks = 0;
3346                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3347                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3348                         pb.inode = inode;
3349                         pb.pctx = &pctx;
3350                         pb.ctx = ctx;
3351                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3352                                      block_buf, process_bad_block, &pb);
3353                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3354                         if (pctx.errcode) {
3355                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3356                                 ctx->flags |= E2F_FLAG_ABORT;
3357                                 return;
3358                         }
3359                         if (pb.bbcheck)
3360                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3361                                 ctx->flags |= E2F_FLAG_ABORT;
3362                                 return;
3363                         }
3364                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3365                         clear_problem_context(&pctx);
3366                         continue;
3367                 } else if (ino == EXT2_ROOT_INO) {
3368                         /*
3369                          * Make sure the root inode is a directory; if
3370                          * not, offer to clear it.  It will be
3371                          * regnerated in pass #3.
3372                          */
3373                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3374                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3375                                         inode->i_dtime = time(NULL);
3376                                         inode->i_links_count = 0;
3377                                         ext2fs_icount_store(ctx->inode_link_info,
3378                                                             ino, 0);
3379                                         e2fsck_write_inode(ctx, ino, inode,
3380                                                            "pass1");
3381                                 }
3382
3383                         }
3384                         /*
3385                          * If dtime is set, offer to clear it.  mke2fs
3386                          * version 0.2b created filesystems with the
3387                          * dtime field set for the root and lost+found
3388                          * directories.  We won't worry about
3389                          * /lost+found, since that can be regenerated
3390                          * easily.  But we will fix the root directory
3391                          * as a special case.
3392                          */
3393                         if (inode->i_dtime && inode->i_links_count) {
3394                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3395                                         inode->i_dtime = 0;
3396                                         e2fsck_write_inode(ctx, ino, inode,
3397                                                            "pass1");
3398                                 }
3399                         }
3400                 } else if (ino == EXT2_JOURNAL_INO) {
3401                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3402                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3403                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3404                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3405                                                 &pctx)) {
3406                                         inode->i_mode = LINUX_S_IFREG;
3407                                         e2fsck_write_inode(ctx, ino, inode,
3408                                                            "pass1");
3409                                 }
3410                                 check_blocks(ctx, &pctx, block_buf);
3411                                 continue;
3412                         }
3413                         if ((inode->i_links_count || inode->i_blocks ||
3414                              inode->i_blocks || inode->i_block[0]) &&
3415                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3416                                         &pctx)) {
3417                                 memset(inode, 0, inode_size);
3418                                 ext2fs_icount_store(ctx->inode_link_info,
3419                                                     ino, 0);
3420                                 e2fsck_write_inode_full(ctx, ino, inode,
3421                                                         inode_size, "pass1");
3422                         }
3423                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3424                         int     problem = 0;
3425
3426                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3427                         if (ino == EXT2_BOOT_LOADER_INO) {
3428                                 if (LINUX_S_ISDIR(inode->i_mode))
3429                                         problem = PR_1_RESERVED_BAD_MODE;
3430                         } else if (ino == EXT2_RESIZE_INO) {
3431                                 if (inode->i_mode &&
3432                                     !LINUX_S_ISREG(inode->i_mode))
3433                                         problem = PR_1_RESERVED_BAD_MODE;
3434                         } else {
3435                                 if (inode->i_mode != 0)
3436                                         problem = PR_1_RESERVED_BAD_MODE;
3437                         }
3438                         if (problem) {
3439                                 if (fix_problem(ctx, problem, &pctx)) {
3440                                         inode->i_mode = 0;
3441                                         e2fsck_write_inode(ctx, ino, inode,
3442                                                            "pass1");
3443                                 }
3444                         }
3445                         check_blocks(ctx, &pctx, block_buf);
3446                         continue;
3447                 }
3448                 /*
3449                  * Check for inodes who might have been part of the
3450                  * orphaned list linked list.  They should have gotten
3451                  * dealt with by now, unless the list had somehow been
3452                  * corrupted.
3453                  *
3454                  * FIXME: In the future, inodes which are still in use
3455                  * (and which are therefore) pending truncation should
3456                  * be handled specially.  Right now we just clear the
3457                  * dtime field, and the normal e2fsck handling of
3458                  * inodes where i_size and the inode blocks are
3459                  * inconsistent is to fix i_size, instead of releasing
3460                  * the extra blocks.  This won't catch the inodes that
3461                  * was at the end of the orphan list, but it's better
3462                  * than nothing.  The right answer is that there
3463                  * shouldn't be any bugs in the orphan list handling.  :-)
3464                  */
3465                 if (inode->i_dtime && !busted_fs_time &&
3466                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3467                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3468                                 inode->i_dtime = inode->i_links_count ?
3469                                         0 : time(NULL);
3470                                 e2fsck_write_inode(ctx, ino, inode,
3471                                                    "pass1");
3472                         }
3473                 }
3474
3475                 /*
3476                  * This code assumes that deleted inodes have
3477                  * i_links_count set to 0.
3478                  */
3479                 if (!inode->i_links_count) {
3480                         if (!inode->i_dtime && inode->i_mode) {
3481                                 if (fix_problem(ctx,
3482                                             PR_1_ZERO_DTIME, &pctx)) {
3483                                         inode->i_dtime = time(NULL);
3484                                         e2fsck_write_inode(ctx, ino, inode,
3485                                                            "pass1");
3486                                 }
3487                         }
3488                         continue;
3489                 }
3490                 /*
3491                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3492                  * deleted files.  Oops.
3493                  *
3494                  * Since all new ext2 implementations get this right,
3495                  * we now assume that the case of non-zero
3496                  * i_links_count and non-zero dtime means that we
3497                  * should keep the file, not delete it.
3498                  *
3499                  */
3500                 if (inode->i_dtime) {
3501                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3502                                 inode->i_dtime = 0;
3503                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3504                         }
3505                 }
3506
3507                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3508                 switch (fs->super->s_creator_os) {
3509                     case EXT2_OS_LINUX:
3510                         frag = inode->osd2.linux2.l_i_frag;
3511                         fsize = inode->osd2.linux2.l_i_fsize;
3512                         break;
3513                     case EXT2_OS_HURD:
3514                         frag = inode->osd2.hurd2.h_i_frag;
3515                         fsize = inode->osd2.hurd2.h_i_fsize;
3516                         break;
3517                     case EXT2_OS_MASIX:
3518                         frag = inode->osd2.masix2.m_i_frag;
3519                         fsize = inode->osd2.masix2.m_i_fsize;
3520                         break;
3521                     default:
3522                         frag = fsize = 0;
3523                 }
3524
3525                 if (inode->i_faddr || frag || fsize ||
3526                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3527                         mark_inode_bad(ctx, ino);
3528                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3529                         if (imagic_fs) {
3530                                 if (!ctx->inode_imagic_map)
3531                                         alloc_imagic_map(ctx);
3532                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3533                                                          ino);
3534                         } else {
3535                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3536                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3537                                         e2fsck_write_inode(ctx, ino,
3538                                                            inode, "pass1");
3539                                 }
3540                         }
3541                 }
3542
3543                 check_inode_extra_space(ctx, &pctx);
3544
3545                 if (LINUX_S_ISDIR(inode->i_mode)) {
3546                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3547                         e2fsck_add_dir_info(ctx, ino, 0);
3548                         ctx->fs_directory_count++;
3549                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3550                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3551                         ctx->fs_regular_count++;
3552                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3553                            e2fsck_pass1_check_device_inode(fs, inode)) {
3554                         check_immutable(ctx, &pctx);
3555                         check_size(ctx, &pctx);
3556                         ctx->fs_chardev_count++;
3557                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3558                            e2fsck_pass1_check_device_inode(fs, inode)) {
3559                         check_immutable(ctx, &pctx);
3560                         check_size(ctx, &pctx);
3561                         ctx->fs_blockdev_count++;
3562                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3563                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3564                         check_immutable(ctx, &pctx);
3565                         ctx->fs_symlinks_count++;
3566                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3567                                 ctx->fs_fast_symlinks_count++;
3568                                 check_blocks(ctx, &pctx, block_buf);
3569                                 continue;
3570                         }
3571                 }
3572                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3573                          e2fsck_pass1_check_device_inode(fs, inode)) {
3574                         check_immutable(ctx, &pctx);
3575                         check_size(ctx, &pctx);
3576                         ctx->fs_fifo_count++;
3577                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3578                            e2fsck_pass1_check_device_inode(fs, inode)) {
3579                         check_immutable(ctx, &pctx);
3580                         check_size(ctx, &pctx);
3581                         ctx->fs_sockets_count++;
3582                 } else
3583                         mark_inode_bad(ctx, ino);
3584                 if (inode->i_block[EXT2_IND_BLOCK])
3585                         ctx->fs_ind_count++;
3586                 if (inode->i_block[EXT2_DIND_BLOCK])
3587                         ctx->fs_dind_count++;
3588                 if (inode->i_block[EXT2_TIND_BLOCK])
3589                         ctx->fs_tind_count++;
3590                 if (inode->i_block[EXT2_IND_BLOCK] ||
3591                     inode->i_block[EXT2_DIND_BLOCK] ||
3592                     inode->i_block[EXT2_TIND_BLOCK] ||
3593                     inode->i_file_acl) {
3594                         inodes_to_process[process_inode_count].ino = ino;
3595                         inodes_to_process[process_inode_count].inode = *inode;
3596                         process_inode_count++;
3597                 } else
3598                         check_blocks(ctx, &pctx, block_buf);
3599
3600                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3601                         return;
3602
3603                 if (process_inode_count >= ctx->process_inode_size) {
3604                         process_inodes(ctx, block_buf);
3605
3606                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3607                                 return;
3608                 }
3609         }
3610         process_inodes(ctx, block_buf);
3611         ext2fs_close_inode_scan(scan);
3612         ehandler_operation(0);
3613
3614         /*
3615          * If any extended attribute blocks' reference counts need to
3616          * be adjusted, either up (ctx->refcount_extra), or down
3617          * (ctx->refcount), then fix them.
3618          */
3619         if (ctx->refcount) {
3620                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3621                 ea_refcount_free(ctx->refcount);
3622                 ctx->refcount = 0;
3623         }
3624         if (ctx->refcount_extra) {
3625                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3626                                         block_buf, +1);
3627                 ea_refcount_free(ctx->refcount_extra);
3628                 ctx->refcount_extra = 0;
3629         }
3630
3631         if (ctx->invalid_bitmaps)
3632                 handle_fs_bad_blocks(ctx);
3633
3634         /* We don't need the block_ea_map any more */
3635         ext2fs_free_block_bitmap(ctx->block_ea_map);
3636         ctx->block_ea_map = 0;
3637
3638         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3639                 ext2fs_block_bitmap save_bmap;
3640
3641                 save_bmap = fs->block_map;
3642                 fs->block_map = ctx->block_found_map;
3643                 clear_problem_context(&pctx);
3644                 pctx.errcode = ext2fs_create_resize_inode(fs);
3645                 if (pctx.errcode) {
3646                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3647                         /* Should never get here */
3648                         ctx->flags |= E2F_FLAG_ABORT;
3649                         return;
3650                 }
3651                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3652                                   "recreate inode");
3653                 inode->i_mtime = time(NULL);
3654                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3655                                   "recreate inode");
3656                 fs->block_map = save_bmap;
3657                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3658         }
3659
3660         if (ctx->flags & E2F_FLAG_RESTART) {
3661                 /*
3662                  * Only the master copy of the superblock and block
3663                  * group descriptors are going to be written during a
3664                  * restart, so set the superblock to be used to be the
3665                  * master superblock.
3666                  */
3667                 ctx->use_superblock = 0;
3668                 unwind_pass1();
3669                 goto endit;
3670         }
3671
3672         if (ctx->block_dup_map) {
3673                 if (ctx->options & E2F_OPT_PREEN) {
3674                         clear_problem_context(&pctx);
3675                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3676                 }
3677                 e2fsck_pass1_dupblocks(ctx, block_buf);
3678         }
3679         ext2fs_free_mem(&inodes_to_process);
3680 endit:
3681         e2fsck_use_inode_shortcuts(ctx, 0);
3682
3683         ext2fs_free_mem(&block_buf);
3684         ext2fs_free_mem(&inode);
3685
3686 }
3687
3688 /*
3689  * When the inode_scan routines call this callback at the end of the
3690  * glock group, call process_inodes.
3691  */
3692 static errcode_t scan_callback(ext2_filsys fs,
3693                                dgrp_t group, void * priv_data)
3694 {
3695         struct scan_callback_struct *scan_struct;
3696         e2fsck_t ctx;
3697
3698         scan_struct = (struct scan_callback_struct *) priv_data;
3699         ctx = scan_struct->ctx;
3700
3701         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3702
3703         if (ctx->progress)
3704                 if ((ctx->progress)(ctx, 1, group+1,
3705                                     ctx->fs->group_desc_count))
3706                         return EXT2_ET_CANCEL_REQUESTED;
3707
3708         return 0;
3709 }
3710
3711 /*
3712  * Process the inodes in the "inodes to process" list.
3713  */
3714 static void process_inodes(e2fsck_t ctx, char *block_buf)
3715 {
3716         int                     i;
3717         struct ext2_inode       *old_stashed_inode;
3718         ext2_ino_t              old_stashed_ino;
3719         const char              *old_operation;
3720         char                    buf[80];
3721         struct problem_context  pctx;
3722
3723         /* begin process_inodes */
3724         if (process_inode_count == 0)
3725                 return;
3726         old_operation = ehandler_operation(0);
3727         old_stashed_inode = ctx->stashed_inode;
3728         old_stashed_ino = ctx->stashed_ino;
3729         qsort(inodes_to_process, process_inode_count,
3730                       sizeof(struct process_inode_block), process_inode_cmp);
3731         clear_problem_context(&pctx);
3732         for (i=0; i < process_inode_count; i++) {
3733                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3734                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3735                 sprintf(buf, _("reading indirect blocks of inode %u"),
3736                         pctx.ino);
3737                 ehandler_operation(buf);
3738                 check_blocks(ctx, &pctx, block_buf);
3739                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3740                         break;
3741         }
3742         ctx->stashed_inode = old_stashed_inode;
3743         ctx->stashed_ino = old_stashed_ino;
3744         process_inode_count = 0;
3745         /* end process inodes */
3746
3747         ehandler_operation(old_operation);
3748 }
3749
3750 static int process_inode_cmp(const void *a, const void *b)
3751 {
3752         const struct process_inode_block *ib_a =
3753                 (const struct process_inode_block *) a;
3754         const struct process_inode_block *ib_b =
3755                 (const struct process_inode_block *) b;
3756         int     ret;
3757
3758         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3759                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3760         if (ret == 0)
3761                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3762         return ret;
3763 }
3764
3765 /*
3766  * Mark an inode as being bad in some what
3767  */
3768 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3769 {
3770         struct          problem_context pctx;
3771
3772         if (!ctx->inode_bad_map) {
3773                 clear_problem_context(&pctx);
3774
3775                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3776                             _("bad inode map"), &ctx->inode_bad_map);
3777                 if (pctx.errcode) {
3778                         pctx.num = 3;
3779                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3780                         /* Should never get here */
3781                         ctx->flags |= E2F_FLAG_ABORT;
3782                         return;
3783                 }
3784         }
3785         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3786 }
3787
3788
3789 /*
3790  * This procedure will allocate the inode imagic table
3791  */
3792 static void alloc_imagic_map(e2fsck_t ctx)
3793 {
3794         struct          problem_context pctx;
3795
3796         clear_problem_context(&pctx);
3797         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3798                                               _("imagic inode map"),
3799                                               &ctx->inode_imagic_map);
3800         if (pctx.errcode) {
3801                 pctx.num = 5;
3802                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3803                 /* Should never get here */
3804                 ctx->flags |= E2F_FLAG_ABORT;
3805                 return;
3806         }
3807 }
3808
3809 /*
3810  * Marks a block as in use, setting the dup_map if it's been set
3811  * already.  Called by process_block and process_bad_block.
3812  *
3813  * WARNING: Assumes checks have already been done to make sure block
3814  * is valid.  This is true in both process_block and process_bad_block.
3815  */
3816 static void mark_block_used(e2fsck_t ctx, blk_t block)
3817 {
3818         struct          problem_context pctx;
3819
3820         clear_problem_context(&pctx);
3821
3822         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3823                 if (!ctx->block_dup_map) {
3824                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3825                               _("multiply claimed block map"),
3826                               &ctx->block_dup_map);
3827                         if (pctx.errcode) {
3828                                 pctx.num = 3;
3829                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3830                                             &pctx);
3831                                 /* Should never get here */
3832                                 ctx->flags |= E2F_FLAG_ABORT;
3833                                 return;
3834                         }
3835                 }
3836                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3837         } else {
3838                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3839         }
3840 }
3841
3842 /*
3843  * Adjust the extended attribute block's reference counts at the end
3844  * of pass 1, either by subtracting out references for EA blocks that
3845  * are still referenced in ctx->refcount, or by adding references for
3846  * EA blocks that had extra references as accounted for in
3847  * ctx->refcount_extra.
3848  */
3849 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3850                                     char *block_buf, int adjust_sign)
3851 {
3852         struct ext2_ext_attr_header     *header;
3853         struct problem_context          pctx;
3854         ext2_filsys                     fs = ctx->fs;
3855         blk_t                           blk;
3856         __u32                           should_be;
3857         int                             count;
3858
3859         clear_problem_context(&pctx);
3860
3861         ea_refcount_intr_begin(refcount);
3862         while (1) {
3863                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3864                         break;
3865                 pctx.blk = blk;
3866                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3867                 if (pctx.errcode) {
3868                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3869                         return;
3870                 }
3871                 header = (struct ext2_ext_attr_header *) block_buf;
3872                 pctx.blkcount = header->h_refcount;
3873                 should_be = header->h_refcount + adjust_sign * count;
3874                 pctx.num = should_be;
3875                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3876                         header->h_refcount = should_be;
3877                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3878                                                              block_buf);
3879                         if (pctx.errcode) {
3880                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3881                                 continue;
3882                         }
3883                 }
3884         }
3885 }
3886
3887 /*
3888  * Handle processing the extended attribute blocks
3889  */
3890 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3891                            char *block_buf)
3892 {
3893         ext2_filsys fs = ctx->fs;
3894         ext2_ino_t      ino = pctx->ino;
3895         struct ext2_inode *inode = pctx->inode;
3896         blk_t           blk;
3897         char *          end;
3898         struct ext2_ext_attr_header *header;
3899         struct ext2_ext_attr_entry *entry;
3900         int             count;
3901         region_t        region;
3902
3903         blk = inode->i_file_acl;
3904         if (blk == 0)
3905                 return 0;
3906
3907         /*
3908          * If the Extended attribute flag isn't set, then a non-zero
3909          * file acl means that the inode is corrupted.
3910          *
3911          * Or if the extended attribute block is an invalid block,
3912          * then the inode is also corrupted.
3913          */
3914         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3915             (blk < fs->super->s_first_data_block) ||
3916             (blk >= fs->super->s_blocks_count)) {
3917                 mark_inode_bad(ctx, ino);
3918                 return 0;
3919         }
3920
3921         /* If ea bitmap hasn't been allocated, create it */
3922         if (!ctx->block_ea_map) {
3923                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3924                                                       _("ext attr block map"),
3925                                                       &ctx->block_ea_map);
3926                 if (pctx->errcode) {
3927                         pctx->num = 2;
3928                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3929                         ctx->flags |= E2F_FLAG_ABORT;
3930                         return 0;
3931                 }
3932         }
3933
3934         /* Create the EA refcount structure if necessary */
3935         if (!ctx->refcount) {
3936                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3937                 if (pctx->errcode) {
3938                         pctx->num = 1;
3939                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3940                         ctx->flags |= E2F_FLAG_ABORT;
3941                         return 0;
3942                 }
3943         }
3944
3945         /* Have we seen this EA block before? */
3946         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3947                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3948                         return 1;
3949                 /* Ooops, this EA was referenced more than it stated */
3950                 if (!ctx->refcount_extra) {
3951                         pctx->errcode = ea_refcount_create(0,
3952                                            &ctx->refcount_extra);
3953                         if (pctx->errcode) {
3954                                 pctx->num = 2;
3955                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3956                                 ctx->flags |= E2F_FLAG_ABORT;
3957                                 return 0;
3958                         }
3959                 }
3960                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3961                 return 1;
3962         }
3963
3964         /*
3965          * OK, we haven't seen this EA block yet.  So we need to
3966          * validate it
3967          */
3968         pctx->blk = blk;
3969         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3970         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3971                 goto clear_extattr;
3972         header = (struct ext2_ext_attr_header *) block_buf;
3973         pctx->blk = inode->i_file_acl;
3974         if (((ctx->ext_attr_ver == 1) &&
3975              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3976             ((ctx->ext_attr_ver == 2) &&
3977              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3978                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3979                         goto clear_extattr;
3980         }
3981
3982         if (header->h_blocks != 1) {
3983                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3984                         goto clear_extattr;
3985         }
3986
3987         region = region_create(0, fs->blocksize);
3988         if (!region) {
3989                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3990                 ctx->flags |= E2F_FLAG_ABORT;
3991                 return 0;
3992         }
3993         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3994                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3995                         goto clear_extattr;
3996         }
3997
3998         entry = (struct ext2_ext_attr_entry *)(header+1);
3999         end = block_buf + fs->blocksize;
4000         while ((char *)entry < end && *(__u32 *)entry) {
4001                 if (region_allocate(region, (char *)entry - (char *)header,
4002                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4003                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4004                                 goto clear_extattr;
4005                 }
4006                 if ((ctx->ext_attr_ver == 1 &&
4007                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4008                     (ctx->ext_attr_ver == 2 &&
4009                      entry->e_name_index == 0)) {
4010                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4011                                 goto clear_extattr;
4012                 }
4013                 if (entry->e_value_block != 0) {
4014                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4015                                 goto clear_extattr;
4016                 }
4017                 if (entry->e_value_size &&
4018                     region_allocate(region, entry->e_value_offs,
4019                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4020                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4021                                 goto clear_extattr;
4022                 }
4023                 entry = EXT2_EXT_ATTR_NEXT(entry);
4024         }
4025         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4026                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4027                         goto clear_extattr;
4028         }
4029         region_free(region);
4030
4031         count = header->h_refcount - 1;
4032         if (count)
4033                 ea_refcount_store(ctx->refcount, blk, count);
4034         mark_block_used(ctx, blk);
4035         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4036
4037         return 1;
4038
4039 clear_extattr:
4040         inode->i_file_acl = 0;
4041         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4042         return 0;
4043 }
4044
4045 /* Returns 1 if bad htree, 0 if OK */
4046 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4047                         ext2_ino_t ino FSCK_ATTR((unused)),
4048                         struct ext2_inode *inode,
4049                         char *block_buf)
4050 {
4051         struct ext2_dx_root_info        *root;
4052         ext2_filsys                     fs = ctx->fs;
4053         errcode_t                       retval;
4054         blk_t                           blk;
4055
4056         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4057              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4058             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4059              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4060                 return 1;
4061
4062         blk = inode->i_block[0];
4063         if (((blk == 0) ||
4064              (blk < fs->super->s_first_data_block) ||
4065              (blk >= fs->super->s_blocks_count)) &&
4066             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4067                 return 1;
4068
4069         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4070         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4071                 return 1;
4072
4073         /* XXX should check that beginning matches a directory */
4074         root = (struct ext2_dx_root_info *) (block_buf + 24);
4075
4076         if ((root->reserved_zero || root->info_length < 8) &&
4077             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4078                 return 1;
4079
4080         pctx->num = root->hash_version;
4081         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4082             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4083             (root->hash_version != EXT2_HASH_TEA) &&
4084             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4085                 return 1;
4086
4087         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4088             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4089                 return 1;
4090
4091         pctx->num = root->indirect_levels;
4092         if ((root->indirect_levels > 1) &&
4093             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4094                 return 1;
4095
4096         return 0;
4097 }
4098
4099 /*
4100  * This subroutine is called on each inode to account for all of the
4101  * blocks used by that inode.
4102  */
4103 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4104                          char *block_buf)
4105 {
4106         ext2_filsys fs = ctx->fs;
4107         struct process_block_struct_1 pb;
4108         ext2_ino_t      ino = pctx->ino;
4109         struct ext2_inode *inode = pctx->inode;
4110         int             bad_size = 0;
4111         int             dirty_inode = 0;
4112         __u64           size;
4113
4114         pb.ino = ino;
4115         pb.num_blocks = 0;
4116         pb.last_block = -1;
4117         pb.num_illegal_blocks = 0;
4118         pb.suppress = 0; pb.clear = 0;
4119         pb.fragmented = 0;
4120         pb.compressed = 0;
4121         pb.previous_block = 0;
4122         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4123         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4124         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4125         pb.inode = inode;
4126         pb.pctx = pctx;
4127         pb.ctx = ctx;
4128         pctx->ino = ino;
4129         pctx->errcode = 0;
4130
4131         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4132                 if (fs->super->s_feature_incompat &
4133                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4134                         pb.compressed = 1;
4135                 else {
4136                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4137                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4138                                 dirty_inode++;
4139                         }
4140                 }
4141         }
4142
4143         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4144                 pb.num_blocks++;
4145
4146         if (ext2fs_inode_has_valid_blocks(inode))
4147                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4148                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4149                                        block_buf, process_block, &pb);
4150         end_problem_latch(ctx, PR_LATCH_BLOCK);
4151         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4152         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4153                 goto out;
4154         if (pctx->errcode)
4155                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4156
4157         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4158                 ctx->fs_fragmented++;
4159
4160         if (pb.clear) {
4161                 inode->i_links_count = 0;
4162                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4163                 inode->i_dtime = time(NULL);
4164                 dirty_inode++;
4165                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4166                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4167                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4168                 /*
4169                  * The inode was probably partially accounted for
4170                  * before processing was aborted, so we need to
4171                  * restart the pass 1 scan.
4172                  */
4173                 ctx->flags |= E2F_FLAG_RESTART;
4174                 goto out;
4175         }
4176
4177         if (inode->i_flags & EXT2_INDEX_FL) {
4178                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4179                         inode->i_flags &= ~EXT2_INDEX_FL;
4180                         dirty_inode++;
4181                 } else {
4182 #ifdef ENABLE_HTREE
4183                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4184 #endif
4185                 }
4186         }
4187         if (ctx->dirs_to_hash && pb.is_dir &&
4188             !(inode->i_flags & EXT2_INDEX_FL) &&
4189             ((inode->i_size / fs->blocksize) >= 3))
4190                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4191
4192         if (!pb.num_blocks && pb.is_dir) {
4193                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4194                         inode->i_links_count = 0;
4195                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4196                         inode->i_dtime = time(NULL);
4197                         dirty_inode++;
4198                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4199                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4200                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4201                         ctx->fs_directory_count--;
4202                         goto out;
4203                 }
4204         }
4205
4206         pb.num_blocks *= (fs->blocksize / 512);
4207
4208         if (pb.is_dir) {
4209                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4210                 if (nblock > (pb.last_block + 1))
4211                         bad_size = 1;
4212                 else if (nblock < (pb.last_block + 1)) {
4213                         if (((pb.last_block + 1) - nblock) >
4214                             fs->super->s_prealloc_dir_blocks)
4215                                 bad_size = 2;
4216                 }
4217         } else {
4218                 size = EXT2_I_SIZE(inode);
4219                 if ((pb.last_block >= 0) &&
4220                     (size < (__u64) pb.last_block * fs->blocksize))
4221                         bad_size = 3;
4222                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4223                         bad_size = 4;
4224         }
4225         /* i_size for symlinks is checked elsewhere */
4226         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4227                 pctx->num = (pb.last_block+1) * fs->blocksize;
4228                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4229                         inode->i_size = pctx->num;
4230                         if (!LINUX_S_ISDIR(inode->i_mode))
4231                                 inode->i_size_high = pctx->num >> 32;
4232                         dirty_inode++;
4233                 }
4234                 pctx->num = 0;
4235         }
4236         if (LINUX_S_ISREG(inode->i_mode) &&
4237             (inode->i_size_high || inode->i_size & 0x80000000UL))
4238                 ctx->large_files++;
4239         if (pb.num_blocks != inode->i_blocks) {
4240                 pctx->num = pb.num_blocks;
4241                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4242                         inode->i_blocks = pb.num_blocks;
4243                         dirty_inode++;
4244                 }
4245                 pctx->num = 0;
4246         }
4247 out:
4248         if (dirty_inode)
4249                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4250 }
4251
4252
4253 /*
4254  * This is a helper function for check_blocks().
4255  */
4256 static int process_block(ext2_filsys fs,
4257                   blk_t *block_nr,
4258                   e2_blkcnt_t blockcnt,
4259                   blk_t ref_block FSCK_ATTR((unused)),
4260                   int ref_offset FSCK_ATTR((unused)),
4261                   void *priv_data)
4262 {
4263         struct process_block_struct_1 *p;
4264         struct problem_context *pctx;
4265         blk_t   blk = *block_nr;
4266         int     ret_code = 0;
4267         int     problem = 0;
4268         e2fsck_t        ctx;
4269
4270         p = (struct process_block_struct_1 *) priv_data;
4271         pctx = p->pctx;
4272         ctx = p->ctx;
4273
4274         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4275                 /* todo: Check that the comprblk_fl is high, that the
4276                    blkaddr pattern looks right (all non-holes up to
4277                    first EXT2FS_COMPRESSED_BLKADDR, then all
4278                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4279                    that the feature_incompat bit is high, and that the
4280                    inode is a regular file.  If we're doing a "full
4281                    check" (a concept introduced to e2fsck by e2compr,
4282                    meaning that we look at data blocks as well as
4283                    metadata) then call some library routine that
4284                    checks the compressed data.  I'll have to think
4285                    about this, because one particularly important
4286                    problem to be able to fix is to recalculate the
4287                    cluster size if necessary.  I think that perhaps
4288                    we'd better do most/all e2compr-specific checks
4289                    separately, after the non-e2compr checks.  If not
4290                    doing a full check, it may be useful to test that
4291                    the personality is linux; e.g. if it isn't then
4292                    perhaps this really is just an illegal block. */
4293                 return 0;
4294         }
4295
4296         if (blk == 0) {
4297                 if (p->is_dir == 0) {
4298                         /*
4299                          * Should never happen, since only directories
4300                          * get called with BLOCK_FLAG_HOLE
4301                          */
4302 #ifdef DEBUG_E2FSCK
4303                         printf("process_block() called with blk == 0, "
4304                                "blockcnt=%d, inode %lu???\n",
4305                                blockcnt, p->ino);
4306 #endif
4307                         return 0;
4308                 }
4309                 if (blockcnt < 0)
4310                         return 0;
4311                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4312                         goto mark_dir;
4313                 }
4314                 return 0;
4315         }
4316
4317         /*
4318          * Simplistic fragmentation check.  We merely require that the
4319          * file be contiguous.  (Which can never be true for really
4320          * big files that are greater than a block group.)
4321          */
4322         if (!HOLE_BLKADDR(p->previous_block)) {
4323                 if (p->previous_block+1 != blk)
4324                         p->fragmented = 1;
4325         }
4326         p->previous_block = blk;
4327
4328         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4329                 problem = PR_1_TOOBIG_DIR;
4330         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4331                 problem = PR_1_TOOBIG_REG;
4332         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4333                 problem = PR_1_TOOBIG_SYMLINK;
4334
4335         if (blk < fs->super->s_first_data_block ||
4336             blk >= fs->super->s_blocks_count)
4337                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4338
4339         if (problem) {
4340                 p->num_illegal_blocks++;
4341                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4342                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4343                                 p->clear = 1;
4344                                 return BLOCK_ABORT;
4345                         }
4346                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4347                                 p->suppress = 1;
4348                                 set_latch_flags(PR_LATCH_BLOCK,
4349                                                 PRL_SUPPRESS, 0);
4350                         }
4351                 }
4352                 pctx->blk = blk;
4353                 pctx->blkcount = blockcnt;
4354                 if (fix_problem(ctx, problem, pctx)) {
4355                         blk = *block_nr = 0;
4356                         ret_code = BLOCK_CHANGED;
4357                         goto mark_dir;
4358                 } else
4359                         return 0;
4360         }
4361
4362         if (p->ino == EXT2_RESIZE_INO) {
4363                 /*
4364                  * The resize inode has already be sanity checked
4365                  * during pass #0 (the superblock checks).  All we
4366                  * have to do is mark the double indirect block as
4367                  * being in use; all of the other blocks are handled
4368                  * by mark_table_blocks()).
4369                  */
4370                 if (blockcnt == BLOCK_COUNT_DIND)
4371                         mark_block_used(ctx, blk);
4372         } else
4373                 mark_block_used(ctx, blk);
4374         p->num_blocks++;
4375         if (blockcnt >= 0)
4376                 p->last_block = blockcnt;
4377 mark_dir:
4378         if (p->is_dir && (blockcnt >= 0)) {
4379                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4380                                                     blk, blockcnt);
4381                 if (pctx->errcode) {
4382                         pctx->blk = blk;
4383                         pctx->num = blockcnt;
4384                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4385                         /* Should never get here */
4386                         ctx->flags |= E2F_FLAG_ABORT;
4387                         return BLOCK_ABORT;
4388                 }
4389         }
4390         return ret_code;
4391 }
4392
4393 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4394                       blk_t *block_nr,
4395                       e2_blkcnt_t blockcnt,
4396                       blk_t ref_block FSCK_ATTR((unused)),
4397                       int ref_offset FSCK_ATTR((unused)),
4398                       void *priv_data EXT2FS_ATTR((unused)))
4399 {
4400         /*
4401          * Note: This function processes blocks for the bad blocks
4402          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4403          */
4404
4405         printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4406         return BLOCK_ERROR;
4407 }
4408
4409 /*
4410  * This routine gets called at the end of pass 1 if bad blocks are
4411  * detected in the superblock, group descriptors, inode_bitmaps, or
4412  * block bitmaps.  At this point, all of the blocks have been mapped
4413  * out, so we can try to allocate new block(s) to replace the bad
4414  * blocks.
4415  */
4416 static void handle_fs_bad_blocks(e2fsck_t ctx)
4417 {
4418         printf("Bad blocks detected on your filesystem\n"
4419                 "You should get your data off as the device will soon die\n");
4420 }
4421
4422 /*
4423  * This routine marks all blocks which are used by the superblock,
4424  * group descriptors, inode bitmaps, and block bitmaps.
4425  */
4426 static void mark_table_blocks(e2fsck_t ctx)
4427 {
4428         ext2_filsys fs = ctx->fs;
4429         blk_t   block, b;
4430         dgrp_t  i;
4431         int     j;
4432         struct problem_context pctx;
4433
4434         clear_problem_context(&pctx);
4435
4436         block = fs->super->s_first_data_block;
4437         for (i = 0; i < fs->group_desc_count; i++) {
4438                 pctx.group = i;
4439
4440                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4441
4442                 /*
4443                  * Mark the blocks used for the inode table
4444                  */
4445                 if (fs->group_desc[i].bg_inode_table) {
4446                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4447                              j < fs->inode_blocks_per_group;
4448                              j++, b++) {
4449                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4450                                                              b)) {
4451                                         pctx.blk = b;
4452                                         if (fix_problem(ctx,
4453                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4454                                                 ctx->invalid_inode_table_flag[i]++;
4455                                                 ctx->invalid_bitmaps++;
4456                                         }
4457                                 } else {
4458                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
4459                                                              b);
4460                                 }
4461                         }
4462                 }
4463
4464                 /*
4465                  * Mark block used for the block bitmap
4466                  */
4467                 if (fs->group_desc[i].bg_block_bitmap) {
4468                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4469                                      fs->group_desc[i].bg_block_bitmap)) {
4470                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4471                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4472                                         ctx->invalid_block_bitmap_flag[i]++;
4473                                         ctx->invalid_bitmaps++;
4474                                 }
4475                         } else {
4476                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4477                                      fs->group_desc[i].bg_block_bitmap);
4478                     }
4479
4480                 }
4481                 /*
4482                  * Mark block used for the inode bitmap
4483                  */
4484                 if (fs->group_desc[i].bg_inode_bitmap) {
4485                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4486                                      fs->group_desc[i].bg_inode_bitmap)) {
4487                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4488                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4489                                         ctx->invalid_inode_bitmap_flag[i]++;
4490                                         ctx->invalid_bitmaps++;
4491                                 }
4492                         } else {
4493                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4494                                      fs->group_desc[i].bg_inode_bitmap);
4495                         }
4496                 }
4497                 block += fs->super->s_blocks_per_group;
4498         }
4499 }
4500
4501 /*
4502  * Thes subroutines short circuits ext2fs_get_blocks and
4503  * ext2fs_check_directory; we use them since we already have the inode
4504  * structure, so there's no point in letting the ext2fs library read
4505  * the inode again.
4506  */
4507 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4508                                   blk_t *blocks)
4509 {
4510         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4511         int     i;
4512
4513         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4514                 return EXT2_ET_CALLBACK_NOTHANDLED;
4515
4516         for (i=0; i < EXT2_N_BLOCKS; i++)
4517                 blocks[i] = ctx->stashed_inode->i_block[i];
4518         return 0;
4519 }
4520
4521 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4522                                   struct ext2_inode *inode)
4523 {
4524         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4525
4526         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4527                 return EXT2_ET_CALLBACK_NOTHANDLED;
4528         *inode = *ctx->stashed_inode;
4529         return 0;
4530 }
4531
4532 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4533                             struct ext2_inode *inode)
4534 {
4535         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4536
4537         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4538                 *ctx->stashed_inode = *inode;
4539         return EXT2_ET_CALLBACK_NOTHANDLED;
4540 }
4541
4542 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4543 {
4544         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545
4546         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4547                 return EXT2_ET_CALLBACK_NOTHANDLED;
4548
4549         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4550                 return EXT2_ET_NO_DIRECTORY;
4551         return 0;
4552 }
4553
4554 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4555 {
4556         ext2_filsys fs = ctx->fs;
4557
4558         if (bool) {
4559                 fs->get_blocks = pass1_get_blocks;
4560                 fs->check_directory = pass1_check_directory;
4561                 fs->read_inode = pass1_read_inode;
4562                 fs->write_inode = pass1_write_inode;
4563                 ctx->stashed_ino = 0;
4564         } else {
4565                 fs->get_blocks = 0;
4566                 fs->check_directory = 0;
4567                 fs->read_inode = 0;
4568                 fs->write_inode = 0;
4569         }
4570 }
4571
4572 /*
4573  * pass1b.c --- Pass #1b of e2fsck
4574  *
4575  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4576  * only invoked if pass 1 discovered blocks which are in use by more
4577  * than one inode.
4578  *
4579  * Pass1B scans the data blocks of all the inodes again, generating a
4580  * complete list of duplicate blocks and which inodes have claimed
4581  * them.
4582  *
4583  * Pass1C does a tree-traversal of the filesystem, to determine the
4584  * parent directories of these inodes.  This step is necessary so that
4585  * e2fsck can print out the pathnames of affected inodes.
4586  *
4587  * Pass1D is a reconciliation pass.  For each inode with duplicate
4588  * blocks, the user is prompted if s/he would like to clone the file
4589  * (so that the file gets a fresh copy of the duplicated blocks) or
4590  * simply to delete the file.
4591  *
4592  */
4593
4594
4595 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4596 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4597 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4598
4599 /* Define an extension to the ext2 library's block count information */
4600 #define BLOCK_COUNT_EXTATTR     (-5)
4601
4602 struct block_el {
4603         blk_t   block;
4604         struct block_el *next;
4605 };
4606
4607 struct inode_el {
4608         ext2_ino_t      inode;
4609         struct inode_el *next;
4610 };
4611
4612 struct dup_block {
4613         int             num_bad;
4614         struct inode_el *inode_list;
4615 };
4616
4617 /*
4618  * This structure stores information about a particular inode which
4619  * is sharing blocks with other inodes.  This information is collected
4620  * to display to the user, so that the user knows what files he or she
4621  * is dealing with, when trying to decide how to resolve the conflict
4622  * of multiply-claimed blocks.
4623  */
4624 struct dup_inode {
4625         ext2_ino_t              dir;
4626         int                     num_dupblocks;
4627         struct ext2_inode       inode;
4628         struct block_el         *block_list;
4629 };
4630
4631 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4632                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4633                                 int ref_offset, void *priv_data);
4634 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4635                         struct dup_inode *dp, char *block_buf);
4636 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4637                       struct dup_inode *dp, char* block_buf);
4638 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4639
4640 static void pass1b(e2fsck_t ctx, char *block_buf);
4641 static void pass1c(e2fsck_t ctx, char *block_buf);
4642 static void pass1d(e2fsck_t ctx, char *block_buf);
4643
4644 static int dup_inode_count = 0;
4645
4646 static dict_t blk_dict, ino_dict;
4647
4648 static ext2fs_inode_bitmap inode_dup_map;
4649
4650 static int dict_int_cmp(const void *a, const void *b)
4651 {
4652         intptr_t        ia, ib;
4653
4654         ia = (intptr_t)a;
4655         ib = (intptr_t)b;
4656
4657         return (ia-ib);
4658 }
4659
4660 /*
4661  * Add a duplicate block record
4662  */
4663 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4664                      struct ext2_inode *inode)
4665 {
4666         dnode_t *n;
4667         struct dup_block        *db;
4668         struct dup_inode        *di;
4669         struct block_el         *blk_el;
4670         struct inode_el         *ino_el;
4671
4672         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4673         if (n)
4674                 db = (struct dup_block *) dnode_get(n);
4675         else {
4676                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4677                          sizeof(struct dup_block), "duplicate block header");
4678                 db->num_bad = 0;
4679                 db->inode_list = 0;
4680                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4681         }
4682         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4683                          sizeof(struct inode_el), "inode element");
4684         ino_el->inode = ino;
4685         ino_el->next = db->inode_list;
4686         db->inode_list = ino_el;
4687         db->num_bad++;
4688
4689         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4690         if (n)
4691                 di = (struct dup_inode *) dnode_get(n);
4692         else {
4693                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4694                          sizeof(struct dup_inode), "duplicate inode header");
4695                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4696                 di->num_dupblocks = 0;
4697                 di->block_list = 0;
4698                 di->inode = *inode;
4699                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4700         }
4701         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4702                          sizeof(struct block_el), "block element");
4703         blk_el->block = blk;
4704         blk_el->next = di->block_list;
4705         di->block_list = blk_el;
4706         di->num_dupblocks++;
4707 }
4708
4709 /*
4710  * Free a duplicate inode record
4711  */
4712 static void inode_dnode_free(dnode_t *node)
4713 {
4714         struct dup_inode        *di;
4715         struct block_el         *p, *next;
4716
4717         di = (struct dup_inode *) dnode_get(node);
4718         for (p = di->block_list; p; p = next) {
4719                 next = p->next;
4720                 free(p);
4721         }
4722         free(node);
4723 }
4724
4725 /*
4726  * Free a duplicate block record
4727  */
4728 static void block_dnode_free(dnode_t *node)
4729 {
4730         struct dup_block        *db;
4731         struct inode_el         *p, *next;
4732
4733         db = (struct dup_block *) dnode_get(node);
4734         for (p = db->inode_list; p; p = next) {
4735                 next = p->next;
4736                 free(p);
4737         }
4738         free(node);
4739 }
4740
4741
4742 /*
4743  * Main procedure for handling duplicate blocks
4744  */
4745 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4746 {
4747         ext2_filsys             fs = ctx->fs;
4748         struct problem_context  pctx;
4749
4750         clear_problem_context(&pctx);
4751
4752         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4753                       _("multiply claimed inode map"), &inode_dup_map);
4754         if (pctx.errcode) {
4755                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4756                 ctx->flags |= E2F_FLAG_ABORT;
4757                 return;
4758         }
4759
4760         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4761         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4762         dict_set_allocator(&ino_dict, inode_dnode_free);
4763         dict_set_allocator(&blk_dict, block_dnode_free);
4764
4765         pass1b(ctx, block_buf);
4766         pass1c(ctx, block_buf);
4767         pass1d(ctx, block_buf);
4768
4769         /*
4770          * Time to free all of the accumulated data structures that we
4771          * don't need anymore.
4772          */
4773         dict_free_nodes(&ino_dict);
4774         dict_free_nodes(&blk_dict);
4775 }
4776
4777 /*
4778  * Scan the inodes looking for inodes that contain duplicate blocks.
4779  */
4780 struct process_block_struct_1b {
4781         e2fsck_t        ctx;
4782         ext2_ino_t      ino;
4783         int             dup_blocks;
4784         struct ext2_inode *inode;
4785         struct problem_context *pctx;
4786 };
4787
4788 static void pass1b(e2fsck_t ctx, char *block_buf)
4789 {
4790         ext2_filsys fs = ctx->fs;
4791         ext2_ino_t ino;
4792         struct ext2_inode inode;
4793         ext2_inode_scan scan;
4794         struct process_block_struct_1b pb;
4795         struct problem_context pctx;
4796
4797         clear_problem_context(&pctx);
4798
4799         if (!(ctx->options & E2F_OPT_PREEN))
4800                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4801         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4802                                               &scan);
4803         if (pctx.errcode) {
4804                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4805                 ctx->flags |= E2F_FLAG_ABORT;
4806                 return;
4807         }
4808         ctx->stashed_inode = &inode;
4809         pb.ctx = ctx;
4810         pb.pctx = &pctx;
4811         pctx.str = "pass1b";
4812         while (1) {
4813                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4814                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4815                         continue;
4816                 if (pctx.errcode) {
4817                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4818                         ctx->flags |= E2F_FLAG_ABORT;
4819                         return;
4820                 }
4821                 if (!ino)
4822                         break;
4823                 pctx.ino = ctx->stashed_ino = ino;
4824                 if ((ino != EXT2_BAD_INO) &&
4825                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4826                         continue;
4827
4828                 pb.ino = ino;
4829                 pb.dup_blocks = 0;
4830                 pb.inode = &inode;
4831
4832                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4833                     (ino == EXT2_BAD_INO))
4834                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4835                                      0, block_buf, process_pass1b_block, &pb);
4836                 if (inode.i_file_acl)
4837                         process_pass1b_block(fs, &inode.i_file_acl,
4838                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4839                 if (pb.dup_blocks) {
4840                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4841                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4842                             ino == EXT2_ROOT_INO)
4843                                 dup_inode_count++;
4844                 }
4845                 if (pctx.errcode)
4846                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4847         }
4848         ext2fs_close_inode_scan(scan);
4849         e2fsck_use_inode_shortcuts(ctx, 0);
4850 }
4851
4852 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4853                                 blk_t   *block_nr,
4854                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4855                                 blk_t ref_blk FSCK_ATTR((unused)),
4856                                 int ref_offset FSCK_ATTR((unused)),
4857                                 void *priv_data)
4858 {
4859         struct process_block_struct_1b *p;
4860         e2fsck_t ctx;
4861
4862         if (HOLE_BLKADDR(*block_nr))
4863                 return 0;
4864         p = (struct process_block_struct_1b *) priv_data;
4865         ctx = p->ctx;
4866
4867         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4868                 return 0;
4869
4870         /* OK, this is a duplicate block */
4871         if (p->ino != EXT2_BAD_INO) {
4872                 p->pctx->blk = *block_nr;
4873                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4874         }
4875         p->dup_blocks++;
4876         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4877
4878         add_dupe(ctx, p->ino, *block_nr, p->inode);
4879
4880         return 0;
4881 }
4882
4883 /*
4884  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4885  * is used so that we can print pathnames when prompting the user for
4886  * what to do.
4887  */
4888 struct search_dir_struct {
4889         int             count;
4890         ext2_ino_t      first_inode;
4891         ext2_ino_t      max_inode;
4892 };
4893
4894 static int search_dirent_proc(ext2_ino_t dir, int entry,
4895                               struct ext2_dir_entry *dirent,
4896                               int offset FSCK_ATTR((unused)),
4897                               int blocksize FSCK_ATTR((unused)),
4898                               char *buf FSCK_ATTR((unused)),
4899                               void *priv_data)
4900 {
4901         struct search_dir_struct *sd;
4902         struct dup_inode        *p;
4903         dnode_t                 *n;
4904
4905         sd = (struct search_dir_struct *) priv_data;
4906
4907         if (dirent->inode > sd->max_inode)
4908                 /* Should abort this inode, but not everything */
4909                 return 0;
4910
4911         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4912             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4913                 return 0;
4914
4915         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4916         if (!n)
4917                 return 0;
4918         p = (struct dup_inode *) dnode_get(n);
4919         p->dir = dir;
4920         sd->count--;
4921
4922         return sd->count ? 0 : DIRENT_ABORT;
4923 }
4924
4925
4926 static void pass1c(e2fsck_t ctx, char *block_buf)
4927 {
4928         ext2_filsys fs = ctx->fs;
4929         struct search_dir_struct sd;
4930         struct problem_context pctx;
4931
4932         clear_problem_context(&pctx);
4933
4934         if (!(ctx->options & E2F_OPT_PREEN))
4935                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4936
4937         /*
4938          * Search through all directories to translate inodes to names
4939          * (by searching for the containing directory for that inode.)
4940          */
4941         sd.count = dup_inode_count;
4942         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4943         sd.max_inode = fs->super->s_inodes_count;
4944         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4945                                   search_dirent_proc, &sd);
4946 }
4947
4948 static void pass1d(e2fsck_t ctx, char *block_buf)
4949 {
4950         ext2_filsys fs = ctx->fs;
4951         struct dup_inode        *p, *t;
4952         struct dup_block        *q;
4953         ext2_ino_t              *shared, ino;
4954         int     shared_len;
4955         int     i;
4956         int     file_ok;
4957         int     meta_data = 0;
4958         struct problem_context pctx;
4959         dnode_t *n, *m;
4960         struct block_el *s;
4961         struct inode_el *r;
4962
4963         clear_problem_context(&pctx);
4964
4965         if (!(ctx->options & E2F_OPT_PREEN))
4966                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4967         e2fsck_read_bitmaps(ctx);
4968
4969         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4970         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4971         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4972                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4973                                 "Shared inode list");
4974         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4975                 p = (struct dup_inode *) dnode_get(n);
4976                 shared_len = 0;
4977                 file_ok = 1;
4978                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4979                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4980                         continue;
4981
4982                 /*
4983                  * Find all of the inodes which share blocks with this
4984                  * one.  First we find all of the duplicate blocks
4985                  * belonging to this inode, and then search each block
4986                  * get the list of inodes, and merge them together.
4987                  */
4988                 for (s = p->block_list; s; s = s->next) {
4989                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4990                         if (!m)
4991                                 continue; /* Should never happen... */
4992                         q = (struct dup_block *) dnode_get(m);
4993                         if (q->num_bad > 1)
4994                                 file_ok = 0;
4995                         if (check_if_fs_block(ctx, s->block)) {
4996                                 file_ok = 0;
4997                                 meta_data = 1;
4998                         }
4999
5000                         /*
5001                          * Add all inodes used by this block to the
5002                          * shared[] --- which is a unique list, so
5003                          * if an inode is already in shared[], don't
5004                          * add it again.
5005                          */
5006                         for (r = q->inode_list; r; r = r->next) {
5007                                 if (r->inode == ino)
5008                                         continue;
5009                                 for (i = 0; i < shared_len; i++)
5010                                         if (shared[i] == r->inode)
5011                                                 break;
5012                                 if (i == shared_len) {
5013                                         shared[shared_len++] = r->inode;
5014                                 }
5015                         }
5016                 }
5017
5018                 /*
5019                  * Report the inode that we are working on
5020                  */
5021                 pctx.inode = &p->inode;
5022                 pctx.ino = ino;
5023                 pctx.dir = p->dir;
5024                 pctx.blkcount = p->num_dupblocks;
5025                 pctx.num = meta_data ? shared_len+1 : shared_len;
5026                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5027                 pctx.blkcount = 0;
5028                 pctx.num = 0;
5029
5030                 if (meta_data)
5031                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5032
5033                 for (i = 0; i < shared_len; i++) {
5034                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5035                         if (!m)
5036                                 continue; /* should never happen */
5037                         t = (struct dup_inode *) dnode_get(m);
5038                         /*
5039                          * Report the inode that we are sharing with
5040                          */
5041                         pctx.inode = &t->inode;
5042                         pctx.ino = shared[i];
5043                         pctx.dir = t->dir;
5044                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5045                 }
5046                 if (file_ok) {
5047                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5048                         continue;
5049                 }
5050                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5051                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5052                         if (pctx.errcode)
5053                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5054                         else
5055                                 continue;
5056                 }
5057                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5058                         delete_file(ctx, ino, p, block_buf);
5059                 else
5060                         ext2fs_unmark_valid(fs);
5061         }
5062         ext2fs_free_mem(&shared);
5063 }
5064
5065 /*
5066  * Drop the refcount on the dup_block structure, and clear the entry
5067  * in the block_dup_map if appropriate.
5068  */
5069 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5070 {
5071         p->num_bad--;
5072         if (p->num_bad <= 0 ||
5073             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5074                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5075 }
5076
5077 static int delete_file_block(ext2_filsys fs,
5078                              blk_t      *block_nr,
5079                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5080                              blk_t ref_block FSCK_ATTR((unused)),
5081                              int ref_offset FSCK_ATTR((unused)),
5082                              void *priv_data)
5083 {
5084         struct process_block_struct_1b *pb;
5085         struct dup_block *p;
5086         dnode_t *n;
5087         e2fsck_t ctx;
5088
5089         pb = (struct process_block_struct_1b *) priv_data;
5090         ctx = pb->ctx;
5091
5092         if (HOLE_BLKADDR(*block_nr))
5093                 return 0;
5094
5095         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5096                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5097                 if (n) {
5098                         p = (struct dup_block *) dnode_get(n);
5099                         decrement_badcount(ctx, *block_nr, p);
5100                 } else
5101                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5102                                 *block_nr);
5103         } else {
5104                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5105                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5106         }
5107
5108         return 0;
5109 }
5110
5111 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5112                         struct dup_inode *dp, char* block_buf)
5113 {
5114         ext2_filsys fs = ctx->fs;
5115         struct process_block_struct_1b pb;
5116         struct ext2_inode       inode;
5117         struct problem_context  pctx;
5118         unsigned int            count;
5119
5120         clear_problem_context(&pctx);
5121         pctx.ino = pb.ino = ino;
5122         pb.dup_blocks = dp->num_dupblocks;
5123         pb.ctx = ctx;
5124         pctx.str = "delete_file";
5125
5126         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5127         if (ext2fs_inode_has_valid_blocks(&inode))
5128                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5129                                                      delete_file_block, &pb);
5130         if (pctx.errcode)
5131                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5132         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5133         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5134         if (ctx->inode_bad_map)
5135                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5136         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5137
5138         /* Inode may have changed by block_iterate, so reread it */
5139         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5140         inode.i_links_count = 0;
5141         inode.i_dtime = time(NULL);
5142         if (inode.i_file_acl &&
5143             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5144                 count = 1;
5145                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5146                                                    block_buf, -1, &count);
5147                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5148                         pctx.errcode = 0;
5149                         count = 1;
5150                 }
5151                 if (pctx.errcode) {
5152                         pctx.blk = inode.i_file_acl;
5153                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5154                 }
5155                 /*
5156                  * If the count is zero, then arrange to have the
5157                  * block deleted.  If the block is in the block_dup_map,
5158                  * also call delete_file_block since it will take care
5159                  * of keeping the accounting straight.
5160                  */
5161                 if ((count == 0) ||
5162                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5163                                              inode.i_file_acl))
5164                         delete_file_block(fs, &inode.i_file_acl,
5165                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5166         }
5167         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5168 }
5169
5170 struct clone_struct {
5171         errcode_t       errcode;
5172         ext2_ino_t      dir;
5173         char    *buf;
5174         e2fsck_t ctx;
5175 };
5176
5177 static int clone_file_block(ext2_filsys fs,
5178                             blk_t       *block_nr,
5179                             e2_blkcnt_t blockcnt,
5180                             blk_t ref_block FSCK_ATTR((unused)),
5181                             int ref_offset FSCK_ATTR((unused)),
5182                             void *priv_data)
5183 {
5184         struct dup_block *p;
5185         blk_t   new_block;
5186         errcode_t       retval;
5187         struct clone_struct *cs = (struct clone_struct *) priv_data;
5188         dnode_t *n;
5189         e2fsck_t ctx;
5190
5191         ctx = cs->ctx;
5192
5193         if (HOLE_BLKADDR(*block_nr))
5194                 return 0;
5195
5196         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5197                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5198                 if (n) {
5199                         p = (struct dup_block *) dnode_get(n);
5200                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5201                                                   &new_block);
5202                         if (retval) {
5203                                 cs->errcode = retval;
5204                                 return BLOCK_ABORT;
5205                         }
5206                         if (cs->dir && (blockcnt >= 0)) {
5207                                 retval = ext2fs_set_dir_block(fs->dblist,
5208                                       cs->dir, new_block, blockcnt);
5209                                 if (retval) {
5210                                         cs->errcode = retval;
5211                                         return BLOCK_ABORT;
5212                                 }
5213                         }
5214
5215                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5216                                                      cs->buf);
5217                         if (retval) {
5218                                 cs->errcode = retval;
5219                                 return BLOCK_ABORT;
5220                         }
5221                         retval = io_channel_write_blk(fs->io, new_block, 1,
5222                                                       cs->buf);
5223                         if (retval) {
5224                                 cs->errcode = retval;
5225                                 return BLOCK_ABORT;
5226                         }
5227                         decrement_badcount(ctx, *block_nr, p);
5228                         *block_nr = new_block;
5229                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5230                                                  new_block);
5231                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5232                         return BLOCK_CHANGED;
5233                 } else
5234                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5235                                 *block_nr);
5236         }
5237         return 0;
5238 }
5239
5240 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5241                       struct dup_inode *dp, char* block_buf)
5242 {
5243         ext2_filsys fs = ctx->fs;
5244         errcode_t       retval;
5245         struct clone_struct cs;
5246         struct problem_context  pctx;
5247         blk_t           blk;
5248         dnode_t         *n;
5249         struct inode_el *ino_el;
5250         struct dup_block        *db;
5251         struct dup_inode        *di;
5252
5253         clear_problem_context(&pctx);
5254         cs.errcode = 0;
5255         cs.dir = 0;
5256         cs.ctx = ctx;
5257         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5258         if (retval)
5259                 return retval;
5260
5261         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5262                 cs.dir = ino;
5263
5264         pctx.ino = ino;
5265         pctx.str = "clone_file";
5266         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5267                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5268                                                      clone_file_block, &cs);
5269         ext2fs_mark_bb_dirty(fs);
5270         if (pctx.errcode) {
5271                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5272                 retval = pctx.errcode;
5273                 goto errout;
5274         }
5275         if (cs.errcode) {
5276                 bb_error_msg(_("returned from clone_file_block"));
5277                 retval = cs.errcode;
5278                 goto errout;
5279         }
5280         /* The inode may have changed on disk, so we have to re-read it */
5281         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5282         blk = dp->inode.i_file_acl;
5283         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5284                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5285                     BLOCK_CHANGED)) {
5286                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5287                 /*
5288                  * If we cloned the EA block, find all other inodes
5289                  * which refered to that EA block, and modify
5290                  * them to point to the new EA block.
5291                  */
5292                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5293                 db = (struct dup_block *) dnode_get(n);
5294                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5295                         if (ino_el->inode == ino)
5296                                 continue;
5297                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5298                         di = (struct dup_inode *) dnode_get(n);
5299                         if (di->inode.i_file_acl == blk) {
5300                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5301                                 e2fsck_write_inode(ctx, ino_el->inode,
5302                                            &di->inode, "clone file EA");
5303                                 decrement_badcount(ctx, blk, db);
5304                         }
5305                 }
5306         }
5307         retval = 0;
5308 errout:
5309         ext2fs_free_mem(&cs.buf);
5310         return retval;
5311 }
5312
5313 /*
5314  * This routine returns 1 if a block overlaps with one of the superblocks,
5315  * group descriptors, inode bitmaps, or block bitmaps.
5316  */
5317 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5318 {
5319         ext2_filsys fs = ctx->fs;
5320         blk_t   block;
5321         dgrp_t  i;
5322
5323         block = fs->super->s_first_data_block;
5324         for (i = 0; i < fs->group_desc_count; i++) {
5325
5326                 /* Check superblocks/block group descriptros */
5327                 if (ext2fs_bg_has_super(fs, i)) {
5328                         if (test_block >= block &&
5329                             (test_block <= block + fs->desc_blocks))
5330                                 return 1;
5331                 }
5332
5333                 /* Check the inode table */
5334                 if ((fs->group_desc[i].bg_inode_table) &&
5335                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5336                     (test_block < (fs->group_desc[i].bg_inode_table +
5337                                    fs->inode_blocks_per_group)))
5338                         return 1;
5339
5340                 /* Check the bitmap blocks */
5341                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5342                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5343                         return 1;
5344
5345                 block += fs->super->s_blocks_per_group;
5346         }
5347         return 0;
5348 }
5349 /*
5350  * pass2.c --- check directory structure
5351  *
5352  * Pass 2 of e2fsck iterates through all active directory inodes, and
5353  * applies to following tests to each directory entry in the directory
5354  * blocks in the inodes:
5355  *
5356  *      - The length of the directory entry (rec_len) should be at
5357  *              least 8 bytes, and no more than the remaining space
5358  *              left in the directory block.
5359  *      - The length of the name in the directory entry (name_len)
5360  *              should be less than (rec_len - 8).
5361  *      - The inode number in the directory entry should be within
5362  *              legal bounds.
5363  *      - The inode number should refer to a in-use inode.
5364  *      - The first entry should be '.', and its inode should be
5365  *              the inode of the directory.
5366  *      - The second entry should be '..'.
5367  *
5368  * To minimize disk seek time, the directory blocks are processed in
5369  * sorted order of block numbers.
5370  *
5371  * Pass 2 also collects the following information:
5372  *      - The inode numbers of the subdirectories for each directory.
5373  *
5374  * Pass 2 relies on the following information from previous passes:
5375  *      - The directory information collected in pass 1.
5376  *      - The inode_used_map bitmap
5377  *      - The inode_bad_map bitmap
5378  *      - The inode_dir_map bitmap
5379  *
5380  * Pass 2 frees the following data structures
5381  *      - The inode_bad_map bitmap
5382  *      - The inode_reg_map bitmap
5383  */
5384
5385 /*
5386  * Keeps track of how many times an inode is referenced.
5387  */
5388 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5389 static int check_dir_block(ext2_filsys fs,
5390                            struct ext2_db_entry *dir_blocks_info,
5391                            void *priv_data);
5392 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5393                               struct problem_context *pctx);
5394 static int update_dir_block(ext2_filsys fs,
5395                             blk_t       *block_nr,
5396                             e2_blkcnt_t blockcnt,
5397                             blk_t       ref_block,
5398                             int         ref_offset,
5399                             void        *priv_data);
5400 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5401 static int htree_depth(struct dx_dir_info *dx_dir,
5402                        struct dx_dirblock_info *dx_db);
5403 static int special_dir_block_cmp(const void *a, const void *b);
5404
5405 struct check_dir_struct {
5406         char *buf;
5407         struct problem_context  pctx;
5408         int     count, max;
5409         e2fsck_t ctx;
5410 };
5411
5412 static void e2fsck_pass2(e2fsck_t ctx)
5413 {
5414         struct ext2_super_block *sb = ctx->fs->super;
5415         struct problem_context  pctx;
5416         ext2_filsys             fs = ctx->fs;
5417         char                    *buf;
5418         struct dir_info         *dir;
5419         struct check_dir_struct cd;
5420         struct dx_dir_info      *dx_dir;
5421         struct dx_dirblock_info *dx_db, *dx_parent;
5422         int                     b;
5423         int                     i, depth;
5424         problem_t               code;
5425         int                     bad_dir;
5426
5427         clear_problem_context(&cd.pctx);
5428
5429         /* Pass 2 */
5430
5431         if (!(ctx->options & E2F_OPT_PREEN))
5432                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5433
5434         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5435                                                 0, ctx->inode_link_info,
5436                                                 &ctx->inode_count);
5437         if (cd.pctx.errcode) {
5438                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5439                 ctx->flags |= E2F_FLAG_ABORT;
5440                 return;
5441         }
5442         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5443                                               "directory scan buffer");
5444
5445         /*
5446          * Set up the parent pointer for the root directory, if
5447          * present.  (If the root directory is not present, we will
5448          * create it in pass 3.)
5449          */
5450         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5451         if (dir)
5452                 dir->parent = EXT2_ROOT_INO;
5453
5454         cd.buf = buf;
5455         cd.ctx = ctx;
5456         cd.count = 1;
5457         cd.max = ext2fs_dblist_count(fs->dblist);
5458
5459         if (ctx->progress)
5460                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5461
5462         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5463                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5464
5465         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5466                                                 &cd);
5467         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5468                 return;
5469         if (cd.pctx.errcode) {
5470                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5471                 ctx->flags |= E2F_FLAG_ABORT;
5472                 return;
5473         }
5474
5475 #ifdef ENABLE_HTREE
5476         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5477                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478                         return;
5479                 if (dx_dir->numblocks == 0)
5480                         continue;
5481                 clear_problem_context(&pctx);
5482                 bad_dir = 0;
5483                 pctx.dir = dx_dir->ino;
5484                 dx_db = dx_dir->dx_block;
5485                 if (dx_db->flags & DX_FLAG_REFERENCED)
5486                         dx_db->flags |= DX_FLAG_DUP_REF;
5487                 else
5488                         dx_db->flags |= DX_FLAG_REFERENCED;
5489                 /*
5490                  * Find all of the first and last leaf blocks, and
5491                  * update their parent's min and max hash values
5492                  */
5493                 for (b=0, dx_db = dx_dir->dx_block;
5494                      b < dx_dir->numblocks;
5495                      b++, dx_db++) {
5496                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5497                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5498                                 continue;
5499                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5500                         /*
5501                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5502                          */
5503                         if (dx_db->flags & DX_FLAG_FIRST)
5504                                 dx_parent->min_hash = dx_db->min_hash;
5505                         /*
5506                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5507                          */
5508                         if (dx_db->flags & DX_FLAG_LAST)
5509                                 dx_parent->max_hash = dx_db->max_hash;
5510                 }
5511
5512                 for (b=0, dx_db = dx_dir->dx_block;
5513                      b < dx_dir->numblocks;
5514                      b++, dx_db++) {
5515                         pctx.blkcount = b;
5516                         pctx.group = dx_db->parent;
5517                         code = 0;
5518                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5519                             (dx_db->min_hash < dx_db->node_min_hash)) {
5520                                 pctx.blk = dx_db->min_hash;
5521                                 pctx.blk2 = dx_db->node_min_hash;
5522                                 code = PR_2_HTREE_MIN_HASH;
5523                                 fix_problem(ctx, code, &pctx);
5524                                 bad_dir++;
5525                         }
5526                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5527                                 depth = htree_depth(dx_dir, dx_db);
5528                                 if (depth != dx_dir->depth) {
5529                                         code = PR_2_HTREE_BAD_DEPTH;
5530                                         fix_problem(ctx, code, &pctx);
5531                                         bad_dir++;
5532                                 }
5533                         }
5534                         /*
5535                          * This test doesn't apply for the root block
5536                          * at block #0
5537                          */
5538                         if (b &&
5539                             (dx_db->max_hash > dx_db->node_max_hash)) {
5540                                 pctx.blk = dx_db->max_hash;
5541                                 pctx.blk2 = dx_db->node_max_hash;
5542                                 code = PR_2_HTREE_MAX_HASH;
5543                                 fix_problem(ctx, code, &pctx);
5544                                 bad_dir++;
5545                         }
5546                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5547                                 code = PR_2_HTREE_NOTREF;
5548                                 fix_problem(ctx, code, &pctx);
5549                                 bad_dir++;
5550                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5551                                 code = PR_2_HTREE_DUPREF;
5552                                 fix_problem(ctx, code, &pctx);
5553                                 bad_dir++;
5554                         }
5555                         if (code == 0)
5556                                 continue;
5557                 }
5558                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5559                         clear_htree(ctx, dx_dir->ino);
5560                         dx_dir->numblocks = 0;
5561                 }
5562         }
5563 #endif
5564         ext2fs_free_mem(&buf);
5565         ext2fs_free_dblist(fs->dblist);
5566
5567         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5568         ctx->inode_bad_map = 0;
5569         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5570         ctx->inode_reg_map = 0;
5571
5572         clear_problem_context(&pctx);
5573         if (ctx->large_files) {
5574                 if (!(sb->s_feature_ro_compat &
5575                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5576                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5577                         sb->s_feature_ro_compat |=
5578                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5579                         ext2fs_mark_super_dirty(fs);
5580                 }
5581                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5582                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5583                         ext2fs_update_dynamic_rev(fs);
5584                         ext2fs_mark_super_dirty(fs);
5585                 }
5586         } else if (!ctx->large_files &&
5587             (sb->s_feature_ro_compat &
5588               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5589                 if (fs->flags & EXT2_FLAG_RW) {
5590                         sb->s_feature_ro_compat &=
5591                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5592                         ext2fs_mark_super_dirty(fs);
5593                 }
5594         }
5595
5596 }
5597
5598 #define MAX_DEPTH 32000
5599 static int htree_depth(struct dx_dir_info *dx_dir,
5600                        struct dx_dirblock_info *dx_db)
5601 {
5602         int     depth = 0;
5603
5604         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5605                 dx_db = &dx_dir->dx_block[dx_db->parent];
5606                 depth++;
5607         }
5608         return depth;
5609 }
5610
5611 static int dict_de_cmp(const void *a, const void *b)
5612 {
5613         const struct ext2_dir_entry *de_a, *de_b;
5614         int     a_len, b_len;
5615
5616         de_a = (const struct ext2_dir_entry *) a;
5617         a_len = de_a->name_len & 0xFF;
5618         de_b = (const struct ext2_dir_entry *) b;
5619         b_len = de_b->name_len & 0xFF;
5620
5621         if (a_len != b_len)
5622                 return (a_len - b_len);
5623
5624         return strncmp(de_a->name, de_b->name, a_len);
5625 }
5626
5627 /*
5628  * This is special sort function that makes sure that directory blocks
5629  * with a dirblock of zero are sorted to the beginning of the list.
5630  * This guarantees that the root node of the htree directories are
5631  * processed first, so we know what hash version to use.
5632  */
5633 static int special_dir_block_cmp(const void *a, const void *b)
5634 {
5635         const struct ext2_db_entry *db_a =
5636                 (const struct ext2_db_entry *) a;
5637         const struct ext2_db_entry *db_b =
5638                 (const struct ext2_db_entry *) b;
5639
5640         if (db_a->blockcnt && !db_b->blockcnt)
5641                 return 1;
5642
5643         if (!db_a->blockcnt && db_b->blockcnt)
5644                 return -1;
5645
5646         if (db_a->blk != db_b->blk)
5647                 return (int) (db_a->blk - db_b->blk);
5648
5649         if (db_a->ino != db_b->ino)
5650                 return (int) (db_a->ino - db_b->ino);
5651
5652         return (int) (db_a->blockcnt - db_b->blockcnt);
5653 }
5654
5655
5656 /*
5657  * Make sure the first entry in the directory is '.', and that the
5658  * directory entry is sane.
5659  */
5660 static int check_dot(e2fsck_t ctx,
5661                      struct ext2_dir_entry *dirent,
5662                      ext2_ino_t ino, struct problem_context *pctx)
5663 {
5664         struct ext2_dir_entry *nextdir;
5665         int     status = 0;
5666         int     created = 0;
5667         int     new_len;
5668         int     problem = 0;
5669
5670         if (!dirent->inode)
5671                 problem = PR_2_MISSING_DOT;
5672         else if (((dirent->name_len & 0xFF) != 1) ||
5673                  (dirent->name[0] != '.'))
5674                 problem = PR_2_1ST_NOT_DOT;
5675         else if (dirent->name[1] != '\0')
5676                 problem = PR_2_DOT_NULL_TERM;
5677
5678         if (problem) {
5679                 if (fix_problem(ctx, problem, pctx)) {
5680                         if (dirent->rec_len < 12)
5681                                 dirent->rec_len = 12;
5682                         dirent->inode = ino;
5683                         dirent->name_len = 1;
5684                         dirent->name[0] = '.';
5685                         dirent->name[1] = '\0';
5686                         status = 1;
5687                         created = 1;
5688                 }
5689         }
5690         if (dirent->inode != ino) {
5691                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5692                         dirent->inode = ino;
5693                         status = 1;
5694                 }
5695         }
5696         if (dirent->rec_len > 12) {
5697                 new_len = dirent->rec_len - 12;
5698                 if (new_len > 12) {
5699                         if (created ||
5700                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5701                                 nextdir = (struct ext2_dir_entry *)
5702                                         ((char *) dirent + 12);
5703                                 dirent->rec_len = 12;
5704                                 nextdir->rec_len = new_len;
5705                                 nextdir->inode = 0;
5706                                 nextdir->name_len = 0;
5707                                 status = 1;
5708                         }
5709                 }
5710         }
5711         return status;
5712 }
5713
5714 /*
5715  * Make sure the second entry in the directory is '..', and that the
5716  * directory entry is sane.  We do not check the inode number of '..'
5717  * here; this gets done in pass 3.
5718  */
5719 static int check_dotdot(e2fsck_t ctx,
5720                         struct ext2_dir_entry *dirent,
5721                         struct dir_info *dir, struct problem_context *pctx)
5722 {
5723         int             problem = 0;
5724
5725         if (!dirent->inode)
5726                 problem = PR_2_MISSING_DOT_DOT;
5727         else if (((dirent->name_len & 0xFF) != 2) ||
5728                  (dirent->name[0] != '.') ||
5729                  (dirent->name[1] != '.'))
5730                 problem = PR_2_2ND_NOT_DOT_DOT;
5731         else if (dirent->name[2] != '\0')
5732                 problem = PR_2_DOT_DOT_NULL_TERM;
5733
5734         if (problem) {
5735                 if (fix_problem(ctx, problem, pctx)) {
5736                         if (dirent->rec_len < 12)
5737                                 dirent->rec_len = 12;
5738                         /*
5739                          * Note: we don't have the parent inode just
5740                          * yet, so we will fill it in with the root
5741                          * inode.  This will get fixed in pass 3.
5742                          */
5743                         dirent->inode = EXT2_ROOT_INO;
5744                         dirent->name_len = 2;
5745                         dirent->name[0] = '.';
5746                         dirent->name[1] = '.';
5747                         dirent->name[2] = '\0';
5748                         return 1;
5749                 }
5750                 return 0;
5751         }
5752         dir->dotdot = dirent->inode;
5753         return 0;
5754 }
5755
5756 /*
5757  * Check to make sure a directory entry doesn't contain any illegal
5758  * characters.
5759  */
5760 static int check_name(e2fsck_t ctx,
5761                       struct ext2_dir_entry *dirent,
5762                       struct problem_context *pctx)
5763 {
5764         int     i;
5765         int     fixup = -1;
5766         int     ret = 0;
5767
5768         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5769                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5770                         if (fixup < 0) {
5771                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5772                         }
5773                         if (fixup) {
5774                                 dirent->name[i] = '.';
5775                                 ret = 1;
5776                         }
5777                 }
5778         }
5779         return ret;
5780 }
5781
5782 /*
5783  * Check the directory filetype (if present)
5784  */
5785
5786 /*
5787  * Given a mode, return the ext2 file type
5788  */
5789 static int ext2_file_type(unsigned int mode)
5790 {
5791         if (LINUX_S_ISREG(mode))
5792                 return EXT2_FT_REG_FILE;
5793
5794         if (LINUX_S_ISDIR(mode))
5795                 return EXT2_FT_DIR;
5796
5797         if (LINUX_S_ISCHR(mode))
5798                 return EXT2_FT_CHRDEV;
5799
5800         if (LINUX_S_ISBLK(mode))
5801                 return EXT2_FT_BLKDEV;
5802
5803         if (LINUX_S_ISLNK(mode))
5804                 return EXT2_FT_SYMLINK;
5805
5806         if (LINUX_S_ISFIFO(mode))
5807                 return EXT2_FT_FIFO;
5808
5809         if (LINUX_S_ISSOCK(mode))
5810                 return EXT2_FT_SOCK;
5811
5812         return 0;
5813 }
5814
5815 static int check_filetype(e2fsck_t ctx,
5816                                    struct ext2_dir_entry *dirent,
5817                                    struct problem_context *pctx)
5818 {
5819         int     filetype = dirent->name_len >> 8;
5820         int     should_be = EXT2_FT_UNKNOWN;
5821         struct ext2_inode       inode;
5822
5823         if (!(ctx->fs->super->s_feature_incompat &
5824               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5825                 if (filetype == 0 ||
5826                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5827                         return 0;
5828                 dirent->name_len = dirent->name_len & 0xFF;
5829                 return 1;
5830         }
5831
5832         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5833                 should_be = EXT2_FT_DIR;
5834         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5835                                             dirent->inode)) {
5836                 should_be = EXT2_FT_REG_FILE;
5837         } else if (ctx->inode_bad_map &&
5838                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5839                                             dirent->inode))
5840                 should_be = 0;
5841         else {
5842                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5843                                   "check_filetype");
5844                 should_be = ext2_file_type(inode.i_mode);
5845         }
5846         if (filetype == should_be)
5847                 return 0;
5848         pctx->num = should_be;
5849
5850         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5851                         pctx) == 0)
5852                 return 0;
5853
5854         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5855         return 1;
5856 }
5857
5858 #ifdef ENABLE_HTREE
5859 static void parse_int_node(ext2_filsys fs,
5860                            struct ext2_db_entry *db,
5861                            struct check_dir_struct *cd,
5862                            struct dx_dir_info   *dx_dir,
5863                            char *block_buf)
5864 {
5865         struct          ext2_dx_root_info  *root;
5866         struct          ext2_dx_entry *ent;
5867         struct          ext2_dx_countlimit *limit;
5868         struct dx_dirblock_info *dx_db;
5869         int             i, expect_limit, count;
5870         blk_t           blk;
5871         ext2_dirhash_t  min_hash = 0xffffffff;
5872         ext2_dirhash_t  max_hash = 0;
5873         ext2_dirhash_t  hash = 0, prev_hash;
5874
5875         if (db->blockcnt == 0) {
5876                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5877                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5878         } else {
5879                 ent = (struct ext2_dx_entry *) (block_buf+8);
5880         }
5881         limit = (struct ext2_dx_countlimit *) ent;
5882
5883         count = ext2fs_le16_to_cpu(limit->count);
5884         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5885                 sizeof(struct ext2_dx_entry);
5886         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5887                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5888                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5889                         goto clear_and_exit;
5890         }
5891         if (count > expect_limit) {
5892                 cd->pctx.num = count;
5893                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5894                         goto clear_and_exit;
5895                 count = expect_limit;
5896         }
5897
5898         for (i=0; i < count; i++) {
5899                 prev_hash = hash;
5900                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5901                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5902                 /* Check to make sure the block is valid */
5903                 if (blk > (blk_t) dx_dir->numblocks) {
5904                         cd->pctx.blk = blk;
5905                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5906                                         &cd->pctx))
5907                                 goto clear_and_exit;
5908                 }
5909                 if (hash < prev_hash &&
5910                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5911                         goto clear_and_exit;
5912                 dx_db = &dx_dir->dx_block[blk];
5913                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5914                         dx_db->flags |= DX_FLAG_DUP_REF;
5915                 } else {
5916                         dx_db->flags |= DX_FLAG_REFERENCED;
5917                         dx_db->parent = db->blockcnt;
5918                 }
5919                 if (hash < min_hash)
5920                         min_hash = hash;
5921                 if (hash > max_hash)
5922                         max_hash = hash;
5923                 dx_db->node_min_hash = hash;
5924                 if ((i+1) < count)
5925                         dx_db->node_max_hash =
5926                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5927                 else {
5928                         dx_db->node_max_hash = 0xfffffffe;
5929                         dx_db->flags |= DX_FLAG_LAST;
5930                 }
5931                 if (i == 0)
5932                         dx_db->flags |= DX_FLAG_FIRST;
5933         }
5934         dx_db = &dx_dir->dx_block[db->blockcnt];
5935         dx_db->min_hash = min_hash;
5936         dx_db->max_hash = max_hash;
5937         return;
5938
5939 clear_and_exit:
5940         clear_htree(cd->ctx, cd->pctx.ino);
5941         dx_dir->numblocks = 0;
5942 }
5943 #endif /* ENABLE_HTREE */
5944
5945 /*
5946  * Given a busted directory, try to salvage it somehow.
5947  *
5948  */
5949 static void salvage_directory(ext2_filsys fs,
5950                               struct ext2_dir_entry *dirent,
5951                               struct ext2_dir_entry *prev,
5952                               unsigned int *offset)
5953 {
5954         char    *cp = (char *) dirent;
5955         int left = fs->blocksize - *offset - dirent->rec_len;
5956         int name_len = dirent->name_len & 0xFF;
5957
5958         /*
5959          * Special case of directory entry of size 8: copy what's left
5960          * of the directory block up to cover up the invalid hole.
5961          */
5962         if ((left >= 12) && (dirent->rec_len == 8)) {
5963                 memmove(cp, cp+8, left);
5964                 memset(cp + left, 0, 8);
5965                 return;
5966         }
5967         /*
5968          * If the directory entry overruns the end of the directory
5969          * block, and the name is small enough to fit, then adjust the
5970          * record length.
5971          */
5972         if ((left < 0) &&
5973             (name_len + 8 <= dirent->rec_len + left) &&
5974             dirent->inode <= fs->super->s_inodes_count &&
5975             strnlen(dirent->name, name_len) == name_len) {
5976                 dirent->rec_len += left;
5977                 return;
5978         }
5979         /*
5980          * If the directory entry is a multiple of four, so it is
5981          * valid, let the previous directory entry absorb the invalid
5982          * one.
5983          */
5984         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5985                 prev->rec_len += dirent->rec_len;
5986                 *offset += dirent->rec_len;
5987                 return;
5988         }
5989         /*
5990          * Default salvage method --- kill all of the directory
5991          * entries for the rest of the block.  We will either try to
5992          * absorb it into the previous directory entry, or create a
5993          * new empty directory entry the rest of the directory block.
5994          */
5995         if (prev) {
5996                 prev->rec_len += fs->blocksize - *offset;
5997                 *offset = fs->blocksize;
5998         } else {
5999                 dirent->rec_len = fs->blocksize - *offset;
6000                 dirent->name_len = 0;
6001                 dirent->inode = 0;
6002         }
6003 }
6004
6005 static int check_dir_block(ext2_filsys fs,
6006                            struct ext2_db_entry *db,
6007                            void *priv_data)
6008 {
6009         struct dir_info         *subdir, *dir;
6010         struct dx_dir_info      *dx_dir;
6011 #ifdef ENABLE_HTREE
6012         struct dx_dirblock_info *dx_db = NULL;
6013 #endif /* ENABLE_HTREE */
6014         struct ext2_dir_entry   *dirent, *prev;
6015         ext2_dirhash_t          hash;
6016         unsigned int            offset = 0;
6017         int                     dir_modified = 0;
6018         int                     dot_state;
6019         blk_t                   block_nr = db->blk;
6020         ext2_ino_t              ino = db->ino;
6021         __u16                   links;
6022         struct check_dir_struct *cd;
6023         char                    *buf;
6024         e2fsck_t                ctx;
6025         int                     problem;
6026         struct ext2_dx_root_info *root;
6027         struct ext2_dx_countlimit *limit;
6028         static dict_t de_dict;
6029         struct problem_context  pctx;
6030         int     dups_found = 0;
6031
6032         cd = (struct check_dir_struct *) priv_data;
6033         buf = cd->buf;
6034         ctx = cd->ctx;
6035
6036         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6037                 return DIRENT_ABORT;
6038
6039         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6040                 return DIRENT_ABORT;
6041
6042         /*
6043          * Make sure the inode is still in use (could have been
6044          * deleted in the duplicate/bad blocks pass.
6045          */
6046         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6047                 return 0;
6048
6049         cd->pctx.ino = ino;
6050         cd->pctx.blk = block_nr;
6051         cd->pctx.blkcount = db->blockcnt;
6052         cd->pctx.ino2 = 0;
6053         cd->pctx.dirent = 0;
6054         cd->pctx.num = 0;
6055
6056         if (db->blk == 0) {
6057                 if (allocate_dir_block(ctx, db, &cd->pctx))
6058                         return 0;
6059                 block_nr = db->blk;
6060         }
6061
6062         if (db->blockcnt)
6063                 dot_state = 2;
6064         else
6065                 dot_state = 0;
6066
6067         if (ctx->dirs_to_hash &&
6068             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6069                 dups_found++;
6070
6071         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6072         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6073                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6074         if (cd->pctx.errcode) {
6075                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6076                         ctx->flags |= E2F_FLAG_ABORT;
6077                         return DIRENT_ABORT;
6078                 }
6079                 memset(buf, 0, fs->blocksize);
6080         }
6081 #ifdef ENABLE_HTREE
6082         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6083         if (dx_dir && dx_dir->numblocks) {
6084                 if (db->blockcnt >= dx_dir->numblocks) {
6085                         printf("XXX should never happen!!!\n");
6086                         abort();
6087                 }
6088                 dx_db = &dx_dir->dx_block[db->blockcnt];
6089                 dx_db->type = DX_DIRBLOCK_LEAF;
6090                 dx_db->phys = block_nr;
6091                 dx_db->min_hash = ~0;
6092                 dx_db->max_hash = 0;
6093
6094                 dirent = (struct ext2_dir_entry *) buf;
6095                 limit = (struct ext2_dx_countlimit *) (buf+8);
6096                 if (db->blockcnt == 0) {
6097                         root = (struct ext2_dx_root_info *) (buf + 24);
6098                         dx_db->type = DX_DIRBLOCK_ROOT;
6099                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6100                         if ((root->reserved_zero ||
6101                              root->info_length < 8 ||
6102                              root->indirect_levels > 1) &&
6103                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6104                                 clear_htree(ctx, ino);
6105                                 dx_dir->numblocks = 0;
6106                                 dx_db = 0;
6107                         }
6108                         dx_dir->hashversion = root->hash_version;
6109                         dx_dir->depth = root->indirect_levels + 1;
6110                 } else if ((dirent->inode == 0) &&
6111                            (dirent->rec_len == fs->blocksize) &&
6112                            (dirent->name_len == 0) &&
6113                            (ext2fs_le16_to_cpu(limit->limit) ==
6114                             ((fs->blocksize-8) /
6115                              sizeof(struct ext2_dx_entry))))
6116                         dx_db->type = DX_DIRBLOCK_NODE;
6117         }
6118 #endif /* ENABLE_HTREE */
6119
6120         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6121         prev = 0;
6122         do {
6123                 problem = 0;
6124                 dirent = (struct ext2_dir_entry *) (buf + offset);
6125                 cd->pctx.dirent = dirent;
6126                 cd->pctx.num = offset;
6127                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6128                     (dirent->rec_len < 12) ||
6129                     ((dirent->rec_len % 4) != 0) ||
6130                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6131                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6132                                 salvage_directory(fs, dirent, prev, &offset);
6133                                 dir_modified++;
6134                                 continue;
6135                         } else
6136                                 goto abort_free_dict;
6137                 }
6138                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6139                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6140                                 dirent->name_len = EXT2_NAME_LEN;
6141                                 dir_modified++;
6142                         }
6143                 }
6144
6145                 if (dot_state == 0) {
6146                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6147                                 dir_modified++;
6148                 } else if (dot_state == 1) {
6149                         dir = e2fsck_get_dir_info(ctx, ino);
6150                         if (!dir) {
6151                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6152                                 goto abort_free_dict;
6153                         }
6154                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6155                                 dir_modified++;
6156                 } else if (dirent->inode == ino) {
6157                         problem = PR_2_LINK_DOT;
6158                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6159                                 dirent->inode = 0;
6160                                 dir_modified++;
6161                                 goto next;
6162                         }
6163                 }
6164                 if (!dirent->inode)
6165                         goto next;
6166
6167                 /*
6168                  * Make sure the inode listed is a legal one.
6169                  */
6170                 if (((dirent->inode != EXT2_ROOT_INO) &&
6171                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6172                     (dirent->inode > fs->super->s_inodes_count)) {
6173                         problem = PR_2_BAD_INO;
6174                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6175                                                dirent->inode))) {
6176                         /*
6177                          * If the inode is unused, offer to clear it.
6178                          */
6179                         problem = PR_2_UNUSED_INODE;
6180                 } else if ((dot_state > 1) &&
6181                            ((dirent->name_len & 0xFF) == 1) &&
6182                            (dirent->name[0] == '.')) {
6183                         /*
6184                          * If there's a '.' entry in anything other
6185                          * than the first directory entry, it's a
6186                          * duplicate entry that should be removed.
6187                          */
6188                         problem = PR_2_DUP_DOT;
6189                 } else if ((dot_state > 1) &&
6190                            ((dirent->name_len & 0xFF) == 2) &&
6191                            (dirent->name[0] == '.') &&
6192                            (dirent->name[1] == '.')) {
6193                         /*
6194                          * If there's a '..' entry in anything other
6195                          * than the second directory entry, it's a
6196                          * duplicate entry that should be removed.
6197                          */
6198                         problem = PR_2_DUP_DOT_DOT;
6199                 } else if ((dot_state > 1) &&
6200                            (dirent->inode == EXT2_ROOT_INO)) {
6201                         /*
6202                          * Don't allow links to the root directory.
6203                          * We check this specially to make sure we
6204                          * catch this error case even if the root
6205                          * directory hasn't been created yet.
6206                          */
6207                         problem = PR_2_LINK_ROOT;
6208                 } else if ((dot_state > 1) &&
6209                            (dirent->name_len & 0xFF) == 0) {
6210                         /*
6211                          * Don't allow zero-length directory names.
6212                          */
6213                         problem = PR_2_NULL_NAME;
6214                 }
6215
6216                 if (problem) {
6217                         if (fix_problem(ctx, problem, &cd->pctx)) {
6218                                 dirent->inode = 0;
6219                                 dir_modified++;
6220                                 goto next;
6221                         } else {
6222                                 ext2fs_unmark_valid(fs);
6223                                 if (problem == PR_2_BAD_INO)
6224                                         goto next;
6225                         }
6226                 }
6227
6228                 /*
6229                  * If the inode was marked as having bad fields in
6230                  * pass1, process it and offer to fix/clear it.
6231                  * (We wait until now so that we can display the
6232                  * pathname to the user.)
6233                  */
6234                 if (ctx->inode_bad_map &&
6235                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6236                                              dirent->inode)) {
6237                         if (e2fsck_process_bad_inode(ctx, ino,
6238                                                      dirent->inode,
6239                                                      buf + fs->blocksize)) {
6240                                 dirent->inode = 0;
6241                                 dir_modified++;
6242                                 goto next;
6243                         }
6244                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6245                                 return DIRENT_ABORT;
6246                 }
6247
6248                 if (check_name(ctx, dirent, &cd->pctx))
6249                         dir_modified++;
6250
6251                 if (check_filetype(ctx, dirent, &cd->pctx))
6252                         dir_modified++;
6253
6254 #ifdef ENABLE_HTREE
6255                 if (dx_db) {
6256                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6257                                        (dirent->name_len & 0xFF),
6258                                        fs->super->s_hash_seed, &hash, 0);
6259                         if (hash < dx_db->min_hash)
6260                                 dx_db->min_hash = hash;
6261                         if (hash > dx_db->max_hash)
6262                                 dx_db->max_hash = hash;
6263                 }
6264 #endif
6265
6266                 /*
6267                  * If this is a directory, then mark its parent in its
6268                  * dir_info structure.  If the parent field is already
6269                  * filled in, then this directory has more than one
6270                  * hard link.  We assume the first link is correct,
6271                  * and ask the user if he/she wants to clear this one.
6272                  */
6273                 if ((dot_state > 1) &&
6274                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6275                                               dirent->inode))) {
6276                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6277                         if (!subdir) {
6278                                 cd->pctx.ino = dirent->inode;
6279                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6280                                 goto abort_free_dict;
6281                         }
6282                         if (subdir->parent) {
6283                                 cd->pctx.ino2 = subdir->parent;
6284                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6285                                                 &cd->pctx)) {
6286                                         dirent->inode = 0;
6287                                         dir_modified++;
6288                                         goto next;
6289                                 }
6290                                 cd->pctx.ino2 = 0;
6291                         } else
6292                                 subdir->parent = ino;
6293                 }
6294
6295                 if (dups_found) {
6296                         ;
6297                 } else if (dict_lookup(&de_dict, dirent)) {
6298                         clear_problem_context(&pctx);
6299                         pctx.ino = ino;
6300                         pctx.dirent = dirent;
6301                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6302                         if (!ctx->dirs_to_hash)
6303                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6304                         if (ctx->dirs_to_hash)
6305                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6306                         dups_found++;
6307                 } else
6308                         dict_alloc_insert(&de_dict, dirent, dirent);
6309
6310                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6311                                         &links);
6312                 if (links > 1)
6313                         ctx->fs_links_count++;
6314                 ctx->fs_total_count++;
6315         next:
6316                 prev = dirent;
6317                 offset += dirent->rec_len;
6318                 dot_state++;
6319         } while (offset < fs->blocksize);
6320 #ifdef ENABLE_HTREE
6321         if (dx_db) {
6322                 cd->pctx.dir = cd->pctx.ino;
6323                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6324                     (dx_db->type == DX_DIRBLOCK_NODE))
6325                         parse_int_node(fs, db, cd, dx_dir, buf);
6326         }
6327 #endif /* ENABLE_HTREE */
6328         if (offset != fs->blocksize) {
6329                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6330                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6331                         dirent->rec_len = cd->pctx.num;
6332                         dir_modified++;
6333                 }
6334         }
6335         if (dir_modified) {
6336                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6337                 if (cd->pctx.errcode) {
6338                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6339                                          &cd->pctx))
6340                                 goto abort_free_dict;
6341                 }
6342                 ext2fs_mark_changed(fs);
6343         }
6344         dict_free_nodes(&de_dict);
6345         return 0;
6346 abort_free_dict:
6347         dict_free_nodes(&de_dict);
6348         ctx->flags |= E2F_FLAG_ABORT;
6349         return DIRENT_ABORT;
6350 }
6351
6352 /*
6353  * This function is called to deallocate a block, and is an interator
6354  * functioned called by deallocate inode via ext2fs_iterate_block().
6355  */
6356 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6357                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6358                                   blk_t ref_block FSCK_ATTR((unused)),
6359                                   int ref_offset FSCK_ATTR((unused)),
6360                                   void *priv_data)
6361 {
6362         e2fsck_t        ctx = (e2fsck_t) priv_data;
6363
6364         if (HOLE_BLKADDR(*block_nr))
6365                 return 0;
6366         if ((*block_nr < fs->super->s_first_data_block) ||
6367             (*block_nr >= fs->super->s_blocks_count))
6368                 return 0;
6369         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6370         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6371         return 0;
6372 }
6373
6374 /*
6375  * This fuction deallocates an inode
6376  */
6377 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6378 {
6379         ext2_filsys fs = ctx->fs;
6380         struct ext2_inode       inode;
6381         struct problem_context  pctx;
6382         __u32                   count;
6383
6384         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6385         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6386         inode.i_links_count = 0;
6387         inode.i_dtime = time(NULL);
6388         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6389         clear_problem_context(&pctx);
6390         pctx.ino = ino;
6391
6392         /*
6393          * Fix up the bitmaps...
6394          */
6395         e2fsck_read_bitmaps(ctx);
6396         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6397         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6398         if (ctx->inode_bad_map)
6399                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6400         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6401
6402         if (inode.i_file_acl &&
6403             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6404                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6405                                                    block_buf, -1, &count);
6406                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6407                         pctx.errcode = 0;
6408                         count = 1;
6409                 }
6410                 if (pctx.errcode) {
6411                         pctx.blk = inode.i_file_acl;
6412                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6413                         ctx->flags |= E2F_FLAG_ABORT;
6414                         return;
6415                 }
6416                 if (count == 0) {
6417                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6418                                                    inode.i_file_acl);
6419                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6420                 }
6421                 inode.i_file_acl = 0;
6422         }
6423
6424         if (!ext2fs_inode_has_valid_blocks(&inode))
6425                 return;
6426
6427         if (LINUX_S_ISREG(inode.i_mode) &&
6428             (inode.i_size_high || inode.i_size & 0x80000000UL))
6429                 ctx->large_files--;
6430
6431         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6432                                             deallocate_inode_block, ctx);
6433         if (pctx.errcode) {
6434                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6435                 ctx->flags |= E2F_FLAG_ABORT;
6436                 return;
6437         }
6438 }
6439
6440 /*
6441  * This fuction clears the htree flag on an inode
6442  */
6443 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6444 {
6445         struct ext2_inode       inode;
6446
6447         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6448         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6449         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6450         if (ctx->dirs_to_hash)
6451                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6452 }
6453
6454
6455 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6456                                     ext2_ino_t ino, char *buf)
6457 {
6458         ext2_filsys fs = ctx->fs;
6459         struct ext2_inode       inode;
6460         int                     inode_modified = 0;
6461         int                     not_fixed = 0;
6462         unsigned char           *frag, *fsize;
6463         struct problem_context  pctx;
6464         int     problem = 0;
6465
6466         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6467
6468         clear_problem_context(&pctx);
6469         pctx.ino = ino;
6470         pctx.dir = dir;
6471         pctx.inode = &inode;
6472
6473         if (inode.i_file_acl &&
6474             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6475             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6476                 inode.i_file_acl = 0;
6477 #if BB_BIG_ENDIAN
6478                 /*
6479                  * This is a special kludge to deal with long symlinks
6480                  * on big endian systems.  i_blocks had already been
6481                  * decremented earlier in pass 1, but since i_file_acl
6482                  * hadn't yet been cleared, ext2fs_read_inode()
6483                  * assumed that the file was short symlink and would
6484                  * not have byte swapped i_block[0].  Hence, we have
6485                  * to byte-swap it here.
6486                  */
6487                 if (LINUX_S_ISLNK(inode.i_mode) &&
6488                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6489                     (inode.i_blocks == fs->blocksize >> 9))
6490                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6491 #endif
6492                 inode_modified++;
6493         } else
6494                 not_fixed++;
6495
6496         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6497             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6498             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6499             !(LINUX_S_ISSOCK(inode.i_mode)))
6500                 problem = PR_2_BAD_MODE;
6501         else if (LINUX_S_ISCHR(inode.i_mode)
6502                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6503                 problem = PR_2_BAD_CHAR_DEV;
6504         else if (LINUX_S_ISBLK(inode.i_mode)
6505                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6506                 problem = PR_2_BAD_BLOCK_DEV;
6507         else if (LINUX_S_ISFIFO(inode.i_mode)
6508                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6509                 problem = PR_2_BAD_FIFO;
6510         else if (LINUX_S_ISSOCK(inode.i_mode)
6511                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6512                 problem = PR_2_BAD_SOCKET;
6513         else if (LINUX_S_ISLNK(inode.i_mode)
6514                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6515                 problem = PR_2_INVALID_SYMLINK;
6516         }
6517
6518         if (problem) {
6519                 if (fix_problem(ctx, problem, &pctx)) {
6520                         deallocate_inode(ctx, ino, 0);
6521                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6522                                 return 0;
6523                         return 1;
6524                 } else
6525                         not_fixed++;
6526                 problem = 0;
6527         }
6528
6529         if (inode.i_faddr) {
6530                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6531                         inode.i_faddr = 0;
6532                         inode_modified++;
6533                 } else
6534                         not_fixed++;
6535         }
6536
6537         switch (fs->super->s_creator_os) {
6538             case EXT2_OS_LINUX:
6539                 frag = &inode.osd2.linux2.l_i_frag;
6540                 fsize = &inode.osd2.linux2.l_i_fsize;
6541                 break;
6542             case EXT2_OS_HURD:
6543                 frag = &inode.osd2.hurd2.h_i_frag;
6544                 fsize = &inode.osd2.hurd2.h_i_fsize;
6545                 break;
6546             case EXT2_OS_MASIX:
6547                 frag = &inode.osd2.masix2.m_i_frag;
6548                 fsize = &inode.osd2.masix2.m_i_fsize;
6549                 break;
6550             default:
6551                 frag = fsize = 0;
6552         }
6553         if (frag && *frag) {
6554                 pctx.num = *frag;
6555                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6556                         *frag = 0;
6557                         inode_modified++;
6558                 } else
6559                         not_fixed++;
6560                 pctx.num = 0;
6561         }
6562         if (fsize && *fsize) {
6563                 pctx.num = *fsize;
6564                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6565                         *fsize = 0;
6566                         inode_modified++;
6567                 } else
6568                         not_fixed++;
6569                 pctx.num = 0;
6570         }
6571
6572         if (inode.i_file_acl &&
6573             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6574              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6575                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6576                         inode.i_file_acl = 0;
6577                         inode_modified++;
6578                 } else
6579                         not_fixed++;
6580         }
6581         if (inode.i_dir_acl &&
6582             LINUX_S_ISDIR(inode.i_mode)) {
6583                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6584                         inode.i_dir_acl = 0;
6585                         inode_modified++;
6586                 } else
6587                         not_fixed++;
6588         }
6589
6590         if (inode_modified)
6591                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6592         if (!not_fixed)
6593                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6594         return 0;
6595 }
6596
6597
6598 /*
6599  * allocate_dir_block --- this function allocates a new directory
6600  *      block for a particular inode; this is done if a directory has
6601  *      a "hole" in it, or if a directory has a illegal block number
6602  *      that was zeroed out and now needs to be replaced.
6603  */
6604 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6605                               struct problem_context *pctx)
6606 {
6607         ext2_filsys fs = ctx->fs;
6608         blk_t                   blk;
6609         char                    *block;
6610         struct ext2_inode       inode;
6611
6612         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6613                 return 1;
6614
6615         /*
6616          * Read the inode and block bitmaps in; we'll be messing with
6617          * them.
6618          */
6619         e2fsck_read_bitmaps(ctx);
6620
6621         /*
6622          * First, find a free block
6623          */
6624         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6625         if (pctx->errcode) {
6626                 pctx->str = "ext2fs_new_block";
6627                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6628                 return 1;
6629         }
6630         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6631         ext2fs_mark_block_bitmap(fs->block_map, blk);
6632         ext2fs_mark_bb_dirty(fs);
6633
6634         /*
6635          * Now let's create the actual data block for the inode
6636          */
6637         if (db->blockcnt)
6638                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6639         else
6640                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6641                                                      EXT2_ROOT_INO, &block);
6642
6643         if (pctx->errcode) {
6644                 pctx->str = "ext2fs_new_dir_block";
6645                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6646                 return 1;
6647         }
6648
6649         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6650         ext2fs_free_mem(&block);
6651         if (pctx->errcode) {
6652                 pctx->str = "ext2fs_write_dir_block";
6653                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6654                 return 1;
6655         }
6656
6657         /*
6658          * Update the inode block count
6659          */
6660         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6661         inode.i_blocks += fs->blocksize / 512;
6662         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6663                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6664         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6665
6666         /*
6667          * Finally, update the block pointers for the inode
6668          */
6669         db->blk = blk;
6670         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6671                                       0, update_dir_block, db);
6672         if (pctx->errcode) {
6673                 pctx->str = "ext2fs_block_iterate";
6674                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6675                 return 1;
6676         }
6677
6678         return 0;
6679 }
6680
6681 /*
6682  * This is a helper function for allocate_dir_block().
6683  */
6684 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6685                             blk_t       *block_nr,
6686                             e2_blkcnt_t blockcnt,
6687                             blk_t ref_block FSCK_ATTR((unused)),
6688                             int ref_offset FSCK_ATTR((unused)),
6689                             void *priv_data)
6690 {
6691         struct ext2_db_entry *db;
6692
6693         db = (struct ext2_db_entry *) priv_data;
6694         if (db->blockcnt == (int) blockcnt) {
6695                 *block_nr = db->blk;
6696                 return BLOCK_CHANGED;
6697         }
6698         return 0;
6699 }
6700
6701 /*
6702  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6703  *
6704  * Pass #3 assures that all directories are connected to the
6705  * filesystem tree, using the following algorithm:
6706  *
6707  * First, the root directory is checked to make sure it exists; if
6708  * not, e2fsck will offer to create a new one.  It is then marked as
6709  * "done".
6710  *
6711  * Then, pass3 interates over all directory inodes; for each directory
6712  * it attempts to trace up the filesystem tree, using dirinfo.parent
6713  * until it reaches a directory which has been marked "done".  If it
6714  * cannot do so, then the directory must be disconnected, and e2fsck
6715  * will offer to reconnect it to /lost+found.  While it is chasing
6716  * parent pointers up the filesystem tree, if pass3 sees a directory
6717  * twice, then it has detected a filesystem loop, and it will again
6718  * offer to reconnect the directory to /lost+found in to break the
6719  * filesystem loop.
6720  *
6721  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6722  * reconnect inodes to /lost+found; this subroutine is also used by
6723  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6724  * is responsible for creating /lost+found if it does not exist.
6725  *
6726  * Pass 3 frees the following data structures:
6727  *      - The dirinfo directory information cache.
6728  */
6729
6730 static void check_root(e2fsck_t ctx);
6731 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6732                            struct problem_context *pctx);
6733 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6734
6735 static ext2fs_inode_bitmap inode_loop_detect;
6736 static ext2fs_inode_bitmap inode_done_map;
6737
6738 static void e2fsck_pass3(e2fsck_t ctx)
6739 {
6740         ext2_filsys fs = ctx->fs;
6741         int             i;
6742         struct problem_context  pctx;
6743         struct dir_info *dir;
6744         unsigned long maxdirs, count;
6745
6746         clear_problem_context(&pctx);
6747
6748         /* Pass 3 */
6749
6750         if (!(ctx->options & E2F_OPT_PREEN))
6751                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6752
6753         /*
6754          * Allocate some bitmaps to do loop detection.
6755          */
6756         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6757                                                     &inode_done_map);
6758         if (pctx.errcode) {
6759                 pctx.num = 2;
6760                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6761                 ctx->flags |= E2F_FLAG_ABORT;
6762                 goto abort_exit;
6763         }
6764         check_root(ctx);
6765         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6766                 goto abort_exit;
6767
6768         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6769
6770         maxdirs = e2fsck_get_num_dirinfo(ctx);
6771         count = 1;
6772
6773         if (ctx->progress)
6774                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6775                         goto abort_exit;
6776
6777         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6778                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6779                         goto abort_exit;
6780                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6781                         goto abort_exit;
6782                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6783                         if (check_directory(ctx, dir, &pctx))
6784                                 goto abort_exit;
6785         }
6786
6787         /*
6788          * Force the creation of /lost+found if not present
6789          */
6790         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6791                 e2fsck_get_lost_and_found(ctx, 1);
6792
6793         /*
6794          * If there are any directories that need to be indexed or
6795          * optimized, do it here.
6796          */
6797         e2fsck_rehash_directories(ctx);
6798
6799 abort_exit:
6800         e2fsck_free_dir_info(ctx);
6801         ext2fs_free_inode_bitmap(inode_loop_detect);
6802         inode_loop_detect = 0;
6803         ext2fs_free_inode_bitmap(inode_done_map);
6804         inode_done_map = 0;
6805 }
6806
6807 /*
6808  * This makes sure the root inode is present; if not, we ask if the
6809  * user wants us to create it.  Not creating it is a fatal error.
6810  */
6811 static void check_root(e2fsck_t ctx)
6812 {
6813         ext2_filsys fs = ctx->fs;
6814         blk_t                   blk;
6815         struct ext2_inode       inode;
6816         char *                  block;
6817         struct problem_context  pctx;
6818
6819         clear_problem_context(&pctx);
6820
6821         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6822                 /*
6823                  * If the root inode is not a directory, die here.  The
6824                  * user must have answered 'no' in pass1 when we
6825                  * offered to clear it.
6826                  */
6827                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6828                                                EXT2_ROOT_INO))) {
6829                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6830                         ctx->flags |= E2F_FLAG_ABORT;
6831                 }
6832                 return;
6833         }
6834
6835         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6836                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6837                 ctx->flags |= E2F_FLAG_ABORT;
6838                 return;
6839         }
6840
6841         e2fsck_read_bitmaps(ctx);
6842
6843         /*
6844          * First, find a free block
6845          */
6846         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6847         if (pctx.errcode) {
6848                 pctx.str = "ext2fs_new_block";
6849                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6850                 ctx->flags |= E2F_FLAG_ABORT;
6851                 return;
6852         }
6853         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6854         ext2fs_mark_block_bitmap(fs->block_map, blk);
6855         ext2fs_mark_bb_dirty(fs);
6856
6857         /*
6858          * Now let's create the actual data block for the inode
6859          */
6860         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6861                                             &block);
6862         if (pctx.errcode) {
6863                 pctx.str = "ext2fs_new_dir_block";
6864                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6865                 ctx->flags |= E2F_FLAG_ABORT;
6866                 return;
6867         }
6868
6869         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6870         if (pctx.errcode) {
6871                 pctx.str = "ext2fs_write_dir_block";
6872                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6873                 ctx->flags |= E2F_FLAG_ABORT;
6874                 return;
6875         }
6876         ext2fs_free_mem(&block);
6877
6878         /*
6879          * Set up the inode structure
6880          */
6881         memset(&inode, 0, sizeof(inode));
6882         inode.i_mode = 040755;
6883         inode.i_size = fs->blocksize;
6884         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6885         inode.i_links_count = 2;
6886         inode.i_blocks = fs->blocksize / 512;
6887         inode.i_block[0] = blk;
6888
6889         /*
6890          * Write out the inode.
6891          */
6892         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6893         if (pctx.errcode) {
6894                 pctx.str = "ext2fs_write_inode";
6895                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6896                 ctx->flags |= E2F_FLAG_ABORT;
6897                 return;
6898         }
6899
6900         /*
6901          * Miscellaneous bookkeeping...
6902          */
6903         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6904         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6905         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6906
6907         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6908         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6909         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6910         ext2fs_mark_ib_dirty(fs);
6911 }
6912
6913 /*
6914  * This subroutine is responsible for making sure that a particular
6915  * directory is connected to the root; if it isn't we trace it up as
6916  * far as we can go, and then offer to connect the resulting parent to
6917  * the lost+found.  We have to do loop detection; if we ever discover
6918  * a loop, we treat that as a disconnected directory and offer to
6919  * reparent it to lost+found.
6920  *
6921  * However, loop detection is expensive, because for very large
6922  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6923  * is non-trivial.  Loops in filesystems are also a rare error case,
6924  * and we shouldn't optimize for error cases.  So we try two passes of
6925  * the algorithm.  The first time, we ignore loop detection and merely
6926  * increment a counter; if the counter exceeds some extreme threshold,
6927  * then we try again with the loop detection bitmap enabled.
6928  */
6929 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6930                            struct problem_context *pctx)
6931 {
6932         ext2_filsys     fs = ctx->fs;
6933         struct dir_info *p = dir;
6934         int             loop_pass = 0, parent_count = 0;
6935
6936         if (!p)
6937                 return 0;
6938
6939         while (1) {
6940                 /*
6941                  * Mark this inode as being "done"; by the time we
6942                  * return from this function, the inode we either be
6943                  * verified as being connected to the directory tree,
6944                  * or we will have offered to reconnect this to
6945                  * lost+found.
6946                  *
6947                  * If it was marked done already, then we've reached a
6948                  * parent we've already checked.
6949                  */
6950                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6951                         break;
6952
6953                 /*
6954                  * If this directory doesn't have a parent, or we've
6955                  * seen the parent once already, then offer to
6956                  * reparent it to lost+found
6957                  */
6958                 if (!p->parent ||
6959                     (loop_pass &&
6960                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6961                                               p->parent)))) {
6962                         pctx->ino = p->ino;
6963                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6964                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6965                                         ext2fs_unmark_valid(fs);
6966                                 else {
6967                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
6968                                         p->parent = ctx->lost_and_found;
6969                                         fix_dotdot(ctx, p, ctx->lost_and_found);
6970                                 }
6971                         }
6972                         break;
6973                 }
6974                 p = e2fsck_get_dir_info(ctx, p->parent);
6975                 if (!p) {
6976                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6977                         return 0;
6978                 }
6979                 if (loop_pass) {
6980                         ext2fs_mark_inode_bitmap(inode_loop_detect,
6981                                                  p->ino);
6982                 } else if (parent_count++ > 2048) {
6983                         /*
6984                          * If we've run into a path depth that's
6985                          * greater than 2048, try again with the inode
6986                          * loop bitmap turned on and start from the
6987                          * top.
6988                          */
6989                         loop_pass = 1;
6990                         if (inode_loop_detect)
6991                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
6992                         else {
6993                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6994                                 if (pctx->errcode) {
6995                                         pctx->num = 1;
6996                                         fix_problem(ctx,
6997                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6998                                         ctx->flags |= E2F_FLAG_ABORT;
6999                                         return -1;
7000                                 }
7001                         }
7002                         p = dir;
7003                 }
7004         }
7005
7006         /*
7007          * Make sure that .. and the parent directory are the same;
7008          * offer to fix it if not.
7009          */
7010         if (dir->parent != dir->dotdot) {
7011                 pctx->ino = dir->ino;
7012                 pctx->ino2 = dir->dotdot;
7013                 pctx->dir = dir->parent;
7014                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7015                         fix_dotdot(ctx, dir, dir->parent);
7016         }
7017         return 0;
7018 }
7019
7020 /*
7021  * This routine gets the lost_and_found inode, making it a directory
7022  * if necessary
7023  */
7024 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7025 {
7026         ext2_filsys fs = ctx->fs;
7027         ext2_ino_t                      ino;
7028         blk_t                   blk;
7029         errcode_t               retval;
7030         struct ext2_inode       inode;
7031         char *                  block;
7032         static const char       name[] = "lost+found";
7033         struct  problem_context pctx;
7034         struct dir_info         *dirinfo;
7035
7036         if (ctx->lost_and_found)
7037                 return ctx->lost_and_found;
7038
7039         clear_problem_context(&pctx);
7040
7041         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7042                                sizeof(name)-1, 0, &ino);
7043         if (retval && !fix)
7044                 return 0;
7045         if (!retval) {
7046                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7047                         ctx->lost_and_found = ino;
7048                         return ino;
7049                 }
7050
7051                 /* Lost+found isn't a directory! */
7052                 if (!fix)
7053                         return 0;
7054                 pctx.ino = ino;
7055                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7056                         return 0;
7057
7058                 /* OK, unlink the old /lost+found file. */
7059                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7060                 if (pctx.errcode) {
7061                         pctx.str = "ext2fs_unlink";
7062                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7063                         return 0;
7064                 }
7065                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7066                 if (dirinfo)
7067                         dirinfo->parent = 0;
7068                 e2fsck_adjust_inode_count(ctx, ino, -1);
7069         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7070                 pctx.errcode = retval;
7071                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7072         }
7073         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7074                 return 0;
7075
7076         /*
7077          * Read the inode and block bitmaps in; we'll be messing with
7078          * them.
7079          */
7080         e2fsck_read_bitmaps(ctx);
7081
7082         /*
7083          * First, find a free block
7084          */
7085         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7086         if (retval) {
7087                 pctx.errcode = retval;
7088                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7089                 return 0;
7090         }
7091         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7092         ext2fs_block_alloc_stats(fs, blk, +1);
7093
7094         /*
7095          * Next find a free inode.
7096          */
7097         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7098                                   ctx->inode_used_map, &ino);
7099         if (retval) {
7100                 pctx.errcode = retval;
7101                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7102                 return 0;
7103         }
7104         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7105         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7106         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7107
7108         /*
7109          * Now let's create the actual data block for the inode
7110          */
7111         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7112         if (retval) {
7113                 pctx.errcode = retval;
7114                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7115                 return 0;
7116         }
7117
7118         retval = ext2fs_write_dir_block(fs, blk, block);
7119         ext2fs_free_mem(&block);
7120         if (retval) {
7121                 pctx.errcode = retval;
7122                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7123                 return 0;
7124         }
7125
7126         /*
7127          * Set up the inode structure
7128          */
7129         memset(&inode, 0, sizeof(inode));
7130         inode.i_mode = 040700;
7131         inode.i_size = fs->blocksize;
7132         inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7133         inode.i_links_count = 2;
7134         inode.i_blocks = fs->blocksize / 512;
7135         inode.i_block[0] = blk;
7136
7137         /*
7138          * Next, write out the inode.
7139          */
7140         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7141         if (pctx.errcode) {
7142                 pctx.str = "ext2fs_write_inode";
7143                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7144                 return 0;
7145         }
7146         /*
7147          * Finally, create the directory link
7148          */
7149         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7150         if (pctx.errcode) {
7151                 pctx.str = "ext2fs_link";
7152                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153                 return 0;
7154         }
7155
7156         /*
7157          * Miscellaneous bookkeeping that needs to be kept straight.
7158          */
7159         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7160         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7161         ext2fs_icount_store(ctx->inode_count, ino, 2);
7162         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7163         ctx->lost_and_found = ino;
7164         return ino;
7165 }
7166
7167 /*
7168  * This routine will connect a file to lost+found
7169  */
7170 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7171 {
7172         ext2_filsys fs = ctx->fs;
7173         errcode_t       retval;
7174         char            name[80];
7175         struct problem_context  pctx;
7176         struct ext2_inode       inode;
7177         int             file_type = 0;
7178
7179         clear_problem_context(&pctx);
7180         pctx.ino = ino;
7181
7182         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7183                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7184                         ctx->bad_lost_and_found++;
7185         }
7186         if (ctx->bad_lost_and_found) {
7187                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7188                 return 1;
7189         }
7190
7191         sprintf(name, "#%u", ino);
7192         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7193                 file_type = ext2_file_type(inode.i_mode);
7194         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7195         if (retval == EXT2_ET_DIR_NO_SPACE) {
7196                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7197                         return 1;
7198                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7199                                                  1, 0);
7200                 if (retval) {
7201                         pctx.errcode = retval;
7202                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7203                         return 1;
7204                 }
7205                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7206                                      ino, file_type);
7207         }
7208         if (retval) {
7209                 pctx.errcode = retval;
7210                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7211                 return 1;
7212         }
7213         e2fsck_adjust_inode_count(ctx, ino, 1);
7214
7215         return 0;
7216 }
7217
7218 /*
7219  * Utility routine to adjust the inode counts on an inode.
7220  */
7221 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7222 {
7223         ext2_filsys fs = ctx->fs;
7224         errcode_t               retval;
7225         struct ext2_inode       inode;
7226
7227         if (!ino)
7228                 return 0;
7229
7230         retval = ext2fs_read_inode(fs, ino, &inode);
7231         if (retval)
7232                 return retval;
7233
7234         if (adj == 1) {
7235                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7236                 if (inode.i_links_count == (__u16) ~0)
7237                         return 0;
7238                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7239                 inode.i_links_count++;
7240         } else if (adj == -1) {
7241                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7242                 if (inode.i_links_count == 0)
7243                         return 0;
7244                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7245                 inode.i_links_count--;
7246         }
7247
7248         retval = ext2fs_write_inode(fs, ino, &inode);
7249         if (retval)
7250                 return retval;
7251
7252         return 0;
7253 }
7254
7255 /*
7256  * Fix parent --- this routine fixes up the parent of a directory.
7257  */
7258 struct fix_dotdot_struct {
7259         ext2_filsys     fs;
7260         ext2_ino_t      parent;
7261         int             done;
7262         e2fsck_t        ctx;
7263 };
7264
7265 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7266                            int  offset FSCK_ATTR((unused)),
7267                            int  blocksize FSCK_ATTR((unused)),
7268                            char *buf FSCK_ATTR((unused)),
7269                            void *priv_data)
7270 {
7271         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7272         errcode_t       retval;
7273         struct problem_context pctx;
7274
7275         if ((dirent->name_len & 0xFF) != 2)
7276                 return 0;
7277         if (strncmp(dirent->name, "..", 2))
7278                 return 0;
7279
7280         clear_problem_context(&pctx);
7281
7282         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7283         if (retval) {
7284                 pctx.errcode = retval;
7285                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7286         }
7287         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7288         if (retval) {
7289                 pctx.errcode = retval;
7290                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7291         }
7292         dirent->inode = fp->parent;
7293
7294         fp->done++;
7295         return DIRENT_ABORT | DIRENT_CHANGED;
7296 }
7297
7298 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7299 {
7300         ext2_filsys fs = ctx->fs;
7301         errcode_t       retval;
7302         struct fix_dotdot_struct fp;
7303         struct problem_context pctx;
7304
7305         fp.fs = fs;
7306         fp.parent = parent;
7307         fp.done = 0;
7308         fp.ctx = ctx;
7309
7310         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7311                                     0, fix_dotdot_proc, &fp);
7312         if (retval || !fp.done) {
7313                 clear_problem_context(&pctx);
7314                 pctx.ino = dir->ino;
7315                 pctx.errcode = retval;
7316                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7317                             PR_3_FIX_PARENT_NOFIND, &pctx);
7318                 ext2fs_unmark_valid(fs);
7319         }
7320         dir->dotdot = parent;
7321 }
7322
7323 /*
7324  * These routines are responsible for expanding a /lost+found if it is
7325  * too small.
7326  */
7327
7328 struct expand_dir_struct {
7329         int                     num;
7330         int                     guaranteed_size;
7331         int                     newblocks;
7332         int                     last_block;
7333         errcode_t               err;
7334         e2fsck_t                ctx;
7335 };
7336
7337 static int expand_dir_proc(ext2_filsys fs,
7338                            blk_t        *blocknr,
7339                            e2_blkcnt_t  blockcnt,
7340                            blk_t ref_block FSCK_ATTR((unused)),
7341                            int ref_offset FSCK_ATTR((unused)),
7342                            void *priv_data)
7343 {
7344         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7345         blk_t   new_blk;
7346         static blk_t    last_blk = 0;
7347         char            *block;
7348         errcode_t       retval;
7349         e2fsck_t        ctx;
7350
7351         ctx = es->ctx;
7352
7353         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7354                 return BLOCK_ABORT;
7355
7356         if (blockcnt > 0)
7357                 es->last_block = blockcnt;
7358         if (*blocknr) {
7359                 last_blk = *blocknr;
7360                 return 0;
7361         }
7362         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7363                                   &new_blk);
7364         if (retval) {
7365                 es->err = retval;
7366                 return BLOCK_ABORT;
7367         }
7368         if (blockcnt > 0) {
7369                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7370                 if (retval) {
7371                         es->err = retval;
7372                         return BLOCK_ABORT;
7373                 }
7374                 es->num--;
7375                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7376         } else {
7377                 retval = ext2fs_get_mem(fs->blocksize, &block);
7378                 if (retval) {
7379                         es->err = retval;
7380                         return BLOCK_ABORT;
7381                 }
7382                 memset(block, 0, fs->blocksize);
7383                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7384         }
7385         if (retval) {
7386                 es->err = retval;
7387                 return BLOCK_ABORT;
7388         }
7389         ext2fs_free_mem(&block);
7390         *blocknr = new_blk;
7391         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7392         ext2fs_block_alloc_stats(fs, new_blk, +1);
7393         es->newblocks++;
7394
7395         if (es->num == 0)
7396                 return (BLOCK_CHANGED | BLOCK_ABORT);
7397         else
7398                 return BLOCK_CHANGED;
7399 }
7400
7401 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7402                                   int num, int guaranteed_size)
7403 {
7404         ext2_filsys fs = ctx->fs;
7405         errcode_t       retval;
7406         struct expand_dir_struct es;
7407         struct ext2_inode       inode;
7408
7409         if (!(fs->flags & EXT2_FLAG_RW))
7410                 return EXT2_ET_RO_FILSYS;
7411
7412         /*
7413          * Read the inode and block bitmaps in; we'll be messing with
7414          * them.
7415          */
7416         e2fsck_read_bitmaps(ctx);
7417
7418         retval = ext2fs_check_directory(fs, dir);
7419         if (retval)
7420                 return retval;
7421
7422         es.num = num;
7423         es.guaranteed_size = guaranteed_size;
7424         es.last_block = 0;
7425         es.err = 0;
7426         es.newblocks = 0;
7427         es.ctx = ctx;
7428
7429         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7430                                        0, expand_dir_proc, &es);
7431
7432         if (es.err)
7433                 return es.err;
7434
7435         /*
7436          * Update the size and block count fields in the inode.
7437          */
7438         retval = ext2fs_read_inode(fs, dir, &inode);
7439         if (retval)
7440                 return retval;
7441
7442         inode.i_size = (es.last_block + 1) * fs->blocksize;
7443         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7444
7445         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7446
7447         return 0;
7448 }
7449
7450 /*
7451  * pass4.c -- pass #4 of e2fsck: Check reference counts
7452  *
7453  * Pass 4 frees the following data structures:
7454  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7455  */
7456
7457 /*
7458  * This routine is called when an inode is not connected to the
7459  * directory tree.
7460  *
7461  * This subroutine returns 1 then the caller shouldn't bother with the
7462  * rest of the pass 4 tests.
7463  */
7464 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7465 {
7466         ext2_filsys fs = ctx->fs;
7467         struct ext2_inode       inode;
7468         struct problem_context  pctx;
7469
7470         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7471         clear_problem_context(&pctx);
7472         pctx.ino = i;
7473         pctx.inode = &inode;
7474
7475         /*
7476          * Offer to delete any zero-length files that does not have
7477          * blocks.  If there is an EA block, it might have useful
7478          * information, so we won't prompt to delete it, but let it be
7479          * reconnected to lost+found.
7480          */
7481         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7482                                 LINUX_S_ISDIR(inode.i_mode))) {
7483                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7484                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7485                         inode.i_links_count = 0;
7486                         inode.i_dtime = time(NULL);
7487                         e2fsck_write_inode(ctx, i, &inode,
7488                                            "disconnect_inode");
7489                         /*
7490                          * Fix up the bitmaps...
7491                          */
7492                         e2fsck_read_bitmaps(ctx);
7493                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7494                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7495                         ext2fs_inode_alloc_stats2(fs, i, -1,
7496                                                   LINUX_S_ISDIR(inode.i_mode));
7497                         return 0;
7498                 }
7499         }
7500
7501         /*
7502          * Prompt to reconnect.
7503          */
7504         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7505                 if (e2fsck_reconnect_file(ctx, i))
7506                         ext2fs_unmark_valid(fs);
7507         } else {
7508                 /*
7509                  * If we don't attach the inode, then skip the
7510                  * i_links_test since there's no point in trying to
7511                  * force i_links_count to zero.
7512                  */
7513                 ext2fs_unmark_valid(fs);
7514                 return 1;
7515         }
7516         return 0;
7517 }
7518
7519
7520 static void e2fsck_pass4(e2fsck_t ctx)
7521 {
7522         ext2_filsys fs = ctx->fs;
7523         ext2_ino_t      i;
7524         struct ext2_inode       inode;
7525         struct problem_context  pctx;
7526         __u16   link_count, link_counted;
7527         char    *buf = NULL;
7528         int     group, maxgroup;
7529
7530         /* Pass 4 */
7531
7532         clear_problem_context(&pctx);
7533
7534         if (!(ctx->options & E2F_OPT_PREEN))
7535                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7536
7537         group = 0;
7538         maxgroup = fs->group_desc_count;
7539         if (ctx->progress)
7540                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7541                         return;
7542
7543         for (i=1; i <= fs->super->s_inodes_count; i++) {
7544                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7545                         return;
7546                 if ((i % fs->super->s_inodes_per_group) == 0) {
7547                         group++;
7548                         if (ctx->progress)
7549                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7550                                         return;
7551                 }
7552                 if (i == EXT2_BAD_INO ||
7553                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7554                         continue;
7555                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7556                     (ctx->inode_imagic_map &&
7557                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7558                         continue;
7559                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7560                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7561                 if (link_counted == 0) {
7562                         if (!buf)
7563                                 buf = e2fsck_allocate_memory(ctx,
7564                                      fs->blocksize, "bad_inode buffer");
7565                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7566                                 continue;
7567                         if (disconnect_inode(ctx, i))
7568                                 continue;
7569                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7570                                             &link_count);
7571                         ext2fs_icount_fetch(ctx->inode_count, i,
7572                                             &link_counted);
7573                 }
7574                 if (link_counted != link_count) {
7575                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7576                         pctx.ino = i;
7577                         pctx.inode = &inode;
7578                         if (link_count != inode.i_links_count) {
7579                                 pctx.num = link_count;
7580                                 fix_problem(ctx,
7581                                             PR_4_INCONSISTENT_COUNT, &pctx);
7582                         }
7583                         pctx.num = link_counted;
7584                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7585                                 inode.i_links_count = link_counted;
7586                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7587                         }
7588                 }
7589         }
7590         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7591         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7592         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7593         ctx->inode_imagic_map = 0;
7594         ext2fs_free_mem(&buf);
7595 }
7596
7597 /*
7598  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7599  */
7600
7601 #define NO_BLK ((blk_t) -1)
7602
7603 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7604                             struct problem_context *pctx)
7605 {
7606         switch (problem) {
7607         case PR_5_BLOCK_UNUSED:
7608                 if (pctx->blk == pctx->blk2)
7609                         pctx->blk2 = 0;
7610                 else
7611                         problem = PR_5_BLOCK_RANGE_UNUSED;
7612                 break;
7613         case PR_5_BLOCK_USED:
7614                 if (pctx->blk == pctx->blk2)
7615                         pctx->blk2 = 0;
7616                 else
7617                         problem = PR_5_BLOCK_RANGE_USED;
7618                 break;
7619         case PR_5_INODE_UNUSED:
7620                 if (pctx->ino == pctx->ino2)
7621                         pctx->ino2 = 0;
7622                 else
7623                         problem = PR_5_INODE_RANGE_UNUSED;
7624                 break;
7625         case PR_5_INODE_USED:
7626                 if (pctx->ino == pctx->ino2)
7627                         pctx->ino2 = 0;
7628                 else
7629                         problem = PR_5_INODE_RANGE_USED;
7630                 break;
7631         }
7632         fix_problem(ctx, problem, pctx);
7633         pctx->blk = pctx->blk2 = NO_BLK;
7634         pctx->ino = pctx->ino2 = 0;
7635 }
7636
7637 static void check_block_bitmaps(e2fsck_t ctx)
7638 {
7639         ext2_filsys fs = ctx->fs;
7640         blk_t   i;
7641         int     *free_array;
7642         int     group = 0;
7643         unsigned int    blocks = 0;
7644         unsigned int    free_blocks = 0;
7645         int     group_free = 0;
7646         int     actual, bitmap;
7647         struct problem_context  pctx;
7648         int     problem, save_problem, fixit, had_problem;
7649         errcode_t       retval;
7650
7651         clear_problem_context(&pctx);
7652         free_array = (int *) e2fsck_allocate_memory(ctx,
7653             fs->group_desc_count * sizeof(int), "free block count array");
7654
7655         if ((fs->super->s_first_data_block <
7656              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7657             (fs->super->s_blocks_count-1 >
7658              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7659                 pctx.num = 1;
7660                 pctx.blk = fs->super->s_first_data_block;
7661                 pctx.blk2 = fs->super->s_blocks_count -1;
7662                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7663                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7664                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7665
7666                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7667                 return;
7668         }
7669
7670         if ((fs->super->s_first_data_block <
7671              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7672             (fs->super->s_blocks_count-1 >
7673              ext2fs_get_block_bitmap_end(fs->block_map))) {
7674                 pctx.num = 2;
7675                 pctx.blk = fs->super->s_first_data_block;
7676                 pctx.blk2 = fs->super->s_blocks_count -1;
7677                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7678                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7679                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7680
7681                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7682                 return;
7683         }
7684
7685 redo_counts:
7686         had_problem = 0;
7687         save_problem = 0;
7688         pctx.blk = pctx.blk2 = NO_BLK;
7689         for (i = fs->super->s_first_data_block;
7690              i < fs->super->s_blocks_count;
7691              i++) {
7692                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7693                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7694
7695                 if (actual == bitmap)
7696                         goto do_counts;
7697
7698                 if (!actual && bitmap) {
7699                         /*
7700                          * Block not used, but marked in use in the bitmap.
7701                          */
7702                         problem = PR_5_BLOCK_UNUSED;
7703                 } else {
7704                         /*
7705                          * Block used, but not marked in use in the bitmap.
7706                          */
7707                         problem = PR_5_BLOCK_USED;
7708                 }
7709                 if (pctx.blk == NO_BLK) {
7710                         pctx.blk = pctx.blk2 = i;
7711                         save_problem = problem;
7712                 } else {
7713                         if ((problem == save_problem) &&
7714                             (pctx.blk2 == i-1))
7715                                 pctx.blk2++;
7716                         else {
7717                                 print_bitmap_problem(ctx, save_problem, &pctx);
7718                                 pctx.blk = pctx.blk2 = i;
7719                                 save_problem = problem;
7720                         }
7721                 }
7722                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7723                 had_problem++;
7724
7725         do_counts:
7726                 if (!bitmap) {
7727                         group_free++;
7728                         free_blocks++;
7729                 }
7730                 blocks ++;
7731                 if ((blocks == fs->super->s_blocks_per_group) ||
7732                     (i == fs->super->s_blocks_count-1)) {
7733                         free_array[group] = group_free;
7734                         group ++;
7735                         blocks = 0;
7736                         group_free = 0;
7737                         if (ctx->progress)
7738                                 if ((ctx->progress)(ctx, 5, group,
7739                                                     fs->group_desc_count*2))
7740                                         return;
7741                 }
7742         }
7743         if (pctx.blk != NO_BLK)
7744                 print_bitmap_problem(ctx, save_problem, &pctx);
7745         if (had_problem)
7746                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7747         else
7748                 fixit = -1;
7749         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7750
7751         if (fixit == 1) {
7752                 ext2fs_free_block_bitmap(fs->block_map);
7753                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7754                                                   &fs->block_map);
7755                 if (retval) {
7756                         clear_problem_context(&pctx);
7757                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7758                         ctx->flags |= E2F_FLAG_ABORT;
7759                         return;
7760                 }
7761                 ext2fs_set_bitmap_padding(fs->block_map);
7762                 ext2fs_mark_bb_dirty(fs);
7763
7764                 /* Redo the counts */
7765                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7766                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7767                 goto redo_counts;
7768         } else if (fixit == 0)
7769                 ext2fs_unmark_valid(fs);
7770
7771         for (i = 0; i < fs->group_desc_count; i++) {
7772                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7773                         pctx.group = i;
7774                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7775                         pctx.blk2 = free_array[i];
7776
7777                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7778                                         &pctx)) {
7779                                 fs->group_desc[i].bg_free_blocks_count =
7780                                         free_array[i];
7781                                 ext2fs_mark_super_dirty(fs);
7782                         } else
7783                                 ext2fs_unmark_valid(fs);
7784                 }
7785         }
7786         if (free_blocks != fs->super->s_free_blocks_count) {
7787                 pctx.group = 0;
7788                 pctx.blk = fs->super->s_free_blocks_count;
7789                 pctx.blk2 = free_blocks;
7790
7791                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7792                         fs->super->s_free_blocks_count = free_blocks;
7793                         ext2fs_mark_super_dirty(fs);
7794                 } else
7795                         ext2fs_unmark_valid(fs);
7796         }
7797         ext2fs_free_mem(&free_array);
7798 }
7799
7800 static void check_inode_bitmaps(e2fsck_t ctx)
7801 {
7802         ext2_filsys fs = ctx->fs;
7803         ext2_ino_t      i;
7804         unsigned int    free_inodes = 0;
7805         int             group_free = 0;
7806         int             dirs_count = 0;
7807         int             group = 0;
7808         unsigned int    inodes = 0;
7809         int             *free_array;
7810         int             *dir_array;
7811         int             actual, bitmap;
7812         errcode_t       retval;
7813         struct problem_context  pctx;
7814         int             problem, save_problem, fixit, had_problem;
7815
7816         clear_problem_context(&pctx);
7817         free_array = (int *) e2fsck_allocate_memory(ctx,
7818             fs->group_desc_count * sizeof(int), "free inode count array");
7819
7820         dir_array = (int *) e2fsck_allocate_memory(ctx,
7821            fs->group_desc_count * sizeof(int), "directory count array");
7822
7823         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7824             (fs->super->s_inodes_count >
7825              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7826                 pctx.num = 3;
7827                 pctx.blk = 1;
7828                 pctx.blk2 = fs->super->s_inodes_count;
7829                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7830                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7831                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7832
7833                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7834                 return;
7835         }
7836         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7837             (fs->super->s_inodes_count >
7838              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7839                 pctx.num = 4;
7840                 pctx.blk = 1;
7841                 pctx.blk2 = fs->super->s_inodes_count;
7842                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7843                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7844                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7845
7846                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7847                 return;
7848         }
7849
7850 redo_counts:
7851         had_problem = 0;
7852         save_problem = 0;
7853         pctx.ino = pctx.ino2 = 0;
7854         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7855                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7856                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7857
7858                 if (actual == bitmap)
7859                         goto do_counts;
7860
7861                 if (!actual && bitmap) {
7862                         /*
7863                          * Inode wasn't used, but marked in bitmap
7864                          */
7865                         problem = PR_5_INODE_UNUSED;
7866                 } else /* if (actual && !bitmap) */ {
7867                         /*
7868                          * Inode used, but not in bitmap
7869                          */
7870                         problem = PR_5_INODE_USED;
7871                 }
7872                 if (pctx.ino == 0) {
7873                         pctx.ino = pctx.ino2 = i;
7874                         save_problem = problem;
7875                 } else {
7876                         if ((problem == save_problem) &&
7877                             (pctx.ino2 == i-1))
7878                                 pctx.ino2++;
7879                         else {
7880                                 print_bitmap_problem(ctx, save_problem, &pctx);
7881                                 pctx.ino = pctx.ino2 = i;
7882                                 save_problem = problem;
7883                         }
7884                 }
7885                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7886                 had_problem++;
7887
7888 do_counts:
7889                 if (!bitmap) {
7890                         group_free++;
7891                         free_inodes++;
7892                 } else {
7893                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7894                                 dirs_count++;
7895                 }
7896                 inodes++;
7897                 if ((inodes == fs->super->s_inodes_per_group) ||
7898                     (i == fs->super->s_inodes_count)) {
7899                         free_array[group] = group_free;
7900                         dir_array[group] = dirs_count;
7901                         group ++;
7902                         inodes = 0;
7903                         group_free = 0;
7904                         dirs_count = 0;
7905                         if (ctx->progress)
7906                                 if ((ctx->progress)(ctx, 5,
7907                                             group + fs->group_desc_count,
7908                                             fs->group_desc_count*2))
7909                                         return;
7910                 }
7911         }
7912         if (pctx.ino)
7913                 print_bitmap_problem(ctx, save_problem, &pctx);
7914
7915         if (had_problem)
7916                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7917         else
7918                 fixit = -1;
7919         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7920
7921         if (fixit == 1) {
7922                 ext2fs_free_inode_bitmap(fs->inode_map);
7923                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7924                                                   &fs->inode_map);
7925                 if (retval) {
7926                         clear_problem_context(&pctx);
7927                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7928                         ctx->flags |= E2F_FLAG_ABORT;
7929                         return;
7930                 }
7931                 ext2fs_set_bitmap_padding(fs->inode_map);
7932                 ext2fs_mark_ib_dirty(fs);
7933
7934                 /* redo counts */
7935                 inodes = 0; free_inodes = 0; group_free = 0;
7936                 dirs_count = 0; group = 0;
7937                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7938                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7939                 goto redo_counts;
7940         } else if (fixit == 0)
7941                 ext2fs_unmark_valid(fs);
7942
7943         for (i = 0; i < fs->group_desc_count; i++) {
7944                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7945                         pctx.group = i;
7946                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7947                         pctx.ino2 = free_array[i];
7948                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7949                                         &pctx)) {
7950                                 fs->group_desc[i].bg_free_inodes_count =
7951                                         free_array[i];
7952                                 ext2fs_mark_super_dirty(fs);
7953                         } else
7954                                 ext2fs_unmark_valid(fs);
7955                 }
7956                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7957                         pctx.group = i;
7958                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7959                         pctx.ino2 = dir_array[i];
7960
7961                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7962                                         &pctx)) {
7963                                 fs->group_desc[i].bg_used_dirs_count =
7964                                         dir_array[i];
7965                                 ext2fs_mark_super_dirty(fs);
7966                         } else
7967                                 ext2fs_unmark_valid(fs);
7968                 }
7969         }
7970         if (free_inodes != fs->super->s_free_inodes_count) {
7971                 pctx.group = -1;
7972                 pctx.ino = fs->super->s_free_inodes_count;
7973                 pctx.ino2 = free_inodes;
7974
7975                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7976                         fs->super->s_free_inodes_count = free_inodes;
7977                         ext2fs_mark_super_dirty(fs);
7978                 } else
7979                         ext2fs_unmark_valid(fs);
7980         }
7981         ext2fs_free_mem(&free_array);
7982         ext2fs_free_mem(&dir_array);
7983 }
7984
7985 static void check_inode_end(e2fsck_t ctx)
7986 {
7987         ext2_filsys fs = ctx->fs;
7988         ext2_ino_t      end, save_inodes_count, i;
7989         struct problem_context  pctx;
7990
7991         clear_problem_context(&pctx);
7992
7993         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7994         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7995                                                      &save_inodes_count);
7996         if (pctx.errcode) {
7997                 pctx.num = 1;
7998                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7999                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8000                 return;
8001         }
8002         if (save_inodes_count == end)
8003                 return;
8004
8005         for (i = save_inodes_count + 1; i <= end; i++) {
8006                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8007                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8008                                 for (i = save_inodes_count + 1; i <= end; i++)
8009                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8010                                                                  i);
8011                                 ext2fs_mark_ib_dirty(fs);
8012                         } else
8013                                 ext2fs_unmark_valid(fs);
8014                         break;
8015                 }
8016         }
8017
8018         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8019                                                      save_inodes_count, 0);
8020         if (pctx.errcode) {
8021                 pctx.num = 2;
8022                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8023                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8024                 return;
8025         }
8026 }
8027
8028 static void check_block_end(e2fsck_t ctx)
8029 {
8030         ext2_filsys fs = ctx->fs;
8031         blk_t   end, save_blocks_count, i;
8032         struct problem_context  pctx;
8033
8034         clear_problem_context(&pctx);
8035
8036         end = fs->block_map->start +
8037                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8038         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8039                                                      &save_blocks_count);
8040         if (pctx.errcode) {
8041                 pctx.num = 3;
8042                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8043                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8044                 return;
8045         }
8046         if (save_blocks_count == end)
8047                 return;
8048
8049         for (i = save_blocks_count + 1; i <= end; i++) {
8050                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8051                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8052                                 for (i = save_blocks_count + 1; i <= end; i++)
8053                                         ext2fs_mark_block_bitmap(fs->block_map,
8054                                                                  i);
8055                                 ext2fs_mark_bb_dirty(fs);
8056                         } else
8057                                 ext2fs_unmark_valid(fs);
8058                         break;
8059                 }
8060         }
8061
8062         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8063                                                      save_blocks_count, 0);
8064         if (pctx.errcode) {
8065                 pctx.num = 4;
8066                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8067                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8068                 return;
8069         }
8070 }
8071
8072 static void e2fsck_pass5(e2fsck_t ctx)
8073 {
8074         struct problem_context  pctx;
8075
8076         /* Pass 5 */
8077
8078         clear_problem_context(&pctx);
8079
8080         if (!(ctx->options & E2F_OPT_PREEN))
8081                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8082
8083         if (ctx->progress)
8084                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8085                         return;
8086
8087         e2fsck_read_bitmaps(ctx);
8088
8089         check_block_bitmaps(ctx);
8090         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8091                 return;
8092         check_inode_bitmaps(ctx);
8093         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8094                 return;
8095         check_inode_end(ctx);
8096         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8097                 return;
8098         check_block_end(ctx);
8099         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100                 return;
8101
8102         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8103         ctx->inode_used_map = 0;
8104         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8105         ctx->inode_dir_map = 0;
8106         ext2fs_free_block_bitmap(ctx->block_found_map);
8107         ctx->block_found_map = 0;
8108 }
8109
8110 /*
8111  * problem.c --- report filesystem problems to the user
8112  */
8113
8114 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8115 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8116 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8117 #define PR_MSG_ONLY     0x000008 /* Print message only */
8118
8119 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8120
8121 #define PR_FATAL        0x001000 /* Fatal error */
8122 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8123                                  /* ask another */
8124 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8125 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8126 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8127 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8128 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8129
8130
8131 #define PROMPT_NONE     0
8132 #define PROMPT_FIX      1
8133 #define PROMPT_CLEAR    2
8134 #define PROMPT_RELOCATE 3
8135 #define PROMPT_ALLOCATE 4
8136 #define PROMPT_EXPAND   5
8137 #define PROMPT_CONNECT  6
8138 #define PROMPT_CREATE   7
8139 #define PROMPT_SALVAGE  8
8140 #define PROMPT_TRUNCATE 9
8141 #define PROMPT_CLEAR_INODE 10
8142 #define PROMPT_ABORT    11
8143 #define PROMPT_SPLIT    12
8144 #define PROMPT_CONTINUE 13
8145 #define PROMPT_CLONE    14
8146 #define PROMPT_DELETE   15
8147 #define PROMPT_SUPPRESS 16
8148 #define PROMPT_UNLINK   17
8149 #define PROMPT_CLEAR_HTREE 18
8150 #define PROMPT_RECREATE 19
8151 #define PROMPT_NULL     20
8152
8153 struct e2fsck_problem {
8154         problem_t       e2p_code;
8155         const char *    e2p_description;
8156         char            prompt;
8157         int             flags;
8158         problem_t       second_code;
8159 };
8160
8161 struct latch_descr {
8162         int             latch_code;
8163         problem_t       question;
8164         problem_t       end_message;
8165         int             flags;
8166 };
8167
8168 /*
8169  * These are the prompts which are used to ask the user if they want
8170  * to fix a problem.
8171  */
8172 static const char *const prompt[] = {
8173         N_("(no prompt)"),      /* 0 */
8174         N_("Fix"),              /* 1 */
8175         N_("Clear"),            /* 2 */
8176         N_("Relocate"),         /* 3 */
8177         N_("Allocate"),         /* 4 */
8178         N_("Expand"),           /* 5 */
8179         N_("Connect to /lost+found"), /* 6 */
8180         N_("Create"),           /* 7 */
8181         N_("Salvage"),          /* 8 */
8182         N_("Truncate"),         /* 9 */
8183         N_("Clear inode"),      /* 10 */
8184         N_("Abort"),            /* 11 */
8185         N_("Split"),            /* 12 */
8186         N_("Continue"),         /* 13 */
8187         N_("Clone multiply-claimed blocks"), /* 14 */
8188         N_("Delete file"),      /* 15 */
8189         N_("Suppress messages"),/* 16 */
8190         N_("Unlink"),           /* 17 */
8191         N_("Clear HTree index"),/* 18 */
8192         N_("Recreate"),         /* 19 */
8193         "",                     /* 20 */
8194 };
8195
8196 /*
8197  * These messages are printed when we are preen mode and we will be
8198  * automatically fixing the problem.
8199  */
8200 static const char *const preen_msg[] = {
8201         N_("(NONE)"),           /* 0 */
8202         N_("FIXED"),            /* 1 */
8203         N_("CLEARED"),          /* 2 */
8204         N_("RELOCATED"),        /* 3 */
8205         N_("ALLOCATED"),        /* 4 */
8206         N_("EXPANDED"),         /* 5 */
8207         N_("RECONNECTED"),      /* 6 */
8208         N_("CREATED"),          /* 7 */
8209         N_("SALVAGED"),         /* 8 */
8210         N_("TRUNCATED"),        /* 9 */
8211         N_("INODE CLEARED"),    /* 10 */
8212         N_("ABORTED"),          /* 11 */
8213         N_("SPLIT"),            /* 12 */
8214         N_("CONTINUING"),       /* 13 */
8215         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8216         N_("FILE DELETED"),     /* 15 */
8217         N_("SUPPRESSED"),       /* 16 */
8218         N_("UNLINKED"),         /* 17 */
8219         N_("HTREE INDEX CLEARED"),/* 18 */
8220         N_("WILL RECREATE"),    /* 19 */
8221         "",                     /* 20 */
8222 };
8223
8224 static const struct e2fsck_problem problem_table[] = {
8225
8226         /* Pre-Pass 1 errors */
8227
8228         /* Block bitmap not in group */
8229         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8230           PROMPT_RELOCATE, PR_LATCH_RELOC },
8231
8232         /* Inode bitmap not in group */
8233         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8234           PROMPT_RELOCATE, PR_LATCH_RELOC },
8235
8236         /* Inode table not in group */
8237         { PR_0_ITABLE_NOT_GROUP,
8238           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8239           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8240           PROMPT_RELOCATE, PR_LATCH_RELOC },
8241
8242         /* Superblock corrupt */
8243         { PR_0_SB_CORRUPT,
8244           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8245           "@f.  If the @v is valid and it really contains an ext2\n"
8246           "@f (and not swap or ufs or something else), then the @S\n"
8247           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8248           "    e2fsck -b %S <@v>\n\n"),
8249           PROMPT_NONE, PR_FATAL },
8250
8251         /* Filesystem size is wrong */
8252         { PR_0_FS_SIZE_WRONG,
8253           N_("The @f size (according to the @S) is %b @bs\n"
8254           "The physical size of the @v is %c @bs\n"
8255           "Either the @S or the partition table is likely to be corrupt!\n"),
8256           PROMPT_ABORT, 0 },
8257
8258         /* Fragments not supported */
8259         { PR_0_NO_FRAGMENTS,
8260           N_("@S @b_size = %b, fragsize = %c.\n"
8261           "This version of e2fsck does not support fragment sizes different\n"
8262           "from the @b size.\n"),
8263           PROMPT_NONE, PR_FATAL },
8264
8265           /* Bad blocks_per_group */
8266         { PR_0_BLOCKS_PER_GROUP,
8267           N_("@S @bs_per_group = %b, should have been %c\n"),
8268           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8269
8270         /* Bad first_data_block */
8271         { PR_0_FIRST_DATA_BLOCK,
8272           N_("@S first_data_@b = %b, should have been %c\n"),
8273           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8274
8275         /* Adding UUID to filesystem */
8276         { PR_0_ADD_UUID,
8277           N_("@f did not have a UUID; generating one.\n\n"),
8278           PROMPT_NONE, 0 },
8279
8280         /* Relocate hint */
8281         { PR_0_RELOCATE_HINT,
8282           N_("Note: if several inode or block bitmap blocks or part\n"
8283           "of the inode table require relocation, you may wish to try\n"
8284           "running e2fsck with the '-b %S' option first.  The problem\n"
8285           "may lie only with the primary block group descriptors, and\n"
8286           "the backup block group descriptors may be OK.\n\n"),
8287           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8288
8289         /* Miscellaneous superblock corruption */
8290         { PR_0_MISC_CORRUPT_SUPER,
8291           N_("Corruption found in @S.  (%s = %N).\n"),
8292           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8293
8294         /* Error determing physical device size of filesystem */
8295         { PR_0_GETSIZE_ERROR,
8296           N_("Error determining size of the physical @v: %m\n"),
8297           PROMPT_NONE, PR_FATAL },
8298
8299         /* Inode count in superblock is incorrect */
8300         { PR_0_INODE_COUNT_WRONG,
8301           N_("@i count in @S is %i, @s %j.\n"),
8302           PROMPT_FIX, 0 },
8303
8304         { PR_0_HURD_CLEAR_FILETYPE,
8305           N_("The Hurd does not support the filetype feature.\n"),
8306           PROMPT_CLEAR, 0 },
8307
8308         /* Journal inode is invalid */
8309         { PR_0_JOURNAL_BAD_INODE,
8310           N_("@S has an @n ext3 @j (@i %i).\n"),
8311           PROMPT_CLEAR, PR_PREEN_OK },
8312
8313         /* The external journal has (unsupported) multiple filesystems */
8314         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8315           N_("External @j has multiple @f users (unsupported).\n"),
8316           PROMPT_NONE, PR_FATAL },
8317
8318         /* Can't find external journal */
8319         { PR_0_CANT_FIND_JOURNAL,
8320           N_("Can't find external @j\n"),
8321           PROMPT_NONE, PR_FATAL },
8322
8323         /* External journal has bad superblock */
8324         { PR_0_EXT_JOURNAL_BAD_SUPER,
8325           N_("External @j has bad @S\n"),
8326           PROMPT_NONE, PR_FATAL },
8327
8328         /* Superblock has a bad journal UUID */
8329         { PR_0_JOURNAL_BAD_UUID,
8330           N_("External @j does not support this @f\n"),
8331           PROMPT_NONE, PR_FATAL },
8332
8333         /* Journal has an unknown superblock type */
8334         { PR_0_JOURNAL_UNSUPP_SUPER,
8335           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8336              "It is likely that your copy of e2fsck is old and/or doesn't "
8337              "support this @j format.\n"
8338              "It is also possible the @j @S is corrupt.\n"),
8339           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8340
8341         /* Journal superblock is corrupt */
8342         { PR_0_JOURNAL_BAD_SUPER,
8343           N_("Ext3 @j @S is corrupt.\n"),
8344           PROMPT_FIX, PR_PREEN_OK },
8345
8346         /* Superblock flag should be cleared */
8347         { PR_0_JOURNAL_HAS_JOURNAL,
8348           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8349           PROMPT_CLEAR, PR_PREEN_OK },
8350
8351         /* Superblock flag is incorrect */
8352         { PR_0_JOURNAL_RECOVER_SET,
8353           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8354           PROMPT_CLEAR, PR_PREEN_OK },
8355
8356         /* Journal has data, but recovery flag is clear */
8357         { PR_0_JOURNAL_RECOVERY_CLEAR,
8358           N_("ext3 recovery flag is clear, but @j has data.\n"),
8359           PROMPT_NONE, 0 },
8360
8361         /* Ask if we should clear the journal */
8362         { PR_0_JOURNAL_RESET_JOURNAL,
8363           N_("Clear @j"),
8364           PROMPT_NULL, PR_PREEN_NOMSG },
8365
8366         /* Ask if we should run the journal anyway */
8367         { PR_0_JOURNAL_RUN,
8368           N_("Run @j anyway"),
8369           PROMPT_NULL, 0 },
8370
8371         /* Run the journal by default */
8372         { PR_0_JOURNAL_RUN_DEFAULT,
8373           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8374           PROMPT_NONE, 0 },
8375
8376         /* Clearing orphan inode */
8377         { PR_0_ORPHAN_CLEAR_INODE,
8378           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8379           PROMPT_NONE, 0 },
8380
8381         /* Illegal block found in orphaned inode */
8382         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8383            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8384           PROMPT_NONE, 0 },
8385
8386         /* Already cleared block found in orphaned inode */
8387         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8388            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8389           PROMPT_NONE, 0 },
8390
8391         /* Illegal orphan inode in superblock */
8392         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8393           N_("@I @o @i %i in @S.\n"),
8394           PROMPT_NONE, 0 },
8395
8396         /* Illegal inode in orphaned inode list */
8397         { PR_0_ORPHAN_ILLEGAL_INODE,
8398           N_("@I @i %i in @o @i list.\n"),
8399           PROMPT_NONE, 0 },
8400
8401         /* Filesystem revision is 0, but feature flags are set */
8402         { PR_0_FS_REV_LEVEL,
8403           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8404           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8405
8406         /* Journal superblock has an unknown read-only feature flag set */
8407         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8408           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8409           PROMPT_ABORT, 0 },
8410
8411         /* Journal superblock has an unknown incompatible feature flag set */
8412         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8413           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8414           PROMPT_ABORT, 0 },
8415
8416         /* Journal has unsupported version number */
8417         { PR_0_JOURNAL_UNSUPP_VERSION,
8418           N_("@j version not supported by this e2fsck.\n"),
8419           PROMPT_ABORT, 0 },
8420
8421         /* Moving journal to hidden file */
8422         { PR_0_MOVE_JOURNAL,
8423           N_("Moving @j from /%s to hidden @i.\n\n"),
8424           PROMPT_NONE, 0 },
8425
8426         /* Error moving journal to hidden file */
8427         { PR_0_ERR_MOVE_JOURNAL,
8428           N_("Error moving @j: %m\n\n"),
8429           PROMPT_NONE, 0 },
8430
8431         /* Clearing V2 journal superblock */
8432         { PR_0_CLEAR_V2_JOURNAL,
8433           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8434              "Clearing fields beyond the V1 @j @S...\n\n"),
8435           PROMPT_NONE, 0 },
8436
8437         /* Backup journal inode blocks */
8438         { PR_0_BACKUP_JNL,
8439           N_("Backing up @j @i @b information.\n\n"),
8440           PROMPT_NONE, 0 },
8441
8442         /* Reserved blocks w/o resize_inode */
8443         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8444           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8445              "is %N; @s zero.  "),
8446           PROMPT_FIX, 0 },
8447
8448         /* Resize_inode not enabled, but resize inode is non-zero */
8449         { PR_0_CLEAR_RESIZE_INODE,
8450           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8451           PROMPT_CLEAR, 0 },
8452
8453         /* Resize inode invalid */
8454         { PR_0_RESIZE_INODE_INVALID,
8455           N_("Resize @i not valid.  "),
8456           PROMPT_RECREATE, 0 },
8457
8458         /* Pass 1 errors */
8459
8460         /* Pass 1: Checking inodes, blocks, and sizes */
8461         { PR_1_PASS_HEADER,
8462           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8463           PROMPT_NONE, 0 },
8464
8465         /* Root directory is not an inode */
8466         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8467           PROMPT_CLEAR, 0 },
8468
8469         /* Root directory has dtime set */
8470         { PR_1_ROOT_DTIME,
8471           N_("@r has dtime set (probably due to old mke2fs).  "),
8472           PROMPT_FIX, PR_PREEN_OK },
8473
8474         /* Reserved inode has bad mode */
8475         { PR_1_RESERVED_BAD_MODE,
8476           N_("Reserved @i %i (%Q) has @n mode.  "),
8477           PROMPT_CLEAR, PR_PREEN_OK },
8478
8479         /* Deleted inode has zero dtime */
8480         { PR_1_ZERO_DTIME,
8481           N_("@D @i %i has zero dtime.  "),
8482           PROMPT_FIX, PR_PREEN_OK },
8483
8484         /* Inode in use, but dtime set */
8485         { PR_1_SET_DTIME,
8486           N_("@i %i is in use, but has dtime set.  "),
8487           PROMPT_FIX, PR_PREEN_OK },
8488
8489         /* Zero-length directory */
8490         { PR_1_ZERO_LENGTH_DIR,
8491           N_("@i %i is a @z @d.  "),
8492           PROMPT_CLEAR, PR_PREEN_OK },
8493
8494         /* Block bitmap conflicts with some other fs block */
8495         { PR_1_BB_CONFLICT,
8496           N_("@g %g's @b @B at %b @C.\n"),
8497           PROMPT_RELOCATE, 0 },
8498
8499         /* Inode bitmap conflicts with some other fs block */
8500         { PR_1_IB_CONFLICT,
8501           N_("@g %g's @i @B at %b @C.\n"),
8502           PROMPT_RELOCATE, 0 },
8503
8504         /* Inode table conflicts with some other fs block */
8505         { PR_1_ITABLE_CONFLICT,
8506           N_("@g %g's @i table at %b @C.\n"),
8507           PROMPT_RELOCATE, 0 },
8508
8509         /* Block bitmap is on a bad block */
8510         { PR_1_BB_BAD_BLOCK,
8511           N_("@g %g's @b @B (%b) is bad.  "),
8512           PROMPT_RELOCATE, 0 },
8513
8514         /* Inode bitmap is on a bad block */
8515         { PR_1_IB_BAD_BLOCK,
8516           N_("@g %g's @i @B (%b) is bad.  "),
8517           PROMPT_RELOCATE, 0 },
8518
8519         /* Inode has incorrect i_size */
8520         { PR_1_BAD_I_SIZE,
8521           N_("@i %i, i_size is %Is, @s %N.  "),
8522           PROMPT_FIX, PR_PREEN_OK },
8523
8524         /* Inode has incorrect i_blocks */
8525         { PR_1_BAD_I_BLOCKS,
8526           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8527           PROMPT_FIX, PR_PREEN_OK },
8528
8529         /* Illegal blocknumber in inode */
8530         { PR_1_ILLEGAL_BLOCK_NUM,
8531           N_("@I @b #%B (%b) in @i %i.  "),
8532           PROMPT_CLEAR, PR_LATCH_BLOCK },
8533
8534         /* Block number overlaps fs metadata */
8535         { PR_1_BLOCK_OVERLAPS_METADATA,
8536           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8537           PROMPT_CLEAR, PR_LATCH_BLOCK },
8538
8539         /* Inode has illegal blocks (latch question) */
8540         { PR_1_INODE_BLOCK_LATCH,
8541           N_("@i %i has illegal @b(s).  "),
8542           PROMPT_CLEAR, 0 },
8543
8544         /* Too many bad blocks in inode */
8545         { PR_1_TOO_MANY_BAD_BLOCKS,
8546           N_("Too many illegal @bs in @i %i.\n"),
8547           PROMPT_CLEAR_INODE, PR_NO_OK },
8548
8549         /* Illegal block number in bad block inode */
8550         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8551           N_("@I @b #%B (%b) in bad @b @i.  "),
8552           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8553
8554         /* Bad block inode has illegal blocks (latch question) */
8555         { PR_1_INODE_BBLOCK_LATCH,
8556           N_("Bad @b @i has illegal @b(s).  "),
8557           PROMPT_CLEAR, 0 },
8558
8559         /* Duplicate or bad blocks in use! */
8560         { PR_1_DUP_BLOCKS_PREENSTOP,
8561           N_("Duplicate or bad @b in use!\n"),
8562           PROMPT_NONE, 0 },
8563
8564         /* Bad block used as bad block indirect block */
8565         { PR_1_BBINODE_BAD_METABLOCK,
8566           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8567           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8568
8569         /* Inconsistency can't be fixed prompt */
8570         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8571           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8572              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8573              "in the @f.\n"),
8574           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8575
8576         /* Bad primary block */
8577         { PR_1_BAD_PRIMARY_BLOCK,
8578           N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8579           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8580
8581         /* Bad primary block prompt */
8582         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8583           N_("You can remove this @b from the bad @b list and hope\n"
8584              "that the @b is really OK.  But there are no guarantees.\n\n"),
8585           PROMPT_CLEAR, PR_PREEN_NOMSG },
8586
8587         /* Bad primary superblock */
8588         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8589           N_("The primary @S (%b) is on the bad @b list.\n"),
8590           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8591
8592         /* Bad primary block group descriptors */
8593         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8594           N_("Block %b in the primary @g descriptors "
8595           "is on the bad @b list\n"),
8596           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8597
8598         /* Bad superblock in group */
8599         { PR_1_BAD_SUPERBLOCK,
8600           N_("Warning: Group %g's @S (%b) is bad.\n"),
8601           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8602
8603         /* Bad block group descriptors in group */
8604         { PR_1_BAD_GROUP_DESCRIPTORS,
8605           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8606           "@b (%b).\n"),
8607           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8608
8609         /* Block claimed for no reason */
8610         { PR_1_PROGERR_CLAIMED_BLOCK,
8611           N_("Programming error?  @b #%b claimed for no reason in "
8612           "process_bad_@b.\n"),
8613           PROMPT_NONE, PR_PREEN_OK },
8614
8615         /* Error allocating blocks for relocating metadata */
8616         { PR_1_RELOC_BLOCK_ALLOCATE,
8617           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8618           PROMPT_NONE, PR_PREEN_OK },
8619
8620         /* Error allocating block buffer during relocation process */
8621         { PR_1_RELOC_MEMORY_ALLOCATE,
8622           N_("@A @b buffer for relocating %s\n"),
8623           PROMPT_NONE, PR_PREEN_OK },
8624
8625         /* Relocating metadata group information from X to Y */
8626         { PR_1_RELOC_FROM_TO,
8627           N_("Relocating @g %g's %s from %b to %c...\n"),
8628           PROMPT_NONE, PR_PREEN_OK },
8629
8630         /* Relocating metatdata group information to X */
8631         { PR_1_RELOC_TO,
8632           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8633           PROMPT_NONE, PR_PREEN_OK },
8634
8635         /* Block read error during relocation process */
8636         { PR_1_RELOC_READ_ERR,
8637           N_("Warning: could not read @b %b of %s: %m\n"),
8638           PROMPT_NONE, PR_PREEN_OK },
8639
8640         /* Block write error during relocation process */
8641         { PR_1_RELOC_WRITE_ERR,
8642           N_("Warning: could not write @b %b for %s: %m\n"),
8643           PROMPT_NONE, PR_PREEN_OK },
8644
8645         /* Error allocating inode bitmap */
8646         { PR_1_ALLOCATE_IBITMAP_ERROR,
8647           N_("@A @i @B (%N): %m\n"),
8648           PROMPT_NONE, PR_FATAL },
8649
8650         /* Error allocating block bitmap */
8651         { PR_1_ALLOCATE_BBITMAP_ERROR,
8652           N_("@A @b @B (%N): %m\n"),
8653           PROMPT_NONE, PR_FATAL },
8654
8655         /* Error allocating icount structure */
8656         { PR_1_ALLOCATE_ICOUNT,
8657           N_("@A icount link information: %m\n"),
8658           PROMPT_NONE, PR_FATAL },
8659
8660         /* Error allocating dbcount */
8661         { PR_1_ALLOCATE_DBCOUNT,
8662           N_("@A @d @b array: %m\n"),
8663           PROMPT_NONE, PR_FATAL },
8664
8665         /* Error while scanning inodes */
8666         { PR_1_ISCAN_ERROR,
8667           N_("Error while scanning @is (%i): %m\n"),
8668           PROMPT_NONE, PR_FATAL },
8669
8670         /* Error while iterating over blocks */
8671         { PR_1_BLOCK_ITERATE,
8672           N_("Error while iterating over @bs in @i %i: %m\n"),
8673           PROMPT_NONE, PR_FATAL },
8674
8675         /* Error while storing inode count information */
8676         { PR_1_ICOUNT_STORE,
8677           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8678           PROMPT_NONE, PR_FATAL },
8679
8680         /* Error while storing directory block information */
8681         { PR_1_ADD_DBLOCK,
8682           N_("Error storing @d @b information "
8683           "(@i=%i, @b=%b, num=%N): %m\n"),
8684           PROMPT_NONE, PR_FATAL },
8685
8686         /* Error while reading inode (for clearing) */
8687         { PR_1_READ_INODE,
8688           N_("Error reading @i %i: %m\n"),
8689           PROMPT_NONE, PR_FATAL },
8690
8691         /* Suppress messages prompt */
8692         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8693
8694         /* Imagic flag set on an inode when filesystem doesn't support it */
8695         { PR_1_SET_IMAGIC,
8696           N_("@i %i has imagic flag set.  "),
8697           PROMPT_CLEAR, 0 },
8698
8699         /* Immutable flag set on a device or socket inode */
8700         { PR_1_SET_IMMUTABLE,
8701           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8702              "or append-only flag set.  "),
8703           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8704
8705         /* Compression flag set on an inode when filesystem doesn't support it */
8706         { PR_1_COMPR_SET,
8707           N_("@i %i has @cion flag set on @f without @cion support.  "),
8708           PROMPT_CLEAR, 0 },
8709
8710         /* Non-zero size for device, fifo or socket inode */
8711         { PR_1_SET_NONZSIZE,
8712           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8713           PROMPT_FIX, PR_PREEN_OK },
8714
8715         /* Filesystem revision is 0, but feature flags are set */
8716         { PR_1_FS_REV_LEVEL,
8717           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8718           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8719
8720         /* Journal inode is not in use, but contains data */
8721         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8722           N_("@j @i is not in use, but contains data.  "),
8723           PROMPT_CLEAR, PR_PREEN_OK },
8724
8725         /* Journal has bad mode */
8726         { PR_1_JOURNAL_BAD_MODE,
8727           N_("@j is not regular file.  "),
8728           PROMPT_FIX, PR_PREEN_OK },
8729
8730         /* Deal with inodes that were part of orphan linked list */
8731         { PR_1_LOW_DTIME,
8732           N_("@i %i was part of the @o @i list.  "),
8733           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8734
8735         /* Deal with inodes that were part of corrupted orphan linked
8736            list (latch question) */
8737         { PR_1_ORPHAN_LIST_REFUGEES,
8738           N_("@is that were part of a corrupted orphan linked list found.  "),
8739           PROMPT_FIX, 0 },
8740
8741         /* Error allocating refcount structure */
8742         { PR_1_ALLOCATE_REFCOUNT,
8743           N_("@A refcount structure (%N): %m\n"),
8744           PROMPT_NONE, PR_FATAL },
8745
8746         /* Error reading extended attribute block */
8747         { PR_1_READ_EA_BLOCK,
8748           N_("Error reading @a @b %b for @i %i.  "),
8749           PROMPT_CLEAR, 0 },
8750
8751         /* Invalid extended attribute block */
8752         { PR_1_BAD_EA_BLOCK,
8753           N_("@i %i has a bad @a @b %b.  "),
8754           PROMPT_CLEAR, 0 },
8755
8756         /* Error reading Extended Attribute block while fixing refcount */
8757         { PR_1_EXTATTR_READ_ABORT,
8758           N_("Error reading @a @b %b (%m).  "),
8759           PROMPT_ABORT, 0 },
8760
8761         /* Extended attribute reference count incorrect */
8762         { PR_1_EXTATTR_REFCOUNT,
8763           N_("@a @b %b has reference count %B, @s %N.  "),
8764           PROMPT_FIX, 0 },
8765
8766         /* Error writing Extended Attribute block while fixing refcount */
8767         { PR_1_EXTATTR_WRITE,
8768           N_("Error writing @a @b %b (%m).  "),
8769           PROMPT_ABORT, 0 },
8770
8771         /* Multiple EA blocks not supported */
8772         { PR_1_EA_MULTI_BLOCK,
8773           N_("@a @b %b has h_@bs > 1.  "),
8774           PROMPT_CLEAR, 0},
8775
8776         /* Error allocating EA region allocation structure */
8777         { PR_1_EA_ALLOC_REGION,
8778           N_("@A @a @b %b.  "),
8779           PROMPT_ABORT, 0},
8780
8781         /* Error EA allocation collision */
8782         { PR_1_EA_ALLOC_COLLISION,
8783           N_("@a @b %b is corrupt (allocation collision).  "),
8784           PROMPT_CLEAR, 0},
8785
8786         /* Bad extended attribute name */
8787         { PR_1_EA_BAD_NAME,
8788           N_("@a @b %b is corrupt (@n name).  "),
8789           PROMPT_CLEAR, 0},
8790
8791         /* Bad extended attribute value */
8792         { PR_1_EA_BAD_VALUE,
8793           N_("@a @b %b is corrupt (@n value).  "),
8794           PROMPT_CLEAR, 0},
8795
8796         /* Inode too big (latch question) */
8797         { PR_1_INODE_TOOBIG,
8798           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8799
8800         /* Directory too big */
8801         { PR_1_TOOBIG_DIR,
8802           N_("@b #%B (%b) causes @d to be too big.  "),
8803           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8804
8805         /* Regular file too big */
8806         { PR_1_TOOBIG_REG,
8807           N_("@b #%B (%b) causes file to be too big.  "),
8808           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8809
8810         /* Symlink too big */
8811         { PR_1_TOOBIG_SYMLINK,
8812           N_("@b #%B (%b) causes symlink to be too big.  "),
8813           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8814
8815         /* INDEX_FL flag set on a non-HTREE filesystem */
8816         { PR_1_HTREE_SET,
8817           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8818           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8819
8820         /* INDEX_FL flag set on a non-directory */
8821         { PR_1_HTREE_NODIR,
8822           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8823           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8824
8825         /* Invalid root node in HTREE directory */
8826         { PR_1_HTREE_BADROOT,
8827           N_("@h %i has an @n root node.\n"),
8828           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8829
8830         /* Unsupported hash version in HTREE directory */
8831         { PR_1_HTREE_HASHV,
8832           N_("@h %i has an unsupported hash version (%N)\n"),
8833           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8834
8835         /* Incompatible flag in HTREE root node */
8836         { PR_1_HTREE_INCOMPAT,
8837           N_("@h %i uses an incompatible htree root node flag.\n"),
8838           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8839
8840         /* HTREE too deep */
8841         { PR_1_HTREE_DEPTH,
8842           N_("@h %i has a tree depth (%N) which is too big\n"),
8843           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8844
8845         /* Bad block has indirect block that conflicts with filesystem block */
8846         { PR_1_BB_FS_BLOCK,
8847           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8848              "@f metadata.  "),
8849           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8850
8851         /* Resize inode failed */
8852         { PR_1_RESIZE_INODE_CREATE,
8853           N_("Resize @i (re)creation failed: %m."),
8854           PROMPT_ABORT, 0 },
8855
8856         /* invalid inode->i_extra_isize */
8857         { PR_1_EXTRA_ISIZE,
8858           N_("@i %i has a extra size (%IS) which is @n\n"),
8859           PROMPT_FIX, PR_PREEN_OK },
8860
8861         /* invalid ea entry->e_name_len */
8862         { PR_1_ATTR_NAME_LEN,
8863           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8864           PROMPT_CLEAR, PR_PREEN_OK },
8865
8866         /* invalid ea entry->e_value_size */
8867         { PR_1_ATTR_VALUE_SIZE,
8868           N_("@a in @i %i has a value size (%N) which is @n\n"),
8869           PROMPT_CLEAR, PR_PREEN_OK },
8870
8871         /* invalid ea entry->e_value_offs */
8872         { PR_1_ATTR_VALUE_OFFSET,
8873           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8874           PROMPT_CLEAR, PR_PREEN_OK },
8875
8876         /* invalid ea entry->e_value_block */
8877         { PR_1_ATTR_VALUE_BLOCK,
8878           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8879           PROMPT_CLEAR, PR_PREEN_OK },
8880
8881         /* invalid ea entry->e_hash */
8882         { PR_1_ATTR_HASH,
8883           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8884           PROMPT_CLEAR, PR_PREEN_OK },
8885
8886         /* Pass 1b errors */
8887
8888         /* Pass 1B: Rescan for duplicate/bad blocks */
8889         { PR_1B_PASS_HEADER,
8890           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8891           "Pass 1B: Rescanning for @m @bs\n"),
8892           PROMPT_NONE, 0 },
8893
8894         /* Duplicate/bad block(s) header */
8895         { PR_1B_DUP_BLOCK_HEADER,
8896           N_("@m @b(s) in @i %i:"),
8897           PROMPT_NONE, 0 },
8898
8899         /* Duplicate/bad block(s) in inode */
8900         { PR_1B_DUP_BLOCK,
8901           " %b",
8902           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8903
8904         /* Duplicate/bad block(s) end */
8905         { PR_1B_DUP_BLOCK_END,
8906           "\n",
8907           PROMPT_NONE, PR_PREEN_NOHDR },
8908
8909         /* Error while scanning inodes */
8910         { PR_1B_ISCAN_ERROR,
8911           N_("Error while scanning inodes (%i): %m\n"),
8912           PROMPT_NONE, PR_FATAL },
8913
8914         /* Error allocating inode bitmap */
8915         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8916           N_("@A @i @B (@i_dup_map): %m\n"),
8917           PROMPT_NONE, PR_FATAL },
8918
8919         /* Error while iterating over blocks */
8920         { PR_1B_BLOCK_ITERATE,
8921           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8922           PROMPT_NONE, 0 },
8923
8924         /* Error adjusting EA refcount */
8925         { PR_1B_ADJ_EA_REFCOUNT,
8926           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8927           PROMPT_NONE, 0 },
8928
8929
8930         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8931         { PR_1C_PASS_HEADER,
8932           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8933           PROMPT_NONE, 0 },
8934
8935
8936         /* Pass 1D: Reconciling multiply-claimed blocks */
8937         { PR_1D_PASS_HEADER,
8938           N_("Pass 1D: Reconciling @m @bs\n"),
8939           PROMPT_NONE, 0 },
8940
8941         /* File has duplicate blocks */
8942         { PR_1D_DUP_FILE,
8943           N_("File %Q (@i #%i, mod time %IM)\n"
8944           "  has %B @m @b(s), shared with %N file(s):\n"),
8945           PROMPT_NONE, 0 },
8946
8947         /* List of files sharing duplicate blocks */
8948         { PR_1D_DUP_FILE_LIST,
8949           N_("\t%Q (@i #%i, mod time %IM)\n"),
8950           PROMPT_NONE, 0 },
8951
8952         /* File sharing blocks with filesystem metadata  */
8953         { PR_1D_SHARE_METADATA,
8954           N_("\t<@f metadata>\n"),
8955           PROMPT_NONE, 0 },
8956
8957         /* Report of how many duplicate/bad inodes */
8958         { PR_1D_NUM_DUP_INODES,
8959           N_("(There are %N @is containing @m @bs.)\n\n"),
8960           PROMPT_NONE, 0 },
8961
8962         /* Duplicated blocks already reassigned or cloned. */
8963         { PR_1D_DUP_BLOCKS_DEALT,
8964           N_("@m @bs already reassigned or cloned.\n\n"),
8965           PROMPT_NONE, 0 },
8966
8967         /* Clone duplicate/bad blocks? */
8968         { PR_1D_CLONE_QUESTION,
8969           "", PROMPT_CLONE, PR_NO_OK },
8970
8971         /* Delete file? */
8972         { PR_1D_DELETE_QUESTION,
8973           "", PROMPT_DELETE, 0 },
8974
8975         /* Couldn't clone file (error) */
8976         { PR_1D_CLONE_ERROR,
8977           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8978
8979         /* Pass 2 errors */
8980
8981         /* Pass 2: Checking directory structure */
8982         { PR_2_PASS_HEADER,
8983           N_("Pass 2: Checking @d structure\n"),
8984           PROMPT_NONE, 0 },
8985
8986         /* Bad inode number for '.' */
8987         { PR_2_BAD_INODE_DOT,
8988           N_("@n @i number for '.' in @d @i %i.\n"),
8989           PROMPT_FIX, 0 },
8990
8991         /* Directory entry has bad inode number */
8992         { PR_2_BAD_INO,
8993           N_("@E has @n @i #: %Di.\n"),
8994           PROMPT_CLEAR, 0 },
8995
8996         /* Directory entry has deleted or unused inode */
8997         { PR_2_UNUSED_INODE,
8998           N_("@E has @D/unused @i %Di.  "),
8999           PROMPT_CLEAR, PR_PREEN_OK },
9000
9001         /* Directry entry is link to '.' */
9002         { PR_2_LINK_DOT,
9003           N_("@E @L to '.'  "),
9004           PROMPT_CLEAR, 0 },
9005
9006         /* Directory entry points to inode now located in a bad block */
9007         { PR_2_BB_INODE,
9008           N_("@E points to @i (%Di) located in a bad @b.\n"),
9009           PROMPT_CLEAR, 0 },
9010
9011         /* Directory entry contains a link to a directory */
9012         { PR_2_LINK_DIR,
9013           N_("@E @L to @d %P (%Di).\n"),
9014           PROMPT_CLEAR, 0 },
9015
9016         /* Directory entry contains a link to the root directry */
9017         { PR_2_LINK_ROOT,
9018           N_("@E @L to the @r.\n"),
9019           PROMPT_CLEAR, 0 },
9020
9021         /* Directory entry has illegal characters in its name */
9022         { PR_2_BAD_NAME,
9023           N_("@E has illegal characters in its name.\n"),
9024           PROMPT_FIX, 0 },
9025
9026         /* Missing '.' in directory inode */
9027         { PR_2_MISSING_DOT,
9028           N_("Missing '.' in @d @i %i.\n"),
9029           PROMPT_FIX, 0 },
9030
9031         /* Missing '..' in directory inode */
9032         { PR_2_MISSING_DOT_DOT,
9033           N_("Missing '..' in @d @i %i.\n"),
9034           PROMPT_FIX, 0 },
9035
9036         /* First entry in directory inode doesn't contain '.' */
9037         { PR_2_1ST_NOT_DOT,
9038           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9039           PROMPT_FIX, 0 },
9040
9041         /* Second entry in directory inode doesn't contain '..' */
9042         { PR_2_2ND_NOT_DOT_DOT,
9043           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9044           PROMPT_FIX, 0 },
9045
9046         /* i_faddr should be zero */
9047         { PR_2_FADDR_ZERO,
9048           N_("i_faddr @F %IF, @s zero.\n"),
9049           PROMPT_CLEAR, 0 },
9050
9051         /* i_file_acl should be zero */
9052         { PR_2_FILE_ACL_ZERO,
9053           N_("i_file_acl @F %If, @s zero.\n"),
9054           PROMPT_CLEAR, 0 },
9055
9056         /* i_dir_acl should be zero */
9057         { PR_2_DIR_ACL_ZERO,
9058           N_("i_dir_acl @F %Id, @s zero.\n"),
9059           PROMPT_CLEAR, 0 },
9060
9061         /* i_frag should be zero */
9062         { PR_2_FRAG_ZERO,
9063           N_("i_frag @F %N, @s zero.\n"),
9064           PROMPT_CLEAR, 0 },
9065
9066         /* i_fsize should be zero */
9067         { PR_2_FSIZE_ZERO,
9068           N_("i_fsize @F %N, @s zero.\n"),
9069           PROMPT_CLEAR, 0 },
9070
9071         /* inode has bad mode */
9072         { PR_2_BAD_MODE,
9073           N_("@i %i (%Q) has @n mode (%Im).\n"),
9074           PROMPT_CLEAR, 0 },
9075
9076         /* directory corrupted */
9077         { PR_2_DIR_CORRUPTED,
9078           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9079           PROMPT_SALVAGE, 0 },
9080
9081         /* filename too long */
9082         { PR_2_FILENAME_LONG,
9083           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9084           PROMPT_TRUNCATE, 0 },
9085
9086         /* Directory inode has a missing block (hole) */
9087         { PR_2_DIRECTORY_HOLE,
9088           N_("@d @i %i has an unallocated @b #%B.  "),
9089           PROMPT_ALLOCATE, 0 },
9090
9091         /* '.' is not NULL terminated */
9092         { PR_2_DOT_NULL_TERM,
9093           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9094           PROMPT_FIX, 0 },
9095
9096         /* '..' is not NULL terminated */
9097         { PR_2_DOT_DOT_NULL_TERM,
9098           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9099           PROMPT_FIX, 0 },
9100
9101         /* Illegal character device inode */
9102         { PR_2_BAD_CHAR_DEV,
9103           N_("@i %i (%Q) is an @I character @v.\n"),
9104           PROMPT_CLEAR, 0 },
9105
9106         /* Illegal block device inode */
9107         { PR_2_BAD_BLOCK_DEV,
9108           N_("@i %i (%Q) is an @I @b @v.\n"),
9109           PROMPT_CLEAR, 0 },
9110
9111         /* Duplicate '.' entry */
9112         { PR_2_DUP_DOT,
9113           N_("@E is duplicate '.' @e.\n"),
9114           PROMPT_FIX, 0 },
9115
9116         /* Duplicate '..' entry */
9117         { PR_2_DUP_DOT_DOT,
9118           N_("@E is duplicate '..' @e.\n"),
9119           PROMPT_FIX, 0 },
9120
9121         /* Internal error: couldn't find dir_info */
9122         { PR_2_NO_DIRINFO,
9123           N_("Internal error: cannot find dir_info for %i.\n"),
9124           PROMPT_NONE, PR_FATAL },
9125
9126         /* Final rec_len is wrong */
9127         { PR_2_FINAL_RECLEN,
9128           N_("@E has rec_len of %Dr, @s %N.\n"),
9129           PROMPT_FIX, 0 },
9130
9131         /* Error allocating icount structure */
9132         { PR_2_ALLOCATE_ICOUNT,
9133           N_("@A icount structure: %m\n"),
9134           PROMPT_NONE, PR_FATAL },
9135
9136         /* Error iterating over directory blocks */
9137         { PR_2_DBLIST_ITERATE,
9138           N_("Error iterating over @d @bs: %m\n"),
9139           PROMPT_NONE, PR_FATAL },
9140
9141         /* Error reading directory block */
9142         { PR_2_READ_DIRBLOCK,
9143           N_("Error reading @d @b %b (@i %i): %m\n"),
9144           PROMPT_CONTINUE, 0 },
9145
9146         /* Error writing directory block */
9147         { PR_2_WRITE_DIRBLOCK,
9148           N_("Error writing @d @b %b (@i %i): %m\n"),
9149           PROMPT_CONTINUE, 0 },
9150
9151         /* Error allocating new directory block */
9152         { PR_2_ALLOC_DIRBOCK,
9153           N_("@A new @d @b for @i %i (%s): %m\n"),
9154           PROMPT_NONE, 0 },
9155
9156         /* Error deallocating inode */
9157         { PR_2_DEALLOC_INODE,
9158           N_("Error deallocating @i %i: %m\n"),
9159           PROMPT_NONE, PR_FATAL },
9160
9161         /* Directory entry for '.' is big.  Split? */
9162         { PR_2_SPLIT_DOT,
9163           N_("@d @e for '.' is big.  "),
9164           PROMPT_SPLIT, PR_NO_OK },
9165
9166         /* Illegal FIFO inode */
9167         { PR_2_BAD_FIFO,
9168           N_("@i %i (%Q) is an @I FIFO.\n"),
9169           PROMPT_CLEAR, 0 },
9170
9171         /* Illegal socket inode */
9172         { PR_2_BAD_SOCKET,
9173           N_("@i %i (%Q) is an @I socket.\n"),
9174           PROMPT_CLEAR, 0 },
9175
9176         /* Directory filetype not set */
9177         { PR_2_SET_FILETYPE,
9178           N_("Setting filetype for @E to %N.\n"),
9179           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9180
9181         /* Directory filetype incorrect */
9182         { PR_2_BAD_FILETYPE,
9183           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9184           PROMPT_FIX, 0 },
9185
9186         /* Directory filetype set on filesystem */
9187         { PR_2_CLEAR_FILETYPE,
9188           N_("@E has filetype set.\n"),
9189           PROMPT_CLEAR, PR_PREEN_OK },
9190
9191         /* Directory filename is null */
9192         { PR_2_NULL_NAME,
9193           N_("@E has a @z name.\n"),
9194           PROMPT_CLEAR, 0 },
9195
9196         /* Invalid symlink */
9197         { PR_2_INVALID_SYMLINK,
9198           N_("Symlink %Q (@i #%i) is @n.\n"),
9199           PROMPT_CLEAR, 0 },
9200
9201         /* i_file_acl (extended attribute block) is bad */
9202         { PR_2_FILE_ACL_BAD,
9203           N_("@a @b @F @n (%If).\n"),
9204           PROMPT_CLEAR, 0 },
9205
9206         /* Filesystem contains large files, but has no such flag in sb */
9207         { PR_2_FEATURE_LARGE_FILES,
9208           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9209           PROMPT_FIX, 0 },
9210
9211         /* Node in HTREE directory not referenced */
9212         { PR_2_HTREE_NOTREF,
9213           N_("@p @h %d: node (%B) not referenced\n"),
9214           PROMPT_NONE, 0 },
9215
9216         /* Node in HTREE directory referenced twice */
9217         { PR_2_HTREE_DUPREF,
9218           N_("@p @h %d: node (%B) referenced twice\n"),
9219           PROMPT_NONE, 0 },
9220
9221         /* Node in HTREE directory has bad min hash */
9222         { PR_2_HTREE_MIN_HASH,
9223           N_("@p @h %d: node (%B) has bad min hash\n"),
9224           PROMPT_NONE, 0 },
9225
9226         /* Node in HTREE directory has bad max hash */
9227         { PR_2_HTREE_MAX_HASH,
9228           N_("@p @h %d: node (%B) has bad max hash\n"),
9229           PROMPT_NONE, 0 },
9230
9231         /* Clear invalid HTREE directory */
9232         { PR_2_HTREE_CLEAR,
9233           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9234
9235         /* Bad block in htree interior node */
9236         { PR_2_HTREE_BADBLK,
9237           N_("@p @h %d (%q): bad @b number %b.\n"),
9238           PROMPT_CLEAR_HTREE, 0 },
9239
9240         /* Error adjusting EA refcount */
9241         { PR_2_ADJ_EA_REFCOUNT,
9242           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9243           PROMPT_NONE, PR_FATAL },
9244
9245         /* Invalid HTREE root node */
9246         { PR_2_HTREE_BAD_ROOT,
9247           N_("@p @h %d: root node is @n\n"),
9248           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9249
9250         /* Invalid HTREE limit */
9251         { PR_2_HTREE_BAD_LIMIT,
9252           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9253           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9254
9255         /* Invalid HTREE count */
9256         { PR_2_HTREE_BAD_COUNT,
9257           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9258           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9259
9260         /* HTREE interior node has out-of-order hashes in table */
9261         { PR_2_HTREE_HASH_ORDER,
9262           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9263           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9264
9265         /* Node in HTREE directory has invalid depth */
9266         { PR_2_HTREE_BAD_DEPTH,
9267           N_("@p @h %d: node (%B) has @n depth\n"),
9268           PROMPT_NONE, 0 },
9269
9270         /* Duplicate directory entry found */
9271         { PR_2_DUPLICATE_DIRENT,
9272           N_("Duplicate @E found.  "),
9273           PROMPT_CLEAR, 0 },
9274
9275         /* Non-unique filename found */
9276         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9277           N_("@E has a non-unique filename.\nRename to %s"),
9278           PROMPT_NULL, 0 },
9279
9280         /* Duplicate directory entry found */
9281         { PR_2_REPORT_DUP_DIRENT,
9282           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9283           PROMPT_NONE, 0 },
9284
9285         /* Pass 3 errors */
9286
9287         /* Pass 3: Checking directory connectivity */
9288         { PR_3_PASS_HEADER,
9289           N_("Pass 3: Checking @d connectivity\n"),
9290           PROMPT_NONE, 0 },
9291
9292         /* Root inode not allocated */
9293         { PR_3_NO_ROOT_INODE,
9294           N_("@r not allocated.  "),
9295           PROMPT_ALLOCATE, 0 },
9296
9297         /* No room in lost+found */
9298         { PR_3_EXPAND_LF_DIR,
9299           N_("No room in @l @d.  "),
9300           PROMPT_EXPAND, 0 },
9301
9302         /* Unconnected directory inode */
9303         { PR_3_UNCONNECTED_DIR,
9304           N_("Unconnected @d @i %i (%p)\n"),
9305           PROMPT_CONNECT, 0 },
9306
9307         /* /lost+found not found */
9308         { PR_3_NO_LF_DIR,
9309           N_("/@l not found.  "),
9310           PROMPT_CREATE, PR_PREEN_OK },
9311
9312         /* .. entry is incorrect */
9313         { PR_3_BAD_DOT_DOT,
9314           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9315           PROMPT_FIX, 0 },
9316
9317         /* Bad or non-existent /lost+found.  Cannot reconnect */
9318         { PR_3_NO_LPF,
9319           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9320           PROMPT_NONE, 0 },
9321
9322         /* Could not expand /lost+found */
9323         { PR_3_CANT_EXPAND_LPF,
9324           N_("Could not expand /@l: %m\n"),
9325           PROMPT_NONE, 0 },
9326
9327         /* Could not reconnect inode */
9328         { PR_3_CANT_RECONNECT,
9329           N_("Could not reconnect %i: %m\n"),
9330           PROMPT_NONE, 0 },
9331
9332         /* Error while trying to find /lost+found */
9333         { PR_3_ERR_FIND_LPF,
9334           N_("Error while trying to find /@l: %m\n"),
9335           PROMPT_NONE, 0 },
9336
9337         /* Error in ext2fs_new_block while creating /lost+found */
9338         { PR_3_ERR_LPF_NEW_BLOCK,
9339           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9340           PROMPT_NONE, 0 },
9341
9342         /* Error in ext2fs_new_inode while creating /lost+found */
9343         { PR_3_ERR_LPF_NEW_INODE,
9344           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9345           PROMPT_NONE, 0 },
9346
9347         /* Error in ext2fs_new_dir_block while creating /lost+found */
9348         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9349           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9350           PROMPT_NONE, 0 },
9351
9352         /* Error while writing directory block for /lost+found */
9353         { PR_3_ERR_LPF_WRITE_BLOCK,
9354           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9355           PROMPT_NONE, 0 },
9356
9357         /* Error while adjusting inode count */
9358         { PR_3_ADJUST_INODE,
9359           N_("Error while adjusting @i count on @i %i\n"),
9360           PROMPT_NONE, 0 },
9361
9362         /* Couldn't fix parent directory -- error */
9363         { PR_3_FIX_PARENT_ERR,
9364           N_("Couldn't fix parent of @i %i: %m\n\n"),
9365           PROMPT_NONE, 0 },
9366
9367         /* Couldn't fix parent directory -- couldn't find it */
9368         { PR_3_FIX_PARENT_NOFIND,
9369           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9370           PROMPT_NONE, 0 },
9371
9372         /* Error allocating inode bitmap */
9373         { PR_3_ALLOCATE_IBITMAP_ERROR,
9374           N_("@A @i @B (%N): %m\n"),
9375           PROMPT_NONE, PR_FATAL },
9376
9377         /* Error creating root directory */
9378         { PR_3_CREATE_ROOT_ERROR,
9379           N_("Error creating root @d (%s): %m\n"),
9380           PROMPT_NONE, PR_FATAL },
9381
9382         /* Error creating lost and found directory */
9383         { PR_3_CREATE_LPF_ERROR,
9384           N_("Error creating /@l @d (%s): %m\n"),
9385           PROMPT_NONE, PR_FATAL },
9386
9387         /* Root inode is not directory; aborting */
9388         { PR_3_ROOT_NOT_DIR_ABORT,
9389           N_("@r is not a @d; aborting.\n"),
9390           PROMPT_NONE, PR_FATAL },
9391
9392         /* Cannot proceed without a root inode. */
9393         { PR_3_NO_ROOT_INODE_ABORT,
9394           N_("can't proceed without a @r.\n"),
9395           PROMPT_NONE, PR_FATAL },
9396
9397         /* Internal error: couldn't find dir_info */
9398         { PR_3_NO_DIRINFO,
9399           N_("Internal error: cannot find dir_info for %i.\n"),
9400           PROMPT_NONE, PR_FATAL },
9401
9402         /* Lost+found not a directory */
9403         { PR_3_LPF_NOTDIR,
9404           N_("/@l is not a @d (ino=%i)\n"),
9405           PROMPT_UNLINK, 0 },
9406
9407         /* Pass 3A Directory Optimization       */
9408
9409         /* Pass 3A: Optimizing directories */
9410         { PR_3A_PASS_HEADER,
9411           N_("Pass 3A: Optimizing directories\n"),
9412           PROMPT_NONE, PR_PREEN_NOMSG },
9413
9414         /* Error iterating over directories */
9415         { PR_3A_OPTIMIZE_ITER,
9416           N_("Failed to create dirs_to_hash iterator: %m"),
9417           PROMPT_NONE, 0 },
9418
9419         /* Error rehash directory */
9420         { PR_3A_OPTIMIZE_DIR_ERR,
9421           N_("Failed to optimize directory %q (%d): %m"),
9422           PROMPT_NONE, 0 },
9423
9424         /* Rehashing dir header */
9425         { PR_3A_OPTIMIZE_DIR_HEADER,
9426           N_("Optimizing directories: "),
9427           PROMPT_NONE, PR_MSG_ONLY },
9428
9429         /* Rehashing directory %d */
9430         { PR_3A_OPTIMIZE_DIR,
9431           " %d",
9432           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9433
9434         /* Rehashing dir end */
9435         { PR_3A_OPTIMIZE_DIR_END,
9436           "\n",
9437           PROMPT_NONE, PR_PREEN_NOHDR },
9438
9439         /* Pass 4 errors */
9440
9441         /* Pass 4: Checking reference counts */
9442         { PR_4_PASS_HEADER,
9443           N_("Pass 4: Checking reference counts\n"),
9444           PROMPT_NONE, 0 },
9445
9446         /* Unattached zero-length inode */
9447         { PR_4_ZERO_LEN_INODE,
9448           N_("@u @z @i %i.  "),
9449           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9450
9451         /* Unattached inode */
9452         { PR_4_UNATTACHED_INODE,
9453           N_("@u @i %i\n"),
9454           PROMPT_CONNECT, 0 },
9455
9456         /* Inode ref count wrong */
9457         { PR_4_BAD_REF_COUNT,
9458           N_("@i %i ref count is %Il, @s %N.  "),
9459           PROMPT_FIX, PR_PREEN_OK },
9460
9461         { PR_4_INCONSISTENT_COUNT,
9462           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9463           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9464           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9465           "They @s the same!\n"),
9466           PROMPT_NONE, 0 },
9467
9468         /* Pass 5 errors */
9469
9470         /* Pass 5: Checking group summary information */
9471         { PR_5_PASS_HEADER,
9472           N_("Pass 5: Checking @g summary information\n"),
9473           PROMPT_NONE, 0 },
9474
9475         /* Padding at end of inode bitmap is not set. */
9476         { PR_5_INODE_BMAP_PADDING,
9477           N_("Padding at end of @i @B is not set. "),
9478           PROMPT_FIX, PR_PREEN_OK },
9479
9480         /* Padding at end of block bitmap is not set. */
9481         { PR_5_BLOCK_BMAP_PADDING,
9482           N_("Padding at end of @b @B is not set. "),
9483           PROMPT_FIX, PR_PREEN_OK },
9484
9485         /* Block bitmap differences header */
9486         { PR_5_BLOCK_BITMAP_HEADER,
9487           N_("@b @B differences: "),
9488           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9489
9490         /* Block not used, but marked in bitmap */
9491         { PR_5_BLOCK_UNUSED,
9492           " -%b",
9493           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9494
9495         /* Block used, but not marked used in bitmap */
9496         { PR_5_BLOCK_USED,
9497           " +%b",
9498           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9499
9500         /* Block bitmap differences end */
9501         { PR_5_BLOCK_BITMAP_END,
9502           "\n",
9503           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9504
9505         /* Inode bitmap differences header */
9506         { PR_5_INODE_BITMAP_HEADER,
9507           N_("@i @B differences: "),
9508           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9509
9510         /* Inode not used, but marked in bitmap */
9511         { PR_5_INODE_UNUSED,
9512           " -%i",
9513           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9514
9515         /* Inode used, but not marked used in bitmap */
9516         { PR_5_INODE_USED,
9517           " +%i",
9518           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9519
9520         /* Inode bitmap differences end */
9521         { PR_5_INODE_BITMAP_END,
9522           "\n",
9523           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9524
9525         /* Free inodes count for group wrong */
9526         { PR_5_FREE_INODE_COUNT_GROUP,
9527           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9528           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9529
9530         /* Directories count for group wrong */
9531         { PR_5_FREE_DIR_COUNT_GROUP,
9532           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9533           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9534
9535         /* Free inodes count wrong */
9536         { PR_5_FREE_INODE_COUNT,
9537           N_("Free @is count wrong (%i, counted=%j).\n"),
9538           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9539
9540         /* Free blocks count for group wrong */
9541         { PR_5_FREE_BLOCK_COUNT_GROUP,
9542           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9543           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9544
9545         /* Free blocks count wrong */
9546         { PR_5_FREE_BLOCK_COUNT,
9547           N_("Free @bs count wrong (%b, counted=%c).\n"),
9548           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9549
9550         /* Programming error: bitmap endpoints don't match */
9551         { PR_5_BMAP_ENDPOINTS,
9552           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9553           "match calculated @B endpoints (%i, %j)\n"),
9554           PROMPT_NONE, PR_FATAL },
9555
9556         /* Internal error: fudging end of bitmap */
9557         { PR_5_FUDGE_BITMAP_ERROR,
9558           N_("Internal error: fudging end of bitmap (%N)\n"),
9559           PROMPT_NONE, PR_FATAL },
9560
9561         /* Error copying in replacement inode bitmap */
9562         { PR_5_COPY_IBITMAP_ERROR,
9563           N_("Error copying in replacement @i @B: %m\n"),
9564           PROMPT_NONE, PR_FATAL },
9565
9566         /* Error copying in replacement block bitmap */
9567         { PR_5_COPY_BBITMAP_ERROR,
9568           N_("Error copying in replacement @b @B: %m\n"),
9569           PROMPT_NONE, PR_FATAL },
9570
9571         /* Block range not used, but marked in bitmap */
9572         { PR_5_BLOCK_RANGE_UNUSED,
9573           " -(%b--%c)",
9574           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9575
9576         /* Block range used, but not marked used in bitmap */
9577         { PR_5_BLOCK_RANGE_USED,
9578           " +(%b--%c)",
9579           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9580
9581         /* Inode range not used, but marked in bitmap */
9582         { PR_5_INODE_RANGE_UNUSED,
9583           " -(%i--%j)",
9584           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9585
9586         /* Inode range used, but not marked used in bitmap */
9587         { PR_5_INODE_RANGE_USED,
9588           " +(%i--%j)",
9589           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9590
9591         { 0 }
9592 };
9593
9594 /*
9595  * This is the latch flags register.  It allows several problems to be
9596  * "latched" together.  This means that the user has to answer but one
9597  * question for the set of problems, and all of the associated
9598  * problems will be either fixed or not fixed.
9599  */
9600 static struct latch_descr pr_latch_info[] = {
9601         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9602         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9603         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9604         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9605         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9606         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9607         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9608         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9609         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9610         { -1, 0, 0 },
9611 };
9612
9613 static const struct e2fsck_problem *find_problem(problem_t code)
9614 {
9615         int     i;
9616
9617         for (i=0; problem_table[i].e2p_code; i++) {
9618                 if (problem_table[i].e2p_code == code)
9619                         return &problem_table[i];
9620         }
9621         return 0;
9622 }
9623
9624 static struct latch_descr *find_latch(int code)
9625 {
9626         int     i;
9627
9628         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9629                 if (pr_latch_info[i].latch_code == code)
9630                         return &pr_latch_info[i];
9631         }
9632         return 0;
9633 }
9634
9635 int end_problem_latch(e2fsck_t ctx, int mask)
9636 {
9637         struct latch_descr *ldesc;
9638         struct problem_context pctx;
9639         int answer = -1;
9640
9641         ldesc = find_latch(mask);
9642         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9643                 clear_problem_context(&pctx);
9644                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9645         }
9646         ldesc->flags &= ~(PRL_VARIABLE);
9647         return answer;
9648 }
9649
9650 int set_latch_flags(int mask, int setflags, int clearflags)
9651 {
9652         struct latch_descr *ldesc;
9653
9654         ldesc = find_latch(mask);
9655         if (!ldesc)
9656                 return -1;
9657         ldesc->flags |= setflags;
9658         ldesc->flags &= ~clearflags;
9659         return 0;
9660 }
9661
9662 void clear_problem_context(struct problem_context *ctx)
9663 {
9664         memset(ctx, 0, sizeof(struct problem_context));
9665         ctx->blkcount = -1;
9666         ctx->group = -1;
9667 }
9668
9669 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9670 {
9671         ext2_filsys fs = ctx->fs;
9672         const struct e2fsck_problem *ptr;
9673         struct latch_descr *ldesc = NULL;
9674         const char *message;
9675         int             def_yn, answer, ans;
9676         int             print_answer = 0;
9677         int             suppress = 0;
9678
9679         ptr = find_problem(code);
9680         if (!ptr) {
9681                 printf(_("Unhandled error code (0x%x)!\n"), code);
9682                 return 0;
9683         }
9684         def_yn = 1;
9685         if ((ptr->flags & PR_NO_DEFAULT) ||
9686             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9687             (ctx->options & E2F_OPT_NO))
9688                 def_yn= 0;
9689
9690         /*
9691          * Do special latch processing.  This is where we ask the
9692          * latch question, if it exists
9693          */
9694         if (ptr->flags & PR_LATCH_MASK) {
9695                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9696                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9697                         ans = fix_problem(ctx, ldesc->question, pctx);
9698                         if (ans == 1)
9699                                 ldesc->flags |= PRL_YES;
9700                         if (ans == 0)
9701                                 ldesc->flags |= PRL_NO;
9702                         ldesc->flags |= PRL_LATCHED;
9703                 }
9704                 if (ldesc->flags & PRL_SUPPRESS)
9705                         suppress++;
9706         }
9707         if ((ptr->flags & PR_PREEN_NOMSG) &&
9708             (ctx->options & E2F_OPT_PREEN))
9709                 suppress++;
9710         if ((ptr->flags & PR_NO_NOMSG) &&
9711             (ctx->options & E2F_OPT_NO))
9712                 suppress++;
9713         if (!suppress) {
9714                 message = ptr->e2p_description;
9715                 if ((ctx->options & E2F_OPT_PREEN) &&
9716                     !(ptr->flags & PR_PREEN_NOHDR)) {
9717                         printf("%s: ", ctx->device_name ?
9718                                ctx->device_name : ctx->filesystem_name);
9719                 }
9720                 if (*message)
9721                         print_e2fsck_message(ctx, _(message), pctx, 1);
9722         }
9723         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9724                 preenhalt(ctx);
9725
9726         if (ptr->flags & PR_FATAL)
9727                 bb_error_msg_and_die(0);
9728
9729         if (ptr->prompt == PROMPT_NONE) {
9730                 if (ptr->flags & PR_NOCOLLATE)
9731                         answer = -1;
9732                 else
9733                         answer = def_yn;
9734         } else {
9735                 if (ctx->options & E2F_OPT_PREEN) {
9736                         answer = def_yn;
9737                         if (!(ptr->flags & PR_PREEN_NOMSG))
9738                                 print_answer = 1;
9739                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9740                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9741                         if (!suppress)
9742                                 print_answer = 1;
9743                         if (ldesc->flags & PRL_YES)
9744                                 answer = 1;
9745                         else
9746                                 answer = 0;
9747                 } else
9748                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9749                 if (!answer && !(ptr->flags & PR_NO_OK))
9750                         ext2fs_unmark_valid(fs);
9751
9752                 if (print_answer)
9753                         printf("%s.\n", answer ?
9754                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9755
9756         }
9757
9758         if ((ptr->prompt == PROMPT_ABORT) && answer)
9759                 bb_error_msg_and_die(0);
9760
9761         if (ptr->flags & PR_AFTER_CODE)
9762                 answer = fix_problem(ctx, ptr->second_code, pctx);
9763
9764         return answer;
9765 }
9766
9767 /*
9768  * linux/fs/recovery.c
9769  *
9770  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9771  */
9772
9773 /*
9774  * Maintain information about the progress of the recovery job, so that
9775  * the different passes can carry information between them.
9776  */
9777 struct recovery_info
9778 {
9779         tid_t           start_transaction;
9780         tid_t           end_transaction;
9781
9782         int             nr_replays;
9783         int             nr_revokes;
9784         int             nr_revoke_hits;
9785 };
9786
9787 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9788 static int do_one_pass(journal_t *journal,
9789                                 struct recovery_info *info, enum passtype pass);
9790 static int scan_revoke_records(journal_t *, struct buffer_head *,
9791                                 tid_t, struct recovery_info *);
9792
9793 /*
9794  * Read a block from the journal
9795  */
9796
9797 static int jread(struct buffer_head **bhp, journal_t *journal,
9798                  unsigned int offset)
9799 {
9800         int err;
9801         unsigned long blocknr;
9802         struct buffer_head *bh;
9803
9804         *bhp = NULL;
9805
9806         err = journal_bmap(journal, offset, &blocknr);
9807
9808         if (err) {
9809                 printf("JBD: bad block at offset %u\n", offset);
9810                 return err;
9811         }
9812
9813         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9814         if (!bh)
9815                 return -ENOMEM;
9816
9817         if (!buffer_uptodate(bh)) {
9818                 /* If this is a brand new buffer, start readahead.
9819                    Otherwise, we assume we are already reading it.  */
9820                 if (!buffer_req(bh))
9821                         do_readahead(journal, offset);
9822                 wait_on_buffer(bh);
9823         }
9824
9825         if (!buffer_uptodate(bh)) {
9826                 printf("JBD: Failed to read block at offset %u\n", offset);
9827                 brelse(bh);
9828                 return -EIO;
9829         }
9830
9831         *bhp = bh;
9832         return 0;
9833 }
9834
9835
9836 /*
9837  * Count the number of in-use tags in a journal descriptor block.
9838  */
9839
9840 static int count_tags(struct buffer_head *bh, int size)
9841 {
9842         char *                  tagp;
9843         journal_block_tag_t *   tag;
9844         int                     nr = 0;
9845
9846         tagp = &bh->b_data[sizeof(journal_header_t)];
9847
9848         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9849                 tag = (journal_block_tag_t *) tagp;
9850
9851                 nr++;
9852                 tagp += sizeof(journal_block_tag_t);
9853                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9854                         tagp += 16;
9855
9856                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9857                         break;
9858         }
9859
9860         return nr;
9861 }
9862
9863
9864 /* Make sure we wrap around the log correctly! */
9865 #define wrap(journal, var)                                            \
9866 do {                                                                \
9867         if (var >= (journal)->j_last)                                   \
9868                 var -= ((journal)->j_last - (journal)->j_first);        \
9869 } while (0)
9870
9871 /**
9872  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9873  * @journal: the journal to recover
9874  *
9875  * The primary function for recovering the log contents when mounting a
9876  * journaled device.
9877  *
9878  * Recovery is done in three passes.  In the first pass, we look for the
9879  * end of the log.  In the second, we assemble the list of revoke
9880  * blocks.  In the third and final pass, we replay any un-revoked blocks
9881  * in the log.
9882  */
9883 int journal_recover(journal_t *journal)
9884 {
9885         int                     err;
9886         journal_superblock_t *  sb;
9887
9888         struct recovery_info    info;
9889
9890         memset(&info, 0, sizeof(info));
9891         sb = journal->j_superblock;
9892
9893         /*
9894          * The journal superblock's s_start field (the current log head)
9895          * is always zero if, and only if, the journal was cleanly
9896          * unmounted.
9897          */
9898
9899         if (!sb->s_start) {
9900                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9901                 return 0;
9902         }
9903
9904         err = do_one_pass(journal, &info, PASS_SCAN);
9905         if (!err)
9906                 err = do_one_pass(journal, &info, PASS_REVOKE);
9907         if (!err)
9908                 err = do_one_pass(journal, &info, PASS_REPLAY);
9909
9910         /* Restart the log at the next transaction ID, thus invalidating
9911          * any existing commit records in the log. */
9912         journal->j_transaction_sequence = ++info.end_transaction;
9913
9914         journal_clear_revoke(journal);
9915         sync_blockdev(journal->j_fs_dev);
9916         return err;
9917 }
9918
9919 static int do_one_pass(journal_t *journal,
9920                         struct recovery_info *info, enum passtype pass)
9921 {
9922         unsigned int            first_commit_ID, next_commit_ID;
9923         unsigned long           next_log_block;
9924         int                     err, success = 0;
9925         journal_superblock_t *  sb;
9926         journal_header_t *      tmp;
9927         struct buffer_head *    bh;
9928         unsigned int            sequence;
9929         int                     blocktype;
9930
9931         /* Precompute the maximum metadata descriptors in a descriptor block */
9932         int                     MAX_BLOCKS_PER_DESC;
9933         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9934                                / sizeof(journal_block_tag_t));
9935
9936         /*
9937          * First thing is to establish what we expect to find in the log
9938          * (in terms of transaction IDs), and where (in terms of log
9939          * block offsets): query the superblock.
9940          */
9941
9942         sb = journal->j_superblock;
9943         next_commit_ID = ntohl(sb->s_sequence);
9944         next_log_block = ntohl(sb->s_start);
9945
9946         first_commit_ID = next_commit_ID;
9947         if (pass == PASS_SCAN)
9948                 info->start_transaction = first_commit_ID;
9949
9950         /*
9951          * Now we walk through the log, transaction by transaction,
9952          * making sure that each transaction has a commit block in the
9953          * expected place.  Each complete transaction gets replayed back
9954          * into the main filesystem.
9955          */
9956
9957         while (1) {
9958                 int                     flags;
9959                 char *                  tagp;
9960                 journal_block_tag_t *   tag;
9961                 struct buffer_head *    obh;
9962                 struct buffer_head *    nbh;
9963
9964                 /* If we already know where to stop the log traversal,
9965                  * check right now that we haven't gone past the end of
9966                  * the log. */
9967
9968                 if (pass != PASS_SCAN)
9969                         if (tid_geq(next_commit_ID, info->end_transaction))
9970                                 break;
9971
9972                 /* Skip over each chunk of the transaction looking
9973                  * either the next descriptor block or the final commit
9974                  * record. */
9975
9976                 err = jread(&bh, journal, next_log_block);
9977                 if (err)
9978                         goto failed;
9979
9980                 next_log_block++;
9981                 wrap(journal, next_log_block);
9982
9983                 /* What kind of buffer is it?
9984                  *
9985                  * If it is a descriptor block, check that it has the
9986                  * expected sequence number.  Otherwise, we're all done
9987                  * here. */
9988
9989                 tmp = (journal_header_t *)bh->b_data;
9990
9991                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9992                         brelse(bh);
9993                         break;
9994                 }
9995
9996                 blocktype = ntohl(tmp->h_blocktype);
9997                 sequence = ntohl(tmp->h_sequence);
9998
9999                 if (sequence != next_commit_ID) {
10000                         brelse(bh);
10001                         break;
10002                 }
10003
10004                 /* OK, we have a valid descriptor block which matches
10005                  * all of the sequence number checks.  What are we going
10006                  * to do with it?  That depends on the pass... */
10007
10008                 switch (blocktype) {
10009                 case JFS_DESCRIPTOR_BLOCK:
10010                         /* If it is a valid descriptor block, replay it
10011                          * in pass REPLAY; otherwise, just skip over the
10012                          * blocks it describes. */
10013                         if (pass != PASS_REPLAY) {
10014                                 next_log_block +=
10015                                         count_tags(bh, journal->j_blocksize);
10016                                 wrap(journal, next_log_block);
10017                                 brelse(bh);
10018                                 continue;
10019                         }
10020
10021                         /* A descriptor block: we can now write all of
10022                          * the data blocks.  Yay, useful work is finally
10023                          * getting done here! */
10024
10025                         tagp = &bh->b_data[sizeof(journal_header_t)];
10026                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10027                                <= journal->j_blocksize) {
10028                                 unsigned long io_block;
10029
10030                                 tag = (journal_block_tag_t *) tagp;
10031                                 flags = ntohl(tag->t_flags);
10032
10033                                 io_block = next_log_block++;
10034                                 wrap(journal, next_log_block);
10035                                 err = jread(&obh, journal, io_block);
10036                                 if (err) {
10037                                         /* Recover what we can, but
10038                                          * report failure at the end. */
10039                                         success = err;
10040                                         printf("JBD: IO error %d recovering "
10041                                                 "block %ld in log\n",
10042                                                 err, io_block);
10043                                 } else {
10044                                         unsigned long blocknr;
10045
10046                                         blocknr = ntohl(tag->t_blocknr);
10047
10048                                         /* If the block has been
10049                                          * revoked, then we're all done
10050                                          * here. */
10051                                         if (journal_test_revoke
10052                                             (journal, blocknr,
10053                                              next_commit_ID)) {
10054                                                 brelse(obh);
10055                                                 ++info->nr_revoke_hits;
10056                                                 goto skip_write;
10057                                         }
10058
10059                                         /* Find a buffer for the new
10060                                          * data being restored */
10061                                         nbh = getblk(journal->j_fs_dev,
10062                                                        blocknr,
10063                                                      journal->j_blocksize);
10064                                         if (nbh == NULL) {
10065                                                 printf("JBD: Out of memory "
10066                                                        "during recovery.\n");
10067                                                 err = -ENOMEM;
10068                                                 brelse(bh);
10069                                                 brelse(obh);
10070                                                 goto failed;
10071                                         }
10072
10073                                         lock_buffer(nbh);
10074                                         memcpy(nbh->b_data, obh->b_data,
10075                                                         journal->j_blocksize);
10076                                         if (flags & JFS_FLAG_ESCAPE) {
10077                                                 *((unsigned int *)bh->b_data) =
10078                                                         htonl(JFS_MAGIC_NUMBER);
10079                                         }
10080
10081                                         mark_buffer_uptodate(nbh, 1);
10082                                         mark_buffer_dirty(nbh);
10083                                         ++info->nr_replays;
10084                                         /* ll_rw_block(WRITE, 1, &nbh); */
10085                                         unlock_buffer(nbh);
10086                                         brelse(obh);
10087                                         brelse(nbh);
10088                                 }
10089
10090                         skip_write:
10091                                 tagp += sizeof(journal_block_tag_t);
10092                                 if (!(flags & JFS_FLAG_SAME_UUID))
10093                                         tagp += 16;
10094
10095                                 if (flags & JFS_FLAG_LAST_TAG)
10096                                         break;
10097                         }
10098
10099                         brelse(bh);
10100                         continue;
10101
10102                 case JFS_COMMIT_BLOCK:
10103                         /* Found an expected commit block: not much to
10104                          * do other than move on to the next sequence
10105                          * number. */
10106                         brelse(bh);
10107                         next_commit_ID++;
10108                         continue;
10109
10110                 case JFS_REVOKE_BLOCK:
10111                         /* If we aren't in the REVOKE pass, then we can
10112                          * just skip over this block. */
10113                         if (pass != PASS_REVOKE) {
10114                                 brelse(bh);
10115                                 continue;
10116                         }
10117
10118                         err = scan_revoke_records(journal, bh,
10119                                                   next_commit_ID, info);
10120                         brelse(bh);
10121                         if (err)
10122                                 goto failed;
10123                         continue;
10124
10125                 default:
10126                         goto done;
10127                 }
10128         }
10129
10130  done:
10131         /*
10132          * We broke out of the log scan loop: either we came to the
10133          * known end of the log or we found an unexpected block in the
10134          * log.  If the latter happened, then we know that the "current"
10135          * transaction marks the end of the valid log.
10136          */
10137
10138         if (pass == PASS_SCAN)
10139                 info->end_transaction = next_commit_ID;
10140         else {
10141                 /* It's really bad news if different passes end up at
10142                  * different places (but possible due to IO errors). */
10143                 if (info->end_transaction != next_commit_ID) {
10144                         printf("JBD: recovery pass %d ended at "
10145                                 "transaction %u, expected %u\n",
10146                                 pass, next_commit_ID, info->end_transaction);
10147                         if (!success)
10148                                 success = -EIO;
10149                 }
10150         }
10151
10152         return success;
10153
10154  failed:
10155         return err;
10156 }
10157
10158
10159 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10160
10161 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10162                                tid_t sequence, struct recovery_info *info)
10163 {
10164         journal_revoke_header_t *header;
10165         int offset, max;
10166
10167         header = (journal_revoke_header_t *) bh->b_data;
10168         offset = sizeof(journal_revoke_header_t);
10169         max = ntohl(header->r_count);
10170
10171         while (offset < max) {
10172                 unsigned long blocknr;
10173                 int err;
10174
10175                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10176                 offset += 4;
10177                 err = journal_set_revoke(journal, blocknr, sequence);
10178                 if (err)
10179                         return err;
10180                 ++info->nr_revokes;
10181         }
10182         return 0;
10183 }
10184
10185
10186 /*
10187  * rehash.c --- rebuild hash tree directories
10188  *
10189  * This algorithm is designed for simplicity of implementation and to
10190  * pack the directory as much as possible.  It however requires twice
10191  * as much memory as the size of the directory.  The maximum size
10192  * directory supported using a 4k blocksize is roughly a gigabyte, and
10193  * so there may very well be problems with machines that don't have
10194  * virtual memory, and obscenely large directories.
10195  *
10196  * An alternate algorithm which is much more disk intensive could be
10197  * written, and probably will need to be written in the future.  The
10198  * design goals of such an algorithm are: (a) use (roughly) constant
10199  * amounts of memory, no matter how large the directory, (b) the
10200  * directory must be safe at all times, even if e2fsck is interrupted
10201  * in the middle, (c) we must use minimal amounts of extra disk
10202  * blocks.  This pretty much requires an incremental approach, where
10203  * we are reading from one part of the directory, and inserting into
10204  * the front half.  So the algorithm will have to keep track of a
10205  * moving block boundary between the new tree and the old tree, and
10206  * files will need to be moved from the old directory and inserted
10207  * into the new tree.  If the new directory requires space which isn't
10208  * yet available, blocks from the beginning part of the old directory
10209  * may need to be moved to the end of the directory to make room for
10210  * the new tree:
10211  *
10212  *    --------------------------------------------------------
10213  *    |  new tree   |        | old tree                      |
10214  *    --------------------------------------------------------
10215  *                  ^ ptr    ^ptr
10216  *                tail new   head old
10217  *
10218  * This is going to be a pain in the tuckus to implement, and will
10219  * require a lot more disk accesses.  So I'm going to skip it for now;
10220  * it's only really going to be an issue for really, really big
10221  * filesystems (when we reach the level of tens of millions of files
10222  * in a single directory).  It will probably be easier to simply
10223  * require that e2fsck use VM first.
10224  */
10225
10226 struct fill_dir_struct {
10227         char *buf;
10228         struct ext2_inode *inode;
10229         int err;
10230         e2fsck_t ctx;
10231         struct hash_entry *harray;
10232         int max_array, num_array;
10233         int dir_size;
10234         int compress;
10235         ino_t parent;
10236 };
10237
10238 struct hash_entry {
10239         ext2_dirhash_t  hash;
10240         ext2_dirhash_t  minor_hash;
10241         struct ext2_dir_entry   *dir;
10242 };
10243
10244 struct out_dir {
10245         int             num;
10246         int             max;
10247         char            *buf;
10248         ext2_dirhash_t  *hashes;
10249 };
10250
10251 static int fill_dir_block(ext2_filsys fs,
10252                           blk_t *block_nr,
10253                           e2_blkcnt_t blockcnt,
10254                           blk_t ref_block FSCK_ATTR((unused)),
10255                           int ref_offset FSCK_ATTR((unused)),
10256                           void *priv_data)
10257 {
10258         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10259         struct hash_entry       *new_array, *ent;
10260         struct ext2_dir_entry   *dirent;
10261         char                    *dir;
10262         unsigned int            offset, dir_offset;
10263
10264         if (blockcnt < 0)
10265                 return 0;
10266
10267         offset = blockcnt * fs->blocksize;
10268         if (offset + fs->blocksize > fd->inode->i_size) {
10269                 fd->err = EXT2_ET_DIR_CORRUPTED;
10270                 return BLOCK_ABORT;
10271         }
10272         dir = (fd->buf+offset);
10273         if (HOLE_BLKADDR(*block_nr)) {
10274                 memset(dir, 0, fs->blocksize);
10275                 dirent = (struct ext2_dir_entry *) dir;
10276                 dirent->rec_len = fs->blocksize;
10277         } else {
10278                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10279                 if (fd->err)
10280                         return BLOCK_ABORT;
10281         }
10282         /* While the directory block is "hot", index it. */
10283         dir_offset = 0;
10284         while (dir_offset < fs->blocksize) {
10285                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10286                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10287                     (dirent->rec_len < 8) ||
10288                     ((dirent->rec_len % 4) != 0) ||
10289                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10290                         fd->err = EXT2_ET_DIR_CORRUPTED;
10291                         return BLOCK_ABORT;
10292                 }
10293                 dir_offset += dirent->rec_len;
10294                 if (dirent->inode == 0)
10295                         continue;
10296                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10297                     (dirent->name[0] == '.'))
10298                         continue;
10299                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10300                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10301                         fd->parent = dirent->inode;
10302                         continue;
10303                 }
10304                 if (fd->num_array >= fd->max_array) {
10305                         new_array = xrealloc(fd->harray,
10306                             sizeof(struct hash_entry) * (fd->max_array+500));
10307                         fd->harray = new_array;
10308                         fd->max_array += 500;
10309                 }
10310                 ent = fd->harray + fd->num_array++;
10311                 ent->dir = dirent;
10312                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10313                 if (fd->compress)
10314                         ent->hash = ent->minor_hash = 0;
10315                 else {
10316                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10317                                                  dirent->name,
10318                                                  dirent->name_len & 0xFF,
10319                                                  fs->super->s_hash_seed,
10320                                                  &ent->hash, &ent->minor_hash);
10321                         if (fd->err)
10322                                 return BLOCK_ABORT;
10323                 }
10324         }
10325
10326         return 0;
10327 }
10328
10329 /* Used for sorting the hash entry */
10330 static int name_cmp(const void *a, const void *b)
10331 {
10332         const struct hash_entry *he_a = (const struct hash_entry *) a;
10333         const struct hash_entry *he_b = (const struct hash_entry *) b;
10334         int     ret;
10335         int     min_len;
10336
10337         min_len = he_a->dir->name_len;
10338         if (min_len > he_b->dir->name_len)
10339                 min_len = he_b->dir->name_len;
10340
10341         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10342         if (ret == 0) {
10343                 if (he_a->dir->name_len > he_b->dir->name_len)
10344                         ret = 1;
10345                 else if (he_a->dir->name_len < he_b->dir->name_len)
10346                         ret = -1;
10347                 else
10348                         ret = he_b->dir->inode - he_a->dir->inode;
10349         }
10350         return ret;
10351 }
10352
10353 /* Used for sorting the hash entry */
10354 static int hash_cmp(const void *a, const void *b)
10355 {
10356         const struct hash_entry *he_a = (const struct hash_entry *) a;
10357         const struct hash_entry *he_b = (const struct hash_entry *) b;
10358         int     ret;
10359
10360         if (he_a->hash > he_b->hash)
10361                 ret = 1;
10362         else if (he_a->hash < he_b->hash)
10363                 ret = -1;
10364         else {
10365                 if (he_a->minor_hash > he_b->minor_hash)
10366                         ret = 1;
10367                 else if (he_a->minor_hash < he_b->minor_hash)
10368                         ret = -1;
10369                 else
10370                         ret = name_cmp(a, b);
10371         }
10372         return ret;
10373 }
10374
10375 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10376                                 int blocks)
10377 {
10378         void                    *new_mem;
10379
10380         if (outdir->max) {
10381                 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10382                 outdir->buf = new_mem;
10383                 new_mem = xrealloc(outdir->hashes,
10384                                   blocks * sizeof(ext2_dirhash_t));
10385                 outdir->hashes = new_mem;
10386         } else {
10387                 outdir->buf = xmalloc(blocks * fs->blocksize);
10388                 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10389                 outdir->num = 0;
10390         }
10391         outdir->max = blocks;
10392         return 0;
10393 }
10394
10395 static void free_out_dir(struct out_dir *outdir)
10396 {
10397         free(outdir->buf);
10398         free(outdir->hashes);
10399         outdir->max = 0;
10400         outdir->num =0;
10401 }
10402
10403 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10404                          char ** ret)
10405 {
10406         errcode_t       retval;
10407
10408         if (outdir->num >= outdir->max) {
10409                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10410                 if (retval)
10411                         return retval;
10412         }
10413         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10414         memset(*ret, 0, fs->blocksize);
10415         return 0;
10416 }
10417
10418 /*
10419  * This function is used to make a unique filename.  We do this by
10420  * appending ~0, and then incrementing the number.  However, we cannot
10421  * expand the length of the filename beyond the padding available in
10422  * the directory entry.
10423  */
10424 static void mutate_name(char *str, __u16 *len)
10425 {
10426         int     i;
10427         __u16   l = *len & 0xFF, h = *len & 0xff00;
10428
10429         /*
10430          * First check to see if it looks the name has been mutated
10431          * already
10432          */
10433         for (i = l-1; i > 0; i--) {
10434                 if (!isdigit(str[i]))
10435                         break;
10436         }
10437         if ((i == l-1) || (str[i] != '~')) {
10438                 if (((l-1) & 3) < 2)
10439                         l += 2;
10440                 else
10441                         l = (l+3) & ~3;
10442                 str[l-2] = '~';
10443                 str[l-1] = '0';
10444                 *len = l | h;
10445                 return;
10446         }
10447         for (i = l-1; i >= 0; i--) {
10448                 if (isdigit(str[i])) {
10449                         if (str[i] == '9')
10450                                 str[i] = '0';
10451                         else {
10452                                 str[i]++;
10453                                 return;
10454                         }
10455                         continue;
10456                 }
10457                 if (i == 1) {
10458                         if (str[0] == 'z')
10459                                 str[0] = 'A';
10460                         else if (str[0] == 'Z') {
10461                                 str[0] = '~';
10462                                 str[1] = '0';
10463                         } else
10464                                 str[0]++;
10465                 } else if (i > 0) {
10466                         str[i] = '1';
10467                         str[i-1] = '~';
10468                 } else {
10469                         if (str[0] == '~')
10470                                 str[0] = 'a';
10471                         else
10472                                 str[0]++;
10473                 }
10474                 break;
10475         }
10476 }
10477
10478 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10479                                     ext2_ino_t ino,
10480                                     struct fill_dir_struct *fd)
10481 {
10482         struct problem_context  pctx;
10483         struct hash_entry       *ent, *prev;
10484         int                     i, j;
10485         int                     fixed = 0;
10486         char                    new_name[256];
10487         __u16                   new_len;
10488
10489         clear_problem_context(&pctx);
10490         pctx.ino = ino;
10491
10492         for (i=1; i < fd->num_array; i++) {
10493                 ent = fd->harray + i;
10494                 prev = ent - 1;
10495                 if (!ent->dir->inode ||
10496                     ((ent->dir->name_len & 0xFF) !=
10497                      (prev->dir->name_len & 0xFF)) ||
10498                     (strncmp(ent->dir->name, prev->dir->name,
10499                              ent->dir->name_len & 0xFF)))
10500                         continue;
10501                 pctx.dirent = ent->dir;
10502                 if ((ent->dir->inode == prev->dir->inode) &&
10503                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10504                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10505                         ent->dir->inode = 0;
10506                         fixed++;
10507                         continue;
10508                 }
10509                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10510                 new_len = ent->dir->name_len;
10511                 mutate_name(new_name, &new_len);
10512                 for (j=0; j < fd->num_array; j++) {
10513                         if ((i==j) ||
10514                             ((ent->dir->name_len & 0xFF) !=
10515                              (fd->harray[j].dir->name_len & 0xFF)) ||
10516                             (strncmp(new_name, fd->harray[j].dir->name,
10517                                      new_len & 0xFF)))
10518                                 continue;
10519                         mutate_name(new_name, &new_len);
10520
10521                         j = -1;
10522                 }
10523                 new_name[new_len & 0xFF] = 0;
10524                 pctx.str = new_name;
10525                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10526                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10527                         ent->dir->name_len = new_len;
10528                         ext2fs_dirhash(fs->super->s_def_hash_version,
10529                                        ent->dir->name,
10530                                        ent->dir->name_len & 0xFF,
10531                                        fs->super->s_hash_seed,
10532                                        &ent->hash, &ent->minor_hash);
10533                         fixed++;
10534                 }
10535         }
10536         return fixed;
10537 }
10538
10539
10540 static errcode_t copy_dir_entries(ext2_filsys fs,
10541                                   struct fill_dir_struct *fd,
10542                                   struct out_dir *outdir)
10543 {
10544         errcode_t               retval;
10545         char                    *block_start;
10546         struct hash_entry       *ent;
10547         struct ext2_dir_entry   *dirent;
10548         int                     i, rec_len, left;
10549         ext2_dirhash_t          prev_hash;
10550         int                     offset;
10551
10552         outdir->max = 0;
10553         retval = alloc_size_dir(fs, outdir,
10554                                 (fd->dir_size / fs->blocksize) + 2);
10555         if (retval)
10556                 return retval;
10557         outdir->num = fd->compress ? 0 : 1;
10558         offset = 0;
10559         outdir->hashes[0] = 0;
10560         prev_hash = 1;
10561         if ((retval = get_next_block(fs, outdir, &block_start)))
10562                 return retval;
10563         dirent = (struct ext2_dir_entry *) block_start;
10564         left = fs->blocksize;
10565         for (i=0; i < fd->num_array; i++) {
10566                 ent = fd->harray + i;
10567                 if (ent->dir->inode == 0)
10568                         continue;
10569                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10570                 if (rec_len > left) {
10571                         if (left)
10572                                 dirent->rec_len += left;
10573                         if ((retval = get_next_block(fs, outdir,
10574                                                       &block_start)))
10575                                 return retval;
10576                         offset = 0;
10577                 }
10578                 left = fs->blocksize - offset;
10579                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10580                 if (offset == 0) {
10581                         if (ent->hash == prev_hash)
10582                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10583                         else
10584                                 outdir->hashes[outdir->num-1] = ent->hash;
10585                 }
10586                 dirent->inode = ent->dir->inode;
10587                 dirent->name_len = ent->dir->name_len;
10588                 dirent->rec_len = rec_len;
10589                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10590                 offset += rec_len;
10591                 left -= rec_len;
10592                 if (left < 12) {
10593                         dirent->rec_len += left;
10594                         offset += left;
10595                         left = 0;
10596                 }
10597                 prev_hash = ent->hash;
10598         }
10599         if (left)
10600                 dirent->rec_len += left;
10601
10602         return 0;
10603 }
10604
10605
10606 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10607                                     ext2_ino_t ino, ext2_ino_t parent)
10608 {
10609         struct ext2_dir_entry           *dir;
10610         struct ext2_dx_root_info        *root;
10611         struct ext2_dx_countlimit       *limits;
10612         int                             filetype = 0;
10613
10614         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10615                 filetype = EXT2_FT_DIR << 8;
10616
10617         memset(buf, 0, fs->blocksize);
10618         dir = (struct ext2_dir_entry *) buf;
10619         dir->inode = ino;
10620         dir->name[0] = '.';
10621         dir->name_len = 1 | filetype;
10622         dir->rec_len = 12;
10623         dir = (struct ext2_dir_entry *) (buf + 12);
10624         dir->inode = parent;
10625         dir->name[0] = '.';
10626         dir->name[1] = '.';
10627         dir->name_len = 2 | filetype;
10628         dir->rec_len = fs->blocksize - 12;
10629
10630         root = (struct ext2_dx_root_info *) (buf+24);
10631         root->reserved_zero = 0;
10632         root->hash_version = fs->super->s_def_hash_version;
10633         root->info_length = 8;
10634         root->indirect_levels = 0;
10635         root->unused_flags = 0;
10636
10637         limits = (struct ext2_dx_countlimit *) (buf+32);
10638         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10639         limits->count = 0;
10640
10641         return root;
10642 }
10643
10644
10645 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10646 {
10647         struct ext2_dir_entry           *dir;
10648         struct ext2_dx_countlimit       *limits;
10649
10650         memset(buf, 0, fs->blocksize);
10651         dir = (struct ext2_dir_entry *) buf;
10652         dir->inode = 0;
10653         dir->rec_len = fs->blocksize;
10654
10655         limits = (struct ext2_dx_countlimit *) (buf+8);
10656         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10657         limits->count = 0;
10658
10659         return (struct ext2_dx_entry *) limits;
10660 }
10661
10662 /*
10663  * This function takes the leaf nodes which have been written in
10664  * outdir, and populates the root node and any necessary interior nodes.
10665  */
10666 static errcode_t calculate_tree(ext2_filsys fs,
10667                                 struct out_dir *outdir,
10668                                 ext2_ino_t ino,
10669                                 ext2_ino_t parent)
10670 {
10671         struct ext2_dx_root_info        *root_info;
10672         struct ext2_dx_entry            *root, *dx_ent = NULL;
10673         struct ext2_dx_countlimit       *root_limit, *limit;
10674         errcode_t                       retval;
10675         char                            * block_start;
10676         int                             i, c1, c2, nblks;
10677         int                             limit_offset, root_offset;
10678
10679         root_info = set_root_node(fs, outdir->buf, ino, parent);
10680         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10681                 root_info->info_length;
10682         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10683         c1 = root_limit->limit;
10684         nblks = outdir->num;
10685
10686         /* Write out the pointer blocks */
10687         if (nblks-1 <= c1) {
10688                 /* Just write out the root block, and we're done */
10689                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10690                 for (i=1; i < nblks; i++) {
10691                         root->block = ext2fs_cpu_to_le32(i);
10692                         if (i != 1)
10693                                 root->hash =
10694                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10695                         root++;
10696                         c1--;
10697                 }
10698         } else {
10699                 c2 = 0;
10700                 limit = 0;
10701                 root_info->indirect_levels = 1;
10702                 for (i=1; i < nblks; i++) {
10703                         if (c1 == 0)
10704                                 return ENOSPC;
10705                         if (c2 == 0) {
10706                                 if (limit)
10707                                         limit->limit = limit->count =
10708                 ext2fs_cpu_to_le16(limit->limit);
10709                                 root = (struct ext2_dx_entry *)
10710                                         (outdir->buf + root_offset);
10711                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10712                                 if (i != 1)
10713                                         root->hash =
10714                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10715                                 if ((retval =  get_next_block(fs, outdir,
10716                                                               &block_start)))
10717                                         return retval;
10718                                 dx_ent = set_int_node(fs, block_start);
10719                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10720                                 c2 = limit->limit;
10721                                 root_offset += sizeof(struct ext2_dx_entry);
10722                                 c1--;
10723                         }
10724                         dx_ent->block = ext2fs_cpu_to_le32(i);
10725                         if (c2 != limit->limit)
10726                                 dx_ent->hash =
10727                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10728                         dx_ent++;
10729                         c2--;
10730                 }
10731                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10732                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10733         }
10734         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10735         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10736         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10737
10738         return 0;
10739 }
10740
10741 struct write_dir_struct {
10742         struct out_dir *outdir;
10743         errcode_t       err;
10744         e2fsck_t        ctx;
10745         int             cleared;
10746 };
10747
10748 /*
10749  * Helper function which writes out a directory block.
10750  */
10751 static int write_dir_block(ext2_filsys fs,
10752                            blk_t        *block_nr,
10753                            e2_blkcnt_t blockcnt,
10754                            blk_t ref_block FSCK_ATTR((unused)),
10755                            int ref_offset FSCK_ATTR((unused)),
10756                            void *priv_data)
10757 {
10758         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10759         blk_t   blk;
10760         char    *dir;
10761
10762         if (*block_nr == 0)
10763                 return 0;
10764         if (blockcnt >= wd->outdir->num) {
10765                 e2fsck_read_bitmaps(wd->ctx);
10766                 blk = *block_nr;
10767                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10768                 ext2fs_block_alloc_stats(fs, blk, -1);
10769                 *block_nr = 0;
10770                 wd->cleared++;
10771                 return BLOCK_CHANGED;
10772         }
10773         if (blockcnt < 0)
10774                 return 0;
10775
10776         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10777         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10778         if (wd->err)
10779                 return BLOCK_ABORT;
10780         return 0;
10781 }
10782
10783 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10784                                  struct out_dir *outdir,
10785                                  ext2_ino_t ino, int compress)
10786 {
10787         struct write_dir_struct wd;
10788         errcode_t       retval;
10789         struct ext2_inode       inode;
10790
10791         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10792         if (retval)
10793                 return retval;
10794
10795         wd.outdir = outdir;
10796         wd.err = 0;
10797         wd.ctx = ctx;
10798         wd.cleared = 0;
10799
10800         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10801                                        write_dir_block, &wd);
10802         if (retval)
10803                 return retval;
10804         if (wd.err)
10805                 return wd.err;
10806
10807         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10808         if (compress)
10809                 inode.i_flags &= ~EXT2_INDEX_FL;
10810         else
10811                 inode.i_flags |= EXT2_INDEX_FL;
10812         inode.i_size = outdir->num * fs->blocksize;
10813         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10814         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10815
10816         return 0;
10817 }
10818
10819 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10820 {
10821         ext2_filsys             fs = ctx->fs;
10822         errcode_t               retval;
10823         struct ext2_inode       inode;
10824         char                    *dir_buf = NULL;
10825         struct fill_dir_struct  fd;
10826         struct out_dir          outdir;
10827
10828         outdir.max = outdir.num = 0;
10829         outdir.buf = 0;
10830         outdir.hashes = 0;
10831         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10832
10833         retval = ENOMEM;
10834         fd.harray = 0;
10835         dir_buf = xmalloc(inode.i_size);
10836
10837         fd.max_array = inode.i_size / 32;
10838         fd.num_array = 0;
10839         fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10840
10841         fd.ctx = ctx;
10842         fd.buf = dir_buf;
10843         fd.inode = &inode;
10844         fd.err = 0;
10845         fd.dir_size = 0;
10846         fd.compress = 0;
10847         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10848             (inode.i_size / fs->blocksize) < 2)
10849                 fd.compress = 1;
10850         fd.parent = 0;
10851
10852         /* Read in the entire directory into memory */
10853         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10854                                        fill_dir_block, &fd);
10855         if (fd.err) {
10856                 retval = fd.err;
10857                 goto errout;
10858         }
10859
10860         /* Sort the list */
10861 resort:
10862         if (fd.compress)
10863                 qsort(fd.harray+2, fd.num_array-2,
10864                       sizeof(struct hash_entry), name_cmp);
10865         else
10866                 qsort(fd.harray, fd.num_array,
10867                       sizeof(struct hash_entry), hash_cmp);
10868
10869         /*
10870          * Look for duplicates
10871          */
10872         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10873                 goto resort;
10874
10875         if (ctx->options & E2F_OPT_NO) {
10876                 retval = 0;
10877                 goto errout;
10878         }
10879
10880         /*
10881          * Copy the directory entries.  In a htree directory these
10882          * will become the leaf nodes.
10883          */
10884         retval = copy_dir_entries(fs, &fd, &outdir);
10885         if (retval)
10886                 goto errout;
10887
10888         free(dir_buf); dir_buf = 0;
10889
10890         if (!fd.compress) {
10891                 /* Calculate the interior nodes */
10892                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10893                 if (retval)
10894                         goto errout;
10895         }
10896
10897         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10898
10899 errout:
10900         free(dir_buf);
10901         free(fd.harray);
10902
10903         free_out_dir(&outdir);
10904         return retval;
10905 }
10906
10907 void e2fsck_rehash_directories(e2fsck_t ctx)
10908 {
10909         struct problem_context  pctx;
10910         struct dir_info         *dir;
10911         ext2_u32_iterate        iter;
10912         ext2_ino_t              ino;
10913         errcode_t               retval;
10914         int                     i, cur, max, all_dirs, dir_index, first = 1;
10915
10916         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10917
10918         if (!ctx->dirs_to_hash && !all_dirs)
10919                 return;
10920
10921         e2fsck_get_lost_and_found(ctx, 0);
10922
10923         clear_problem_context(&pctx);
10924
10925         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10926         cur = 0;
10927         if (all_dirs) {
10928                 i = 0;
10929                 max = e2fsck_get_num_dirinfo(ctx);
10930         } else {
10931                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10932                                                        &iter);
10933                 if (retval) {
10934                         pctx.errcode = retval;
10935                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10936                         return;
10937                 }
10938                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10939         }
10940         while (1) {
10941                 if (all_dirs) {
10942                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10943                                 break;
10944                         ino = dir->ino;
10945                 } else {
10946                         if (!ext2fs_u32_list_iterate(iter, &ino))
10947                                 break;
10948                 }
10949                 if (ino == ctx->lost_and_found)
10950                         continue;
10951                 pctx.dir = ino;
10952                 if (first) {
10953                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10954                         first = 0;
10955                 }
10956                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10957                 if (pctx.errcode) {
10958                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10959                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10960                 }
10961                 if (ctx->progress && !ctx->progress_fd)
10962                         e2fsck_simple_progress(ctx, "Rebuilding directory",
10963                                100.0 * (float) (++cur) / (float) max, ino);
10964         }
10965         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10966         if (!all_dirs)
10967                 ext2fs_u32_list_iterate_end(iter);
10968
10969         ext2fs_u32_list_free(ctx->dirs_to_hash);
10970         ctx->dirs_to_hash = 0;
10971 }
10972
10973 /*
10974  * linux/fs/revoke.c
10975  *
10976  * Journal revoke routines for the generic filesystem journaling code;
10977  * part of the ext2fs journaling system.
10978  *
10979  * Revoke is the mechanism used to prevent old log records for deleted
10980  * metadata from being replayed on top of newer data using the same
10981  * blocks.  The revoke mechanism is used in two separate places:
10982  *
10983  * + Commit: during commit we write the entire list of the current
10984  *   transaction's revoked blocks to the journal
10985  *
10986  * + Recovery: during recovery we record the transaction ID of all
10987  *   revoked blocks.  If there are multiple revoke records in the log
10988  *   for a single block, only the last one counts, and if there is a log
10989  *   entry for a block beyond the last revoke, then that log entry still
10990  *   gets replayed.
10991  *
10992  * We can get interactions between revokes and new log data within a
10993  * single transaction:
10994  *
10995  * Block is revoked and then journaled:
10996  *   The desired end result is the journaling of the new block, so we
10997  *   cancel the revoke before the transaction commits.
10998  *
10999  * Block is journaled and then revoked:
11000  *   The revoke must take precedence over the write of the block, so we
11001  *   need either to cancel the journal entry or to write the revoke
11002  *   later in the log than the log block.  In this case, we choose the
11003  *   latter: journaling a block cancels any revoke record for that block
11004  *   in the current transaction, so any revoke for that block in the
11005  *   transaction must have happened after the block was journaled and so
11006  *   the revoke must take precedence.
11007  *
11008  * Block is revoked and then written as data:
11009  *   The data write is allowed to succeed, but the revoke is _not_
11010  *   cancelled.  We still need to prevent old log records from
11011  *   overwriting the new data.  We don't even need to clear the revoke
11012  *   bit here.
11013  *
11014  * Revoke information on buffers is a tri-state value:
11015  *
11016  * RevokeValid clear:   no cached revoke status, need to look it up
11017  * RevokeValid set, Revoked clear:
11018  *                      buffer has not been revoked, and cancel_revoke
11019  *                      need do nothing.
11020  * RevokeValid set, Revoked set:
11021  *                      buffer has been revoked.
11022  */
11023
11024 static kmem_cache_t *revoke_record_cache;
11025 static kmem_cache_t *revoke_table_cache;
11026
11027 /* Each revoke record represents one single revoked block.  During
11028    journal replay, this involves recording the transaction ID of the
11029    last transaction to revoke this block. */
11030
11031 struct jbd_revoke_record_s
11032 {
11033         struct list_head  hash;
11034         tid_t             sequence;     /* Used for recovery only */
11035         unsigned long     blocknr;
11036 };
11037
11038
11039 /* The revoke table is just a simple hash table of revoke records. */
11040 struct jbd_revoke_table_s
11041 {
11042         /* It is conceivable that we might want a larger hash table
11043          * for recovery.  Must be a power of two. */
11044         int               hash_size;
11045         int               hash_shift;
11046         struct list_head *hash_table;
11047 };
11048
11049
11050 /* Utility functions to maintain the revoke table */
11051
11052 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11053 static int hash(journal_t *journal, unsigned long block)
11054 {
11055         struct jbd_revoke_table_s *table = journal->j_revoke;
11056         int hash_shift = table->hash_shift;
11057
11058         return ((block << (hash_shift - 6)) ^
11059                 (block >> 13) ^
11060                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11061 }
11062
11063 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11064                               tid_t seq)
11065 {
11066         struct list_head *hash_list;
11067         struct jbd_revoke_record_s *record;
11068
11069         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11070         if (!record)
11071                 goto oom;
11072
11073         record->sequence = seq;
11074         record->blocknr = blocknr;
11075         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11076         list_add(&record->hash, hash_list);
11077         return 0;
11078
11079 oom:
11080         return -ENOMEM;
11081 }
11082
11083 /* Find a revoke record in the journal's hash table. */
11084
11085 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11086                                                       unsigned long blocknr)
11087 {
11088         struct list_head *hash_list;
11089         struct jbd_revoke_record_s *record;
11090
11091         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11092
11093         record = (struct jbd_revoke_record_s *) hash_list->next;
11094         while (&(record->hash) != hash_list) {
11095                 if (record->blocknr == blocknr)
11096                         return record;
11097                 record = (struct jbd_revoke_record_s *) record->hash.next;
11098         }
11099         return NULL;
11100 }
11101
11102 int journal_init_revoke_caches(void)
11103 {
11104         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11105         if (revoke_record_cache == 0)
11106                 return -ENOMEM;
11107
11108         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11109         if (revoke_table_cache == 0) {
11110                 do_cache_destroy(revoke_record_cache);
11111                 revoke_record_cache = NULL;
11112                 return -ENOMEM;
11113         }
11114         return 0;
11115 }
11116
11117 void journal_destroy_revoke_caches(void)
11118 {
11119         do_cache_destroy(revoke_record_cache);
11120         revoke_record_cache = 0;
11121         do_cache_destroy(revoke_table_cache);
11122         revoke_table_cache = 0;
11123 }
11124
11125 /* Initialise the revoke table for a given journal to a given size. */
11126
11127 int journal_init_revoke(journal_t *journal, int hash_size)
11128 {
11129         int shift, tmp;
11130
11131         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11132         if (!journal->j_revoke)
11133                 return -ENOMEM;
11134
11135         /* Check that the hash_size is a power of two */
11136         journal->j_revoke->hash_size = hash_size;
11137
11138         shift = 0;
11139         tmp = hash_size;
11140         while ((tmp >>= 1UL) != 0UL)
11141                 shift++;
11142         journal->j_revoke->hash_shift = shift;
11143
11144         journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11145
11146         for (tmp = 0; tmp < hash_size; tmp++)
11147                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11148
11149         return 0;
11150 }
11151
11152 /* Destoy a journal's revoke table.  The table must already be empty! */
11153
11154 void journal_destroy_revoke(journal_t *journal)
11155 {
11156         struct jbd_revoke_table_s *table;
11157         struct list_head *hash_list;
11158         int i;
11159
11160         table = journal->j_revoke;
11161         if (!table)
11162                 return;
11163
11164         for (i=0; i<table->hash_size; i++) {
11165                 hash_list = &table->hash_table[i];
11166         }
11167
11168         free(table->hash_table);
11169         free(table);
11170         journal->j_revoke = NULL;
11171 }
11172
11173 /*
11174  * Revoke support for recovery.
11175  *
11176  * Recovery needs to be able to:
11177  *
11178  *  record all revoke records, including the tid of the latest instance
11179  *  of each revoke in the journal
11180  *
11181  *  check whether a given block in a given transaction should be replayed
11182  *  (ie. has not been revoked by a revoke record in that or a subsequent
11183  *  transaction)
11184  *
11185  *  empty the revoke table after recovery.
11186  */
11187
11188 /*
11189  * First, setting revoke records.  We create a new revoke record for
11190  * every block ever revoked in the log as we scan it for recovery, and
11191  * we update the existing records if we find multiple revokes for a
11192  * single block.
11193  */
11194
11195 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11196                        tid_t sequence)
11197 {
11198         struct jbd_revoke_record_s *record;
11199
11200         record = find_revoke_record(journal, blocknr);
11201         if (record) {
11202                 /* If we have multiple occurences, only record the
11203                  * latest sequence number in the hashed record */
11204                 if (tid_gt(sequence, record->sequence))
11205                         record->sequence = sequence;
11206                 return 0;
11207         }
11208         return insert_revoke_hash(journal, blocknr, sequence);
11209 }
11210
11211 /*
11212  * Test revoke records.  For a given block referenced in the log, has
11213  * that block been revoked?  A revoke record with a given transaction
11214  * sequence number revokes all blocks in that transaction and earlier
11215  * ones, but later transactions still need replayed.
11216  */
11217
11218 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11219                         tid_t sequence)
11220 {
11221         struct jbd_revoke_record_s *record;
11222
11223         record = find_revoke_record(journal, blocknr);
11224         if (!record)
11225                 return 0;
11226         if (tid_gt(sequence, record->sequence))
11227                 return 0;
11228         return 1;
11229 }
11230
11231 /*
11232  * Finally, once recovery is over, we need to clear the revoke table so
11233  * that it can be reused by the running filesystem.
11234  */
11235
11236 void journal_clear_revoke(journal_t *journal)
11237 {
11238         int i;
11239         struct list_head *hash_list;
11240         struct jbd_revoke_record_s *record;
11241         struct jbd_revoke_table_s *revoke_var;
11242
11243         revoke_var = journal->j_revoke;
11244
11245         for (i = 0; i < revoke_var->hash_size; i++) {
11246                 hash_list = &revoke_var->hash_table[i];
11247                 while (!list_empty(hash_list)) {
11248                         record = (struct jbd_revoke_record_s*) hash_list->next;
11249                         list_del(&record->hash);
11250                         free(record);
11251                 }
11252         }
11253 }
11254
11255 /*
11256  * e2fsck.c - superblock checks
11257  */
11258
11259 #define MIN_CHECK 1
11260 #define MAX_CHECK 2
11261
11262 static void check_super_value(e2fsck_t ctx, const char *descr,
11263                               unsigned long value, int flags,
11264                               unsigned long min_val, unsigned long max_val)
11265 {
11266         struct          problem_context pctx;
11267
11268         if (((flags & MIN_CHECK) && (value < min_val)) ||
11269             ((flags & MAX_CHECK) && (value > max_val))) {
11270                 clear_problem_context(&pctx);
11271                 pctx.num = value;
11272                 pctx.str = descr;
11273                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11274                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11275         }
11276 }
11277
11278 /*
11279  * This routine may get stubbed out in special compilations of the
11280  * e2fsck code..
11281  */
11282 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11283 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11284 {
11285         return (ext2fs_get_device_size(ctx->filesystem_name,
11286                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11287                                        &ctx->num_blocks));
11288 }
11289 #endif
11290
11291 /*
11292  * helper function to release an inode
11293  */
11294 struct process_block_struct {
11295         e2fsck_t        ctx;
11296         char            *buf;
11297         struct problem_context *pctx;
11298         int             truncating;
11299         int             truncate_offset;
11300         e2_blkcnt_t     truncate_block;
11301         int             truncated_blocks;
11302         int             abort;
11303         errcode_t       errcode;
11304 };
11305
11306 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11307                                e2_blkcnt_t blockcnt,
11308                                blk_t    ref_blk FSCK_ATTR((unused)),
11309                                int      ref_offset FSCK_ATTR((unused)),
11310                                void *priv_data)
11311 {
11312         struct process_block_struct *pb;
11313         e2fsck_t                ctx;
11314         struct problem_context  *pctx;
11315         blk_t                   blk = *block_nr;
11316         int                     retval = 0;
11317
11318         pb = (struct process_block_struct *) priv_data;
11319         ctx = pb->ctx;
11320         pctx = pb->pctx;
11321
11322         pctx->blk = blk;
11323         pctx->blkcount = blockcnt;
11324
11325         if (HOLE_BLKADDR(blk))
11326                 return 0;
11327
11328         if ((blk < fs->super->s_first_data_block) ||
11329             (blk >= fs->super->s_blocks_count)) {
11330                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11331         return_abort:
11332                 pb->abort = 1;
11333                 return BLOCK_ABORT;
11334         }
11335
11336         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11337                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11338                 goto return_abort;
11339         }
11340
11341         /*
11342          * If we are deleting an orphan, then we leave the fields alone.
11343          * If we are truncating an orphan, then update the inode fields
11344          * and clean up any partial block data.
11345          */
11346         if (pb->truncating) {
11347                 /*
11348                  * We only remove indirect blocks if they are
11349                  * completely empty.
11350                  */
11351                 if (blockcnt < 0) {
11352                         int     i, limit;
11353                         blk_t   *bp;
11354
11355                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11356                                                         pb->buf);
11357                         if (pb->errcode)
11358                                 goto return_abort;
11359
11360                         limit = fs->blocksize >> 2;
11361                         for (i = 0, bp = (blk_t *) pb->buf;
11362                              i < limit;  i++, bp++)
11363                                 if (*bp)
11364                                         return 0;
11365                 }
11366                 /*
11367                  * We don't remove direct blocks until we've reached
11368                  * the truncation block.
11369                  */
11370                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11371                         return 0;
11372                 /*
11373                  * If part of the last block needs truncating, we do
11374                  * it here.
11375                  */
11376                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11377                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11378                                                         pb->buf);
11379                         if (pb->errcode)
11380                                 goto return_abort;
11381                         memset(pb->buf + pb->truncate_offset, 0,
11382                                fs->blocksize - pb->truncate_offset);
11383                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11384                                                          pb->buf);
11385                         if (pb->errcode)
11386                                 goto return_abort;
11387                 }
11388                 pb->truncated_blocks++;
11389                 *block_nr = 0;
11390                 retval |= BLOCK_CHANGED;
11391         }
11392
11393         ext2fs_block_alloc_stats(fs, blk, -1);
11394         return retval;
11395 }
11396
11397 /*
11398  * This function releases an inode.  Returns 1 if an inconsistency was
11399  * found.  If the inode has a link count, then it is being truncated and
11400  * not deleted.
11401  */
11402 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11403                                 struct ext2_inode *inode, char *block_buf,
11404                                 struct problem_context *pctx)
11405 {
11406         struct process_block_struct     pb;
11407         ext2_filsys                     fs = ctx->fs;
11408         errcode_t                       retval;
11409         __u32                           count;
11410
11411         if (!ext2fs_inode_has_valid_blocks(inode))
11412                 return 0;
11413
11414         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11415         pb.ctx = ctx;
11416         pb.abort = 0;
11417         pb.errcode = 0;
11418         pb.pctx = pctx;
11419         if (inode->i_links_count) {
11420                 pb.truncating = 1;
11421                 pb.truncate_block = (e2_blkcnt_t)
11422                         ((((long long)inode->i_size_high << 32) +
11423                           inode->i_size + fs->blocksize - 1) /
11424                          fs->blocksize);
11425                 pb.truncate_offset = inode->i_size % fs->blocksize;
11426         } else {
11427                 pb.truncating = 0;
11428                 pb.truncate_block = 0;
11429                 pb.truncate_offset = 0;
11430         }
11431         pb.truncated_blocks = 0;
11432         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11433                                       block_buf, release_inode_block, &pb);
11434         if (retval) {
11435                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11436                         ino);
11437                 return 1;
11438         }
11439         if (pb.abort)
11440                 return 1;
11441
11442         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11443         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11444
11445         if (pb.truncated_blocks)
11446                 inode->i_blocks -= pb.truncated_blocks *
11447                         (fs->blocksize / 512);
11448
11449         if (inode->i_file_acl) {
11450                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11451                                                    block_buf, -1, &count);
11452                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11453                         retval = 0;
11454                         count = 1;
11455                 }
11456                 if (retval) {
11457                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11458                                 ino);
11459                         return 1;
11460                 }
11461                 if (count == 0)
11462                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11463                 inode->i_file_acl = 0;
11464         }
11465         return 0;
11466 }
11467
11468 /*
11469  * This function releases all of the orphan inodes.  It returns 1 if
11470  * it hit some error, and 0 on success.
11471  */
11472 static int release_orphan_inodes(e2fsck_t ctx)
11473 {
11474         ext2_filsys fs = ctx->fs;
11475         ext2_ino_t      ino, next_ino;
11476         struct ext2_inode inode;
11477         struct problem_context pctx;
11478         char *block_buf;
11479
11480         if ((ino = fs->super->s_last_orphan) == 0)
11481                 return 0;
11482
11483         /*
11484          * Win or lose, we won't be using the head of the orphan inode
11485          * list again.
11486          */
11487         fs->super->s_last_orphan = 0;
11488         ext2fs_mark_super_dirty(fs);
11489
11490         /*
11491          * If the filesystem contains errors, don't run the orphan
11492          * list, since the orphan list can't be trusted; and we're
11493          * going to be running a full e2fsck run anyway...
11494          */
11495         if (fs->super->s_state & EXT2_ERROR_FS)
11496                 return 0;
11497
11498         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11499             (ino > fs->super->s_inodes_count)) {
11500                 clear_problem_context(&pctx);
11501                 pctx.ino = ino;
11502                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11503                 return 1;
11504         }
11505
11506         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11507                                                     "block iterate buffer");
11508         e2fsck_read_bitmaps(ctx);
11509
11510         while (ino) {
11511                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11512                 clear_problem_context(&pctx);
11513                 pctx.ino = ino;
11514                 pctx.inode = &inode;
11515                 pctx.str = inode.i_links_count ? _("Truncating") :
11516                         _("Clearing");
11517
11518                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11519
11520                 next_ino = inode.i_dtime;
11521                 if (next_ino &&
11522                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11523                      (next_ino > fs->super->s_inodes_count))) {
11524                         pctx.ino = next_ino;
11525                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11526                         goto return_abort;
11527                 }
11528
11529                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11530                         goto return_abort;
11531
11532                 if (!inode.i_links_count) {
11533                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11534                                                   LINUX_S_ISDIR(inode.i_mode));
11535                         inode.i_dtime = time(NULL);
11536                 } else {
11537                         inode.i_dtime = 0;
11538                 }
11539                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11540                 ino = next_ino;
11541         }
11542         ext2fs_free_mem(&block_buf);
11543         return 0;
11544 return_abort:
11545         ext2fs_free_mem(&block_buf);
11546         return 1;
11547 }
11548
11549 /*
11550  * Check the resize inode to make sure it is sane.  We check both for
11551  * the case where on-line resizing is not enabled (in which case the
11552  * resize inode should be cleared) as well as the case where on-line
11553  * resizing is enabled.
11554  */
11555 static void check_resize_inode(e2fsck_t ctx)
11556 {
11557         ext2_filsys fs = ctx->fs;
11558         struct ext2_inode inode;
11559         struct problem_context  pctx;
11560         int             i, j, gdt_off, ind_off;
11561         blk_t           blk, pblk, expect;
11562         __u32           *dind_buf = NULL, *ind_buf;
11563         errcode_t       retval;
11564
11565         clear_problem_context(&pctx);
11566
11567         /*
11568          * If the resize inode feature isn't set, then
11569          * s_reserved_gdt_blocks must be zero.
11570          */
11571         if (!(fs->super->s_feature_compat &
11572               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11573                 if (fs->super->s_reserved_gdt_blocks) {
11574                         pctx.num = fs->super->s_reserved_gdt_blocks;
11575                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11576                                         &pctx)) {
11577                                 fs->super->s_reserved_gdt_blocks = 0;
11578                                 ext2fs_mark_super_dirty(fs);
11579                         }
11580                 }
11581         }
11582
11583         /* Read the resize inode */
11584         pctx.ino = EXT2_RESIZE_INO;
11585         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11586         if (retval) {
11587                 if (fs->super->s_feature_compat &
11588                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11589                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11590                 return;
11591         }
11592
11593         /*
11594          * If the resize inode feature isn't set, check to make sure
11595          * the resize inode is cleared; then we're done.
11596          */
11597         if (!(fs->super->s_feature_compat &
11598               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11599                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11600                         if (inode.i_block[i])
11601                                 break;
11602                 }
11603                 if ((i < EXT2_N_BLOCKS) &&
11604                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11605                         memset(&inode, 0, sizeof(inode));
11606                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11607                                            "clear_resize");
11608                 }
11609                 return;
11610         }
11611
11612         /*
11613          * The resize inode feature is enabled; check to make sure the
11614          * only block in use is the double indirect block
11615          */
11616         blk = inode.i_block[EXT2_DIND_BLOCK];
11617         for (i=0; i < EXT2_N_BLOCKS; i++) {
11618                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11619                         break;
11620         }
11621         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11622             !(inode.i_mode & LINUX_S_IFREG) ||
11623             (blk < fs->super->s_first_data_block ||
11624              blk >= fs->super->s_blocks_count)) {
11625         resize_inode_invalid:
11626                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11627                         memset(&inode, 0, sizeof(inode));
11628                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11629                                            "clear_resize");
11630                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11631                 }
11632                 if (!(ctx->options & E2F_OPT_READONLY)) {
11633                         fs->super->s_state &= ~EXT2_VALID_FS;
11634                         ext2fs_mark_super_dirty(fs);
11635                 }
11636                 goto cleanup;
11637         }
11638         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11639                                                     "resize dind buffer");
11640         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11641
11642         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11643         if (retval)
11644                 goto resize_inode_invalid;
11645
11646         gdt_off = fs->desc_blocks;
11647         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11648         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11649              i++, gdt_off++, pblk++) {
11650                 gdt_off %= fs->blocksize/4;
11651                 if (dind_buf[gdt_off] != pblk)
11652                         goto resize_inode_invalid;
11653                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11654                 if (retval)
11655                         goto resize_inode_invalid;
11656                 ind_off = 0;
11657                 for (j = 1; j < fs->group_desc_count; j++) {
11658                         if (!ext2fs_bg_has_super(fs, j))
11659                                 continue;
11660                         expect = pblk + (j * fs->super->s_blocks_per_group);
11661                         if (ind_buf[ind_off] != expect)
11662                                 goto resize_inode_invalid;
11663                         ind_off++;
11664                 }
11665         }
11666
11667 cleanup:
11668         ext2fs_free_mem(&dind_buf);
11669
11670  }
11671
11672 static void check_super_block(e2fsck_t ctx)
11673 {
11674         ext2_filsys fs = ctx->fs;
11675         blk_t   first_block, last_block;
11676         struct ext2_super_block *sb = fs->super;
11677         struct ext2_group_desc *gd;
11678         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11679         blk_t   bpg_max;
11680         int     inodes_per_block;
11681         int     ipg_max;
11682         int     inode_size;
11683         dgrp_t  i;
11684         blk_t   should_be;
11685         struct problem_context  pctx;
11686         __u32   free_blocks = 0, free_inodes = 0;
11687
11688         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11689         ipg_max = inodes_per_block * (blocks_per_group - 4);
11690         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11691                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11692         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11693         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11694                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11695
11696         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11697                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11698         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11699                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11700         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11701                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11702
11703         clear_problem_context(&pctx);
11704
11705         /*
11706          * Verify the super block constants...
11707          */
11708         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11709                           MIN_CHECK, 1, 0);
11710         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11711                           MIN_CHECK, 1, 0);
11712         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11713                           MAX_CHECK, 0, sb->s_blocks_count);
11714         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11715                           MIN_CHECK | MAX_CHECK, 0,
11716                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11717         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11718                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11719         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11720                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11721                           bpg_max);
11722         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11723                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11724         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11725                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11726         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11727                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11728         check_super_value(ctx, "reserved_gdt_blocks",
11729                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11730                           fs->blocksize/4);
11731         inode_size = EXT2_INODE_SIZE(sb);
11732         check_super_value(ctx, "inode_size",
11733                           inode_size, MIN_CHECK | MAX_CHECK,
11734                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11735         if (inode_size & (inode_size - 1)) {
11736                 pctx.num = inode_size;
11737                 pctx.str = "inode_size";
11738                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11739                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11740                 return;
11741         }
11742
11743         if (!ctx->num_blocks) {
11744                 pctx.errcode = e2fsck_get_device_size(ctx);
11745                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11746                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11747                         ctx->flags |= E2F_FLAG_ABORT;
11748                         return;
11749                 }
11750                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11751                     (ctx->num_blocks < sb->s_blocks_count)) {
11752                         pctx.blk = sb->s_blocks_count;
11753                         pctx.blk2 = ctx->num_blocks;
11754                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11755                                 ctx->flags |= E2F_FLAG_ABORT;
11756                                 return;
11757                         }
11758                 }
11759         }
11760
11761         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11762                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11763                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11764                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11765                 ctx->flags |= E2F_FLAG_ABORT;
11766                 return;
11767         }
11768
11769         should_be = sb->s_frags_per_group >>
11770                 (sb->s_log_block_size - sb->s_log_frag_size);
11771         if (sb->s_blocks_per_group != should_be) {
11772                 pctx.blk = sb->s_blocks_per_group;
11773                 pctx.blk2 = should_be;
11774                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11775                 ctx->flags |= E2F_FLAG_ABORT;
11776                 return;
11777         }
11778
11779         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11780         if (sb->s_first_data_block != should_be) {
11781                 pctx.blk = sb->s_first_data_block;
11782                 pctx.blk2 = should_be;
11783                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11784                 ctx->flags |= E2F_FLAG_ABORT;
11785                 return;
11786         }
11787
11788         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11789         if (sb->s_inodes_count != should_be) {
11790                 pctx.ino = sb->s_inodes_count;
11791                 pctx.ino2 = should_be;
11792                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11793                         sb->s_inodes_count = should_be;
11794                         ext2fs_mark_super_dirty(fs);
11795                 }
11796         }
11797
11798         /*
11799          * Verify the group descriptors....
11800          */
11801         first_block =  sb->s_first_data_block;
11802         last_block = first_block + blocks_per_group;
11803
11804         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11805                 pctx.group = i;
11806
11807                 if (i == fs->group_desc_count - 1)
11808                         last_block = sb->s_blocks_count;
11809                 if ((gd->bg_block_bitmap < first_block) ||
11810                     (gd->bg_block_bitmap >= last_block)) {
11811                         pctx.blk = gd->bg_block_bitmap;
11812                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11813                                 gd->bg_block_bitmap = 0;
11814                 }
11815                 if (gd->bg_block_bitmap == 0) {
11816                         ctx->invalid_block_bitmap_flag[i]++;
11817                         ctx->invalid_bitmaps++;
11818                 }
11819                 if ((gd->bg_inode_bitmap < first_block) ||
11820                     (gd->bg_inode_bitmap >= last_block)) {
11821                         pctx.blk = gd->bg_inode_bitmap;
11822                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11823                                 gd->bg_inode_bitmap = 0;
11824                 }
11825                 if (gd->bg_inode_bitmap == 0) {
11826                         ctx->invalid_inode_bitmap_flag[i]++;
11827                         ctx->invalid_bitmaps++;
11828                 }
11829                 if ((gd->bg_inode_table < first_block) ||
11830                     ((gd->bg_inode_table +
11831                       fs->inode_blocks_per_group - 1) >= last_block)) {
11832                         pctx.blk = gd->bg_inode_table;
11833                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11834                                 gd->bg_inode_table = 0;
11835                 }
11836                 if (gd->bg_inode_table == 0) {
11837                         ctx->invalid_inode_table_flag[i]++;
11838                         ctx->invalid_bitmaps++;
11839                 }
11840                 free_blocks += gd->bg_free_blocks_count;
11841                 free_inodes += gd->bg_free_inodes_count;
11842                 first_block += sb->s_blocks_per_group;
11843                 last_block += sb->s_blocks_per_group;
11844
11845                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11846                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11847                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11848                         ext2fs_unmark_valid(fs);
11849
11850         }
11851
11852         /*
11853          * Update the global counts from the block group counts.  This
11854          * is needed for an experimental patch which eliminates
11855          * locking the entire filesystem when allocating blocks or
11856          * inodes; if the filesystem is not unmounted cleanly, the
11857          * global counts may not be accurate.
11858          */
11859         if ((free_blocks != sb->s_free_blocks_count) ||
11860             (free_inodes != sb->s_free_inodes_count)) {
11861                 if (ctx->options & E2F_OPT_READONLY)
11862                         ext2fs_unmark_valid(fs);
11863                 else {
11864                         sb->s_free_blocks_count = free_blocks;
11865                         sb->s_free_inodes_count = free_inodes;
11866                         ext2fs_mark_super_dirty(fs);
11867                 }
11868         }
11869
11870         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11871             (sb->s_free_inodes_count > sb->s_inodes_count))
11872                 ext2fs_unmark_valid(fs);
11873
11874
11875         /*
11876          * If we have invalid bitmaps, set the error state of the
11877          * filesystem.
11878          */
11879         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11880                 sb->s_state &= ~EXT2_VALID_FS;
11881                 ext2fs_mark_super_dirty(fs);
11882         }
11883
11884         clear_problem_context(&pctx);
11885
11886         /*
11887          * If the UUID field isn't assigned, assign it.
11888          */
11889         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11890                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11891                         uuid_generate(sb->s_uuid);
11892                         ext2fs_mark_super_dirty(fs);
11893                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11894                 }
11895         }
11896
11897         /* FIXME - HURD support?
11898          * For the Hurd, check to see if the filetype option is set,
11899          * since it doesn't support it.
11900          */
11901         if (!(ctx->options & E2F_OPT_READONLY) &&
11902             fs->super->s_creator_os == EXT2_OS_HURD &&
11903             (fs->super->s_feature_incompat &
11904              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11905                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11906                         fs->super->s_feature_incompat &=
11907                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11908                         ext2fs_mark_super_dirty(fs);
11909
11910                 }
11911         }
11912
11913         /*
11914          * If we have any of the compatibility flags set, we need to have a
11915          * revision 1 filesystem.  Most kernels will not check the flags on
11916          * a rev 0 filesystem and we may have corruption issues because of
11917          * the incompatible changes to the filesystem.
11918          */
11919         if (!(ctx->options & E2F_OPT_READONLY) &&
11920             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11921             (fs->super->s_feature_compat ||
11922              fs->super->s_feature_ro_compat ||
11923              fs->super->s_feature_incompat) &&
11924             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11925                 ext2fs_update_dynamic_rev(fs);
11926                 ext2fs_mark_super_dirty(fs);
11927         }
11928
11929         check_resize_inode(ctx);
11930
11931         /*
11932          * Clean up any orphan inodes, if present.
11933          */
11934         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11935                 fs->super->s_state &= ~EXT2_VALID_FS;
11936                 ext2fs_mark_super_dirty(fs);
11937         }
11938
11939         /*
11940          * Move the ext3 journal file, if necessary.
11941          */
11942         e2fsck_move_ext3_journal(ctx);
11943 }
11944
11945 /*
11946  * swapfs.c --- byte-swap an ext2 filesystem
11947  */
11948
11949 #ifdef ENABLE_SWAPFS
11950
11951 struct swap_block_struct {
11952         ext2_ino_t      ino;
11953         int             isdir;
11954         errcode_t       errcode;
11955         char            *dir_buf;
11956         struct ext2_inode *inode;
11957 };
11958
11959 /*
11960  * This is a helper function for block_iterate.  We mark all of the
11961  * indirect and direct blocks as changed, so that block_iterate will
11962  * write them out.
11963  */
11964 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11965                       void *priv_data)
11966 {
11967         errcode_t       retval;
11968
11969         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11970
11971         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11972                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11973                 if (retval) {
11974                         sb->errcode = retval;
11975                         return BLOCK_ABORT;
11976                 }
11977                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11978                 if (retval) {
11979                         sb->errcode = retval;
11980                         return BLOCK_ABORT;
11981                 }
11982         }
11983         if (blockcnt >= 0) {
11984                 if (blockcnt < EXT2_NDIR_BLOCKS)
11985                         return 0;
11986                 return BLOCK_CHANGED;
11987         }
11988         if (blockcnt == BLOCK_COUNT_IND) {
11989                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11990                         return 0;
11991                 return BLOCK_CHANGED;
11992         }
11993         if (blockcnt == BLOCK_COUNT_DIND) {
11994                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11995                         return 0;
11996                 return BLOCK_CHANGED;
11997         }
11998         if (blockcnt == BLOCK_COUNT_TIND) {
11999                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12000                         return 0;
12001                 return BLOCK_CHANGED;
12002         }
12003         return BLOCK_CHANGED;
12004 }
12005
12006 /*
12007  * This function is responsible for byte-swapping all of the indirect,
12008  * block pointers.  It is also responsible for byte-swapping directories.
12009  */
12010 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12011                               struct ext2_inode *inode)
12012 {
12013         errcode_t                       retval;
12014         struct swap_block_struct        sb;
12015
12016         sb.ino = ino;
12017         sb.inode = inode;
12018         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12019         sb.errcode = 0;
12020         sb.isdir = 0;
12021         if (LINUX_S_ISDIR(inode->i_mode))
12022                 sb.isdir = 1;
12023
12024         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12025                                       swap_block, &sb);
12026         if (retval) {
12027                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12028                 ctx->flags |= E2F_FLAG_ABORT;
12029                 return;
12030         }
12031         if (sb.errcode) {
12032                 bb_error_msg(_("while calling iterator function"));
12033                 ctx->flags |= E2F_FLAG_ABORT;
12034                 return;
12035         }
12036 }
12037
12038 static void swap_inodes(e2fsck_t ctx)
12039 {
12040         ext2_filsys fs = ctx->fs;
12041         dgrp_t                  group;
12042         unsigned int            i;
12043         ext2_ino_t              ino = 1;
12044         char                    *buf, *block_buf;
12045         errcode_t               retval;
12046         struct ext2_inode *     inode;
12047
12048         e2fsck_use_inode_shortcuts(ctx, 1);
12049
12050         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12051                                 &buf);
12052         if (retval) {
12053                 bb_error_msg(_("while allocating inode buffer"));
12054                 ctx->flags |= E2F_FLAG_ABORT;
12055                 return;
12056         }
12057         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12058                                                     "block interate buffer");
12059         for (group = 0; group < fs->group_desc_count; group++) {
12060                 retval = io_channel_read_blk(fs->io,
12061                       fs->group_desc[group].bg_inode_table,
12062                       fs->inode_blocks_per_group, buf);
12063                 if (retval) {
12064                         bb_error_msg(_("while reading inode table (group %d)"),
12065                                 group);
12066                         ctx->flags |= E2F_FLAG_ABORT;
12067                         return;
12068                 }
12069                 inode = (struct ext2_inode *) buf;
12070                 for (i=0; i < fs->super->s_inodes_per_group;
12071                      i++, ino++, inode++) {
12072                         ctx->stashed_ino = ino;
12073                         ctx->stashed_inode = inode;
12074
12075                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12076                                 ext2fs_swap_inode(fs, inode, inode, 0);
12077
12078                         /*
12079                          * Skip deleted files.
12080                          */
12081                         if (inode->i_links_count == 0)
12082                                 continue;
12083
12084                         if (LINUX_S_ISDIR(inode->i_mode) ||
12085                             ((inode->i_block[EXT2_IND_BLOCK] ||
12086                               inode->i_block[EXT2_DIND_BLOCK] ||
12087                               inode->i_block[EXT2_TIND_BLOCK]) &&
12088                              ext2fs_inode_has_valid_blocks(inode)))
12089                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12090
12091                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12092                                 return;
12093
12094                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12095                                 ext2fs_swap_inode(fs, inode, inode, 1);
12096                 }
12097                 retval = io_channel_write_blk(fs->io,
12098                       fs->group_desc[group].bg_inode_table,
12099                       fs->inode_blocks_per_group, buf);
12100                 if (retval) {
12101                         bb_error_msg(_("while writing inode table (group %d)"),
12102                                 group);
12103                         ctx->flags |= E2F_FLAG_ABORT;
12104                         return;
12105                 }
12106         }
12107         ext2fs_free_mem(&buf);
12108         ext2fs_free_mem(&block_buf);
12109         e2fsck_use_inode_shortcuts(ctx, 0);
12110         ext2fs_flush_icache(fs);
12111 }
12112
12113 #if defined(__powerpc__) && BB_BIG_ENDIAN
12114 /*
12115  * On the PowerPC, the big-endian variant of the ext2 filesystem
12116  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12117  * of each word.  Thus a bitmap with only bit 0 set would be, as
12118  * a string of bytes, 00 00 00 01 00 ...
12119  * To cope with this, we byte-reverse each word of a bitmap if
12120  * we have a big-endian filesystem, that is, if we are *not*
12121  * byte-swapping other word-sized numbers.
12122  */
12123 #define EXT2_BIG_ENDIAN_BITMAPS
12124 #endif
12125
12126 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12127 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12128 {
12129         __u32 *p = (__u32 *) bmap->bitmap;
12130         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12131
12132         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12133                 *p = ext2fs_swab32(*p);
12134 }
12135 #endif
12136
12137
12138 #ifdef ENABLE_SWAPFS
12139 static void swap_filesys(e2fsck_t ctx)
12140 {
12141         ext2_filsys fs = ctx->fs;
12142         if (!(ctx->options & E2F_OPT_PREEN))
12143                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12144
12145         /* Byte swap */
12146
12147         if (fs->super->s_mnt_count) {
12148                 fprintf(stderr, _("%s: the filesystem must be freshly "
12149                         "checked using fsck\n"
12150                         "and not mounted before trying to "
12151                         "byte-swap it.\n"), ctx->device_name);
12152                 ctx->flags |= E2F_FLAG_ABORT;
12153                 return;
12154         }
12155         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12156                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12157                                EXT2_FLAG_SWAP_BYTES_WRITE);
12158                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12159         } else {
12160                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12161                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12162         }
12163         swap_inodes(ctx);
12164         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12165                 return;
12166         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12167                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12168         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12169                        EXT2_FLAG_SWAP_BYTES_WRITE);
12170
12171 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12172         e2fsck_read_bitmaps(ctx);
12173         ext2fs_swap_bitmap(fs->inode_map);
12174         ext2fs_swap_bitmap(fs->block_map);
12175         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12176 #endif
12177         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12178         ext2fs_flush(fs);
12179         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12180 }
12181 #endif  /* ENABLE_SWAPFS */
12182
12183 #endif
12184
12185 /*
12186  * util.c --- miscellaneous utilities
12187  */
12188
12189
12190 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12191                              const char *description)
12192 {
12193         void *ret;
12194         char buf[256];
12195
12196         ret = xzalloc(size);
12197         return ret;
12198 }
12199
12200 static char *string_copy(const char *str, int len)
12201 {
12202         char    *ret;
12203
12204         if (!str)
12205                 return NULL;
12206         if (!len)
12207                 len = strlen(str);
12208         ret = xmalloc(len+1);
12209         strncpy(ret, str, len);
12210         ret[len] = 0;
12211         return ret;
12212 }
12213
12214 #ifndef HAVE_CONIO_H
12215 static int read_a_char(void)
12216 {
12217         char    c;
12218         int     r;
12219         int     fail = 0;
12220
12221         while (1) {
12222                 if (e2fsck_global_ctx &&
12223                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12224                         return 3;
12225                 }
12226                 r = read(0, &c, 1);
12227                 if (r == 1)
12228                         return c;
12229                 if (fail++ > 100)
12230                         break;
12231         }
12232         return EOF;
12233 }
12234 #endif
12235
12236 static int ask_yn(const char * string, int def)
12237 {
12238         int             c;
12239         const char      *defstr;
12240         static const char short_yes[] = "yY";
12241         static const char short_no[] = "nN";
12242
12243 #ifdef HAVE_TERMIOS_H
12244         struct termios  termios, tmp;
12245
12246         tcgetattr (0, &termios);
12247         tmp = termios;
12248         tmp.c_lflag &= ~(ICANON | ECHO);
12249         tmp.c_cc[VMIN] = 1;
12250         tmp.c_cc[VTIME] = 0;
12251         tcsetattr_stdin_TCSANOW(&tmp);
12252 #endif
12253
12254         if (def == 1)
12255                 defstr = "<y>";
12256         else if (def == 0)
12257                 defstr = "<n>";
12258         else
12259                 defstr = " (y/n)";
12260         printf("%s%s? ", string, defstr);
12261         while (1) {
12262                 fflush (stdout);
12263                 if ((c = read_a_char()) == EOF)
12264                         break;
12265                 if (c == 3) {
12266 #ifdef HAVE_TERMIOS_H
12267                         tcsetattr_stdin_TCSANOW(&termios);
12268 #endif
12269                         if (e2fsck_global_ctx &&
12270                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12271                                 puts("\n");
12272                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12273                         }
12274                         puts(_("cancelled!\n"));
12275                         return 0;
12276                 }
12277                 if (strchr(short_yes, (char) c)) {
12278                         def = 1;
12279                         break;
12280                 }
12281                 else if (strchr(short_no, (char) c)) {
12282                         def = 0;
12283                         break;
12284                 }
12285                 else if ((c == ' ' || c == '\n') && (def != -1))
12286                         break;
12287         }
12288         if (def)
12289                 puts("yes\n");
12290         else
12291                 puts ("no\n");
12292 #ifdef HAVE_TERMIOS_H
12293         tcsetattr_stdin_TCSANOW(&termios);
12294 #endif
12295         return def;
12296 }
12297
12298 int ask (e2fsck_t ctx, const char * string, int def)
12299 {
12300         if (ctx->options & E2F_OPT_NO) {
12301                 printf(_("%s? no\n\n"), string);
12302                 return 0;
12303         }
12304         if (ctx->options & E2F_OPT_YES) {
12305                 printf(_("%s? yes\n\n"), string);
12306                 return 1;
12307         }
12308         if (ctx->options & E2F_OPT_PREEN) {
12309                 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12310                 return def;
12311         }
12312         return ask_yn(string, def);
12313 }
12314
12315 void e2fsck_read_bitmaps(e2fsck_t ctx)
12316 {
12317         ext2_filsys fs = ctx->fs;
12318         errcode_t       retval;
12319
12320         if (ctx->invalid_bitmaps) {
12321                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12322                         ctx->device_name);
12323                 bb_error_msg_and_die(0);
12324         }
12325
12326         ehandler_operation(_("reading inode and block bitmaps"));
12327         retval = ext2fs_read_bitmaps(fs);
12328         ehandler_operation(0);
12329         if (retval) {
12330                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12331                         ctx->device_name);
12332                 bb_error_msg_and_die(0);
12333         }
12334 }
12335
12336 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12337 {
12338         ext2_filsys fs = ctx->fs;
12339         errcode_t       retval;
12340
12341         if (ext2fs_test_bb_dirty(fs)) {
12342                 ehandler_operation(_("writing block bitmaps"));
12343                 retval = ext2fs_write_block_bitmap(fs);
12344                 ehandler_operation(0);
12345                 if (retval) {
12346                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12347                                 ctx->device_name);
12348                         bb_error_msg_and_die(0);
12349                 }
12350         }
12351
12352         if (ext2fs_test_ib_dirty(fs)) {
12353                 ehandler_operation(_("writing inode bitmaps"));
12354                 retval = ext2fs_write_inode_bitmap(fs);
12355                 ehandler_operation(0);
12356                 if (retval) {
12357                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12358                                 ctx->device_name);
12359                         bb_error_msg_and_die(0);
12360                 }
12361         }
12362 }
12363
12364 void preenhalt(e2fsck_t ctx)
12365 {
12366         ext2_filsys fs = ctx->fs;
12367
12368         if (!(ctx->options & E2F_OPT_PREEN))
12369                 return;
12370         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12371                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12372                ctx->device_name);
12373         if (fs != NULL) {
12374                 fs->super->s_state |= EXT2_ERROR_FS;
12375                 ext2fs_mark_super_dirty(fs);
12376                 ext2fs_close(fs);
12377         }
12378         exit(EXIT_UNCORRECTED);
12379 }
12380
12381 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12382                               struct ext2_inode * inode, const char *proc)
12383 {
12384         int retval;
12385
12386         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12387         if (retval) {
12388                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12389                 bb_error_msg_and_die(0);
12390         }
12391 }
12392
12393 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12394                                struct ext2_inode * inode, int bufsize,
12395                                const char *proc)
12396 {
12397         int retval;
12398
12399         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12400         if (retval) {
12401                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12402                 bb_error_msg_and_die(0);
12403         }
12404 }
12405
12406 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12407                                struct ext2_inode * inode, const char *proc)
12408 {
12409         int retval;
12410
12411         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12412         if (retval) {
12413                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12414                 bb_error_msg_and_die(0);
12415         }
12416 }
12417
12418 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12419                    io_manager manager)
12420 {
12421         struct ext2_super_block *sb;
12422         io_channel              io = NULL;
12423         void                    *buf = NULL;
12424         int                     blocksize;
12425         blk_t                   superblock, ret_sb = 8193;
12426
12427         if (fs && fs->super) {
12428                 ret_sb = (fs->super->s_blocks_per_group +
12429                           fs->super->s_first_data_block);
12430                 if (ctx) {
12431                         ctx->superblock = ret_sb;
12432                         ctx->blocksize = fs->blocksize;
12433                 }
12434                 return ret_sb;
12435         }
12436
12437         if (ctx) {
12438                 if (ctx->blocksize) {
12439                         ret_sb = ctx->blocksize * 8;
12440                         if (ctx->blocksize == 1024)
12441                                 ret_sb++;
12442                         ctx->superblock = ret_sb;
12443                         return ret_sb;
12444                 }
12445                 ctx->superblock = ret_sb;
12446                 ctx->blocksize = 1024;
12447         }
12448
12449         if (!name || !manager)
12450                 goto cleanup;
12451
12452         if (manager->open(name, 0, &io) != 0)
12453                 goto cleanup;
12454
12455         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12456                 goto cleanup;
12457         sb = (struct ext2_super_block *) buf;
12458
12459         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12460              blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12461                 superblock = blocksize*8;
12462                 if (blocksize == 1024)
12463                         superblock++;
12464                 io_channel_set_blksize(io, blocksize);
12465                 if (io_channel_read_blk(io, superblock,
12466                                         -SUPERBLOCK_SIZE, buf))
12467                         continue;
12468 #if BB_BIG_ENDIAN
12469                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12470                         ext2fs_swap_super(sb);
12471 #endif
12472                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12473                         ret_sb = superblock;
12474                         if (ctx) {
12475                                 ctx->superblock = superblock;
12476                                 ctx->blocksize = blocksize;
12477                         }
12478                         break;
12479                 }
12480         }
12481
12482 cleanup:
12483         if (io)
12484                 io_channel_close(io);
12485         ext2fs_free_mem(&buf);
12486         return ret_sb;
12487 }
12488
12489
12490 /*
12491  * This function runs through the e2fsck passes and calls them all,
12492  * returning restart, abort, or cancel as necessary...
12493  */
12494 typedef void (*pass_t)(e2fsck_t ctx);
12495
12496 static const pass_t e2fsck_passes[] = {
12497         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12498         e2fsck_pass5, 0 };
12499
12500 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12501
12502 static int e2fsck_run(e2fsck_t ctx)
12503 {
12504         int     i;
12505         pass_t  e2fsck_pass;
12506
12507         if (setjmp(ctx->abort_loc)) {
12508                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12509                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12510         }
12511         ctx->flags |= E2F_FLAG_SETJMP_OK;
12512
12513         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12514                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12515                         break;
12516                 e2fsck_pass(ctx);
12517                 if (ctx->progress)
12518                         (void) (ctx->progress)(ctx, 0, 0, 0);
12519         }
12520         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12521
12522         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12523                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12524         return 0;
12525 }
12526
12527
12528 /*
12529  * unix.c - The unix-specific code for e2fsck
12530  */
12531
12532
12533 /* Command line options */
12534 static int swapfs;
12535 #ifdef ENABLE_SWAPFS
12536 static int normalize_swapfs;
12537 #endif
12538 static int cflag;               /* check disk */
12539 static int show_version_only;
12540 static int verbose;
12541
12542 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12543
12544 static void show_stats(e2fsck_t ctx)
12545 {
12546         ext2_filsys fs = ctx->fs;
12547         int inodes, inodes_used, blocks, blocks_used;
12548         int dir_links;
12549         int num_files, num_links;
12550         int frag_percent;
12551
12552         dir_links = 2 * ctx->fs_directory_count - 1;
12553         num_files = ctx->fs_total_count - dir_links;
12554         num_links = ctx->fs_links_count - dir_links;
12555         inodes = fs->super->s_inodes_count;
12556         inodes_used = (fs->super->s_inodes_count -
12557                        fs->super->s_free_inodes_count);
12558         blocks = fs->super->s_blocks_count;
12559         blocks_used = (fs->super->s_blocks_count -
12560                        fs->super->s_free_blocks_count);
12561
12562         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12563         frag_percent = (frag_percent + 5) / 10;
12564
12565         if (!verbose) {
12566                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12567                        ctx->device_name, inodes_used, inodes,
12568                        frag_percent / 10, frag_percent % 10,
12569                        blocks_used, blocks);
12570                 return;
12571         }
12572         printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12573                 100 * inodes_used / inodes);
12574         printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12575                 P_E2("", "s", ctx->fs_fragmented),
12576                 frag_percent / 10, frag_percent % 10);
12577         printf(_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12578                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12579         printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12580                 (int) ((long long) 100 * blocks_used / blocks));
12581         printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12582         printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12583         printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12584         printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12585         printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12586         printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12587         printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12588         printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12589         printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12590         printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12591         printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12592 }
12593
12594 static void check_mount(e2fsck_t ctx)
12595 {
12596         errcode_t       retval;
12597         int             cont;
12598
12599         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12600                                          &ctx->mount_flags);
12601         if (retval) {
12602                 bb_error_msg(_("while determining whether %s is mounted"),
12603                         ctx->filesystem_name);
12604                 return;
12605         }
12606
12607         /*
12608          * If the filesystem isn't mounted, or it's the root filesystem
12609          * and it's mounted read-only, then everything's fine.
12610          */
12611         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12612             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12613              (ctx->mount_flags & EXT2_MF_READONLY)))
12614                 return;
12615
12616         if (ctx->options & E2F_OPT_READONLY) {
12617                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12618                 return;
12619         }
12620
12621         printf(_("%s is mounted.  "), ctx->filesystem_name);
12622         if (!ctx->interactive)
12623                 bb_error_msg_and_die(_("can't continue, aborting"));
12624         printf(_("\n\n\007\007\007\007WARNING!!!  "
12625                "Running e2fsck on a mounted filesystem may cause\n"
12626                "SEVERE filesystem damage.\007\007\007\n\n"));
12627         cont = ask_yn(_("Do you really want to continue"), -1);
12628         if (!cont) {
12629                 printf(_("check aborted.\n"));
12630                 exit(0);
12631         }
12632 }
12633
12634 static int is_on_batt(void)
12635 {
12636         FILE    *f;
12637         DIR     *d;
12638         char    tmp[80], tmp2[80], fname[80];
12639         unsigned int    acflag;
12640         struct dirent*  de;
12641
12642         f = fopen_for_read("/proc/apm");
12643         if (f) {
12644                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12645                         acflag = 1;
12646                 fclose(f);
12647                 return (acflag != 1);
12648         }
12649         d = opendir("/proc/acpi/ac_adapter");
12650         if (d) {
12651                 while ((de=readdir(d)) != NULL) {
12652                         if (!strncmp(".", de->d_name, 1))
12653                                 continue;
12654                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12655                                  de->d_name);
12656                         f = fopen_for_read(fname);
12657                         if (!f)
12658                                 continue;
12659                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12660                                 tmp[0] = 0;
12661                         fclose(f);
12662                         if (strncmp(tmp, "off-line", 8) == 0) {
12663                                 closedir(d);
12664                                 return 1;
12665                         }
12666                 }
12667                 closedir(d);
12668         }
12669         return 0;
12670 }
12671
12672 /*
12673  * This routine checks to see if a filesystem can be skipped; if so,
12674  * it will exit with EXIT_OK.  Under some conditions it will print a
12675  * message explaining why a check is being forced.
12676  */
12677 static void check_if_skip(e2fsck_t ctx)
12678 {
12679         ext2_filsys fs = ctx->fs;
12680         const char *reason = NULL;
12681         unsigned int reason_arg = 0;
12682         long next_check;
12683         int batt = is_on_batt();
12684         time_t now = time(NULL);
12685
12686         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12687                 return;
12688
12689         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12690             !ext2fs_test_valid(fs))
12691                 reason = _(" contains a file system with errors");
12692         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12693                 reason = _(" was not cleanly unmounted");
12694         else if ((fs->super->s_max_mnt_count > 0) &&
12695                  (fs->super->s_mnt_count >=
12696                   (unsigned) fs->super->s_max_mnt_count)) {
12697                 reason = _(" has been mounted %u times without being checked");
12698                 reason_arg = fs->super->s_mnt_count;
12699                 if (batt && (fs->super->s_mnt_count <
12700                              (unsigned) fs->super->s_max_mnt_count*2))
12701                         reason = 0;
12702         } else if (fs->super->s_checkinterval &&
12703                    ((now - fs->super->s_lastcheck) >=
12704                     fs->super->s_checkinterval)) {
12705                 reason = _(" has gone %u days without being checked");
12706                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12707                 if (batt && ((now - fs->super->s_lastcheck) <
12708                              fs->super->s_checkinterval*2))
12709                         reason = 0;
12710         }
12711         if (reason) {
12712                 fputs(ctx->device_name, stdout);
12713                 printf(reason, reason_arg);
12714                 fputs(_(", check forced.\n"), stdout);
12715                 return;
12716         }
12717         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12718                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12719                fs->super->s_inodes_count,
12720                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12721                fs->super->s_blocks_count);
12722         next_check = 100000;
12723         if (fs->super->s_max_mnt_count > 0) {
12724                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12725                 if (next_check <= 0)
12726                         next_check = 1;
12727         }
12728         if (fs->super->s_checkinterval &&
12729             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12730                 next_check = 1;
12731         if (next_check <= 5) {
12732                 if (next_check == 1)
12733                         fputs(_(" (check after next mount)"), stdout);
12734                 else
12735                         printf(_(" (check in %ld mounts)"), next_check);
12736         }
12737         bb_putchar('\n');
12738         ext2fs_close(fs);
12739         ctx->fs = NULL;
12740         e2fsck_free_context(ctx);
12741         exit(EXIT_OK);
12742 }
12743
12744 /*
12745  * For completion notice
12746  */
12747 struct percent_tbl {
12748         int     max_pass;
12749         int     table[32];
12750 };
12751 static const struct percent_tbl e2fsck_tbl = {
12752         5, { 0, 70, 90, 92,  95, 100 }
12753 };
12754
12755 static char bar[128], spaces[128];
12756
12757 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12758                           int max)
12759 {
12760         float   percent;
12761
12762         if (pass <= 0)
12763                 return 0.0;
12764         if (pass > tbl->max_pass || max == 0)
12765                 return 100.0;
12766         percent = ((float) curr) / ((float) max);
12767         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12768                 + tbl->table[pass-1]);
12769 }
12770
12771 void e2fsck_clear_progbar(e2fsck_t ctx)
12772 {
12773         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12774                 return;
12775
12776         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12777                ctx->stop_meta);
12778         fflush(stdout);
12779         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12780 }
12781
12782 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12783                            unsigned int dpynum)
12784 {
12785         static const char spinner[] = "\\|/-";
12786         int     i;
12787         unsigned int    tick;
12788         struct timeval  tv;
12789         int dpywidth;
12790         int fixed_percent;
12791
12792         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12793                 return 0;
12794
12795         /*
12796          * Calculate the new progress position.  If the
12797          * percentage hasn't changed, then we skip out right
12798          * away.
12799          */
12800         fixed_percent = (int) ((10 * percent) + 0.5);
12801         if (ctx->progress_last_percent == fixed_percent)
12802                 return 0;
12803         ctx->progress_last_percent = fixed_percent;
12804
12805         /*
12806          * If we've already updated the spinner once within
12807          * the last 1/8th of a second, no point doing it
12808          * again.
12809          */
12810         gettimeofday(&tv, NULL);
12811         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12812         if ((tick == ctx->progress_last_time) &&
12813             (fixed_percent != 0) && (fixed_percent != 1000))
12814                 return 0;
12815         ctx->progress_last_time = tick;
12816
12817         /*
12818          * Advance the spinner, and note that the progress bar
12819          * will be on the screen
12820          */
12821         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12822         ctx->flags |= E2F_FLAG_PROG_BAR;
12823
12824         dpywidth = 66 - strlen(label);
12825         dpywidth = 8 * (dpywidth / 8);
12826         if (dpynum)
12827                 dpywidth -= 8;
12828
12829         i = ((percent * dpywidth) + 50) / 100;
12830         printf("%s%s: |%s%s", ctx->start_meta, label,
12831                bar + (sizeof(bar) - (i+1)),
12832                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12833         if (fixed_percent == 1000)
12834                 bb_putchar('|');
12835         else
12836                 bb_putchar(spinner[ctx->progress_pos & 3]);
12837         printf(" %4.1f%%  ", percent);
12838         if (dpynum)
12839                 printf("%u\r", dpynum);
12840         else
12841                 fputs(" \r", stdout);
12842         fputs(ctx->stop_meta, stdout);
12843
12844         if (fixed_percent == 1000)
12845                 e2fsck_clear_progbar(ctx);
12846         fflush(stdout);
12847
12848         return 0;
12849 }
12850
12851 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12852                                   unsigned long cur, unsigned long max)
12853 {
12854         char buf[80];
12855         float percent;
12856
12857         if (pass == 0)
12858                 return 0;
12859
12860         if (ctx->progress_fd) {
12861                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12862                 xwrite_str(ctx->progress_fd, buf);
12863         } else {
12864                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12865                 e2fsck_simple_progress(ctx, ctx->device_name,
12866                                        percent, 0);
12867         }
12868         return 0;
12869 }
12870
12871 static void reserve_stdio_fds(void)
12872 {
12873         int     fd;
12874
12875         while (1) {
12876                 fd = open(bb_dev_null, O_RDWR);
12877                 if (fd > 2)
12878                         break;
12879                 if (fd < 0) {
12880                         fprintf(stderr, _("ERROR: Cannot open "
12881                                 "/dev/null (%s)\n"),
12882                                 strerror(errno));
12883                         break;
12884                 }
12885         }
12886         close(fd);
12887 }
12888
12889 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12890 {
12891         e2fsck_t ctx = e2fsck_global_ctx;
12892
12893         if (!ctx)
12894                 return;
12895
12896         ctx->progress = e2fsck_update_progress;
12897         ctx->progress_fd = 0;
12898 }
12899
12900 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12901 {
12902         e2fsck_t ctx = e2fsck_global_ctx;
12903
12904         if (!ctx)
12905                 return;
12906
12907         e2fsck_clear_progbar(ctx);
12908         ctx->progress = 0;
12909 }
12910
12911 static void signal_cancel(int sig FSCK_ATTR((unused)))
12912 {
12913         e2fsck_t ctx = e2fsck_global_ctx;
12914
12915         if (!ctx)
12916                 exit(FSCK_CANCELED);
12917
12918         ctx->flags |= E2F_FLAG_CANCEL;
12919 }
12920
12921 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12922 {
12923         char    *buf, *token, *next, *p, *arg;
12924         int     ea_ver;
12925         int     extended_usage = 0;
12926
12927         buf = string_copy(opts, 0);
12928         for (token = buf; token && *token; token = next) {
12929                 p = strchr(token, ',');
12930                 next = 0;
12931                 if (p) {
12932                         *p = 0;
12933                         next = p+1;
12934                 }
12935                 arg = strchr(token, '=');
12936                 if (arg) {
12937                         *arg = 0;
12938                         arg++;
12939                 }
12940                 if (strcmp(token, "ea_ver") == 0) {
12941                         if (!arg) {
12942                                 extended_usage++;
12943                                 continue;
12944                         }
12945                         ea_ver = strtoul(arg, &p, 0);
12946                         if (*p ||
12947                             ((ea_ver != 1) && (ea_ver != 2))) {
12948                                 fprintf(stderr,
12949                                         _("Invalid EA version.\n"));
12950                                 extended_usage++;
12951                                 continue;
12952                         }
12953                         ctx->ext_attr_ver = ea_ver;
12954                 } else {
12955                         fprintf(stderr, _("Unknown extended option: %s\n"),
12956                                 token);
12957                         extended_usage++;
12958                 }
12959         }
12960         if (extended_usage) {
12961                 bb_error_msg_and_die(
12962                         "Extended options are separated by commas, "
12963                         "and may take an argument which\n"
12964                         "is set off by an equals ('=') sign.  "
12965                         "Valid extended options are:\n"
12966                         "\tea_ver=<ea_version (1 or 2)>\n\n");
12967         }
12968 }
12969
12970
12971 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12972 {
12973         int             flush = 0;
12974         int             c, fd;
12975         e2fsck_t        ctx;
12976         errcode_t       retval;
12977         struct sigaction        sa;
12978         char            *extended_opts = NULL;
12979
12980         retval = e2fsck_allocate_context(&ctx);
12981         if (retval)
12982                 return retval;
12983
12984         *ret_ctx = ctx;
12985
12986         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12987         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12988         if (isatty(0) && isatty(1)) {
12989                 ctx->interactive = 1;
12990         } else {
12991                 ctx->start_meta[0] = '\001';
12992                 ctx->stop_meta[0] = '\002';
12993         }
12994         memset(bar, '=', sizeof(bar)-1);
12995         memset(spaces, ' ', sizeof(spaces)-1);
12996         blkid_get_cache(&ctx->blkid, NULL);
12997
12998         if (argc && *argv)
12999                 ctx->program_name = *argv;
13000         else
13001                 ctx->program_name = "e2fsck";
13002         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13003                 switch (c) {
13004                 case 'C':
13005                         ctx->progress = e2fsck_update_progress;
13006                         ctx->progress_fd = atoi(optarg);
13007                         if (!ctx->progress_fd)
13008                                 break;
13009                         /* Validate the file descriptor to avoid disasters */
13010                         fd = dup(ctx->progress_fd);
13011                         if (fd < 0) {
13012                                 fprintf(stderr,
13013                                 _("Error validating file descriptor %d: %s\n"),
13014                                         ctx->progress_fd,
13015                                         error_message(errno));
13016                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13017                         } else
13018                                 close(fd);
13019                         break;
13020                 case 'D':
13021                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13022                         break;
13023                 case 'E':
13024                         extended_opts = optarg;
13025                         break;
13026                 case 'p':
13027                 case 'a':
13028                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13029                         conflict_opt:
13030                                 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13031                         }
13032                         ctx->options |= E2F_OPT_PREEN;
13033                         break;
13034                 case 'n':
13035                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13036                                 goto conflict_opt;
13037                         ctx->options |= E2F_OPT_NO;
13038                         break;
13039                 case 'y':
13040                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13041                                 goto conflict_opt;
13042                         ctx->options |= E2F_OPT_YES;
13043                         break;
13044                 case 't':
13045                         /* FIXME - This needs to go away in a future path - will change binary */
13046                         fprintf(stderr, _("The -t option is not "
13047                                 "supported on this version of e2fsck.\n"));
13048                         break;
13049                 case 'c':
13050                         if (cflag++)
13051                                 ctx->options |= E2F_OPT_WRITECHECK;
13052                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13053                         break;
13054                 case 'r':
13055                         /* What we do by default, anyway! */
13056                         break;
13057                 case 'b':
13058                         ctx->use_superblock = atoi(optarg);
13059                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13060                         break;
13061                 case 'B':
13062                         ctx->blocksize = atoi(optarg);
13063                         break;
13064                 case 'I':
13065                         ctx->inode_buffer_blocks = atoi(optarg);
13066                         break;
13067                 case 'j':
13068                         ctx->journal_name = string_copy(optarg, 0);
13069                         break;
13070                 case 'P':
13071                         ctx->process_inode_size = atoi(optarg);
13072                         break;
13073                 case 'd':
13074                         ctx->options |= E2F_OPT_DEBUG;
13075                         break;
13076                 case 'f':
13077                         ctx->options |= E2F_OPT_FORCE;
13078                         break;
13079                 case 'F':
13080                         flush = 1;
13081                         break;
13082                 case 'v':
13083                         verbose = 1;
13084                         break;
13085                 case 'V':
13086                         show_version_only = 1;
13087                         break;
13088                 case 'N':
13089                         ctx->device_name = optarg;
13090                         break;
13091 #ifdef ENABLE_SWAPFS
13092                 case 's':
13093                         normalize_swapfs = 1;
13094                 case 'S':
13095                         swapfs = 1;
13096                         break;
13097 #else
13098                 case 's':
13099                 case 'S':
13100                         fprintf(stderr, _("Byte-swapping filesystems "
13101                                           "not compiled in this version "
13102                                           "of e2fsck\n"));
13103                         exit(1);
13104 #endif
13105                 default:
13106                         bb_show_usage();
13107                 }
13108         if (show_version_only)
13109                 return 0;
13110         if (optind != argc - 1)
13111                 bb_show_usage();
13112         if ((ctx->options & E2F_OPT_NO) &&
13113             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13114                 ctx->options |= E2F_OPT_READONLY;
13115         ctx->io_options = strchr(argv[optind], '?');
13116         if (ctx->io_options)
13117                 *ctx->io_options++ = 0;
13118         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13119         if (!ctx->filesystem_name) {
13120                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13121                 bb_error_msg_and_die(0);
13122         }
13123         if (extended_opts)
13124                 parse_extended_opts(ctx, extended_opts);
13125
13126         if (flush) {
13127                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13128                 if (fd < 0) {
13129                         bb_error_msg(_("while opening %s for flushing"),
13130                                 ctx->filesystem_name);
13131                         bb_error_msg_and_die(0);
13132                 }
13133                 if ((retval = ext2fs_sync_device(fd, 1))) {
13134                         bb_error_msg(_("while trying to flush %s"),
13135                                 ctx->filesystem_name);
13136                         bb_error_msg_and_die(0);
13137                 }
13138                 close(fd);
13139         }
13140 #ifdef ENABLE_SWAPFS
13141         if (swapfs && cflag) {
13142                         fprintf(stderr, _("Incompatible options not "
13143                                           "allowed when byte-swapping.\n"));
13144                         exit(EXIT_USAGE);
13145         }
13146 #endif
13147         /*
13148          * Set up signal action
13149          */
13150         memset(&sa, 0, sizeof(struct sigaction));
13151         sa.sa_handler = signal_cancel;
13152         sigaction(SIGINT, &sa, 0);
13153         sigaction(SIGTERM, &sa, 0);
13154 #ifdef SA_RESTART
13155         sa.sa_flags = SA_RESTART;
13156 #endif
13157         e2fsck_global_ctx = ctx;
13158         sa.sa_handler = signal_progress_on;
13159         sigaction(SIGUSR1, &sa, 0);
13160         sa.sa_handler = signal_progress_off;
13161         sigaction(SIGUSR2, &sa, 0);
13162
13163         /* Update our PATH to include /sbin if we need to run badblocks  */
13164         if (cflag)
13165                 e2fs_set_sbin_path();
13166         return 0;
13167 }
13168
13169 static const char my_ver_string[] = E2FSPROGS_VERSION;
13170 static const char my_ver_date[] = E2FSPROGS_DATE;
13171
13172 int e2fsck_main (int argc, char **argv);
13173 int e2fsck_main (int argc, char **argv)
13174 {
13175         errcode_t       retval;
13176         int             exit_value = EXIT_OK;
13177         ext2_filsys     fs = 0;
13178         io_manager      io_ptr;
13179         struct ext2_super_block *sb;
13180         const char      *lib_ver_date;
13181         int             my_ver, lib_ver;
13182         e2fsck_t        ctx;
13183         struct problem_context pctx;
13184         int flags, run_result;
13185
13186         clear_problem_context(&pctx);
13187
13188         my_ver = ext2fs_parse_version_string(my_ver_string);
13189         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13190         if (my_ver > lib_ver) {
13191                 fprintf( stderr, _("Error: ext2fs library version "
13192                         "out of date!\n"));
13193                 show_version_only++;
13194         }
13195
13196         retval = PRS(argc, argv, &ctx);
13197         if (retval) {
13198                 bb_error_msg(_("while trying to initialize program"));
13199                 exit(EXIT_ERROR);
13200         }
13201         reserve_stdio_fds();
13202
13203         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13204                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13205                          my_ver_date);
13206
13207         if (show_version_only) {
13208                 fprintf(stderr, _("\tUsing %s, %s\n"),
13209                         error_message(EXT2_ET_BASE), lib_ver_date);
13210                 exit(EXIT_OK);
13211         }
13212
13213         check_mount(ctx);
13214
13215         if (!(ctx->options & E2F_OPT_PREEN) &&
13216             !(ctx->options & E2F_OPT_NO) &&
13217             !(ctx->options & E2F_OPT_YES)) {
13218                 if (!ctx->interactive)
13219                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13220         }
13221         ctx->superblock = ctx->use_superblock;
13222 restart:
13223 #ifdef CONFIG_TESTIO_DEBUG
13224         io_ptr = test_io_manager;
13225         test_io_backing_manager = unix_io_manager;
13226 #else
13227         io_ptr = unix_io_manager;
13228 #endif
13229         flags = 0;
13230         if ((ctx->options & E2F_OPT_READONLY) == 0)
13231                 flags |= EXT2_FLAG_RW;
13232
13233         if (ctx->superblock && ctx->blocksize) {
13234                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13235                                       flags, ctx->superblock, ctx->blocksize,
13236                                       io_ptr, &fs);
13237         } else if (ctx->superblock) {
13238                 int blocksize;
13239                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13240                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13241                         retval = ext2fs_open2(ctx->filesystem_name,
13242                                               ctx->io_options, flags,
13243                                               ctx->superblock, blocksize,
13244                                               io_ptr, &fs);
13245                         if (!retval)
13246                                 break;
13247                 }
13248         } else
13249                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13250                                       flags, 0, 0, io_ptr, &fs);
13251         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13252             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13253             ((retval == EXT2_ET_BAD_MAGIC) ||
13254              ((retval == 0) && ext2fs_check_desc(fs)))) {
13255                 if (!fs || (fs->group_desc_count > 1)) {
13256                         printf(_("%s trying backup blocks...\n"),
13257                                retval ? _("Couldn't find ext2 superblock,") :
13258                                _("Group descriptors look bad..."));
13259                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13260                         if (fs)
13261                                 ext2fs_close(fs);
13262                         goto restart;
13263                 }
13264         }
13265         if (retval) {
13266                 bb_error_msg(_("while trying to open %s"),
13267                         ctx->filesystem_name);
13268                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13269                         printf(_("The filesystem revision is apparently "
13270                                "too high for this version of e2fsck.\n"
13271                                "(Or the filesystem superblock "
13272                                "is corrupt)\n\n"));
13273                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13274                 } else if (retval == EXT2_ET_SHORT_READ)
13275                         printf(_("Could this be a zero-length partition?\n"));
13276                 else if ((retval == EPERM) || (retval == EACCES))
13277                         printf(_("You must have %s access to the "
13278                                "filesystem or be root\n"),
13279                                (ctx->options & E2F_OPT_READONLY) ?
13280                                "r/o" : "r/w");
13281                 else if (retval == ENXIO)
13282                         printf(_("Possibly non-existent or swap device?\n"));
13283 #ifdef EROFS
13284                 else if (retval == EROFS)
13285                         printf(_("Disk write-protected; use the -n option "
13286                                "to do a read-only\n"
13287                                "check of the device.\n"));
13288 #endif
13289                 else
13290                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13291                 bb_error_msg_and_die(0);
13292         }
13293         ctx->fs = fs;
13294         fs->priv_data = ctx;
13295         sb = fs->super;
13296         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13297                 bb_error_msg(_("while trying to open %s"),
13298                         ctx->filesystem_name);
13299         get_newer:
13300                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13301         }
13302
13303         /*
13304          * Set the device name, which is used whenever we print error
13305          * or informational messages to the user.
13306          */
13307         if (ctx->device_name == 0 &&
13308             (sb->s_volume_name[0] != 0)) {
13309                 ctx->device_name = string_copy(sb->s_volume_name,
13310                                                sizeof(sb->s_volume_name));
13311         }
13312         if (ctx->device_name == 0)
13313                 ctx->device_name = ctx->filesystem_name;
13314
13315         /*
13316          * Make sure the ext3 superblock fields are consistent.
13317          */
13318         retval = e2fsck_check_ext3_journal(ctx);
13319         if (retval) {
13320                 bb_error_msg(_("while checking ext3 journal for %s"),
13321                         ctx->device_name);
13322                 bb_error_msg_and_die(0);
13323         }
13324
13325         /*
13326          * Check to see if we need to do ext3-style recovery.  If so,
13327          * do it, and then restart the fsck.
13328          */
13329         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13330                 if (ctx->options & E2F_OPT_READONLY) {
13331                         printf(_("Warning: skipping journal recovery "
13332                                  "because doing a read-only filesystem "
13333                                  "check.\n"));
13334                         io_channel_flush(ctx->fs->io);
13335                 } else {
13336                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13337                                 /*
13338                                  * Whoops, we attempted to run the
13339                                  * journal twice.  This should never
13340                                  * happen, unless the hardware or
13341                                  * device driver is being bogus.
13342                                  */
13343                                 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13344                                 bb_error_msg_and_die(0);
13345                         }
13346                         retval = e2fsck_run_ext3_journal(ctx);
13347                         if (retval) {
13348                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13349                                         ctx->device_name);
13350                                 bb_error_msg_and_die(0);
13351                         }
13352                         ext2fs_close(ctx->fs);
13353                         ctx->fs = 0;
13354                         ctx->flags |= E2F_FLAG_RESTARTED;
13355                         goto restart;
13356                 }
13357         }
13358
13359         /*
13360          * Check for compatibility with the feature sets.  We need to
13361          * be more stringent than ext2fs_open().
13362          */
13363         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13364             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13365                 bb_error_msg("(%s)", ctx->device_name);
13366                 goto get_newer;
13367         }
13368         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13369                 bb_error_msg("(%s)", ctx->device_name);
13370                 goto get_newer;
13371         }
13372 #ifdef ENABLE_COMPRESSION
13373         /* FIXME - do we support this at all? */
13374         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13375                 bb_error_msg(_("warning: compression support is experimental"));
13376 #endif
13377 #ifndef ENABLE_HTREE
13378         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13379                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13380                           "but filesystem %s has HTREE directories."),
13381                         ctx->device_name);
13382                 goto get_newer;
13383         }
13384 #endif
13385
13386         /*
13387          * If the user specified a specific superblock, presumably the
13388          * master superblock has been trashed.  So we mark the
13389          * superblock as dirty, so it can be written out.
13390          */
13391         if (ctx->superblock &&
13392             !(ctx->options & E2F_OPT_READONLY))
13393                 ext2fs_mark_super_dirty(fs);
13394
13395         /*
13396          * We only update the master superblock because (a) paranoia;
13397          * we don't want to corrupt the backup superblocks, and (b) we
13398          * don't need to update the mount count and last checked
13399          * fields in the backup superblock (the kernel doesn't
13400          * update the backup superblocks anyway).
13401          */
13402         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13403
13404         ehandler_init(fs->io);
13405
13406         if (ctx->superblock)
13407                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13408         ext2fs_mark_valid(fs);
13409         check_super_block(ctx);
13410         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13411                 bb_error_msg_and_die(0);
13412         check_if_skip(ctx);
13413         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13414                 bb_error_msg_and_die(0);
13415 #ifdef ENABLE_SWAPFS
13416
13417 #ifdef WORDS_BIGENDIAN
13418 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13419 #else
13420 #define NATIVE_FLAG 0
13421 #endif
13422
13423
13424         if (normalize_swapfs) {
13425                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13426                         fprintf(stderr, _("%s: Filesystem byte order "
13427                                 "already normalized.\n"), ctx->device_name);
13428                         bb_error_msg_and_die(0);
13429                 }
13430         }
13431         if (swapfs) {
13432                 swap_filesys(ctx);
13433                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13434                         bb_error_msg_and_die(0);
13435         }
13436 #endif
13437
13438         /*
13439          * Mark the system as valid, 'til proven otherwise
13440          */
13441         ext2fs_mark_valid(fs);
13442
13443         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13444         if (retval) {
13445                 bb_error_msg(_("while reading bad blocks inode"));
13446                 preenhalt(ctx);
13447                 printf(_("This doesn't bode well,"
13448                          " but we'll try to go on...\n"));
13449         }
13450
13451         run_result = e2fsck_run(ctx);
13452         e2fsck_clear_progbar(ctx);
13453         if (run_result == E2F_FLAG_RESTART) {
13454                 printf(_("Restarting e2fsck from the beginning...\n"));
13455                 retval = e2fsck_reset_context(ctx);
13456                 if (retval) {
13457                         bb_error_msg(_("while resetting context"));
13458                         bb_error_msg_and_die(0);
13459                 }
13460                 ext2fs_close(fs);
13461                 goto restart;
13462         }
13463         if (run_result & E2F_FLAG_CANCEL) {
13464                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13465                        ctx->device_name : ctx->filesystem_name);
13466                 exit_value |= FSCK_CANCELED;
13467         }
13468         if (run_result & E2F_FLAG_ABORT)
13469                 bb_error_msg_and_die(_("aborted"));
13470
13471         /* Cleanup */
13472         if (ext2fs_test_changed(fs)) {
13473                 exit_value |= EXIT_NONDESTRUCT;
13474                 if (!(ctx->options & E2F_OPT_PREEN))
13475                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13476                                ctx->device_name);
13477                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13478                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13479                                ctx->device_name);
13480                         exit_value |= EXIT_DESTRUCT;
13481                 }
13482         }
13483         if (!ext2fs_test_valid(fs)) {
13484                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13485                          "errors **********\n\n"), ctx->device_name);
13486                 exit_value |= EXIT_UNCORRECTED;
13487                 exit_value &= ~EXIT_NONDESTRUCT;
13488         }
13489         if (exit_value & FSCK_CANCELED)
13490                 exit_value &= ~EXIT_NONDESTRUCT;
13491         else {
13492                 show_stats(ctx);
13493                 if (!(ctx->options & E2F_OPT_READONLY)) {
13494                         if (ext2fs_test_valid(fs)) {
13495                                 if (!(sb->s_state & EXT2_VALID_FS))
13496                                         exit_value |= EXIT_NONDESTRUCT;
13497                                 sb->s_state = EXT2_VALID_FS;
13498                         } else
13499                                 sb->s_state &= ~EXT2_VALID_FS;
13500                         sb->s_mnt_count = 0;
13501                         sb->s_lastcheck = time(NULL);
13502                         ext2fs_mark_super_dirty(fs);
13503                 }
13504         }
13505
13506         e2fsck_write_bitmaps(ctx);
13507
13508         ext2fs_close(fs);
13509         ctx->fs = NULL;
13510         free(ctx->filesystem_name);
13511         free(ctx->journal_name);
13512         e2fsck_free_context(ctx);
13513
13514         return exit_value;
13515 }