77edbd871376e457ed90cc77e7ffb2ad1541feb2
[oweals/busybox.git] / e2fsprogs / e2fsck.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * e2fsck
4  *
5  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6  * Copyright (C) 2006 Garrett Kajmowicz
7  *
8  * Dictionary Abstract Data Type
9  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10  * Free Software License:
11  * All rights are reserved by the author, with the following exceptions:
12  * Permission is granted to freely reproduce and distribute this software,
13  * possibly in exchange for a fee, provided that this copyright notice appears
14  * intact. Permission is also granted to adapt this software to produce
15  * derivative works, as long as the modified versions carry this copyright
16  * notice and additional notices stating that the work has been modified.
17  * This source code may be translated into executable form and incorporated
18  * into proprietary software; there is no requirement for such software to
19  * contain a copyright notice related to this source.
20  *
21  * linux/fs/recovery  and linux/fs/revoke
22  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23  *
24  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25  *
26  * Journal recovery routines for the generic filesystem journaling code;
27  * part of the ext2fs journaling system.
28  *
29  * Licensed under GPLv2 or later, see file License in this tarball for details.
30  */
31
32 #ifndef _GNU_SOURCE
33 #define _GNU_SOURCE 1 /* get strnlen() */
34 #endif
35
36 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
37
38 #define _(x) x
39 #define N_(x) x
40
41 /*
42  * Procedure declarations
43  */
44
45 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
46
47 /* pass1.c */
48 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
49
50 /* pass2.c */
51 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
52                                     ext2_ino_t ino, char *buf);
53
54 /* pass3.c */
55 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
56 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
57                                          int num, int gauranteed_size);
58 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
59 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
60                                            int adj);
61
62 /* rehash.c */
63 static void e2fsck_rehash_directories(e2fsck_t ctx);
64
65 /* util.c */
66 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
67                                     const char *description);
68 static int ask(e2fsck_t ctx, const char * string, int def);
69 static void e2fsck_read_bitmaps(e2fsck_t ctx);
70 static void preenhalt(e2fsck_t ctx);
71 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
72                               struct ext2_inode * inode, const char * proc);
73 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
74                                struct ext2_inode * inode, const char * proc);
75 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
76                            const char *name, io_manager manager);
77
78 /* unix.c */
79 static void e2fsck_clear_progbar(e2fsck_t ctx);
80 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
81                                   float percent, unsigned int dpynum);
82
83
84 /*
85  * problem.h --- e2fsck problem error codes
86  */
87
88 typedef __u32 problem_t;
89
90 struct problem_context {
91         errcode_t       errcode;
92         ext2_ino_t ino, ino2, dir;
93         struct ext2_inode *inode;
94         struct ext2_dir_entry *dirent;
95         blk_t   blk, blk2;
96         e2_blkcnt_t     blkcount;
97         int             group;
98         __u64   num;
99         const char *str;
100 };
101
102
103 /*
104  * Function declarations
105  */
106 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
107 static int end_problem_latch(e2fsck_t ctx, int mask);
108 static int set_latch_flags(int mask, int setflags, int clearflags);
109 static void clear_problem_context(struct problem_context *ctx);
110
111 /*
112  * Dictionary Abstract Data Type
113  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
114  *
115  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
116  * kazlib_1_20
117  */
118
119 #ifndef DICT_H
120 #define DICT_H
121
122 /*
123  * Blurb for inclusion into C++ translation units
124  */
125
126 typedef unsigned long dictcount_t;
127 #define DICTCOUNT_T_MAX ULONG_MAX
128
129 /*
130  * The dictionary is implemented as a red-black tree
131  */
132
133 typedef enum { dnode_red, dnode_black } dnode_color_t;
134
135 typedef struct dnode_t {
136     struct dnode_t *dict_left;
137     struct dnode_t *dict_right;
138     struct dnode_t *dict_parent;
139     dnode_color_t dict_color;
140     const void *dict_key;
141     void *dict_data;
142 } dnode_t;
143
144 typedef int (*dict_comp_t)(const void *, const void *);
145 typedef void (*dnode_free_t)(dnode_t *);
146
147 typedef struct dict_t {
148     dnode_t dict_nilnode;
149     dictcount_t dict_nodecount;
150     dictcount_t dict_maxcount;
151     dict_comp_t dict_compare;
152     dnode_free_t dict_freenode;
153     int dict_dupes;
154 } dict_t;
155
156 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
157
158 typedef struct dict_load_t {
159     dict_t *dict_dictptr;
160     dnode_t dict_nilnode;
161 } dict_load_t;
162
163 #define dict_count(D) ((D)->dict_nodecount)
164 #define dnode_get(N) ((N)->dict_data)
165 #define dnode_getkey(N) ((N)->dict_key)
166
167 #endif
168
169 /*
170  * Compatibility header file for e2fsck which should be included
171  * instead of linux/jfs.h
172  *
173  * Copyright (C) 2000 Stephen C. Tweedie
174  */
175
176 /*
177  * Pull in the definition of the e2fsck context structure
178  */
179
180 struct buffer_head {
181         char            b_data[8192];
182         e2fsck_t        b_ctx;
183         io_channel      b_io;
184         int             b_size;
185         blk_t           b_blocknr;
186         int             b_dirty;
187         int             b_uptodate;
188         int             b_err;
189 };
190
191
192 #define K_DEV_FS        1
193 #define K_DEV_JOURNAL   2
194
195 #define lock_buffer(bh) do {} while(0)
196 #define unlock_buffer(bh) do {} while(0)
197 #define buffer_req(bh) 1
198 #define do_readahead(journal, start) do {} while(0)
199
200 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
201
202 typedef struct {
203         int     object_length;
204 } kmem_cache_t;
205
206 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
207
208 /*
209  * We use the standard libext2fs portability tricks for inline
210  * functions.
211  */
212
213 static kmem_cache_t * do_cache_create(int len)
214 {
215         kmem_cache_t *new_cache;
216
217         new_cache = malloc(sizeof(*new_cache));
218         if (new_cache)
219                 new_cache->object_length = len;
220         return new_cache;
221 }
222
223 static void do_cache_destroy(kmem_cache_t *cache)
224 {
225         free(cache);
226 }
227
228
229 /*
230  * Dictionary Abstract Data Type
231  */
232
233
234 /*
235  * These macros provide short convenient names for structure members,
236  * which are embellished with dict_ prefixes so that they are
237  * properly confined to the documented namespace. It's legal for a
238  * program which uses dict to define, for instance, a macro called ``parent''.
239  * Such a macro would interfere with the dnode_t struct definition.
240  * In general, highly portable and reusable C modules which expose their
241  * structures need to confine structure member names to well-defined spaces.
242  * The resulting identifiers aren't necessarily convenient to use, nor
243  * readable, in the implementation, however!
244  */
245
246 #define left dict_left
247 #define right dict_right
248 #define parent dict_parent
249 #define color dict_color
250 #define key dict_key
251 #define data dict_data
252
253 #define nilnode dict_nilnode
254 #define maxcount dict_maxcount
255 #define compare dict_compare
256 #define dupes dict_dupes
257
258 #define dict_root(D) ((D)->nilnode.left)
259 #define dict_nil(D) (&(D)->nilnode)
260
261 static void dnode_free(dnode_t *node);
262
263 /*
264  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
265  * its right child C are rearranged so that the P instead becomes the left
266  * child of C.   The left subtree of C is inherited as the new right subtree
267  * for P.  The ordering of the keys within the tree is thus preserved.
268  */
269
270 static void rotate_left(dnode_t *upper)
271 {
272     dnode_t *lower, *lowleft, *upparent;
273
274     lower = upper->right;
275     upper->right = lowleft = lower->left;
276     lowleft->parent = upper;
277
278     lower->parent = upparent = upper->parent;
279
280     /* don't need to check for root node here because root->parent is
281        the sentinel nil node, and root->parent->left points back to root */
282
283     if (upper == upparent->left) {
284         upparent->left = lower;
285     } else {
286         assert (upper == upparent->right);
287         upparent->right = lower;
288     }
289
290     lower->left = upper;
291     upper->parent = lower;
292 }
293
294 /*
295  * This operation is the ``mirror'' image of rotate_left. It is
296  * the same procedure, but with left and right interchanged.
297  */
298
299 static void rotate_right(dnode_t *upper)
300 {
301     dnode_t *lower, *lowright, *upparent;
302
303     lower = upper->left;
304     upper->left = lowright = lower->right;
305     lowright->parent = upper;
306
307     lower->parent = upparent = upper->parent;
308
309     if (upper == upparent->right) {
310         upparent->right = lower;
311     } else {
312         assert (upper == upparent->left);
313         upparent->left = lower;
314     }
315
316     lower->right = upper;
317     upper->parent = lower;
318 }
319
320 /*
321  * Do a postorder traversal of the tree rooted at the specified
322  * node and free everything under it.  Used by dict_free().
323  */
324
325 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
326 {
327     if (node == nil)
328         return;
329     free_nodes(dict, node->left, nil);
330     free_nodes(dict, node->right, nil);
331     dict->dict_freenode(node);
332 }
333
334 /*
335  * Verify that the tree contains the given node. This is done by
336  * traversing all of the nodes and comparing their pointers to the
337  * given pointer. Returns 1 if the node is found, otherwise
338  * returns zero. It is intended for debugging purposes.
339  */
340
341 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
342 {
343     if (root != nil) {
344         return root == node
345                 || verify_dict_has_node(nil, root->left, node)
346                 || verify_dict_has_node(nil, root->right, node);
347     }
348     return 0;
349 }
350
351
352 /*
353  * Select a different set of node allocator routines.
354  */
355
356 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
357 {
358     assert (dict_count(dict) == 0);
359     dict->dict_freenode = fr;
360 }
361
362 /*
363  * Free all the nodes in the dictionary by using the dictionary's
364  * installed free routine. The dictionary is emptied.
365  */
366
367 static void dict_free_nodes(dict_t *dict)
368 {
369     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
370     free_nodes(dict, root, nil);
371     dict->dict_nodecount = 0;
372     dict->nilnode.left = &dict->nilnode;
373     dict->nilnode.right = &dict->nilnode;
374 }
375
376 /*
377  * Initialize a user-supplied dictionary object.
378  */
379
380 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
381 {
382     dict->compare = comp;
383     dict->dict_freenode = dnode_free;
384     dict->dict_nodecount = 0;
385     dict->maxcount = maxcount;
386     dict->nilnode.left = &dict->nilnode;
387     dict->nilnode.right = &dict->nilnode;
388     dict->nilnode.parent = &dict->nilnode;
389     dict->nilnode.color = dnode_black;
390     dict->dupes = 0;
391     return dict;
392 }
393
394 /*
395  * Locate a node in the dictionary having the given key.
396  * If the node is not found, a null a pointer is returned (rather than
397  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
398  * located node is returned.
399  */
400
401 static dnode_t *dict_lookup(dict_t *dict, const void *key)
402 {
403     dnode_t *root = dict_root(dict);
404     dnode_t *nil = dict_nil(dict);
405     dnode_t *saved;
406     int result;
407
408     /* simple binary search adapted for trees that contain duplicate keys */
409
410     while (root != nil) {
411         result = dict->compare(key, root->key);
412         if (result < 0)
413             root = root->left;
414         else if (result > 0)
415             root = root->right;
416         else {
417             if (!dict->dupes) { /* no duplicates, return match          */
418                 return root;
419             } else {            /* could be dupes, find leftmost one    */
420                 do {
421                     saved = root;
422                     root = root->left;
423                     while (root != nil && dict->compare(key, root->key))
424                         root = root->right;
425                 } while (root != nil);
426                 return saved;
427             }
428         }
429     }
430
431     return NULL;
432 }
433
434 /*
435  * Insert a node into the dictionary. The node should have been
436  * initialized with a data field. All other fields are ignored.
437  * The behavior is undefined if the user attempts to insert into
438  * a dictionary that is already full (for which the dict_isfull()
439  * function returns true).
440  */
441
442 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
443 {
444     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
445     dnode_t *parent = nil, *uncle, *grandpa;
446     int result = -1;
447
448     node->key = key;
449
450     /* basic binary tree insert */
451
452     while (where != nil) {
453         parent = where;
454         result = dict->compare(key, where->key);
455         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
456         assert (dict->dupes || result != 0);
457         if (result < 0)
458             where = where->left;
459         else
460             where = where->right;
461     }
462
463     assert (where == nil);
464
465     if (result < 0)
466         parent->left = node;
467     else
468         parent->right = node;
469
470     node->parent = parent;
471     node->left = nil;
472     node->right = nil;
473
474     dict->dict_nodecount++;
475
476     /* red black adjustments */
477
478     node->color = dnode_red;
479
480     while (parent->color == dnode_red) {
481         grandpa = parent->parent;
482         if (parent == grandpa->left) {
483             uncle = grandpa->right;
484             if (uncle->color == dnode_red) {    /* red parent, red uncle */
485                 parent->color = dnode_black;
486                 uncle->color = dnode_black;
487                 grandpa->color = dnode_red;
488                 node = grandpa;
489                 parent = grandpa->parent;
490             } else {                            /* red parent, black uncle */
491                 if (node == parent->right) {
492                     rotate_left(parent);
493                     parent = node;
494                     assert (grandpa == parent->parent);
495                     /* rotation between parent and child preserves grandpa */
496                 }
497                 parent->color = dnode_black;
498                 grandpa->color = dnode_red;
499                 rotate_right(grandpa);
500                 break;
501             }
502         } else {        /* symmetric cases: parent == parent->parent->right */
503             uncle = grandpa->left;
504             if (uncle->color == dnode_red) {
505                 parent->color = dnode_black;
506                 uncle->color = dnode_black;
507                 grandpa->color = dnode_red;
508                 node = grandpa;
509                 parent = grandpa->parent;
510             } else {
511                 if (node == parent->left) {
512                     rotate_right(parent);
513                     parent = node;
514                     assert (grandpa == parent->parent);
515                 }
516                 parent->color = dnode_black;
517                 grandpa->color = dnode_red;
518                 rotate_left(grandpa);
519                 break;
520             }
521         }
522     }
523
524     dict_root(dict)->color = dnode_black;
525
526 }
527
528 /*
529  * Allocate a node using the dictionary's allocator routine, give it
530  * the data item.
531  */
532
533 static dnode_t *dnode_init(dnode_t *dnode, void *data)
534 {
535     dnode->data = data;
536     dnode->parent = NULL;
537     dnode->left = NULL;
538     dnode->right = NULL;
539     return dnode;
540 }
541
542 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
543 {
544     dnode_t *node = malloc(sizeof(dnode_t));
545
546     if (node) {
547         dnode_init(node, data);
548         dict_insert(dict, node, key);
549         return 1;
550     }
551     return 0;
552 }
553
554 /*
555  * Return the node with the lowest (leftmost) key. If the dictionary is empty
556  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
557  */
558
559 static dnode_t *dict_first(dict_t *dict)
560 {
561     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
562
563     if (root != nil)
564         while ((left = root->left) != nil)
565             root = left;
566
567     return (root == nil) ? NULL : root;
568 }
569
570 /*
571  * Return the given node's successor node---the node which has the
572  * next key in the the left to right ordering. If the node has
573  * no successor, a null pointer is returned rather than a pointer to
574  * the nil node.
575  */
576
577 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
578 {
579     dnode_t *nil = dict_nil(dict), *parent, *left;
580
581     if (curr->right != nil) {
582         curr = curr->right;
583         while ((left = curr->left) != nil)
584             curr = left;
585         return curr;
586     }
587
588     parent = curr->parent;
589
590     while (parent != nil && curr == parent->right) {
591         curr = parent;
592         parent = curr->parent;
593     }
594
595     return (parent == nil) ? NULL : parent;
596 }
597
598
599 static void dnode_free(dnode_t *node)
600 {
601     free(node);
602 }
603
604
605 #undef left
606 #undef right
607 #undef parent
608 #undef color
609 #undef key
610 #undef data
611
612 #undef nilnode
613 #undef maxcount
614 #undef compare
615 #undef dupes
616
617
618 /*
619  * dirinfo.c --- maintains the directory information table for e2fsck.
620  */
621
622 /*
623  * This subroutine is called during pass1 to create a directory info
624  * entry.  During pass1, the passed-in parent is 0; it will get filled
625  * in during pass2.
626  */
627 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
628 {
629         struct dir_info *dir;
630         int             i, j;
631         ext2_ino_t      num_dirs;
632         errcode_t       retval;
633         unsigned long   old_size;
634
635         if (!ctx->dir_info) {
636                 ctx->dir_info_count = 0;
637                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
638                 if (retval)
639                         num_dirs = 1024;        /* Guess */
640                 ctx->dir_info_size = num_dirs + 10;
641                 ctx->dir_info  = (struct dir_info *)
642                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
643                                                * sizeof (struct dir_info),
644                                                "directory map");
645         }
646
647         if (ctx->dir_info_count >= ctx->dir_info_size) {
648                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
649                 ctx->dir_info_size += 10;
650                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
651                                            sizeof(struct dir_info),
652                                            &ctx->dir_info);
653                 if (retval) {
654                         ctx->dir_info_size -= 10;
655                         return;
656                 }
657         }
658
659         /*
660          * Normally, add_dir_info is called with each inode in
661          * sequential order; but once in a while (like when pass 3
662          * needs to recreate the root directory or lost+found
663          * directory) it is called out of order.  In those cases, we
664          * need to move the dir_info entries down to make room, since
665          * the dir_info array needs to be sorted by inode number for
666          * get_dir_info()'s sake.
667          */
668         if (ctx->dir_info_count &&
669             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
670                 for (i = ctx->dir_info_count-1; i > 0; i--)
671                         if (ctx->dir_info[i-1].ino < ino)
672                                 break;
673                 dir = &ctx->dir_info[i];
674                 if (dir->ino != ino)
675                         for (j = ctx->dir_info_count++; j > i; j--)
676                                 ctx->dir_info[j] = ctx->dir_info[j-1];
677         } else
678                 dir = &ctx->dir_info[ctx->dir_info_count++];
679
680         dir->ino = ino;
681         dir->dotdot = parent;
682         dir->parent = parent;
683 }
684
685 /*
686  * get_dir_info() --- given an inode number, try to find the directory
687  * information entry for it.
688  */
689 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
690 {
691         int     low, high, mid;
692
693         low = 0;
694         high = ctx->dir_info_count-1;
695         if (!ctx->dir_info)
696                 return 0;
697         if (ino == ctx->dir_info[low].ino)
698                 return &ctx->dir_info[low];
699         if  (ino == ctx->dir_info[high].ino)
700                 return &ctx->dir_info[high];
701
702         while (low < high) {
703                 mid = (low+high)/2;
704                 if (mid == low || mid == high)
705                         break;
706                 if (ino == ctx->dir_info[mid].ino)
707                         return &ctx->dir_info[mid];
708                 if (ino < ctx->dir_info[mid].ino)
709                         high = mid;
710                 else
711                         low = mid;
712         }
713         return 0;
714 }
715
716 /*
717  * Free the dir_info structure when it isn't needed any more.
718  */
719 static void e2fsck_free_dir_info(e2fsck_t ctx)
720 {
721         ext2fs_free_mem(&ctx->dir_info);
722         ctx->dir_info_size = 0;
723         ctx->dir_info_count = 0;
724 }
725
726 /*
727  * Return the count of number of directories in the dir_info structure
728  */
729 static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
730 {
731         return ctx->dir_info_count;
732 }
733
734 /*
735  * A simple interator function
736  */
737 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
738 {
739         if (*control >= ctx->dir_info_count)
740                 return 0;
741
742         return(ctx->dir_info + (*control)++);
743 }
744
745 /*
746  * dirinfo.c --- maintains the directory information table for e2fsck.
747  *
748  */
749
750 #ifdef ENABLE_HTREE
751
752 /*
753  * This subroutine is called during pass1 to create a directory info
754  * entry.  During pass1, the passed-in parent is 0; it will get filled
755  * in during pass2.
756  */
757 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
758 {
759         struct dx_dir_info *dir;
760         int             i, j;
761         errcode_t       retval;
762         unsigned long   old_size;
763
764         if (!ctx->dx_dir_info) {
765                 ctx->dx_dir_info_count = 0;
766                 ctx->dx_dir_info_size = 100; /* Guess */
767                 ctx->dx_dir_info  = (struct dx_dir_info *)
768                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
769                                                * sizeof (struct dx_dir_info),
770                                                "directory map");
771         }
772
773         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
774                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
775                 ctx->dx_dir_info_size += 10;
776                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
777                                            sizeof(struct dx_dir_info),
778                                            &ctx->dx_dir_info);
779                 if (retval) {
780                         ctx->dx_dir_info_size -= 10;
781                         return;
782                 }
783         }
784
785         /*
786          * Normally, add_dx_dir_info is called with each inode in
787          * sequential order; but once in a while (like when pass 3
788          * needs to recreate the root directory or lost+found
789          * directory) it is called out of order.  In those cases, we
790          * need to move the dx_dir_info entries down to make room, since
791          * the dx_dir_info array needs to be sorted by inode number for
792          * get_dx_dir_info()'s sake.
793          */
794         if (ctx->dx_dir_info_count &&
795             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
796                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
797                         if (ctx->dx_dir_info[i-1].ino < ino)
798                                 break;
799                 dir = &ctx->dx_dir_info[i];
800                 if (dir->ino != ino)
801                         for (j = ctx->dx_dir_info_count++; j > i; j--)
802                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
803         } else
804                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
805
806         dir->ino = ino;
807         dir->numblocks = num_blocks;
808         dir->hashversion = 0;
809         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
810                                        * sizeof (struct dx_dirblock_info),
811                                        "dx_block info array");
812
813 }
814
815 /*
816  * get_dx_dir_info() --- given an inode number, try to find the directory
817  * information entry for it.
818  */
819 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
820 {
821         int     low, high, mid;
822
823         low = 0;
824         high = ctx->dx_dir_info_count-1;
825         if (!ctx->dx_dir_info)
826                 return 0;
827         if (ino == ctx->dx_dir_info[low].ino)
828                 return &ctx->dx_dir_info[low];
829         if  (ino == ctx->dx_dir_info[high].ino)
830                 return &ctx->dx_dir_info[high];
831
832         while (low < high) {
833                 mid = (low+high)/2;
834                 if (mid == low || mid == high)
835                         break;
836                 if (ino == ctx->dx_dir_info[mid].ino)
837                         return &ctx->dx_dir_info[mid];
838                 if (ino < ctx->dx_dir_info[mid].ino)
839                         high = mid;
840                 else
841                         low = mid;
842         }
843         return 0;
844 }
845
846 /*
847  * Free the dx_dir_info structure when it isn't needed any more.
848  */
849 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
850 {
851         int     i;
852         struct dx_dir_info *dir;
853
854         if (ctx->dx_dir_info) {
855                 dir = ctx->dx_dir_info;
856                 for (i=0; i < ctx->dx_dir_info_count; i++) {
857                         ext2fs_free_mem(&dir->dx_block);
858                 }
859                 ext2fs_free_mem(&ctx->dx_dir_info);
860         }
861         ctx->dx_dir_info_size = 0;
862         ctx->dx_dir_info_count = 0;
863 }
864
865 /*
866  * A simple interator function
867  */
868 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
869 {
870         if (*control >= ctx->dx_dir_info_count)
871                 return 0;
872
873         return(ctx->dx_dir_info + (*control)++);
874 }
875
876 #endif /* ENABLE_HTREE */
877 /*
878  * e2fsck.c - a consistency checker for the new extended file system.
879  *
880  */
881
882 /*
883  * This function allocates an e2fsck context
884  */
885 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
886 {
887         e2fsck_t        context;
888         errcode_t       retval;
889
890         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
891         if (retval)
892                 return retval;
893
894         memset(context, 0, sizeof(struct e2fsck_struct));
895
896         context->process_inode_size = 256;
897         context->ext_attr_ver = 2;
898
899         *ret = context;
900         return 0;
901 }
902
903 struct ea_refcount_el {
904         blk_t   ea_blk;
905         int     ea_count;
906 };
907
908 struct ea_refcount {
909         blk_t           count;
910         blk_t           size;
911         blk_t           cursor;
912         struct ea_refcount_el   *list;
913 };
914
915 static void ea_refcount_free(ext2_refcount_t refcount)
916 {
917         if (!refcount)
918                 return;
919
920         ext2fs_free_mem(&refcount->list);
921         ext2fs_free_mem(&refcount);
922 }
923
924 /*
925  * This function resets an e2fsck context; it is called when e2fsck
926  * needs to be restarted.
927  */
928 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
929 {
930         ctx->flags = 0;
931         ctx->lost_and_found = 0;
932         ctx->bad_lost_and_found = 0;
933         ext2fs_free_inode_bitmap(ctx->inode_used_map);
934         ctx->inode_used_map = 0;
935         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
936         ctx->inode_dir_map = 0;
937         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
938         ctx->inode_reg_map = 0;
939         ext2fs_free_block_bitmap(ctx->block_found_map);
940         ctx->block_found_map = 0;
941         ext2fs_free_icount(ctx->inode_link_info);
942         ctx->inode_link_info = 0;
943         if (ctx->journal_io) {
944                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
945                         io_channel_close(ctx->journal_io);
946                 ctx->journal_io = 0;
947         }
948         if (ctx->fs) {
949                 ext2fs_free_dblist(ctx->fs->dblist);
950                 ctx->fs->dblist = 0;
951         }
952         e2fsck_free_dir_info(ctx);
953 #ifdef ENABLE_HTREE
954         e2fsck_free_dx_dir_info(ctx);
955 #endif
956         ea_refcount_free(ctx->refcount);
957         ctx->refcount = 0;
958         ea_refcount_free(ctx->refcount_extra);
959         ctx->refcount_extra = 0;
960         ext2fs_free_block_bitmap(ctx->block_dup_map);
961         ctx->block_dup_map = 0;
962         ext2fs_free_block_bitmap(ctx->block_ea_map);
963         ctx->block_ea_map = 0;
964         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
965         ctx->inode_bad_map = 0;
966         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
967         ctx->inode_imagic_map = 0;
968         ext2fs_u32_list_free(ctx->dirs_to_hash);
969         ctx->dirs_to_hash = 0;
970
971         /*
972          * Clear the array of invalid meta-data flags
973          */
974         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
975         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
976         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
977
978         /* Clear statistic counters */
979         ctx->fs_directory_count = 0;
980         ctx->fs_regular_count = 0;
981         ctx->fs_blockdev_count = 0;
982         ctx->fs_chardev_count = 0;
983         ctx->fs_links_count = 0;
984         ctx->fs_symlinks_count = 0;
985         ctx->fs_fast_symlinks_count = 0;
986         ctx->fs_fifo_count = 0;
987         ctx->fs_total_count = 0;
988         ctx->fs_sockets_count = 0;
989         ctx->fs_ind_count = 0;
990         ctx->fs_dind_count = 0;
991         ctx->fs_tind_count = 0;
992         ctx->fs_fragmented = 0;
993         ctx->large_files = 0;
994
995         /* Reset the superblock to the user's requested value */
996         ctx->superblock = ctx->use_superblock;
997
998         return 0;
999 }
1000
1001 static void e2fsck_free_context(e2fsck_t ctx)
1002 {
1003         if (!ctx)
1004                 return;
1005
1006         e2fsck_reset_context(ctx);
1007         if (ctx->blkid)
1008                 blkid_put_cache(ctx->blkid);
1009
1010         ext2fs_free_mem(&ctx);
1011 }
1012
1013 /*
1014  * ea_refcount.c
1015  */
1016
1017 /*
1018  * The strategy we use for keeping track of EA refcounts is as
1019  * follows.  We keep a sorted array of first EA blocks and its
1020  * reference counts.  Once the refcount has dropped to zero, it is
1021  * removed from the array to save memory space.  Once the EA block is
1022  * checked, its bit is set in the block_ea_map bitmap.
1023  */
1024
1025
1026 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1027 {
1028         ext2_refcount_t refcount;
1029         errcode_t       retval;
1030         size_t          bytes;
1031
1032         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1033         if (retval)
1034                 return retval;
1035         memset(refcount, 0, sizeof(struct ea_refcount));
1036
1037         if (!size)
1038                 size = 500;
1039         refcount->size = size;
1040         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1041 #ifdef DEBUG
1042         printf("Refcount allocated %d entries, %d bytes.\n",
1043                refcount->size, bytes);
1044 #endif
1045         retval = ext2fs_get_mem(bytes, &refcount->list);
1046         if (retval)
1047                 goto errout;
1048         memset(refcount->list, 0, bytes);
1049
1050         refcount->count = 0;
1051         refcount->cursor = 0;
1052
1053         *ret = refcount;
1054         return 0;
1055
1056 errout:
1057         ea_refcount_free(refcount);
1058         return(retval);
1059 }
1060
1061 /*
1062  * collapse_refcount() --- go through the refcount array, and get rid
1063  * of any count == zero entries
1064  */
1065 static void refcount_collapse(ext2_refcount_t refcount)
1066 {
1067         unsigned int    i, j;
1068         struct ea_refcount_el   *list;
1069
1070         list = refcount->list;
1071         for (i = 0, j = 0; i < refcount->count; i++) {
1072                 if (list[i].ea_count) {
1073                         if (i != j)
1074                                 list[j] = list[i];
1075                         j++;
1076                 }
1077         }
1078 #if defined(DEBUG) || defined(TEST_PROGRAM)
1079         printf("Refcount_collapse: size was %d, now %d\n",
1080                refcount->count, j);
1081 #endif
1082         refcount->count = j;
1083 }
1084
1085
1086 /*
1087  * insert_refcount_el() --- Insert a new entry into the sorted list at a
1088  *      specified position.
1089  */
1090 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1091                                                  blk_t blk, int pos)
1092 {
1093         struct ea_refcount_el   *el;
1094         errcode_t               retval;
1095         blk_t                   new_size = 0;
1096         int                     num;
1097
1098         if (refcount->count >= refcount->size) {
1099                 new_size = refcount->size + 100;
1100 #ifdef DEBUG
1101                 printf("Reallocating refcount %d entries...\n", new_size);
1102 #endif
1103                 retval = ext2fs_resize_mem((size_t) refcount->size *
1104                                            sizeof(struct ea_refcount_el),
1105                                            (size_t) new_size *
1106                                            sizeof(struct ea_refcount_el),
1107                                            &refcount->list);
1108                 if (retval)
1109                         return 0;
1110                 refcount->size = new_size;
1111         }
1112         num = (int) refcount->count - pos;
1113         if (num < 0)
1114                 return 0;       /* should never happen */
1115         if (num) {
1116                 memmove(&refcount->list[pos+1], &refcount->list[pos],
1117                         sizeof(struct ea_refcount_el) * num);
1118         }
1119         refcount->count++;
1120         el = &refcount->list[pos];
1121         el->ea_count = 0;
1122         el->ea_blk = blk;
1123         return el;
1124 }
1125
1126
1127 /*
1128  * get_refcount_el() --- given an block number, try to find refcount
1129  *      information in the sorted list.  If the create flag is set,
1130  *      and we can't find an entry, create one in the sorted list.
1131  */
1132 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1133                                               blk_t blk, int create)
1134 {
1135         float   range;
1136         int     low, high, mid;
1137         blk_t   lowval, highval;
1138
1139         if (!refcount || !refcount->list)
1140                 return 0;
1141 retry:
1142         low = 0;
1143         high = (int) refcount->count-1;
1144         if (create && ((refcount->count == 0) ||
1145                        (blk > refcount->list[high].ea_blk))) {
1146                 if (refcount->count >= refcount->size)
1147                         refcount_collapse(refcount);
1148
1149                 return insert_refcount_el(refcount, blk,
1150                                           (unsigned) refcount->count);
1151         }
1152         if (refcount->count == 0)
1153                 return 0;
1154
1155         if (refcount->cursor >= refcount->count)
1156                 refcount->cursor = 0;
1157         if (blk == refcount->list[refcount->cursor].ea_blk)
1158                 return &refcount->list[refcount->cursor++];
1159 #ifdef DEBUG
1160         printf("Non-cursor get_refcount_el: %u\n", blk);
1161 #endif
1162         while (low <= high) {
1163                 if (low == high)
1164                         mid = low;
1165                 else {
1166                         /* Interpolate for efficiency */
1167                         lowval = refcount->list[low].ea_blk;
1168                         highval = refcount->list[high].ea_blk;
1169
1170                         if (blk < lowval)
1171                                 range = 0;
1172                         else if (blk > highval)
1173                                 range = 1;
1174                         else
1175                                 range = ((float) (blk - lowval)) /
1176                                         (highval - lowval);
1177                         mid = low + ((int) (range * (high-low)));
1178                 }
1179
1180                 if (blk == refcount->list[mid].ea_blk) {
1181                         refcount->cursor = mid+1;
1182                         return &refcount->list[mid];
1183                 }
1184                 if (blk < refcount->list[mid].ea_blk)
1185                         high = mid-1;
1186                 else
1187                         low = mid+1;
1188         }
1189         /*
1190          * If we need to create a new entry, it should be right at
1191          * low (where high will be left at low-1).
1192          */
1193         if (create) {
1194                 if (refcount->count >= refcount->size) {
1195                         refcount_collapse(refcount);
1196                         if (refcount->count < refcount->size)
1197                                 goto retry;
1198                 }
1199                 return insert_refcount_el(refcount, blk, low);
1200         }
1201         return 0;
1202 }
1203
1204 static errcode_t
1205 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1206 {
1207         struct ea_refcount_el   *el;
1208
1209         el = get_refcount_el(refcount, blk, 1);
1210         if (!el)
1211                 return EXT2_ET_NO_MEMORY;
1212         el->ea_count++;
1213
1214         if (ret)
1215                 *ret = el->ea_count;
1216         return 0;
1217 }
1218
1219 static errcode_t
1220 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1221 {
1222         struct ea_refcount_el   *el;
1223
1224         el = get_refcount_el(refcount, blk, 0);
1225         if (!el || el->ea_count == 0)
1226                 return EXT2_ET_INVALID_ARGUMENT;
1227
1228         el->ea_count--;
1229
1230         if (ret)
1231                 *ret = el->ea_count;
1232         return 0;
1233 }
1234
1235 static errcode_t
1236 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1237 {
1238         struct ea_refcount_el   *el;
1239
1240         /*
1241          * Get the refcount element
1242          */
1243         el = get_refcount_el(refcount, blk, count ? 1 : 0);
1244         if (!el)
1245                 return count ? EXT2_ET_NO_MEMORY : 0;
1246         el->ea_count = count;
1247         return 0;
1248 }
1249
1250 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1251 {
1252         refcount->cursor = 0;
1253 }
1254
1255
1256 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1257 {
1258         struct ea_refcount_el   *list;
1259
1260         while (1) {
1261                 if (refcount->cursor >= refcount->count)
1262                         return 0;
1263                 list = refcount->list;
1264                 if (list[refcount->cursor].ea_count) {
1265                         if (ret)
1266                                 *ret = list[refcount->cursor].ea_count;
1267                         return list[refcount->cursor++].ea_blk;
1268                 }
1269                 refcount->cursor++;
1270         }
1271 }
1272
1273
1274 /*
1275  * ehandler.c --- handle bad block errors which come up during the
1276  *      course of an e2fsck session.
1277  */
1278
1279
1280 static const char *operation;
1281
1282 static errcode_t
1283 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1284                          void *data, size_t size FSCK_ATTR((unused)),
1285                          int actual FSCK_ATTR((unused)), errcode_t error)
1286 {
1287         int     i;
1288         char    *p;
1289         ext2_filsys fs = (ext2_filsys) channel->app_data;
1290         e2fsck_t ctx;
1291
1292         ctx = (e2fsck_t) fs->priv_data;
1293
1294         /*
1295          * If more than one block was read, try reading each block
1296          * separately.  We could use the actual bytes read to figure
1297          * out where to start, but we don't bother.
1298          */
1299         if (count > 1) {
1300                 p = (char *) data;
1301                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1302                         error = io_channel_read_blk(channel, block,
1303                                                     1, p);
1304                         if (error)
1305                                 return error;
1306                 }
1307                 return 0;
1308         }
1309         if (operation)
1310                 printf(_("Error reading block %lu (%s) while %s.  "), block,
1311                        error_message(error), operation);
1312         else
1313                 printf(_("Error reading block %lu (%s).  "), block,
1314                        error_message(error));
1315         preenhalt(ctx);
1316         if (ask(ctx, _("Ignore error"), 1)) {
1317                 if (ask(ctx, _("Force rewrite"), 1))
1318                         io_channel_write_blk(channel, block, 1, data);
1319                 return 0;
1320         }
1321
1322         return error;
1323 }
1324
1325 static errcode_t
1326 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1327                         const void *data, size_t size FSCK_ATTR((unused)),
1328                         int actual FSCK_ATTR((unused)), errcode_t error)
1329 {
1330         int             i;
1331         const char      *p;
1332         ext2_filsys fs = (ext2_filsys) channel->app_data;
1333         e2fsck_t ctx;
1334
1335         ctx = (e2fsck_t) fs->priv_data;
1336
1337         /*
1338          * If more than one block was written, try writing each block
1339          * separately.  We could use the actual bytes read to figure
1340          * out where to start, but we don't bother.
1341          */
1342         if (count > 1) {
1343                 p = (const char *) data;
1344                 for (i=0; i < count; i++, p += channel->block_size, block++) {
1345                         error = io_channel_write_blk(channel, block,
1346                                                      1, p);
1347                         if (error)
1348                                 return error;
1349                 }
1350                 return 0;
1351         }
1352
1353         if (operation)
1354                 printf(_("Error writing block %lu (%s) while %s.  "), block,
1355                        error_message(error), operation);
1356         else
1357                 printf(_("Error writing block %lu (%s).  "), block,
1358                        error_message(error));
1359         preenhalt(ctx);
1360         if (ask(ctx, _("Ignore error"), 1))
1361                 return 0;
1362
1363         return error;
1364 }
1365
1366 static const char *ehandler_operation(const char *op)
1367 {
1368         const char *ret = operation;
1369
1370         operation = op;
1371         return ret;
1372 }
1373
1374 static void ehandler_init(io_channel channel)
1375 {
1376         channel->read_error = e2fsck_handle_read_error;
1377         channel->write_error = e2fsck_handle_write_error;
1378 }
1379
1380 /*
1381  * journal.c --- code for handling the "ext3" journal
1382  *
1383  * Copyright (C) 2000 Andreas Dilger
1384  * Copyright (C) 2000 Theodore Ts'o
1385  *
1386  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1387  * Copyright (C) 1999 Red Hat Software
1388  *
1389  * This file may be redistributed under the terms of the
1390  * GNU General Public License version 2 or at your discretion
1391  * any later version.
1392  */
1393
1394 /*
1395  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1396  * This creates a larger static binary, and a smaller binary using
1397  * shared libraries.  It's also probably slightly less CPU-efficient,
1398  * which is why it's not on by default.  But, it's a good way of
1399  * testing the functions in inode_io.c and fileio.c.
1400  */
1401 #undef USE_INODE_IO
1402
1403 /* Kernel compatibility functions for handling the journal.  These allow us
1404  * to use the recovery.c file virtually unchanged from the kernel, so we
1405  * don't have to do much to keep kernel and user recovery in sync.
1406  */
1407 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1408 {
1409 #ifdef USE_INODE_IO
1410         *phys = block;
1411         return 0;
1412 #else
1413         struct inode    *inode = journal->j_inode;
1414         errcode_t       retval;
1415         blk_t           pblk;
1416
1417         if (!inode) {
1418                 *phys = block;
1419                 return 0;
1420         }
1421
1422         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1423                             &inode->i_ext2, NULL, 0, block, &pblk);
1424         *phys = pblk;
1425         return (retval);
1426 #endif
1427 }
1428
1429 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1430 {
1431         struct buffer_head *bh;
1432
1433         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1434         if (!bh)
1435                 return NULL;
1436
1437         bh->b_ctx = kdev->k_ctx;
1438         if (kdev->k_dev == K_DEV_FS)
1439                 bh->b_io = kdev->k_ctx->fs->io;
1440         else
1441                 bh->b_io = kdev->k_ctx->journal_io;
1442         bh->b_size = blocksize;
1443         bh->b_blocknr = blocknr;
1444
1445         return bh;
1446 }
1447
1448 static void sync_blockdev(kdev_t kdev)
1449 {
1450         io_channel      io;
1451
1452         if (kdev->k_dev == K_DEV_FS)
1453                 io = kdev->k_ctx->fs->io;
1454         else
1455                 io = kdev->k_ctx->journal_io;
1456
1457         io_channel_flush(io);
1458 }
1459
1460 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1461 {
1462         int retval;
1463         struct buffer_head *bh;
1464
1465         for (; nr > 0; --nr) {
1466                 bh = *bhp++;
1467                 if (rw == READ && !bh->b_uptodate) {
1468                         retval = io_channel_read_blk(bh->b_io,
1469                                                      bh->b_blocknr,
1470                                                      1, bh->b_data);
1471                         if (retval) {
1472                                 bb_error_msg("while reading block %lu",
1473                                         (unsigned long) bh->b_blocknr);
1474                                 bh->b_err = retval;
1475                                 continue;
1476                         }
1477                         bh->b_uptodate = 1;
1478                 } else if (rw == WRITE && bh->b_dirty) {
1479                         retval = io_channel_write_blk(bh->b_io,
1480                                                       bh->b_blocknr,
1481                                                       1, bh->b_data);
1482                         if (retval) {
1483                                 bb_error_msg("while writing block %lu",
1484                                         (unsigned long) bh->b_blocknr);
1485                                 bh->b_err = retval;
1486                                 continue;
1487                         }
1488                         bh->b_dirty = 0;
1489                         bh->b_uptodate = 1;
1490                 }
1491         }
1492 }
1493
1494 static void mark_buffer_dirty(struct buffer_head *bh)
1495 {
1496         bh->b_dirty = 1;
1497 }
1498
1499 static inline void mark_buffer_clean(struct buffer_head * bh)
1500 {
1501         bh->b_dirty = 0;
1502 }
1503
1504 static void brelse(struct buffer_head *bh)
1505 {
1506         if (bh->b_dirty)
1507                 ll_rw_block(WRITE, 1, &bh);
1508         ext2fs_free_mem(&bh);
1509 }
1510
1511 static int buffer_uptodate(struct buffer_head *bh)
1512 {
1513         return bh->b_uptodate;
1514 }
1515
1516 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1517 {
1518         bh->b_uptodate = val;
1519 }
1520
1521 static void wait_on_buffer(struct buffer_head *bh)
1522 {
1523         if (!bh->b_uptodate)
1524                 ll_rw_block(READ, 1, &bh);
1525 }
1526
1527
1528 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1529 {
1530         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1531
1532         /* if we had an error doing journal recovery, we need a full fsck */
1533         if (error)
1534                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1535         ext2fs_mark_super_dirty(ctx->fs);
1536 }
1537
1538 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1539 {
1540         struct ext2_super_block *sb = ctx->fs->super;
1541         struct ext2_super_block jsuper;
1542         struct problem_context  pctx;
1543         struct buffer_head      *bh;
1544         struct inode            *j_inode = NULL;
1545         struct kdev_s           *dev_fs = NULL, *dev_journal;
1546         const char              *journal_name = 0;
1547         journal_t               *journal = NULL;
1548         errcode_t               retval = 0;
1549         io_manager              io_ptr = 0;
1550         unsigned long           start = 0;
1551         blk_t                   blk;
1552         int                     ext_journal = 0;
1553         int                     tried_backup_jnl = 0;
1554         int                     i;
1555
1556         clear_problem_context(&pctx);
1557
1558         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1559         if (!journal) {
1560                 return EXT2_ET_NO_MEMORY;
1561         }
1562
1563         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1564         if (!dev_fs) {
1565                 retval = EXT2_ET_NO_MEMORY;
1566                 goto errout;
1567         }
1568         dev_journal = dev_fs+1;
1569
1570         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1571         dev_fs->k_dev = K_DEV_FS;
1572         dev_journal->k_dev = K_DEV_JOURNAL;
1573
1574         journal->j_dev = dev_journal;
1575         journal->j_fs_dev = dev_fs;
1576         journal->j_inode = NULL;
1577         journal->j_blocksize = ctx->fs->blocksize;
1578
1579         if (uuid_is_null(sb->s_journal_uuid)) {
1580                 if (!sb->s_journal_inum)
1581                         return EXT2_ET_BAD_INODE_NUM;
1582                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1583                                                  "journal inode");
1584                 if (!j_inode) {
1585                         retval = EXT2_ET_NO_MEMORY;
1586                         goto errout;
1587                 }
1588
1589                 j_inode->i_ctx = ctx;
1590                 j_inode->i_ino = sb->s_journal_inum;
1591
1592                 if ((retval = ext2fs_read_inode(ctx->fs,
1593                                                 sb->s_journal_inum,
1594                                                 &j_inode->i_ext2))) {
1595                 try_backup_journal:
1596                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1597                             tried_backup_jnl)
1598                                 goto errout;
1599                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1600                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1601                                EXT2_N_BLOCKS*4);
1602                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1603                         j_inode->i_ext2.i_links_count = 1;
1604                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1605                         tried_backup_jnl++;
1606                 }
1607                 if (!j_inode->i_ext2.i_links_count ||
1608                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1609                         retval = EXT2_ET_NO_JOURNAL;
1610                         goto try_backup_journal;
1611                 }
1612                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1613                     JFS_MIN_JOURNAL_BLOCKS) {
1614                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1615                         goto try_backup_journal;
1616                 }
1617                 for (i=0; i < EXT2_N_BLOCKS; i++) {
1618                         blk = j_inode->i_ext2.i_block[i];
1619                         if (!blk) {
1620                                 if (i < EXT2_NDIR_BLOCKS) {
1621                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
1622                                         goto try_backup_journal;
1623                                 }
1624                                 continue;
1625                         }
1626                         if (blk < sb->s_first_data_block ||
1627                             blk >= sb->s_blocks_count) {
1628                                 retval = EXT2_ET_BAD_BLOCK_NUM;
1629                                 goto try_backup_journal;
1630                         }
1631                 }
1632                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1633
1634 #ifdef USE_INODE_IO
1635                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1636                                                  &j_inode->i_ext2,
1637                                                  &journal_name);
1638                 if (retval)
1639                         goto errout;
1640
1641                 io_ptr = inode_io_manager;
1642 #else
1643                 journal->j_inode = j_inode;
1644                 ctx->journal_io = ctx->fs->io;
1645                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1646                         goto errout;
1647 #endif
1648         } else {
1649                 ext_journal = 1;
1650                 if (!ctx->journal_name) {
1651                         char uuid[37];
1652
1653                         uuid_unparse(sb->s_journal_uuid, uuid);
1654                         ctx->journal_name = blkid_get_devname(ctx->blkid,
1655                                                               "UUID", uuid);
1656                         if (!ctx->journal_name)
1657                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1658                 }
1659                 journal_name = ctx->journal_name;
1660
1661                 if (!journal_name) {
1662                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1663                         return EXT2_ET_LOAD_EXT_JOURNAL;
1664                 }
1665
1666                 io_ptr = unix_io_manager;
1667         }
1668
1669 #ifndef USE_INODE_IO
1670         if (ext_journal)
1671 #endif
1672                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1673                                       &ctx->journal_io);
1674         if (retval)
1675                 goto errout;
1676
1677         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1678
1679         if (ext_journal) {
1680                 if (ctx->fs->blocksize == 1024)
1681                         start = 1;
1682                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1683                 if (!bh) {
1684                         retval = EXT2_ET_NO_MEMORY;
1685                         goto errout;
1686                 }
1687                 ll_rw_block(READ, 1, &bh);
1688                 if ((retval = bh->b_err) != 0)
1689                         goto errout;
1690                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1691                        sizeof(jsuper));
1692                 brelse(bh);
1693 #if BB_BIG_ENDIAN
1694                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1695                         ext2fs_swap_super(&jsuper);
1696 #endif
1697                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1698                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1699                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1700                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1701                         goto errout;
1702                 }
1703                 /* Make sure the journal UUID is correct */
1704                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1705                            sizeof(jsuper.s_uuid))) {
1706                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1707                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
1708                         goto errout;
1709                 }
1710
1711                 journal->j_maxlen = jsuper.s_blocks_count;
1712                 start++;
1713         }
1714
1715         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1716                 retval = EXT2_ET_NO_MEMORY;
1717                 goto errout;
1718         }
1719
1720         journal->j_sb_buffer = bh;
1721         journal->j_superblock = (journal_superblock_t *)bh->b_data;
1722
1723 #ifdef USE_INODE_IO
1724         ext2fs_free_mem(&j_inode);
1725 #endif
1726
1727         *ret_journal = journal;
1728         return 0;
1729
1730 errout:
1731         ext2fs_free_mem(&dev_fs);
1732         ext2fs_free_mem(&j_inode);
1733         ext2fs_free_mem(&journal);
1734         return retval;
1735
1736 }
1737
1738 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1739                                               struct problem_context *pctx)
1740 {
1741         struct ext2_super_block *sb = ctx->fs->super;
1742         int recover = ctx->fs->super->s_feature_incompat &
1743                 EXT3_FEATURE_INCOMPAT_RECOVER;
1744         int has_journal = ctx->fs->super->s_feature_compat &
1745                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1746
1747         if (has_journal || sb->s_journal_inum) {
1748                 /* The journal inode is bogus, remove and force full fsck */
1749                 pctx->ino = sb->s_journal_inum;
1750                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1751                         if (has_journal && sb->s_journal_inum)
1752                                 printf("*** ext3 journal has been deleted - "
1753                                        "filesystem is now ext2 only ***\n\n");
1754                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1755                         sb->s_journal_inum = 0;
1756                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1757                         e2fsck_clear_recover(ctx, 1);
1758                         return 0;
1759                 }
1760                 return EXT2_ET_BAD_INODE_NUM;
1761         } else if (recover) {
1762                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1763                         e2fsck_clear_recover(ctx, 1);
1764                         return 0;
1765                 }
1766                 return EXT2_ET_UNSUPP_FEATURE;
1767         }
1768         return 0;
1769 }
1770
1771 #define V1_SB_SIZE      0x0024
1772 static void clear_v2_journal_fields(journal_t *journal)
1773 {
1774         e2fsck_t ctx = journal->j_dev->k_ctx;
1775         struct problem_context pctx;
1776
1777         clear_problem_context(&pctx);
1778
1779         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1780                 return;
1781
1782         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1783                ctx->fs->blocksize-V1_SB_SIZE);
1784         mark_buffer_dirty(journal->j_sb_buffer);
1785 }
1786
1787
1788 static errcode_t e2fsck_journal_load(journal_t *journal)
1789 {
1790         e2fsck_t ctx = journal->j_dev->k_ctx;
1791         journal_superblock_t *jsb;
1792         struct buffer_head *jbh = journal->j_sb_buffer;
1793         struct problem_context pctx;
1794
1795         clear_problem_context(&pctx);
1796
1797         ll_rw_block(READ, 1, &jbh);
1798         if (jbh->b_err) {
1799                 bb_error_msg(_("reading journal superblock"));
1800                 return jbh->b_err;
1801         }
1802
1803         jsb = journal->j_superblock;
1804         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1805         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1806                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1807
1808         switch (ntohl(jsb->s_header.h_blocktype)) {
1809         case JFS_SUPERBLOCK_V1:
1810                 journal->j_format_version = 1;
1811                 if (jsb->s_feature_compat ||
1812                     jsb->s_feature_incompat ||
1813                     jsb->s_feature_ro_compat ||
1814                     jsb->s_nr_users)
1815                         clear_v2_journal_fields(journal);
1816                 break;
1817
1818         case JFS_SUPERBLOCK_V2:
1819                 journal->j_format_version = 2;
1820                 if (ntohl(jsb->s_nr_users) > 1 &&
1821                     uuid_is_null(ctx->fs->super->s_journal_uuid))
1822                         clear_v2_journal_fields(journal);
1823                 if (ntohl(jsb->s_nr_users) > 1) {
1824                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1825                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1826                 }
1827                 break;
1828
1829         /*
1830          * These should never appear in a journal super block, so if
1831          * they do, the journal is badly corrupted.
1832          */
1833         case JFS_DESCRIPTOR_BLOCK:
1834         case JFS_COMMIT_BLOCK:
1835         case JFS_REVOKE_BLOCK:
1836                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1837
1838         /* If we don't understand the superblock major type, but there
1839          * is a magic number, then it is likely to be a new format we
1840          * just don't understand, so leave it alone. */
1841         default:
1842                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1843         }
1844
1845         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1846                 return EXT2_ET_UNSUPP_FEATURE;
1847
1848         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1849                 return EXT2_ET_RO_UNSUPP_FEATURE;
1850
1851         /* We have now checked whether we know enough about the journal
1852          * format to be able to proceed safely, so any other checks that
1853          * fail we should attempt to recover from. */
1854         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1855                 bb_error_msg(_("%s: no valid journal superblock found"),
1856                         ctx->device_name);
1857                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1858         }
1859
1860         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1861                 journal->j_maxlen = ntohl(jsb->s_maxlen);
1862         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1863                 bb_error_msg(_("%s: journal too short"),
1864                         ctx->device_name);
1865                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1866         }
1867
1868         journal->j_tail_sequence = ntohl(jsb->s_sequence);
1869         journal->j_transaction_sequence = journal->j_tail_sequence;
1870         journal->j_tail = ntohl(jsb->s_start);
1871         journal->j_first = ntohl(jsb->s_first);
1872         journal->j_last = ntohl(jsb->s_maxlen);
1873
1874         return 0;
1875 }
1876
1877 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1878                                        journal_t *journal)
1879 {
1880         char *p;
1881         union {
1882                 uuid_t uuid;
1883                 __u32 val[4];
1884         } u;
1885         __u32 new_seq = 0;
1886         int i;
1887
1888         /* Leave a valid existing V1 superblock signature alone.
1889          * Anything unrecognisable we overwrite with a new V2
1890          * signature. */
1891
1892         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1893             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1894                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1895                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1896         }
1897
1898         /* Zero out everything else beyond the superblock header */
1899
1900         p = ((char *) jsb) + sizeof(journal_header_t);
1901         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1902
1903         jsb->s_blocksize = htonl(ctx->fs->blocksize);
1904         jsb->s_maxlen = htonl(journal->j_maxlen);
1905         jsb->s_first = htonl(1);
1906
1907         /* Initialize the journal sequence number so that there is "no"
1908          * chance we will find old "valid" transactions in the journal.
1909          * This avoids the need to zero the whole journal (slow to do,
1910          * and risky when we are just recovering the filesystem).
1911          */
1912         uuid_generate(u.uuid);
1913         for (i = 0; i < 4; i ++)
1914                 new_seq ^= u.val[i];
1915         jsb->s_sequence = htonl(new_seq);
1916
1917         mark_buffer_dirty(journal->j_sb_buffer);
1918         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1919 }
1920
1921 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1922                                                   journal_t *journal,
1923                                                   struct problem_context *pctx)
1924 {
1925         struct ext2_super_block *sb = ctx->fs->super;
1926         int recover = ctx->fs->super->s_feature_incompat &
1927                 EXT3_FEATURE_INCOMPAT_RECOVER;
1928
1929         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1930                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1931                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
1932                                                    journal);
1933                         journal->j_transaction_sequence = 1;
1934                         e2fsck_clear_recover(ctx, recover);
1935                         return 0;
1936                 }
1937                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1938         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1939                 return EXT2_ET_CORRUPT_SUPERBLOCK;
1940
1941         return 0;
1942 }
1943
1944 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1945                                    int reset, int drop)
1946 {
1947         journal_superblock_t *jsb;
1948
1949         if (drop)
1950                 mark_buffer_clean(journal->j_sb_buffer);
1951         else if (!(ctx->options & E2F_OPT_READONLY)) {
1952                 jsb = journal->j_superblock;
1953                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1954                 if (reset)
1955                         jsb->s_start = 0; /* this marks the journal as empty */
1956                 mark_buffer_dirty(journal->j_sb_buffer);
1957         }
1958         brelse(journal->j_sb_buffer);
1959
1960         if (ctx->journal_io) {
1961                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1962                         io_channel_close(ctx->journal_io);
1963                 ctx->journal_io = 0;
1964         }
1965
1966 #ifndef USE_INODE_IO
1967         ext2fs_free_mem(&journal->j_inode);
1968 #endif
1969         ext2fs_free_mem(&journal->j_fs_dev);
1970         ext2fs_free_mem(&journal);
1971 }
1972
1973 /*
1974  * This function makes sure that the superblock fields regarding the
1975  * journal are consistent.
1976  */
1977 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1978 {
1979         struct ext2_super_block *sb = ctx->fs->super;
1980         journal_t *journal;
1981         int recover = ctx->fs->super->s_feature_incompat &
1982                 EXT3_FEATURE_INCOMPAT_RECOVER;
1983         struct problem_context pctx;
1984         problem_t problem;
1985         int reset = 0, force_fsck = 0;
1986         int retval;
1987
1988         /* If we don't have any journal features, don't do anything more */
1989         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1990             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1991             uuid_is_null(sb->s_journal_uuid))
1992                 return 0;
1993
1994         clear_problem_context(&pctx);
1995         pctx.num = sb->s_journal_inum;
1996
1997         retval = e2fsck_get_journal(ctx, &journal);
1998         if (retval) {
1999                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2000                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2001                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2002                     (retval == EXT2_ET_NO_JOURNAL))
2003                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2004                 return retval;
2005         }
2006
2007         retval = e2fsck_journal_load(journal);
2008         if (retval) {
2009                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2010                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2011                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2012                                   &pctx))) ||
2013                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2014                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2015                                   &pctx))) ||
2016                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2017                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2018                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2019                                                                   &pctx);
2020                 e2fsck_journal_release(ctx, journal, 0, 1);
2021                 return retval;
2022         }
2023
2024         /*
2025          * We want to make the flags consistent here.  We will not leave with
2026          * needs_recovery set but has_journal clear.  We can't get in a loop
2027          * with -y, -n, or -p, only if a user isn't making up their mind.
2028          */
2029 no_has_journal:
2030         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2031                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2032                 pctx.str = "inode";
2033                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2034                         if (recover &&
2035                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2036                                 goto no_has_journal;
2037                         /*
2038                          * Need a full fsck if we are releasing a
2039                          * journal stored on a reserved inode.
2040                          */
2041                         force_fsck = recover ||
2042                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2043                         /* Clear all of the journal fields */
2044                         sb->s_journal_inum = 0;
2045                         sb->s_journal_dev = 0;
2046                         memset(sb->s_journal_uuid, 0,
2047                                sizeof(sb->s_journal_uuid));
2048                         e2fsck_clear_recover(ctx, force_fsck);
2049                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2050                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2051                         ext2fs_mark_super_dirty(ctx->fs);
2052                 }
2053         }
2054
2055         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2056             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2057             journal->j_superblock->s_start != 0) {
2058                 /* Print status information */
2059                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2060                 if (ctx->superblock)
2061                         problem = PR_0_JOURNAL_RUN_DEFAULT;
2062                 else
2063                         problem = PR_0_JOURNAL_RUN;
2064                 if (fix_problem(ctx, problem, &pctx)) {
2065                         ctx->options |= E2F_OPT_FORCE;
2066                         sb->s_feature_incompat |=
2067                                 EXT3_FEATURE_INCOMPAT_RECOVER;
2068                         ext2fs_mark_super_dirty(ctx->fs);
2069                 } else if (fix_problem(ctx,
2070                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2071                         reset = 1;
2072                         sb->s_state &= ~EXT2_VALID_FS;
2073                         ext2fs_mark_super_dirty(ctx->fs);
2074                 }
2075                 /*
2076                  * If the user answers no to the above question, we
2077                  * ignore the fact that journal apparently has data;
2078                  * accidentally replaying over valid data would be far
2079                  * worse than skipping a questionable recovery.
2080                  *
2081                  * XXX should we abort with a fatal error here?  What
2082                  * will the ext3 kernel code do if a filesystem with
2083                  * !NEEDS_RECOVERY but with a non-zero
2084                  * journal->j_superblock->s_start is mounted?
2085                  */
2086         }
2087
2088         e2fsck_journal_release(ctx, journal, reset, 0);
2089         return retval;
2090 }
2091
2092 static errcode_t recover_ext3_journal(e2fsck_t ctx)
2093 {
2094         journal_t *journal;
2095         int retval;
2096
2097         journal_init_revoke_caches();
2098         retval = e2fsck_get_journal(ctx, &journal);
2099         if (retval)
2100                 return retval;
2101
2102         retval = e2fsck_journal_load(journal);
2103         if (retval)
2104                 goto errout;
2105
2106         retval = journal_init_revoke(journal, 1024);
2107         if (retval)
2108                 goto errout;
2109
2110         retval = -journal_recover(journal);
2111         if (retval)
2112                 goto errout;
2113
2114         if (journal->j_superblock->s_errno) {
2115                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2116                 ext2fs_mark_super_dirty(ctx->fs);
2117                 journal->j_superblock->s_errno = 0;
2118                 mark_buffer_dirty(journal->j_sb_buffer);
2119         }
2120
2121 errout:
2122         journal_destroy_revoke(journal);
2123         journal_destroy_revoke_caches();
2124         e2fsck_journal_release(ctx, journal, 1, 0);
2125         return retval;
2126 }
2127
2128 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2129 {
2130         io_manager io_ptr = ctx->fs->io->manager;
2131         int blocksize = ctx->fs->blocksize;
2132         errcode_t       retval, recover_retval;
2133
2134         printf(_("%s: recovering journal\n"), ctx->device_name);
2135         if (ctx->options & E2F_OPT_READONLY) {
2136                 printf(_("%s: won't do journal recovery while read-only\n"),
2137                        ctx->device_name);
2138                 return EXT2_ET_FILE_RO;
2139         }
2140
2141         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2142                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
2143
2144         recover_retval = recover_ext3_journal(ctx);
2145
2146         /*
2147          * Reload the filesystem context to get up-to-date data from disk
2148          * because journal recovery will change the filesystem under us.
2149          */
2150         ext2fs_close(ctx->fs);
2151         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2152                              ctx->superblock, blocksize, io_ptr,
2153                              &ctx->fs);
2154
2155         if (retval) {
2156                 bb_error_msg(_("while trying to re-open %s"),
2157                         ctx->device_name);
2158                 bb_error_msg_and_die(0);
2159         }
2160         ctx->fs->priv_data = ctx;
2161
2162         /* Set the superblock flags */
2163         e2fsck_clear_recover(ctx, recover_retval);
2164         return recover_retval;
2165 }
2166
2167 /*
2168  * This function will move the journal inode from a visible file in
2169  * the filesystem directory hierarchy to the reserved inode if necessary.
2170  */
2171 static const char * const journal_names[] = {
2172         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2173
2174 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2175 {
2176         struct ext2_super_block *sb = ctx->fs->super;
2177         struct problem_context  pctx;
2178         struct ext2_inode       inode;
2179         ext2_filsys             fs = ctx->fs;
2180         ext2_ino_t              ino;
2181         errcode_t               retval;
2182         const char * const *    cpp;
2183         int                     group, mount_flags;
2184
2185         clear_problem_context(&pctx);
2186
2187         /*
2188          * If the filesystem is opened read-only, or there is no
2189          * journal, then do nothing.
2190          */
2191         if ((ctx->options & E2F_OPT_READONLY) ||
2192             (sb->s_journal_inum == 0) ||
2193             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2194                 return;
2195
2196         /*
2197          * Read in the journal inode
2198          */
2199         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2200                 return;
2201
2202         /*
2203          * If it's necessary to backup the journal inode, do so.
2204          */
2205         if ((sb->s_jnl_backup_type == 0) ||
2206             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2207              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2208                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2209                         memcpy(sb->s_jnl_blocks, inode.i_block,
2210                                EXT2_N_BLOCKS*4);
2211                         sb->s_jnl_blocks[16] = inode.i_size;
2212                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2213                         ext2fs_mark_super_dirty(fs);
2214                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2215                 }
2216         }
2217
2218         /*
2219          * If the journal is already the hidden inode, then do nothing
2220          */
2221         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2222                 return;
2223
2224         /*
2225          * The journal inode had better have only one link and not be readable.
2226          */
2227         if (inode.i_links_count != 1)
2228                 return;
2229
2230         /*
2231          * If the filesystem is mounted, or we can't tell whether
2232          * or not it's mounted, do nothing.
2233          */
2234         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2235         if (retval || (mount_flags & EXT2_MF_MOUNTED))
2236                 return;
2237
2238         /*
2239          * If we can't find the name of the journal inode, then do
2240          * nothing.
2241          */
2242         for (cpp = journal_names; *cpp; cpp++) {
2243                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2244                                        strlen(*cpp), 0, &ino);
2245                 if ((retval == 0) && (ino == sb->s_journal_inum))
2246                         break;
2247         }
2248         if (*cpp == 0)
2249                 return;
2250
2251         /* We need the inode bitmap to be loaded */
2252         retval = ext2fs_read_bitmaps(fs);
2253         if (retval)
2254                 return;
2255
2256         pctx.str = *cpp;
2257         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2258                 return;
2259
2260         /*
2261          * OK, we've done all the checks, let's actually move the
2262          * journal inode.  Errors at this point mean we need to force
2263          * an ext2 filesystem check.
2264          */
2265         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2266                 goto err_out;
2267         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2268                 goto err_out;
2269         sb->s_journal_inum = EXT2_JOURNAL_INO;
2270         ext2fs_mark_super_dirty(fs);
2271         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2272         inode.i_links_count = 0;
2273         inode.i_dtime = time(0);
2274         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2275                 goto err_out;
2276
2277         group = ext2fs_group_of_ino(fs, ino);
2278         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2279         ext2fs_mark_ib_dirty(fs);
2280         fs->group_desc[group].bg_free_inodes_count++;
2281         fs->super->s_free_inodes_count++;
2282         return;
2283
2284 err_out:
2285         pctx.errcode = retval;
2286         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2287         fs->super->s_state &= ~EXT2_VALID_FS;
2288         ext2fs_mark_super_dirty(fs);
2289         return;
2290 }
2291
2292 /*
2293  * message.c --- print e2fsck messages (with compression)
2294  *
2295  * print_e2fsck_message() prints a message to the user, using
2296  * compression techniques and expansions of abbreviations.
2297  *
2298  * The following % expansions are supported:
2299  *
2300  *      %b      <blk>                   block number
2301  *      %B      <blkcount>              integer
2302  *      %c      <blk2>                  block number
2303  *      %Di     <dirent>->ino           inode number
2304  *      %Dn     <dirent>->name          string
2305  *      %Dr     <dirent>->rec_len
2306  *      %Dl     <dirent>->name_len
2307  *      %Dt     <dirent>->filetype
2308  *      %d      <dir>                   inode number
2309  *      %g      <group>                 integer
2310  *      %i      <ino>                   inode number
2311  *      %Is     <inode> -> i_size
2312  *      %IS     <inode> -> i_extra_isize
2313  *      %Ib     <inode> -> i_blocks
2314  *      %Il     <inode> -> i_links_count
2315  *      %Im     <inode> -> i_mode
2316  *      %IM     <inode> -> i_mtime
2317  *      %IF     <inode> -> i_faddr
2318  *      %If     <inode> -> i_file_acl
2319  *      %Id     <inode> -> i_dir_acl
2320  *      %Iu     <inode> -> i_uid
2321  *      %Ig     <inode> -> i_gid
2322  *      %j      <ino2>                  inode number
2323  *      %m      <com_err error message>
2324  *      %N      <num>
2325  *      %p      ext2fs_get_pathname of directory <ino>
2326  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2327  *                      the containing directory.  (If dirent is NULL
2328  *                      then return the pathname of directory <ino2>)
2329  *      %q      ext2fs_get_pathname of directory <dir>
2330  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2331  *                      the containing directory.
2332  *      %s      <str>                   miscellaneous string
2333  *      %S      backup superblock
2334  *      %X      <num> hexadecimal format
2335  *
2336  * The following '@' expansions are supported:
2337  *
2338  *      @a      extended attribute
2339  *      @A      error allocating
2340  *      @b      block
2341  *      @B      bitmap
2342  *      @c      compress
2343  *      @C      conflicts with some other fs block
2344  *      @D      deleted
2345  *      @d      directory
2346  *      @e      entry
2347  *      @E      Entry '%Dn' in %p (%i)
2348  *      @f      filesystem
2349  *      @F      for @i %i (%Q) is
2350  *      @g      group
2351  *      @h      HTREE directory inode
2352  *      @i      inode
2353  *      @I      illegal
2354  *      @j      journal
2355  *      @l      lost+found
2356  *      @L      is a link
2357  *      @m      multiply-claimed
2358  *      @n      invalid
2359  *      @o      orphaned
2360  *      @p      problem in
2361  *      @r      root inode
2362  *      @s      should be
2363  *      @S      superblock
2364  *      @u      unattached
2365  *      @v      device
2366  *      @z      zero-length
2367  */
2368
2369
2370 /*
2371  * This structure defines the abbreviations used by the text strings
2372  * below.  The first character in the string is the index letter.  An
2373  * abbreviation of the form '@<i>' is expanded by looking up the index
2374  * letter <i> in the table below.
2375  */
2376 static const char * const abbrevs[] = {
2377         N_("aextended attribute"),
2378         N_("Aerror allocating"),
2379         N_("bblock"),
2380         N_("Bbitmap"),
2381         N_("ccompress"),
2382         N_("Cconflicts with some other fs @b"),
2383         N_("iinode"),
2384         N_("Iillegal"),
2385         N_("jjournal"),
2386         N_("Ddeleted"),
2387         N_("ddirectory"),
2388         N_("eentry"),
2389         N_("E@e '%Dn' in %p (%i)"),
2390         N_("ffilesystem"),
2391         N_("Ffor @i %i (%Q) is"),
2392         N_("ggroup"),
2393         N_("hHTREE @d @i"),
2394         N_("llost+found"),
2395         N_("Lis a link"),
2396     N_("mmultiply-claimed"),
2397     N_("ninvalid"),
2398         N_("oorphaned"),
2399         N_("pproblem in"),
2400         N_("rroot @i"),
2401         N_("sshould be"),
2402         N_("Ssuper@b"),
2403         N_("uunattached"),
2404         N_("vdevice"),
2405         N_("zzero-length"),
2406         "@@",
2407         0
2408         };
2409
2410 /*
2411  * Give more user friendly names to the "special" inodes.
2412  */
2413 #define num_special_inodes      11
2414 static const char * const special_inode_name[] =
2415 {
2416         N_("<The NULL inode>"),                 /* 0 */
2417         N_("<The bad blocks inode>"),           /* 1 */
2418         "/",                                    /* 2 */
2419         N_("<The ACL index inode>"),            /* 3 */
2420         N_("<The ACL data inode>"),             /* 4 */
2421         N_("<The boot loader inode>"),          /* 5 */
2422         N_("<The undelete directory inode>"),   /* 6 */
2423         N_("<The group descriptor inode>"),     /* 7 */
2424         N_("<The journal inode>"),              /* 8 */
2425         N_("<Reserved inode 9>"),               /* 9 */
2426         N_("<Reserved inode 10>"),              /* 10 */
2427 };
2428
2429 /*
2430  * This function does "safe" printing.  It will convert non-printable
2431  * ASCII characters using '^' and M- notation.
2432  */
2433 static void safe_print(const char *cp, int len)
2434 {
2435         unsigned char   ch;
2436
2437         if (len < 0)
2438                 len = strlen(cp);
2439
2440         while (len--) {
2441                 ch = *cp++;
2442                 if (ch > 128) {
2443                         fputs("M-", stdout);
2444                         ch -= 128;
2445                 }
2446                 if ((ch < 32) || (ch == 0x7f)) {
2447                         fputc('^', stdout);
2448                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2449                 }
2450                 fputc(ch, stdout);
2451         }
2452 }
2453
2454
2455 /*
2456  * This function prints a pathname, using the ext2fs_get_pathname
2457  * function
2458  */
2459 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2460 {
2461         errcode_t       retval;
2462         char            *path;
2463
2464         if (!dir && (ino < num_special_inodes)) {
2465                 fputs(_(special_inode_name[ino]), stdout);
2466                 return;
2467         }
2468
2469         retval = ext2fs_get_pathname(fs, dir, ino, &path);
2470         if (retval)
2471                 fputs("???", stdout);
2472         else {
2473                 safe_print(path, -1);
2474                 ext2fs_free_mem(&path);
2475         }
2476 }
2477
2478 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2479                           struct problem_context *pctx, int first);
2480 /*
2481  * This function handles the '@' expansion.  We allow recursive
2482  * expansion; an @ expression can contain further '@' and '%'
2483  * expressions.
2484  */
2485 static void expand_at_expression(e2fsck_t ctx, char ch,
2486                                           struct problem_context *pctx,
2487                                           int *first)
2488 {
2489         const char * const *cpp;
2490         const char *str;
2491
2492         /* Search for the abbreviation */
2493         for (cpp = abbrevs; *cpp; cpp++) {
2494                 if (ch == *cpp[0])
2495                         break;
2496         }
2497         if (*cpp) {
2498                 str = _(*cpp) + 1;
2499                 if (*first && islower(*str)) {
2500                         *first = 0;
2501                         fputc(toupper(*str++), stdout);
2502                 }
2503                 print_e2fsck_message(ctx, str, pctx, *first);
2504         } else
2505                 printf("@%c", ch);
2506 }
2507
2508 /*
2509  * This function expands '%IX' expressions
2510  */
2511 static void expand_inode_expression(char ch,
2512                                              struct problem_context *ctx)
2513 {
2514         struct ext2_inode       *inode;
2515         struct ext2_inode_large *large_inode;
2516         char *                  time_str;
2517         time_t                  t;
2518         int                     do_gmt = -1;
2519
2520         if (!ctx || !ctx->inode)
2521                 goto no_inode;
2522
2523         inode = ctx->inode;
2524         large_inode = (struct ext2_inode_large *) inode;
2525
2526         switch (ch) {
2527         case 's':
2528                 if (LINUX_S_ISDIR(inode->i_mode))
2529                         printf("%u", inode->i_size);
2530                 else {
2531                         printf("%"PRIu64, (inode->i_size |
2532                                         ((uint64_t) inode->i_size_high << 32)));
2533                 }
2534                 break;
2535         case 'S':
2536                 printf("%u", large_inode->i_extra_isize);
2537                 break;
2538         case 'b':
2539                 printf("%u", inode->i_blocks);
2540                 break;
2541         case 'l':
2542                 printf("%d", inode->i_links_count);
2543                 break;
2544         case 'm':
2545                 printf("0%o", inode->i_mode);
2546                 break;
2547         case 'M':
2548                 /* The diet libc doesn't respect the TZ environemnt variable */
2549                 if (do_gmt == -1) {
2550                         time_str = getenv("TZ");
2551                         if (!time_str)
2552                                 time_str = "";
2553                         do_gmt = !strcmp(time_str, "GMT");
2554                 }
2555                 t = inode->i_mtime;
2556                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2557                 printf("%.24s", time_str);
2558                 break;
2559         case 'F':
2560                 printf("%u", inode->i_faddr);
2561                 break;
2562         case 'f':
2563                 printf("%u", inode->i_file_acl);
2564                 break;
2565         case 'd':
2566                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2567                               inode->i_dir_acl : 0));
2568                 break;
2569         case 'u':
2570                 printf("%d", (inode->i_uid |
2571                               (inode->osd2.linux2.l_i_uid_high << 16)));
2572                 break;
2573         case 'g':
2574                 printf("%d", (inode->i_gid |
2575                               (inode->osd2.linux2.l_i_gid_high << 16)));
2576                 break;
2577         default:
2578         no_inode:
2579                 printf("%%I%c", ch);
2580                 break;
2581         }
2582 }
2583
2584 /*
2585  * This function expands '%dX' expressions
2586  */
2587 static void expand_dirent_expression(char ch,
2588                                               struct problem_context *ctx)
2589 {
2590         struct ext2_dir_entry   *dirent;
2591         int     len;
2592
2593         if (!ctx || !ctx->dirent)
2594                 goto no_dirent;
2595
2596         dirent = ctx->dirent;
2597
2598         switch (ch) {
2599         case 'i':
2600                 printf("%u", dirent->inode);
2601                 break;
2602         case 'n':
2603                 len = dirent->name_len & 0xFF;
2604                 if (len > EXT2_NAME_LEN)
2605                         len = EXT2_NAME_LEN;
2606                 if (len > dirent->rec_len)
2607                         len = dirent->rec_len;
2608                 safe_print(dirent->name, len);
2609                 break;
2610         case 'r':
2611                 printf("%u", dirent->rec_len);
2612                 break;
2613         case 'l':
2614                 printf("%u", dirent->name_len & 0xFF);
2615                 break;
2616         case 't':
2617                 printf("%u", dirent->name_len >> 8);
2618                 break;
2619         default:
2620         no_dirent:
2621                 printf("%%D%c", ch);
2622                 break;
2623         }
2624 }
2625
2626 static void expand_percent_expression(ext2_filsys fs, char ch,
2627                                                struct problem_context *ctx)
2628 {
2629         if (!ctx)
2630                 goto no_context;
2631
2632         switch (ch) {
2633         case '%':
2634                 fputc('%', stdout);
2635                 break;
2636         case 'b':
2637                 printf("%u", ctx->blk);
2638                 break;
2639         case 'B':
2640                 printf("%"PRIi64, ctx->blkcount);
2641                 break;
2642         case 'c':
2643                 printf("%u", ctx->blk2);
2644                 break;
2645         case 'd':
2646                 printf("%u", ctx->dir);
2647                 break;
2648         case 'g':
2649                 printf("%d", ctx->group);
2650                 break;
2651         case 'i':
2652                 printf("%u", ctx->ino);
2653                 break;
2654         case 'j':
2655                 printf("%u", ctx->ino2);
2656                 break;
2657         case 'm':
2658                 printf("%s", error_message(ctx->errcode));
2659                 break;
2660         case 'N':
2661                 printf("%"PRIi64, ctx->num);
2662                 break;
2663         case 'p':
2664                 print_pathname(fs, ctx->ino, 0);
2665                 break;
2666         case 'P':
2667                 print_pathname(fs, ctx->ino2,
2668                                ctx->dirent ? ctx->dirent->inode : 0);
2669                 break;
2670         case 'q':
2671                 print_pathname(fs, ctx->dir, 0);
2672                 break;
2673         case 'Q':
2674                 print_pathname(fs, ctx->dir, ctx->ino);
2675                 break;
2676         case 'S':
2677                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2678                 break;
2679         case 's':
2680                 printf("%s", ctx->str ? ctx->str : "NULL");
2681                 break;
2682         case 'X':
2683                 printf("0x%"PRIi64, ctx->num);
2684                 break;
2685         default:
2686         no_context:
2687                 printf("%%%c", ch);
2688                 break;
2689         }
2690 }
2691
2692
2693 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2694                           struct problem_context *pctx, int first)
2695 {
2696         ext2_filsys fs = ctx->fs;
2697         const char *    cp;
2698         int             i;
2699
2700         e2fsck_clear_progbar(ctx);
2701         for (cp = msg; *cp; cp++) {
2702                 if (cp[0] == '@') {
2703                         cp++;
2704                         expand_at_expression(ctx, *cp, pctx, &first);
2705                 } else if (cp[0] == '%' && cp[1] == 'I') {
2706                         cp += 2;
2707                         expand_inode_expression(*cp, pctx);
2708                 } else if (cp[0] == '%' && cp[1] == 'D') {
2709                         cp += 2;
2710                         expand_dirent_expression(*cp, pctx);
2711                 } else if ((cp[0] == '%')) {
2712                         cp++;
2713                         expand_percent_expression(fs, *cp, pctx);
2714                 } else {
2715                         for (i=0; cp[i]; i++)
2716                                 if ((cp[i] == '@') || cp[i] == '%')
2717                                         break;
2718                         printf("%.*s", i, cp);
2719                         cp += i-1;
2720                 }
2721                 first = 0;
2722         }
2723 }
2724
2725
2726 /*
2727  * region.c --- code which manages allocations within a region.
2728  */
2729
2730 struct region_el {
2731         region_addr_t   start;
2732         region_addr_t   end;
2733         struct region_el *next;
2734 };
2735
2736 struct region_struct {
2737         region_addr_t   min;
2738         region_addr_t   max;
2739         struct region_el *allocated;
2740 };
2741
2742 static region_t region_create(region_addr_t min, region_addr_t max)
2743 {
2744         region_t        region;
2745
2746         region = malloc(sizeof(struct region_struct));
2747         if (!region)
2748                 return NULL;
2749         memset(region, 0, sizeof(struct region_struct));
2750         region->min = min;
2751         region->max = max;
2752         return region;
2753 }
2754
2755 static void region_free(region_t region)
2756 {
2757         struct region_el        *r, *next;
2758
2759         for (r = region->allocated; r; r = next) {
2760                 next = r->next;
2761                 free(r);
2762         }
2763         memset(region, 0, sizeof(struct region_struct));
2764         free(region);
2765 }
2766
2767 static int region_allocate(region_t region, region_addr_t start, int n)
2768 {
2769         struct region_el        *r, *new_region, *prev, *next;
2770         region_addr_t end;
2771
2772         end = start+n;
2773         if ((start < region->min) || (end > region->max))
2774                 return -1;
2775         if (n == 0)
2776                 return 1;
2777
2778         /*
2779          * Search through the linked list.  If we find that it
2780          * conflicts witih something that's already allocated, return
2781          * 1; if we can find an existing region which we can grow, do
2782          * so.  Otherwise, stop when we find the appropriate place
2783          * insert a new region element into the linked list.
2784          */
2785         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2786                 if (((start >= r->start) && (start < r->end)) ||
2787                     ((end > r->start) && (end <= r->end)) ||
2788                     ((start <= r->start) && (end >= r->end)))
2789                         return 1;
2790                 if (end == r->start) {
2791                         r->start = start;
2792                         return 0;
2793                 }
2794                 if (start == r->end) {
2795                         if ((next = r->next)) {
2796                                 if (end > next->start)
2797                                         return 1;
2798                                 if (end == next->start) {
2799                                         r->end = next->end;
2800                                         r->next = next->next;
2801                                         free(next);
2802                                         return 0;
2803                                 }
2804                         }
2805                         r->end = end;
2806                         return 0;
2807                 }
2808                 if (start < r->start)
2809                         break;
2810         }
2811         /*
2812          * Insert a new region element structure into the linked list
2813          */
2814         new_region = malloc(sizeof(struct region_el));
2815         if (!new_region)
2816                 return -1;
2817         new_region->start = start;
2818         new_region->end = start + n;
2819         new_region->next = r;
2820         if (prev)
2821                 prev->next = new_region;
2822         else
2823                 region->allocated = new_region;
2824         return 0;
2825 }
2826
2827 /*
2828  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2829  *
2830  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2831  * and applies the following tests to each inode:
2832  *
2833  *      - The mode field of the inode must be legal.
2834  *      - The size and block count fields of the inode are correct.
2835  *      - A data block must not be used by another inode
2836  *
2837  * Pass 1 also gathers the collects the following information:
2838  *
2839  *      - A bitmap of which inodes are in use.          (inode_used_map)
2840  *      - A bitmap of which inodes are directories.     (inode_dir_map)
2841  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2842  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2843  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2844  *      - A bitmap of which blocks are in use.          (block_found_map)
2845  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2846  *      - The data blocks of the directory inodes.      (dir_map)
2847  *
2848  * Pass 1 is designed to stash away enough information so that the
2849  * other passes should not need to read in the inode information
2850  * during the normal course of a filesystem check.  (Althogh if an
2851  * inconsistency is detected, other passes may need to read in an
2852  * inode to fix it.)
2853  *
2854  * Note that pass 1B will be invoked if there are any duplicate blocks
2855  * found.
2856  */
2857
2858
2859 static int process_block(ext2_filsys fs, blk_t  *blocknr,
2860                          e2_blkcnt_t blockcnt, blk_t ref_blk,
2861                          int ref_offset, void *priv_data);
2862 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2863                              e2_blkcnt_t blockcnt, blk_t ref_blk,
2864                              int ref_offset, void *priv_data);
2865 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2866                          char *block_buf);
2867 static void mark_table_blocks(e2fsck_t ctx);
2868 static void alloc_imagic_map(e2fsck_t ctx);
2869 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2870 static void handle_fs_bad_blocks(e2fsck_t ctx);
2871 static void process_inodes(e2fsck_t ctx, char *block_buf);
2872 static int process_inode_cmp(const void *a, const void *b);
2873 static errcode_t scan_callback(ext2_filsys fs,
2874                                   dgrp_t group, void * priv_data);
2875 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2876                                     char *block_buf, int adjust_sign);
2877 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2878
2879 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2880                                struct ext2_inode * inode, int bufsize,
2881                                const char *proc);
2882
2883 struct process_block_struct_1 {
2884         ext2_ino_t      ino;
2885         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2886                                 fragmented:1, compressed:1, bbcheck:1;
2887         blk_t           num_blocks;
2888         blk_t           max_blocks;
2889         e2_blkcnt_t     last_block;
2890         int             num_illegal_blocks;
2891         blk_t           previous_block;
2892         struct ext2_inode *inode;
2893         struct problem_context *pctx;
2894         ext2fs_block_bitmap fs_meta_blocks;
2895         e2fsck_t        ctx;
2896 };
2897
2898 struct process_inode_block {
2899         ext2_ino_t ino;
2900         struct ext2_inode inode;
2901 };
2902
2903 struct scan_callback_struct {
2904         e2fsck_t        ctx;
2905         char            *block_buf;
2906 };
2907
2908 /*
2909  * For the inodes to process list.
2910  */
2911 static struct process_inode_block *inodes_to_process;
2912 static int process_inode_count;
2913
2914 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2915                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
2916
2917 /*
2918  * Free all memory allocated by pass1 in preparation for restarting
2919  * things.
2920  */
2921 static void unwind_pass1(void)
2922 {
2923         ext2fs_free_mem(&inodes_to_process);
2924 }
2925
2926 /*
2927  * Check to make sure a device inode is real.  Returns 1 if the device
2928  * checks out, 0 if not.
2929  *
2930  * Note: this routine is now also used to check FIFO's and Sockets,
2931  * since they have the same requirement; the i_block fields should be
2932  * zero.
2933  */
2934 static int
2935 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2936 {
2937         int     i;
2938
2939         /*
2940          * If i_blocks is non-zero, or the index flag is set, then
2941          * this is a bogus device/fifo/socket
2942          */
2943         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2944             (inode->i_flags & EXT2_INDEX_FL))
2945                 return 0;
2946
2947         /*
2948          * We should be able to do the test below all the time, but
2949          * because the kernel doesn't forcibly clear the device
2950          * inode's additional i_block fields, there are some rare
2951          * occasions when a legitimate device inode will have non-zero
2952          * additional i_block fields.  So for now, we only complain
2953          * when the immutable flag is set, which should never happen
2954          * for devices.  (And that's when the problem is caused, since
2955          * you can't set or clear immutable flags for devices.)  Once
2956          * the kernel has been fixed we can change this...
2957          */
2958         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2959                 for (i=4; i < EXT2_N_BLOCKS; i++)
2960                         if (inode->i_block[i])
2961                                 return 0;
2962         }
2963         return 1;
2964 }
2965
2966 /*
2967  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2968  * checks out, 0 if not.
2969  */
2970 static int
2971 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2972 {
2973         unsigned int len;
2974         int i;
2975         blk_t   blocks;
2976
2977         if ((inode->i_size_high || inode->i_size == 0) ||
2978             (inode->i_flags & EXT2_INDEX_FL))
2979                 return 0;
2980
2981         blocks = ext2fs_inode_data_blocks(fs, inode);
2982         if (blocks) {
2983                 if ((inode->i_size >= fs->blocksize) ||
2984                     (blocks != fs->blocksize >> 9) ||
2985                     (inode->i_block[0] < fs->super->s_first_data_block) ||
2986                     (inode->i_block[0] >= fs->super->s_blocks_count))
2987                         return 0;
2988
2989                 for (i = 1; i < EXT2_N_BLOCKS; i++)
2990                         if (inode->i_block[i])
2991                                 return 0;
2992
2993                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2994                         return 0;
2995
2996                 len = strnlen(buf, fs->blocksize);
2997                 if (len == fs->blocksize)
2998                         return 0;
2999         } else {
3000                 if (inode->i_size >= sizeof(inode->i_block))
3001                         return 0;
3002
3003                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3004                 if (len == sizeof(inode->i_block))
3005                         return 0;
3006         }
3007         if (len != inode->i_size)
3008                 return 0;
3009         return 1;
3010 }
3011
3012 /*
3013  * If the immutable (or append-only) flag is set on the inode, offer
3014  * to clear it.
3015  */
3016 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3017 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3018 {
3019         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3020                 return;
3021
3022         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3023                 return;
3024
3025         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3026         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3027 }
3028
3029 /*
3030  * If device, fifo or socket, check size is zero -- if not offer to
3031  * clear it
3032  */
3033 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3034 {
3035         struct ext2_inode *inode = pctx->inode;
3036
3037         if ((inode->i_size == 0) && (inode->i_size_high == 0))
3038                 return;
3039
3040         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3041                 return;
3042
3043         inode->i_size = 0;
3044         inode->i_size_high = 0;
3045         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3046 }
3047
3048 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3049 {
3050         struct ext2_super_block *sb = ctx->fs->super;
3051         struct ext2_inode_large *inode;
3052         struct ext2_ext_attr_entry *entry;
3053         char *start, *end;
3054         int storage_size, remain, offs;
3055         int problem = 0;
3056
3057         inode = (struct ext2_inode_large *) pctx->inode;
3058         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3059                 inode->i_extra_isize;
3060         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3061                 inode->i_extra_isize + sizeof(__u32);
3062         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3063         entry = (struct ext2_ext_attr_entry *) start;
3064
3065         /* scan all entry's headers first */
3066
3067         /* take finish entry 0UL into account */
3068         remain = storage_size - sizeof(__u32);
3069         offs = end - start;
3070
3071         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3072
3073                 /* header eats this space */
3074                 remain -= sizeof(struct ext2_ext_attr_entry);
3075
3076                 /* is attribute name valid? */
3077                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3078                         pctx->num = entry->e_name_len;
3079                         problem = PR_1_ATTR_NAME_LEN;
3080                         goto fix;
3081                 }
3082
3083                 /* attribute len eats this space */
3084                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3085
3086                 /* check value size */
3087                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3088                         pctx->num = entry->e_value_size;
3089                         problem = PR_1_ATTR_VALUE_SIZE;
3090                         goto fix;
3091                 }
3092
3093                 /* check value placement */
3094                 if (entry->e_value_offs +
3095                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3096                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3097                         pctx->num = entry->e_value_offs;
3098                         problem = PR_1_ATTR_VALUE_OFFSET;
3099                         goto fix;
3100                 }
3101
3102                 /* e_value_block must be 0 in inode's ea */
3103                 if (entry->e_value_block != 0) {
3104                         pctx->num = entry->e_value_block;
3105                         problem = PR_1_ATTR_VALUE_BLOCK;
3106                         goto fix;
3107                 }
3108
3109                 /* e_hash must be 0 in inode's ea */
3110                 if (entry->e_hash != 0) {
3111                         pctx->num = entry->e_hash;
3112                         problem = PR_1_ATTR_HASH;
3113                         goto fix;
3114                 }
3115
3116                 remain -= entry->e_value_size;
3117                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3118
3119                 entry = EXT2_EXT_ATTR_NEXT(entry);
3120         }
3121 fix:
3122         /*
3123          * it seems like a corruption. it's very unlikely we could repair
3124          * EA(s) in automatic fashion -bzzz
3125          */
3126         if (problem == 0 || !fix_problem(ctx, problem, pctx))
3127                 return;
3128
3129         /* simple remove all possible EA(s) */
3130         *((__u32 *)start) = 0UL;
3131         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3132                                 EXT2_INODE_SIZE(sb), "pass1");
3133 }
3134
3135 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3136 {
3137         struct ext2_super_block *sb = ctx->fs->super;
3138         struct ext2_inode_large *inode;
3139         __u32 *eamagic;
3140         int min, max;
3141
3142         inode = (struct ext2_inode_large *) pctx->inode;
3143         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3144                 /* this isn't large inode. so, nothing to check */
3145                 return;
3146         }
3147
3148         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3149         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3150         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3151         /*
3152          * For now we will allow i_extra_isize to be 0, but really
3153          * implementations should never allow i_extra_isize to be 0
3154          */
3155         if (inode->i_extra_isize &&
3156             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3157                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3158                         return;
3159                 inode->i_extra_isize = min;
3160                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3161                                         EXT2_INODE_SIZE(sb), "pass1");
3162                 return;
3163         }
3164
3165         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3166                         inode->i_extra_isize);
3167         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3168                 /* it seems inode has an extended attribute(s) in body */
3169                 check_ea_in_inode(ctx, pctx);
3170         }
3171 }
3172
3173 static void e2fsck_pass1(e2fsck_t ctx)
3174 {
3175         int     i;
3176         __u64   max_sizes;
3177         ext2_filsys fs = ctx->fs;
3178         ext2_ino_t      ino;
3179         struct ext2_inode *inode;
3180         ext2_inode_scan scan;
3181         char            *block_buf;
3182         unsigned char   frag, fsize;
3183         struct          problem_context pctx;
3184         struct          scan_callback_struct scan_struct;
3185         struct ext2_super_block *sb = ctx->fs->super;
3186         int             imagic_fs;
3187         int             busted_fs_time = 0;
3188         int             inode_size;
3189
3190         clear_problem_context(&pctx);
3191
3192         if (!(ctx->options & E2F_OPT_PREEN))
3193                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3194
3195         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3196             !(ctx->options & E2F_OPT_NO)) {
3197                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3198                         ctx->dirs_to_hash = 0;
3199         }
3200
3201         /* Pass 1 */
3202
3203 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3204
3205         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3206                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3207                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3208                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3209                 max_sizes = (max_sizes * (1UL << i)) - 1;
3210                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3211         }
3212 #undef EXT2_BPP
3213
3214         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3215
3216         /*
3217          * Allocate bitmaps structures
3218          */
3219         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3220                                               &ctx->inode_used_map);
3221         if (pctx.errcode) {
3222                 pctx.num = 1;
3223                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3224                 ctx->flags |= E2F_FLAG_ABORT;
3225                 return;
3226         }
3227         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3228                                 _("directory inode map"), &ctx->inode_dir_map);
3229         if (pctx.errcode) {
3230                 pctx.num = 2;
3231                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3232                 ctx->flags |= E2F_FLAG_ABORT;
3233                 return;
3234         }
3235         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3236                         _("regular file inode map"), &ctx->inode_reg_map);
3237         if (pctx.errcode) {
3238                 pctx.num = 6;
3239                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3240                 ctx->flags |= E2F_FLAG_ABORT;
3241                 return;
3242         }
3243         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3244                                               &ctx->block_found_map);
3245         if (pctx.errcode) {
3246                 pctx.num = 1;
3247                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3248                 ctx->flags |= E2F_FLAG_ABORT;
3249                 return;
3250         }
3251         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3252                                              &ctx->inode_link_info);
3253         if (pctx.errcode) {
3254                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3255                 ctx->flags |= E2F_FLAG_ABORT;
3256                 return;
3257         }
3258         inode_size = EXT2_INODE_SIZE(fs->super);
3259         inode = (struct ext2_inode *)
3260                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3261
3262         inodes_to_process = (struct process_inode_block *)
3263                 e2fsck_allocate_memory(ctx,
3264                                        (ctx->process_inode_size *
3265                                         sizeof(struct process_inode_block)),
3266                                        "array of inodes to process");
3267         process_inode_count = 0;
3268
3269         pctx.errcode = ext2fs_init_dblist(fs, 0);
3270         if (pctx.errcode) {
3271                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3272                 ctx->flags |= E2F_FLAG_ABORT;
3273                 return;
3274         }
3275
3276         /*
3277          * If the last orphan field is set, clear it, since the pass1
3278          * processing will automatically find and clear the orphans.
3279          * In the future, we may want to try using the last_orphan
3280          * linked list ourselves, but for now, we clear it so that the
3281          * ext3 mount code won't get confused.
3282          */
3283         if (!(ctx->options & E2F_OPT_READONLY)) {
3284                 if (fs->super->s_last_orphan) {
3285                         fs->super->s_last_orphan = 0;
3286                         ext2fs_mark_super_dirty(fs);
3287                 }
3288         }
3289
3290         mark_table_blocks(ctx);
3291         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3292                                                     "block interate buffer");
3293         e2fsck_use_inode_shortcuts(ctx, 1);
3294         ehandler_operation(_("doing inode scan"));
3295         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3296                                               &scan);
3297         if (pctx.errcode) {
3298                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3299                 ctx->flags |= E2F_FLAG_ABORT;
3300                 return;
3301         }
3302         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3303         ctx->stashed_inode = inode;
3304         scan_struct.ctx = ctx;
3305         scan_struct.block_buf = block_buf;
3306         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3307         if (ctx->progress)
3308                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3309                         return;
3310         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3311             (fs->super->s_mtime < fs->super->s_inodes_count))
3312                 busted_fs_time = 1;
3313
3314         while (1) {
3315                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3316                                                           inode, inode_size);
3317                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3318                         return;
3319                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3320                         continue;
3321                 }
3322                 if (pctx.errcode) {
3323                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3324                         ctx->flags |= E2F_FLAG_ABORT;
3325                         return;
3326                 }
3327                 if (!ino)
3328                         break;
3329                 pctx.ino = ino;
3330                 pctx.inode = inode;
3331                 ctx->stashed_ino = ino;
3332                 if (inode->i_links_count) {
3333                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3334                                            ino, inode->i_links_count);
3335                         if (pctx.errcode) {
3336                                 pctx.num = inode->i_links_count;
3337                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3338                                 ctx->flags |= E2F_FLAG_ABORT;
3339                                 return;
3340                         }
3341                 }
3342                 if (ino == EXT2_BAD_INO) {
3343                         struct process_block_struct_1 pb;
3344
3345                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3346                                                           &pb.fs_meta_blocks);
3347                         if (pctx.errcode) {
3348                                 pctx.num = 4;
3349                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3350                                 ctx->flags |= E2F_FLAG_ABORT;
3351                                 return;
3352                         }
3353                         pb.ino = EXT2_BAD_INO;
3354                         pb.num_blocks = pb.last_block = 0;
3355                         pb.num_illegal_blocks = 0;
3356                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3357                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3358                         pb.inode = inode;
3359                         pb.pctx = &pctx;
3360                         pb.ctx = ctx;
3361                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3362                                      block_buf, process_bad_block, &pb);
3363                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3364                         if (pctx.errcode) {
3365                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3366                                 ctx->flags |= E2F_FLAG_ABORT;
3367                                 return;
3368                         }
3369                         if (pb.bbcheck)
3370                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3371                                 ctx->flags |= E2F_FLAG_ABORT;
3372                                 return;
3373                         }
3374                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3375                         clear_problem_context(&pctx);
3376                         continue;
3377                 } else if (ino == EXT2_ROOT_INO) {
3378                         /*
3379                          * Make sure the root inode is a directory; if
3380                          * not, offer to clear it.  It will be
3381                          * regnerated in pass #3.
3382                          */
3383                         if (!LINUX_S_ISDIR(inode->i_mode)) {
3384                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3385                                         inode->i_dtime = time(0);
3386                                         inode->i_links_count = 0;
3387                                         ext2fs_icount_store(ctx->inode_link_info,
3388                                                             ino, 0);
3389                                         e2fsck_write_inode(ctx, ino, inode,
3390                                                            "pass1");
3391                                 }
3392
3393                         }
3394                         /*
3395                          * If dtime is set, offer to clear it.  mke2fs
3396                          * version 0.2b created filesystems with the
3397                          * dtime field set for the root and lost+found
3398                          * directories.  We won't worry about
3399                          * /lost+found, since that can be regenerated
3400                          * easily.  But we will fix the root directory
3401                          * as a special case.
3402                          */
3403                         if (inode->i_dtime && inode->i_links_count) {
3404                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3405                                         inode->i_dtime = 0;
3406                                         e2fsck_write_inode(ctx, ino, inode,
3407                                                            "pass1");
3408                                 }
3409                         }
3410                 } else if (ino == EXT2_JOURNAL_INO) {
3411                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3412                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3413                                 if (!LINUX_S_ISREG(inode->i_mode) &&
3414                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3415                                                 &pctx)) {
3416                                         inode->i_mode = LINUX_S_IFREG;
3417                                         e2fsck_write_inode(ctx, ino, inode,
3418                                                            "pass1");
3419                                 }
3420                                 check_blocks(ctx, &pctx, block_buf);
3421                                 continue;
3422                         }
3423                         if ((inode->i_links_count || inode->i_blocks ||
3424                              inode->i_blocks || inode->i_block[0]) &&
3425                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3426                                         &pctx)) {
3427                                 memset(inode, 0, inode_size);
3428                                 ext2fs_icount_store(ctx->inode_link_info,
3429                                                     ino, 0);
3430                                 e2fsck_write_inode_full(ctx, ino, inode,
3431                                                         inode_size, "pass1");
3432                         }
3433                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3434                         int     problem = 0;
3435
3436                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3437                         if (ino == EXT2_BOOT_LOADER_INO) {
3438                                 if (LINUX_S_ISDIR(inode->i_mode))
3439                                         problem = PR_1_RESERVED_BAD_MODE;
3440                         } else if (ino == EXT2_RESIZE_INO) {
3441                                 if (inode->i_mode &&
3442                                     !LINUX_S_ISREG(inode->i_mode))
3443                                         problem = PR_1_RESERVED_BAD_MODE;
3444                         } else {
3445                                 if (inode->i_mode != 0)
3446                                         problem = PR_1_RESERVED_BAD_MODE;
3447                         }
3448                         if (problem) {
3449                                 if (fix_problem(ctx, problem, &pctx)) {
3450                                         inode->i_mode = 0;
3451                                         e2fsck_write_inode(ctx, ino, inode,
3452                                                            "pass1");
3453                                 }
3454                         }
3455                         check_blocks(ctx, &pctx, block_buf);
3456                         continue;
3457                 }
3458                 /*
3459                  * Check for inodes who might have been part of the
3460                  * orphaned list linked list.  They should have gotten
3461                  * dealt with by now, unless the list had somehow been
3462                  * corrupted.
3463                  *
3464                  * FIXME: In the future, inodes which are still in use
3465                  * (and which are therefore) pending truncation should
3466                  * be handled specially.  Right now we just clear the
3467                  * dtime field, and the normal e2fsck handling of
3468                  * inodes where i_size and the inode blocks are
3469                  * inconsistent is to fix i_size, instead of releasing
3470                  * the extra blocks.  This won't catch the inodes that
3471                  * was at the end of the orphan list, but it's better
3472                  * than nothing.  The right answer is that there
3473                  * shouldn't be any bugs in the orphan list handling.  :-)
3474                  */
3475                 if (inode->i_dtime && !busted_fs_time &&
3476                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3477                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3478                                 inode->i_dtime = inode->i_links_count ?
3479                                         0 : time(0);
3480                                 e2fsck_write_inode(ctx, ino, inode,
3481                                                    "pass1");
3482                         }
3483                 }
3484
3485                 /*
3486                  * This code assumes that deleted inodes have
3487                  * i_links_count set to 0.
3488                  */
3489                 if (!inode->i_links_count) {
3490                         if (!inode->i_dtime && inode->i_mode) {
3491                                 if (fix_problem(ctx,
3492                                             PR_1_ZERO_DTIME, &pctx)) {
3493                                         inode->i_dtime = time(0);
3494                                         e2fsck_write_inode(ctx, ino, inode,
3495                                                            "pass1");
3496                                 }
3497                         }
3498                         continue;
3499                 }
3500                 /*
3501                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
3502                  * deleted files.  Oops.
3503                  *
3504                  * Since all new ext2 implementations get this right,
3505                  * we now assume that the case of non-zero
3506                  * i_links_count and non-zero dtime means that we
3507                  * should keep the file, not delete it.
3508                  *
3509                  */
3510                 if (inode->i_dtime) {
3511                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3512                                 inode->i_dtime = 0;
3513                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
3514                         }
3515                 }
3516
3517                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3518                 switch (fs->super->s_creator_os) {
3519                     case EXT2_OS_LINUX:
3520                         frag = inode->osd2.linux2.l_i_frag;
3521                         fsize = inode->osd2.linux2.l_i_fsize;
3522                         break;
3523                     case EXT2_OS_HURD:
3524                         frag = inode->osd2.hurd2.h_i_frag;
3525                         fsize = inode->osd2.hurd2.h_i_fsize;
3526                         break;
3527                     case EXT2_OS_MASIX:
3528                         frag = inode->osd2.masix2.m_i_frag;
3529                         fsize = inode->osd2.masix2.m_i_fsize;
3530                         break;
3531                     default:
3532                         frag = fsize = 0;
3533                 }
3534
3535                 if (inode->i_faddr || frag || fsize ||
3536                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3537                         mark_inode_bad(ctx, ino);
3538                 if (inode->i_flags & EXT2_IMAGIC_FL) {
3539                         if (imagic_fs) {
3540                                 if (!ctx->inode_imagic_map)
3541                                         alloc_imagic_map(ctx);
3542                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3543                                                          ino);
3544                         } else {
3545                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3546                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
3547                                         e2fsck_write_inode(ctx, ino,
3548                                                            inode, "pass1");
3549                                 }
3550                         }
3551                 }
3552
3553                 check_inode_extra_space(ctx, &pctx);
3554
3555                 if (LINUX_S_ISDIR(inode->i_mode)) {
3556                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3557                         e2fsck_add_dir_info(ctx, ino, 0);
3558                         ctx->fs_directory_count++;
3559                 } else if (LINUX_S_ISREG (inode->i_mode)) {
3560                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3561                         ctx->fs_regular_count++;
3562                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3563                            e2fsck_pass1_check_device_inode(fs, inode)) {
3564                         check_immutable(ctx, &pctx);
3565                         check_size(ctx, &pctx);
3566                         ctx->fs_chardev_count++;
3567                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3568                            e2fsck_pass1_check_device_inode(fs, inode)) {
3569                         check_immutable(ctx, &pctx);
3570                         check_size(ctx, &pctx);
3571                         ctx->fs_blockdev_count++;
3572                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3573                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3574                         check_immutable(ctx, &pctx);
3575                         ctx->fs_symlinks_count++;
3576                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3577                                 ctx->fs_fast_symlinks_count++;
3578                                 check_blocks(ctx, &pctx, block_buf);
3579                                 continue;
3580                         }
3581                 }
3582                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3583                          e2fsck_pass1_check_device_inode(fs, inode)) {
3584                         check_immutable(ctx, &pctx);
3585                         check_size(ctx, &pctx);
3586                         ctx->fs_fifo_count++;
3587                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3588                            e2fsck_pass1_check_device_inode(fs, inode)) {
3589                         check_immutable(ctx, &pctx);
3590                         check_size(ctx, &pctx);
3591                         ctx->fs_sockets_count++;
3592                 } else
3593                         mark_inode_bad(ctx, ino);
3594                 if (inode->i_block[EXT2_IND_BLOCK])
3595                         ctx->fs_ind_count++;
3596                 if (inode->i_block[EXT2_DIND_BLOCK])
3597                         ctx->fs_dind_count++;
3598                 if (inode->i_block[EXT2_TIND_BLOCK])
3599                         ctx->fs_tind_count++;
3600                 if (inode->i_block[EXT2_IND_BLOCK] ||
3601                     inode->i_block[EXT2_DIND_BLOCK] ||
3602                     inode->i_block[EXT2_TIND_BLOCK] ||
3603                     inode->i_file_acl) {
3604                         inodes_to_process[process_inode_count].ino = ino;
3605                         inodes_to_process[process_inode_count].inode = *inode;
3606                         process_inode_count++;
3607                 } else
3608                         check_blocks(ctx, &pctx, block_buf);
3609
3610                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3611                         return;
3612
3613                 if (process_inode_count >= ctx->process_inode_size) {
3614                         process_inodes(ctx, block_buf);
3615
3616                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3617                                 return;
3618                 }
3619         }
3620         process_inodes(ctx, block_buf);
3621         ext2fs_close_inode_scan(scan);
3622         ehandler_operation(0);
3623
3624         /*
3625          * If any extended attribute blocks' reference counts need to
3626          * be adjusted, either up (ctx->refcount_extra), or down
3627          * (ctx->refcount), then fix them.
3628          */
3629         if (ctx->refcount) {
3630                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3631                 ea_refcount_free(ctx->refcount);
3632                 ctx->refcount = 0;
3633         }
3634         if (ctx->refcount_extra) {
3635                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3636                                         block_buf, +1);
3637                 ea_refcount_free(ctx->refcount_extra);
3638                 ctx->refcount_extra = 0;
3639         }
3640
3641         if (ctx->invalid_bitmaps)
3642                 handle_fs_bad_blocks(ctx);
3643
3644         /* We don't need the block_ea_map any more */
3645         ext2fs_free_block_bitmap(ctx->block_ea_map);
3646         ctx->block_ea_map = 0;
3647
3648         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3649                 ext2fs_block_bitmap save_bmap;
3650
3651                 save_bmap = fs->block_map;
3652                 fs->block_map = ctx->block_found_map;
3653                 clear_problem_context(&pctx);
3654                 pctx.errcode = ext2fs_create_resize_inode(fs);
3655                 if (pctx.errcode) {
3656                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3657                         /* Should never get here */
3658                         ctx->flags |= E2F_FLAG_ABORT;
3659                         return;
3660                 }
3661                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3662                                   "recreate inode");
3663                 inode->i_mtime = time(0);
3664                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3665                                   "recreate inode");
3666                 fs->block_map = save_bmap;
3667                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3668         }
3669
3670         if (ctx->flags & E2F_FLAG_RESTART) {
3671                 /*
3672                  * Only the master copy of the superblock and block
3673                  * group descriptors are going to be written during a
3674                  * restart, so set the superblock to be used to be the
3675                  * master superblock.
3676                  */
3677                 ctx->use_superblock = 0;
3678                 unwind_pass1();
3679                 goto endit;
3680         }
3681
3682         if (ctx->block_dup_map) {
3683                 if (ctx->options & E2F_OPT_PREEN) {
3684                         clear_problem_context(&pctx);
3685                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3686                 }
3687                 e2fsck_pass1_dupblocks(ctx, block_buf);
3688         }
3689         ext2fs_free_mem(&inodes_to_process);
3690 endit:
3691         e2fsck_use_inode_shortcuts(ctx, 0);
3692
3693         ext2fs_free_mem(&block_buf);
3694         ext2fs_free_mem(&inode);
3695
3696 }
3697
3698 /*
3699  * When the inode_scan routines call this callback at the end of the
3700  * glock group, call process_inodes.
3701  */
3702 static errcode_t scan_callback(ext2_filsys fs,
3703                                dgrp_t group, void * priv_data)
3704 {
3705         struct scan_callback_struct *scan_struct;
3706         e2fsck_t ctx;
3707
3708         scan_struct = (struct scan_callback_struct *) priv_data;
3709         ctx = scan_struct->ctx;
3710
3711         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3712
3713         if (ctx->progress)
3714                 if ((ctx->progress)(ctx, 1, group+1,
3715                                     ctx->fs->group_desc_count))
3716                         return EXT2_ET_CANCEL_REQUESTED;
3717
3718         return 0;
3719 }
3720
3721 /*
3722  * Process the inodes in the "inodes to process" list.
3723  */
3724 static void process_inodes(e2fsck_t ctx, char *block_buf)
3725 {
3726         int                     i;
3727         struct ext2_inode       *old_stashed_inode;
3728         ext2_ino_t              old_stashed_ino;
3729         const char              *old_operation;
3730         char                    buf[80];
3731         struct problem_context  pctx;
3732
3733         /* begin process_inodes */
3734         if (process_inode_count == 0)
3735                 return;
3736         old_operation = ehandler_operation(0);
3737         old_stashed_inode = ctx->stashed_inode;
3738         old_stashed_ino = ctx->stashed_ino;
3739         qsort(inodes_to_process, process_inode_count,
3740                       sizeof(struct process_inode_block), process_inode_cmp);
3741         clear_problem_context(&pctx);
3742         for (i=0; i < process_inode_count; i++) {
3743                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3744                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3745                 sprintf(buf, _("reading indirect blocks of inode %u"),
3746                         pctx.ino);
3747                 ehandler_operation(buf);
3748                 check_blocks(ctx, &pctx, block_buf);
3749                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3750                         break;
3751         }
3752         ctx->stashed_inode = old_stashed_inode;
3753         ctx->stashed_ino = old_stashed_ino;
3754         process_inode_count = 0;
3755         /* end process inodes */
3756
3757         ehandler_operation(old_operation);
3758 }
3759
3760 static int process_inode_cmp(const void *a, const void *b)
3761 {
3762         const struct process_inode_block *ib_a =
3763                 (const struct process_inode_block *) a;
3764         const struct process_inode_block *ib_b =
3765                 (const struct process_inode_block *) b;
3766         int     ret;
3767
3768         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3769                ib_b->inode.i_block[EXT2_IND_BLOCK]);
3770         if (ret == 0)
3771                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3772         return ret;
3773 }
3774
3775 /*
3776  * Mark an inode as being bad in some what
3777  */
3778 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3779 {
3780         struct          problem_context pctx;
3781
3782         if (!ctx->inode_bad_map) {
3783                 clear_problem_context(&pctx);
3784
3785                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3786                             _("bad inode map"), &ctx->inode_bad_map);
3787                 if (pctx.errcode) {
3788                         pctx.num = 3;
3789                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3790                         /* Should never get here */
3791                         ctx->flags |= E2F_FLAG_ABORT;
3792                         return;
3793                 }
3794         }
3795         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3796 }
3797
3798
3799 /*
3800  * This procedure will allocate the inode imagic table
3801  */
3802 static void alloc_imagic_map(e2fsck_t ctx)
3803 {
3804         struct          problem_context pctx;
3805
3806         clear_problem_context(&pctx);
3807         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3808                                               _("imagic inode map"),
3809                                               &ctx->inode_imagic_map);
3810         if (pctx.errcode) {
3811                 pctx.num = 5;
3812                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3813                 /* Should never get here */
3814                 ctx->flags |= E2F_FLAG_ABORT;
3815                 return;
3816         }
3817 }
3818
3819 /*
3820  * Marks a block as in use, setting the dup_map if it's been set
3821  * already.  Called by process_block and process_bad_block.
3822  *
3823  * WARNING: Assumes checks have already been done to make sure block
3824  * is valid.  This is true in both process_block and process_bad_block.
3825  */
3826 static void mark_block_used(e2fsck_t ctx, blk_t block)
3827 {
3828         struct          problem_context pctx;
3829
3830         clear_problem_context(&pctx);
3831
3832         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3833                 if (!ctx->block_dup_map) {
3834                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3835                               _("multiply claimed block map"),
3836                               &ctx->block_dup_map);
3837                         if (pctx.errcode) {
3838                                 pctx.num = 3;
3839                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3840                                             &pctx);
3841                                 /* Should never get here */
3842                                 ctx->flags |= E2F_FLAG_ABORT;
3843                                 return;
3844                         }
3845                 }
3846                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3847         } else {
3848                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3849         }
3850 }
3851
3852 /*
3853  * Adjust the extended attribute block's reference counts at the end
3854  * of pass 1, either by subtracting out references for EA blocks that
3855  * are still referenced in ctx->refcount, or by adding references for
3856  * EA blocks that had extra references as accounted for in
3857  * ctx->refcount_extra.
3858  */
3859 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3860                                     char *block_buf, int adjust_sign)
3861 {
3862         struct ext2_ext_attr_header     *header;
3863         struct problem_context          pctx;
3864         ext2_filsys                     fs = ctx->fs;
3865         blk_t                           blk;
3866         __u32                           should_be;
3867         int                             count;
3868
3869         clear_problem_context(&pctx);
3870
3871         ea_refcount_intr_begin(refcount);
3872         while (1) {
3873                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3874                         break;
3875                 pctx.blk = blk;
3876                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3877                 if (pctx.errcode) {
3878                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3879                         return;
3880                 }
3881                 header = (struct ext2_ext_attr_header *) block_buf;
3882                 pctx.blkcount = header->h_refcount;
3883                 should_be = header->h_refcount + adjust_sign * count;
3884                 pctx.num = should_be;
3885                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3886                         header->h_refcount = should_be;
3887                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3888                                                              block_buf);
3889                         if (pctx.errcode) {
3890                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3891                                 continue;
3892                         }
3893                 }
3894         }
3895 }
3896
3897 /*
3898  * Handle processing the extended attribute blocks
3899  */
3900 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3901                            char *block_buf)
3902 {
3903         ext2_filsys fs = ctx->fs;
3904         ext2_ino_t      ino = pctx->ino;
3905         struct ext2_inode *inode = pctx->inode;
3906         blk_t           blk;
3907         char *          end;
3908         struct ext2_ext_attr_header *header;
3909         struct ext2_ext_attr_entry *entry;
3910         int             count;
3911         region_t        region;
3912
3913         blk = inode->i_file_acl;
3914         if (blk == 0)
3915                 return 0;
3916
3917         /*
3918          * If the Extended attribute flag isn't set, then a non-zero
3919          * file acl means that the inode is corrupted.
3920          *
3921          * Or if the extended attribute block is an invalid block,
3922          * then the inode is also corrupted.
3923          */
3924         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3925             (blk < fs->super->s_first_data_block) ||
3926             (blk >= fs->super->s_blocks_count)) {
3927                 mark_inode_bad(ctx, ino);
3928                 return 0;
3929         }
3930
3931         /* If ea bitmap hasn't been allocated, create it */
3932         if (!ctx->block_ea_map) {
3933                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3934                                                       _("ext attr block map"),
3935                                                       &ctx->block_ea_map);
3936                 if (pctx->errcode) {
3937                         pctx->num = 2;
3938                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3939                         ctx->flags |= E2F_FLAG_ABORT;
3940                         return 0;
3941                 }
3942         }
3943
3944         /* Create the EA refcount structure if necessary */
3945         if (!ctx->refcount) {
3946                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3947                 if (pctx->errcode) {
3948                         pctx->num = 1;
3949                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3950                         ctx->flags |= E2F_FLAG_ABORT;
3951                         return 0;
3952                 }
3953         }
3954
3955         /* Have we seen this EA block before? */
3956         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3957                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3958                         return 1;
3959                 /* Ooops, this EA was referenced more than it stated */
3960                 if (!ctx->refcount_extra) {
3961                         pctx->errcode = ea_refcount_create(0,
3962                                            &ctx->refcount_extra);
3963                         if (pctx->errcode) {
3964                                 pctx->num = 2;
3965                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3966                                 ctx->flags |= E2F_FLAG_ABORT;
3967                                 return 0;
3968                         }
3969                 }
3970                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3971                 return 1;
3972         }
3973
3974         /*
3975          * OK, we haven't seen this EA block yet.  So we need to
3976          * validate it
3977          */
3978         pctx->blk = blk;
3979         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3980         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3981                 goto clear_extattr;
3982         header = (struct ext2_ext_attr_header *) block_buf;
3983         pctx->blk = inode->i_file_acl;
3984         if (((ctx->ext_attr_ver == 1) &&
3985              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3986             ((ctx->ext_attr_ver == 2) &&
3987              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3988                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3989                         goto clear_extattr;
3990         }
3991
3992         if (header->h_blocks != 1) {
3993                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3994                         goto clear_extattr;
3995         }
3996
3997         region = region_create(0, fs->blocksize);
3998         if (!region) {
3999                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4000                 ctx->flags |= E2F_FLAG_ABORT;
4001                 return 0;
4002         }
4003         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4004                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4005                         goto clear_extattr;
4006         }
4007
4008         entry = (struct ext2_ext_attr_entry *)(header+1);
4009         end = block_buf + fs->blocksize;
4010         while ((char *)entry < end && *(__u32 *)entry) {
4011                 if (region_allocate(region, (char *)entry - (char *)header,
4012                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4013                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4014                                 goto clear_extattr;
4015                 }
4016                 if ((ctx->ext_attr_ver == 1 &&
4017                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4018                     (ctx->ext_attr_ver == 2 &&
4019                      entry->e_name_index == 0)) {
4020                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4021                                 goto clear_extattr;
4022                 }
4023                 if (entry->e_value_block != 0) {
4024                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4025                                 goto clear_extattr;
4026                 }
4027                 if (entry->e_value_size &&
4028                     region_allocate(region, entry->e_value_offs,
4029                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4030                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4031                                 goto clear_extattr;
4032                 }
4033                 entry = EXT2_EXT_ATTR_NEXT(entry);
4034         }
4035         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4036                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4037                         goto clear_extattr;
4038         }
4039         region_free(region);
4040
4041         count = header->h_refcount - 1;
4042         if (count)
4043                 ea_refcount_store(ctx->refcount, blk, count);
4044         mark_block_used(ctx, blk);
4045         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4046
4047         return 1;
4048
4049 clear_extattr:
4050         inode->i_file_acl = 0;
4051         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4052         return 0;
4053 }
4054
4055 /* Returns 1 if bad htree, 0 if OK */
4056 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4057                         ext2_ino_t ino FSCK_ATTR((unused)),
4058                         struct ext2_inode *inode,
4059                         char *block_buf)
4060 {
4061         struct ext2_dx_root_info        *root;
4062         ext2_filsys                     fs = ctx->fs;
4063         errcode_t                       retval;
4064         blk_t                           blk;
4065
4066         if ((!LINUX_S_ISDIR(inode->i_mode) &&
4067              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4068             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4069              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4070                 return 1;
4071
4072         blk = inode->i_block[0];
4073         if (((blk == 0) ||
4074              (blk < fs->super->s_first_data_block) ||
4075              (blk >= fs->super->s_blocks_count)) &&
4076             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4077                 return 1;
4078
4079         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4080         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4081                 return 1;
4082
4083         /* XXX should check that beginning matches a directory */
4084         root = (struct ext2_dx_root_info *) (block_buf + 24);
4085
4086         if ((root->reserved_zero || root->info_length < 8) &&
4087             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4088                 return 1;
4089
4090         pctx->num = root->hash_version;
4091         if ((root->hash_version != EXT2_HASH_LEGACY) &&
4092             (root->hash_version != EXT2_HASH_HALF_MD4) &&
4093             (root->hash_version != EXT2_HASH_TEA) &&
4094             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4095                 return 1;
4096
4097         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4098             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4099                 return 1;
4100
4101         pctx->num = root->indirect_levels;
4102         if ((root->indirect_levels > 1) &&
4103             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4104                 return 1;
4105
4106         return 0;
4107 }
4108
4109 /*
4110  * This subroutine is called on each inode to account for all of the
4111  * blocks used by that inode.
4112  */
4113 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4114                          char *block_buf)
4115 {
4116         ext2_filsys fs = ctx->fs;
4117         struct process_block_struct_1 pb;
4118         ext2_ino_t      ino = pctx->ino;
4119         struct ext2_inode *inode = pctx->inode;
4120         int             bad_size = 0;
4121         int             dirty_inode = 0;
4122         __u64           size;
4123
4124         pb.ino = ino;
4125         pb.num_blocks = 0;
4126         pb.last_block = -1;
4127         pb.num_illegal_blocks = 0;
4128         pb.suppress = 0; pb.clear = 0;
4129         pb.fragmented = 0;
4130         pb.compressed = 0;
4131         pb.previous_block = 0;
4132         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4133         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4134         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4135         pb.inode = inode;
4136         pb.pctx = pctx;
4137         pb.ctx = ctx;
4138         pctx->ino = ino;
4139         pctx->errcode = 0;
4140
4141         if (inode->i_flags & EXT2_COMPRBLK_FL) {
4142                 if (fs->super->s_feature_incompat &
4143                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4144                         pb.compressed = 1;
4145                 else {
4146                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4147                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4148                                 dirty_inode++;
4149                         }
4150                 }
4151         }
4152
4153         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4154                 pb.num_blocks++;
4155
4156         if (ext2fs_inode_has_valid_blocks(inode))
4157                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4158                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4159                                        block_buf, process_block, &pb);
4160         end_problem_latch(ctx, PR_LATCH_BLOCK);
4161         end_problem_latch(ctx, PR_LATCH_TOOBIG);
4162         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4163                 goto out;
4164         if (pctx->errcode)
4165                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4166
4167         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4168                 ctx->fs_fragmented++;
4169
4170         if (pb.clear) {
4171                 inode->i_links_count = 0;
4172                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4173                 inode->i_dtime = time(0);
4174                 dirty_inode++;
4175                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4176                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4177                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4178                 /*
4179                  * The inode was probably partially accounted for
4180                  * before processing was aborted, so we need to
4181                  * restart the pass 1 scan.
4182                  */
4183                 ctx->flags |= E2F_FLAG_RESTART;
4184                 goto out;
4185         }
4186
4187         if (inode->i_flags & EXT2_INDEX_FL) {
4188                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4189                         inode->i_flags &= ~EXT2_INDEX_FL;
4190                         dirty_inode++;
4191                 } else {
4192 #ifdef ENABLE_HTREE
4193                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4194 #endif
4195                 }
4196         }
4197         if (ctx->dirs_to_hash && pb.is_dir &&
4198             !(inode->i_flags & EXT2_INDEX_FL) &&
4199             ((inode->i_size / fs->blocksize) >= 3))
4200                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4201
4202         if (!pb.num_blocks && pb.is_dir) {
4203                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4204                         inode->i_links_count = 0;
4205                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4206                         inode->i_dtime = time(0);
4207                         dirty_inode++;
4208                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4209                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4210                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4211                         ctx->fs_directory_count--;
4212                         goto out;
4213                 }
4214         }
4215
4216         pb.num_blocks *= (fs->blocksize / 512);
4217
4218         if (pb.is_dir) {
4219                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4220                 if (nblock > (pb.last_block + 1))
4221                         bad_size = 1;
4222                 else if (nblock < (pb.last_block + 1)) {
4223                         if (((pb.last_block + 1) - nblock) >
4224                             fs->super->s_prealloc_dir_blocks)
4225                                 bad_size = 2;
4226                 }
4227         } else {
4228                 size = EXT2_I_SIZE(inode);
4229                 if ((pb.last_block >= 0) &&
4230                     (size < (__u64) pb.last_block * fs->blocksize))
4231                         bad_size = 3;
4232                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4233                         bad_size = 4;
4234         }
4235         /* i_size for symlinks is checked elsewhere */
4236         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4237                 pctx->num = (pb.last_block+1) * fs->blocksize;
4238                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4239                         inode->i_size = pctx->num;
4240                         if (!LINUX_S_ISDIR(inode->i_mode))
4241                                 inode->i_size_high = pctx->num >> 32;
4242                         dirty_inode++;
4243                 }
4244                 pctx->num = 0;
4245         }
4246         if (LINUX_S_ISREG(inode->i_mode) &&
4247             (inode->i_size_high || inode->i_size & 0x80000000UL))
4248                 ctx->large_files++;
4249         if (pb.num_blocks != inode->i_blocks) {
4250                 pctx->num = pb.num_blocks;
4251                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4252                         inode->i_blocks = pb.num_blocks;
4253                         dirty_inode++;
4254                 }
4255                 pctx->num = 0;
4256         }
4257 out:
4258         if (dirty_inode)
4259                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4260 }
4261
4262
4263 /*
4264  * This is a helper function for check_blocks().
4265  */
4266 static int process_block(ext2_filsys fs,
4267                   blk_t *block_nr,
4268                   e2_blkcnt_t blockcnt,
4269                   blk_t ref_block FSCK_ATTR((unused)),
4270                   int ref_offset FSCK_ATTR((unused)),
4271                   void *priv_data)
4272 {
4273         struct process_block_struct_1 *p;
4274         struct problem_context *pctx;
4275         blk_t   blk = *block_nr;
4276         int     ret_code = 0;
4277         int     problem = 0;
4278         e2fsck_t        ctx;
4279
4280         p = (struct process_block_struct_1 *) priv_data;
4281         pctx = p->pctx;
4282         ctx = p->ctx;
4283
4284         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4285                 /* todo: Check that the comprblk_fl is high, that the
4286                    blkaddr pattern looks right (all non-holes up to
4287                    first EXT2FS_COMPRESSED_BLKADDR, then all
4288                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4289                    that the feature_incompat bit is high, and that the
4290                    inode is a regular file.  If we're doing a "full
4291                    check" (a concept introduced to e2fsck by e2compr,
4292                    meaning that we look at data blocks as well as
4293                    metadata) then call some library routine that
4294                    checks the compressed data.  I'll have to think
4295                    about this, because one particularly important
4296                    problem to be able to fix is to recalculate the
4297                    cluster size if necessary.  I think that perhaps
4298                    we'd better do most/all e2compr-specific checks
4299                    separately, after the non-e2compr checks.  If not
4300                    doing a full check, it may be useful to test that
4301                    the personality is linux; e.g. if it isn't then
4302                    perhaps this really is just an illegal block. */
4303                 return 0;
4304         }
4305
4306         if (blk == 0) {
4307                 if (p->is_dir == 0) {
4308                         /*
4309                          * Should never happen, since only directories
4310                          * get called with BLOCK_FLAG_HOLE
4311                          */
4312 #if DEBUG_E2FSCK
4313                         printf("process_block() called with blk == 0, "
4314                                "blockcnt=%d, inode %lu???\n",
4315                                blockcnt, p->ino);
4316 #endif
4317                         return 0;
4318                 }
4319                 if (blockcnt < 0)
4320                         return 0;
4321                 if (blockcnt * fs->blocksize < p->inode->i_size) {
4322                         goto mark_dir;
4323                 }
4324                 return 0;
4325         }
4326
4327         /*
4328          * Simplistic fragmentation check.  We merely require that the
4329          * file be contiguous.  (Which can never be true for really
4330          * big files that are greater than a block group.)
4331          */
4332         if (!HOLE_BLKADDR(p->previous_block)) {
4333                 if (p->previous_block+1 != blk)
4334                         p->fragmented = 1;
4335         }
4336         p->previous_block = blk;
4337
4338         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4339                 problem = PR_1_TOOBIG_DIR;
4340         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4341                 problem = PR_1_TOOBIG_REG;
4342         if (!p->is_dir && !p->is_reg && blockcnt > 0)
4343                 problem = PR_1_TOOBIG_SYMLINK;
4344
4345         if (blk < fs->super->s_first_data_block ||
4346             blk >= fs->super->s_blocks_count)
4347                 problem = PR_1_ILLEGAL_BLOCK_NUM;
4348
4349         if (problem) {
4350                 p->num_illegal_blocks++;
4351                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4352                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4353                                 p->clear = 1;
4354                                 return BLOCK_ABORT;
4355                         }
4356                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4357                                 p->suppress = 1;
4358                                 set_latch_flags(PR_LATCH_BLOCK,
4359                                                 PRL_SUPPRESS, 0);
4360                         }
4361                 }
4362                 pctx->blk = blk;
4363                 pctx->blkcount = blockcnt;
4364                 if (fix_problem(ctx, problem, pctx)) {
4365                         blk = *block_nr = 0;
4366                         ret_code = BLOCK_CHANGED;
4367                         goto mark_dir;
4368                 } else
4369                         return 0;
4370         }
4371
4372         if (p->ino == EXT2_RESIZE_INO) {
4373                 /*
4374                  * The resize inode has already be sanity checked
4375                  * during pass #0 (the superblock checks).  All we
4376                  * have to do is mark the double indirect block as
4377                  * being in use; all of the other blocks are handled
4378                  * by mark_table_blocks()).
4379                  */
4380                 if (blockcnt == BLOCK_COUNT_DIND)
4381                         mark_block_used(ctx, blk);
4382         } else
4383                 mark_block_used(ctx, blk);
4384         p->num_blocks++;
4385         if (blockcnt >= 0)
4386                 p->last_block = blockcnt;
4387 mark_dir:
4388         if (p->is_dir && (blockcnt >= 0)) {
4389                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4390                                                     blk, blockcnt);
4391                 if (pctx->errcode) {
4392                         pctx->blk = blk;
4393                         pctx->num = blockcnt;
4394                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4395                         /* Should never get here */
4396                         ctx->flags |= E2F_FLAG_ABORT;
4397                         return BLOCK_ABORT;
4398                 }
4399         }
4400         return ret_code;
4401 }
4402
4403 static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4404                       blk_t *block_nr,
4405                       e2_blkcnt_t blockcnt,
4406                       blk_t ref_block FSCK_ATTR((unused)),
4407                       int ref_offset FSCK_ATTR((unused)),
4408                       void *priv_data EXT2FS_ATTR((unused)))
4409 {
4410         /*
4411          * Note: This function processes blocks for the bad blocks
4412          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4413          */
4414
4415         printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4416         return BLOCK_ERROR;
4417 }
4418
4419 /*
4420  * This routine gets called at the end of pass 1 if bad blocks are
4421  * detected in the superblock, group descriptors, inode_bitmaps, or
4422  * block bitmaps.  At this point, all of the blocks have been mapped
4423  * out, so we can try to allocate new block(s) to replace the bad
4424  * blocks.
4425  */
4426 static void handle_fs_bad_blocks(e2fsck_t ctx)
4427 {
4428         printf("Bad blocks detected on your filesystem\n"
4429                 "You should get your data off as the device will soon die\n");
4430 }
4431
4432 /*
4433  * This routine marks all blocks which are used by the superblock,
4434  * group descriptors, inode bitmaps, and block bitmaps.
4435  */
4436 static void mark_table_blocks(e2fsck_t ctx)
4437 {
4438         ext2_filsys fs = ctx->fs;
4439         blk_t   block, b;
4440         dgrp_t  i;
4441         int     j;
4442         struct problem_context pctx;
4443
4444         clear_problem_context(&pctx);
4445
4446         block = fs->super->s_first_data_block;
4447         for (i = 0; i < fs->group_desc_count; i++) {
4448                 pctx.group = i;
4449
4450                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4451
4452                 /*
4453                  * Mark the blocks used for the inode table
4454                  */
4455                 if (fs->group_desc[i].bg_inode_table) {
4456                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
4457                              j < fs->inode_blocks_per_group;
4458                              j++, b++) {
4459                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4460                                                              b)) {
4461                                         pctx.blk = b;
4462                                         if (fix_problem(ctx,
4463                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
4464                                                 ctx->invalid_inode_table_flag[i]++;
4465                                                 ctx->invalid_bitmaps++;
4466                                         }
4467                                 } else {
4468                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
4469                                                              b);
4470                                 }
4471                         }
4472                 }
4473
4474                 /*
4475                  * Mark block used for the block bitmap
4476                  */
4477                 if (fs->group_desc[i].bg_block_bitmap) {
4478                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4479                                      fs->group_desc[i].bg_block_bitmap)) {
4480                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4481                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4482                                         ctx->invalid_block_bitmap_flag[i]++;
4483                                         ctx->invalid_bitmaps++;
4484                                 }
4485                         } else {
4486                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4487                                      fs->group_desc[i].bg_block_bitmap);
4488                     }
4489
4490                 }
4491                 /*
4492                  * Mark block used for the inode bitmap
4493                  */
4494                 if (fs->group_desc[i].bg_inode_bitmap) {
4495                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
4496                                      fs->group_desc[i].bg_inode_bitmap)) {
4497                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4498                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4499                                         ctx->invalid_inode_bitmap_flag[i]++;
4500                                         ctx->invalid_bitmaps++;
4501                                 }
4502                         } else {
4503                             ext2fs_mark_block_bitmap(ctx->block_found_map,
4504                                      fs->group_desc[i].bg_inode_bitmap);
4505                         }
4506                 }
4507                 block += fs->super->s_blocks_per_group;
4508         }
4509 }
4510
4511 /*
4512  * Thes subroutines short circuits ext2fs_get_blocks and
4513  * ext2fs_check_directory; we use them since we already have the inode
4514  * structure, so there's no point in letting the ext2fs library read
4515  * the inode again.
4516  */
4517 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4518                                   blk_t *blocks)
4519 {
4520         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521         int     i;
4522
4523         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4524                 return EXT2_ET_CALLBACK_NOTHANDLED;
4525
4526         for (i=0; i < EXT2_N_BLOCKS; i++)
4527                 blocks[i] = ctx->stashed_inode->i_block[i];
4528         return 0;
4529 }
4530
4531 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4532                                   struct ext2_inode *inode)
4533 {
4534         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4535
4536         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4537                 return EXT2_ET_CALLBACK_NOTHANDLED;
4538         *inode = *ctx->stashed_inode;
4539         return 0;
4540 }
4541
4542 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4543                             struct ext2_inode *inode)
4544 {
4545         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4546
4547         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4548                 *ctx->stashed_inode = *inode;
4549         return EXT2_ET_CALLBACK_NOTHANDLED;
4550 }
4551
4552 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4553 {
4554         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4555
4556         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4557                 return EXT2_ET_CALLBACK_NOTHANDLED;
4558
4559         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4560                 return EXT2_ET_NO_DIRECTORY;
4561         return 0;
4562 }
4563
4564 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4565 {
4566         ext2_filsys fs = ctx->fs;
4567
4568         if (bool) {
4569                 fs->get_blocks = pass1_get_blocks;
4570                 fs->check_directory = pass1_check_directory;
4571                 fs->read_inode = pass1_read_inode;
4572                 fs->write_inode = pass1_write_inode;
4573                 ctx->stashed_ino = 0;
4574         } else {
4575                 fs->get_blocks = 0;
4576                 fs->check_directory = 0;
4577                 fs->read_inode = 0;
4578                 fs->write_inode = 0;
4579         }
4580 }
4581
4582 /*
4583  * pass1b.c --- Pass #1b of e2fsck
4584  *
4585  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4586  * only invoked if pass 1 discovered blocks which are in use by more
4587  * than one inode.
4588  *
4589  * Pass1B scans the data blocks of all the inodes again, generating a
4590  * complete list of duplicate blocks and which inodes have claimed
4591  * them.
4592  *
4593  * Pass1C does a tree-traversal of the filesystem, to determine the
4594  * parent directories of these inodes.  This step is necessary so that
4595  * e2fsck can print out the pathnames of affected inodes.
4596  *
4597  * Pass1D is a reconciliation pass.  For each inode with duplicate
4598  * blocks, the user is prompted if s/he would like to clone the file
4599  * (so that the file gets a fresh copy of the duplicated blocks) or
4600  * simply to delete the file.
4601  *
4602  */
4603
4604
4605 /* Needed for architectures where sizeof(int) != sizeof(void *) */
4606 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4607 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4608
4609 /* Define an extension to the ext2 library's block count information */
4610 #define BLOCK_COUNT_EXTATTR     (-5)
4611
4612 struct block_el {
4613         blk_t   block;
4614         struct block_el *next;
4615 };
4616
4617 struct inode_el {
4618         ext2_ino_t      inode;
4619         struct inode_el *next;
4620 };
4621
4622 struct dup_block {
4623         int             num_bad;
4624         struct inode_el *inode_list;
4625 };
4626
4627 /*
4628  * This structure stores information about a particular inode which
4629  * is sharing blocks with other inodes.  This information is collected
4630  * to display to the user, so that the user knows what files he or she
4631  * is dealing with, when trying to decide how to resolve the conflict
4632  * of multiply-claimed blocks.
4633  */
4634 struct dup_inode {
4635         ext2_ino_t              dir;
4636         int                     num_dupblocks;
4637         struct ext2_inode       inode;
4638         struct block_el         *block_list;
4639 };
4640
4641 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4642                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
4643                                 int ref_offset, void *priv_data);
4644 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4645                         struct dup_inode *dp, char *block_buf);
4646 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4647                       struct dup_inode *dp, char* block_buf);
4648 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4649
4650 static void pass1b(e2fsck_t ctx, char *block_buf);
4651 static void pass1c(e2fsck_t ctx, char *block_buf);
4652 static void pass1d(e2fsck_t ctx, char *block_buf);
4653
4654 static int dup_inode_count = 0;
4655
4656 static dict_t blk_dict, ino_dict;
4657
4658 static ext2fs_inode_bitmap inode_dup_map;
4659
4660 static int dict_int_cmp(const void *a, const void *b)
4661 {
4662         intptr_t        ia, ib;
4663
4664         ia = (intptr_t)a;
4665         ib = (intptr_t)b;
4666
4667         return (ia-ib);
4668 }
4669
4670 /*
4671  * Add a duplicate block record
4672  */
4673 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4674                      struct ext2_inode *inode)
4675 {
4676         dnode_t *n;
4677         struct dup_block        *db;
4678         struct dup_inode        *di;
4679         struct block_el         *blk_el;
4680         struct inode_el         *ino_el;
4681
4682         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4683         if (n)
4684                 db = (struct dup_block *) dnode_get(n);
4685         else {
4686                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4687                          sizeof(struct dup_block), "duplicate block header");
4688                 db->num_bad = 0;
4689                 db->inode_list = 0;
4690                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4691         }
4692         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4693                          sizeof(struct inode_el), "inode element");
4694         ino_el->inode = ino;
4695         ino_el->next = db->inode_list;
4696         db->inode_list = ino_el;
4697         db->num_bad++;
4698
4699         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4700         if (n)
4701                 di = (struct dup_inode *) dnode_get(n);
4702         else {
4703                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4704                          sizeof(struct dup_inode), "duplicate inode header");
4705                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
4706                 di->num_dupblocks = 0;
4707                 di->block_list = 0;
4708                 di->inode = *inode;
4709                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4710         }
4711         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4712                          sizeof(struct block_el), "block element");
4713         blk_el->block = blk;
4714         blk_el->next = di->block_list;
4715         di->block_list = blk_el;
4716         di->num_dupblocks++;
4717 }
4718
4719 /*
4720  * Free a duplicate inode record
4721  */
4722 static void inode_dnode_free(dnode_t *node)
4723 {
4724         struct dup_inode        *di;
4725         struct block_el         *p, *next;
4726
4727         di = (struct dup_inode *) dnode_get(node);
4728         for (p = di->block_list; p; p = next) {
4729                 next = p->next;
4730                 free(p);
4731         }
4732         free(node);
4733 }
4734
4735 /*
4736  * Free a duplicate block record
4737  */
4738 static void block_dnode_free(dnode_t *node)
4739 {
4740         struct dup_block        *db;
4741         struct inode_el         *p, *next;
4742
4743         db = (struct dup_block *) dnode_get(node);
4744         for (p = db->inode_list; p; p = next) {
4745                 next = p->next;
4746                 free(p);
4747         }
4748         free(node);
4749 }
4750
4751
4752 /*
4753  * Main procedure for handling duplicate blocks
4754  */
4755 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4756 {
4757         ext2_filsys             fs = ctx->fs;
4758         struct problem_context  pctx;
4759
4760         clear_problem_context(&pctx);
4761
4762         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4763                       _("multiply claimed inode map"), &inode_dup_map);
4764         if (pctx.errcode) {
4765                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4766                 ctx->flags |= E2F_FLAG_ABORT;
4767                 return;
4768         }
4769
4770         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772         dict_set_allocator(&ino_dict, inode_dnode_free);
4773         dict_set_allocator(&blk_dict, block_dnode_free);
4774
4775         pass1b(ctx, block_buf);
4776         pass1c(ctx, block_buf);
4777         pass1d(ctx, block_buf);
4778
4779         /*
4780          * Time to free all of the accumulated data structures that we
4781          * don't need anymore.
4782          */
4783         dict_free_nodes(&ino_dict);
4784         dict_free_nodes(&blk_dict);
4785 }
4786
4787 /*
4788  * Scan the inodes looking for inodes that contain duplicate blocks.
4789  */
4790 struct process_block_struct_1b {
4791         e2fsck_t        ctx;
4792         ext2_ino_t      ino;
4793         int             dup_blocks;
4794         struct ext2_inode *inode;
4795         struct problem_context *pctx;
4796 };
4797
4798 static void pass1b(e2fsck_t ctx, char *block_buf)
4799 {
4800         ext2_filsys fs = ctx->fs;
4801         ext2_ino_t ino;
4802         struct ext2_inode inode;
4803         ext2_inode_scan scan;
4804         struct process_block_struct_1b pb;
4805         struct problem_context pctx;
4806
4807         clear_problem_context(&pctx);
4808
4809         if (!(ctx->options & E2F_OPT_PREEN))
4810                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4811         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4812                                               &scan);
4813         if (pctx.errcode) {
4814                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4815                 ctx->flags |= E2F_FLAG_ABORT;
4816                 return;
4817         }
4818         ctx->stashed_inode = &inode;
4819         pb.ctx = ctx;
4820         pb.pctx = &pctx;
4821         pctx.str = "pass1b";
4822         while (1) {
4823                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4824                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4825                         continue;
4826                 if (pctx.errcode) {
4827                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4828                         ctx->flags |= E2F_FLAG_ABORT;
4829                         return;
4830                 }
4831                 if (!ino)
4832                         break;
4833                 pctx.ino = ctx->stashed_ino = ino;
4834                 if ((ino != EXT2_BAD_INO) &&
4835                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4836                         continue;
4837
4838                 pb.ino = ino;
4839                 pb.dup_blocks = 0;
4840                 pb.inode = &inode;
4841
4842                 if (ext2fs_inode_has_valid_blocks(&inode) ||
4843                     (ino == EXT2_BAD_INO))
4844                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
4845                                      0, block_buf, process_pass1b_block, &pb);
4846                 if (inode.i_file_acl)
4847                         process_pass1b_block(fs, &inode.i_file_acl,
4848                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4849                 if (pb.dup_blocks) {
4850                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
4851                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
4852                             ino == EXT2_ROOT_INO)
4853                                 dup_inode_count++;
4854                 }
4855                 if (pctx.errcode)
4856                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4857         }
4858         ext2fs_close_inode_scan(scan);
4859         e2fsck_use_inode_shortcuts(ctx, 0);
4860 }
4861
4862 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4863                                 blk_t   *block_nr,
4864                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4865                                 blk_t ref_blk FSCK_ATTR((unused)),
4866                                 int ref_offset FSCK_ATTR((unused)),
4867                                 void *priv_data)
4868 {
4869         struct process_block_struct_1b *p;
4870         e2fsck_t ctx;
4871
4872         if (HOLE_BLKADDR(*block_nr))
4873                 return 0;
4874         p = (struct process_block_struct_1b *) priv_data;
4875         ctx = p->ctx;
4876
4877         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4878                 return 0;
4879
4880         /* OK, this is a duplicate block */
4881         if (p->ino != EXT2_BAD_INO) {
4882                 p->pctx->blk = *block_nr;
4883                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4884         }
4885         p->dup_blocks++;
4886         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4887
4888         add_dupe(ctx, p->ino, *block_nr, p->inode);
4889
4890         return 0;
4891 }
4892
4893 /*
4894  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4895  * is used so that we can print pathnames when prompting the user for
4896  * what to do.
4897  */
4898 struct search_dir_struct {
4899         int             count;
4900         ext2_ino_t      first_inode;
4901         ext2_ino_t      max_inode;
4902 };
4903
4904 static int search_dirent_proc(ext2_ino_t dir, int entry,
4905                               struct ext2_dir_entry *dirent,
4906                               int offset FSCK_ATTR((unused)),
4907                               int blocksize FSCK_ATTR((unused)),
4908                               char *buf FSCK_ATTR((unused)),
4909                               void *priv_data)
4910 {
4911         struct search_dir_struct *sd;
4912         struct dup_inode        *p;
4913         dnode_t                 *n;
4914
4915         sd = (struct search_dir_struct *) priv_data;
4916
4917         if (dirent->inode > sd->max_inode)
4918                 /* Should abort this inode, but not everything */
4919                 return 0;
4920
4921         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4922             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4923                 return 0;
4924
4925         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4926         if (!n)
4927                 return 0;
4928         p = (struct dup_inode *) dnode_get(n);
4929         p->dir = dir;
4930         sd->count--;
4931
4932         return(sd->count ? 0 : DIRENT_ABORT);
4933 }
4934
4935
4936 static void pass1c(e2fsck_t ctx, char *block_buf)
4937 {
4938         ext2_filsys fs = ctx->fs;
4939         struct search_dir_struct sd;
4940         struct problem_context pctx;
4941
4942         clear_problem_context(&pctx);
4943
4944         if (!(ctx->options & E2F_OPT_PREEN))
4945                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4946
4947         /*
4948          * Search through all directories to translate inodes to names
4949          * (by searching for the containing directory for that inode.)
4950          */
4951         sd.count = dup_inode_count;
4952         sd.first_inode = EXT2_FIRST_INODE(fs->super);
4953         sd.max_inode = fs->super->s_inodes_count;
4954         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4955                                   search_dirent_proc, &sd);
4956 }
4957
4958 static void pass1d(e2fsck_t ctx, char *block_buf)
4959 {
4960         ext2_filsys fs = ctx->fs;
4961         struct dup_inode        *p, *t;
4962         struct dup_block        *q;
4963         ext2_ino_t              *shared, ino;
4964         int     shared_len;
4965         int     i;
4966         int     file_ok;
4967         int     meta_data = 0;
4968         struct problem_context pctx;
4969         dnode_t *n, *m;
4970         struct block_el *s;
4971         struct inode_el *r;
4972
4973         clear_problem_context(&pctx);
4974
4975         if (!(ctx->options & E2F_OPT_PREEN))
4976                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4977         e2fsck_read_bitmaps(ctx);
4978
4979         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4980         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4981         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4982                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4983                                 "Shared inode list");
4984         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4985                 p = (struct dup_inode *) dnode_get(n);
4986                 shared_len = 0;
4987                 file_ok = 1;
4988                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4989                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4990                         continue;
4991
4992                 /*
4993                  * Find all of the inodes which share blocks with this
4994                  * one.  First we find all of the duplicate blocks
4995                  * belonging to this inode, and then search each block
4996                  * get the list of inodes, and merge them together.
4997                  */
4998                 for (s = p->block_list; s; s = s->next) {
4999                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5000                         if (!m)
5001                                 continue; /* Should never happen... */
5002                         q = (struct dup_block *) dnode_get(m);
5003                         if (q->num_bad > 1)
5004                                 file_ok = 0;
5005                         if (check_if_fs_block(ctx, s->block)) {
5006                                 file_ok = 0;
5007                                 meta_data = 1;
5008                         }
5009
5010                         /*
5011                          * Add all inodes used by this block to the
5012                          * shared[] --- which is a unique list, so
5013                          * if an inode is already in shared[], don't
5014                          * add it again.
5015                          */
5016                         for (r = q->inode_list; r; r = r->next) {
5017                                 if (r->inode == ino)
5018                                         continue;
5019                                 for (i = 0; i < shared_len; i++)
5020                                         if (shared[i] == r->inode)
5021                                                 break;
5022                                 if (i == shared_len) {
5023                                         shared[shared_len++] = r->inode;
5024                                 }
5025                         }
5026                 }
5027
5028                 /*
5029                  * Report the inode that we are working on
5030                  */
5031                 pctx.inode = &p->inode;
5032                 pctx.ino = ino;
5033                 pctx.dir = p->dir;
5034                 pctx.blkcount = p->num_dupblocks;
5035                 pctx.num = meta_data ? shared_len+1 : shared_len;
5036                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5037                 pctx.blkcount = 0;
5038                 pctx.num = 0;
5039
5040                 if (meta_data)
5041                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5042
5043                 for (i = 0; i < shared_len; i++) {
5044                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5045                         if (!m)
5046                                 continue; /* should never happen */
5047                         t = (struct dup_inode *) dnode_get(m);
5048                         /*
5049                          * Report the inode that we are sharing with
5050                          */
5051                         pctx.inode = &t->inode;
5052                         pctx.ino = shared[i];
5053                         pctx.dir = t->dir;
5054                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5055                 }
5056                 if (file_ok) {
5057                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5058                         continue;
5059                 }
5060                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5061                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
5062                         if (pctx.errcode)
5063                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5064                         else
5065                                 continue;
5066                 }
5067                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5068                         delete_file(ctx, ino, p, block_buf);
5069                 else
5070                         ext2fs_unmark_valid(fs);
5071         }
5072         ext2fs_free_mem(&shared);
5073 }
5074
5075 /*
5076  * Drop the refcount on the dup_block structure, and clear the entry
5077  * in the block_dup_map if appropriate.
5078  */
5079 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5080 {
5081         p->num_bad--;
5082         if (p->num_bad <= 0 ||
5083             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5084                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5085 }
5086
5087 static int delete_file_block(ext2_filsys fs,
5088                              blk_t      *block_nr,
5089                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5090                              blk_t ref_block FSCK_ATTR((unused)),
5091                              int ref_offset FSCK_ATTR((unused)),
5092                              void *priv_data)
5093 {
5094         struct process_block_struct_1b *pb;
5095         struct dup_block *p;
5096         dnode_t *n;
5097         e2fsck_t ctx;
5098
5099         pb = (struct process_block_struct_1b *) priv_data;
5100         ctx = pb->ctx;
5101
5102         if (HOLE_BLKADDR(*block_nr))
5103                 return 0;
5104
5105         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5106                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5107                 if (n) {
5108                         p = (struct dup_block *) dnode_get(n);
5109                         decrement_badcount(ctx, *block_nr, p);
5110                 } else
5111                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5112                                 *block_nr);
5113         } else {
5114                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5115                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5116         }
5117
5118         return 0;
5119 }
5120
5121 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5122                         struct dup_inode *dp, char* block_buf)
5123 {
5124         ext2_filsys fs = ctx->fs;
5125         struct process_block_struct_1b pb;
5126         struct ext2_inode       inode;
5127         struct problem_context  pctx;
5128         unsigned int            count;
5129
5130         clear_problem_context(&pctx);
5131         pctx.ino = pb.ino = ino;
5132         pb.dup_blocks = dp->num_dupblocks;
5133         pb.ctx = ctx;
5134         pctx.str = "delete_file";
5135
5136         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5137         if (ext2fs_inode_has_valid_blocks(&inode))
5138                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5139                                                      delete_file_block, &pb);
5140         if (pctx.errcode)
5141                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5142         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5143         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5144         if (ctx->inode_bad_map)
5145                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5146         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5147
5148         /* Inode may have changed by block_iterate, so reread it */
5149         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5150         inode.i_links_count = 0;
5151         inode.i_dtime = time(0);
5152         if (inode.i_file_acl &&
5153             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5154                 count = 1;
5155                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5156                                                    block_buf, -1, &count);
5157                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5158                         pctx.errcode = 0;
5159                         count = 1;
5160                 }
5161                 if (pctx.errcode) {
5162                         pctx.blk = inode.i_file_acl;
5163                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5164                 }
5165                 /*
5166                  * If the count is zero, then arrange to have the
5167                  * block deleted.  If the block is in the block_dup_map,
5168                  * also call delete_file_block since it will take care
5169                  * of keeping the accounting straight.
5170                  */
5171                 if ((count == 0) ||
5172                     ext2fs_test_block_bitmap(ctx->block_dup_map,
5173                                              inode.i_file_acl))
5174                         delete_file_block(fs, &inode.i_file_acl,
5175                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5176         }
5177         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5178 }
5179
5180 struct clone_struct {
5181         errcode_t       errcode;
5182         ext2_ino_t      dir;
5183         char    *buf;
5184         e2fsck_t ctx;
5185 };
5186
5187 static int clone_file_block(ext2_filsys fs,
5188                             blk_t       *block_nr,
5189                             e2_blkcnt_t blockcnt,
5190                             blk_t ref_block FSCK_ATTR((unused)),
5191                             int ref_offset FSCK_ATTR((unused)),
5192                             void *priv_data)
5193 {
5194         struct dup_block *p;
5195         blk_t   new_block;
5196         errcode_t       retval;
5197         struct clone_struct *cs = (struct clone_struct *) priv_data;
5198         dnode_t *n;
5199         e2fsck_t ctx;
5200
5201         ctx = cs->ctx;
5202
5203         if (HOLE_BLKADDR(*block_nr))
5204                 return 0;
5205
5206         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5207                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5208                 if (n) {
5209                         p = (struct dup_block *) dnode_get(n);
5210                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5211                                                   &new_block);
5212                         if (retval) {
5213                                 cs->errcode = retval;
5214                                 return BLOCK_ABORT;
5215                         }
5216                         if (cs->dir && (blockcnt >= 0)) {
5217                                 retval = ext2fs_set_dir_block(fs->dblist,
5218                                       cs->dir, new_block, blockcnt);
5219                                 if (retval) {
5220                                         cs->errcode = retval;
5221                                         return BLOCK_ABORT;
5222                                 }
5223                         }
5224
5225                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
5226                                                      cs->buf);
5227                         if (retval) {
5228                                 cs->errcode = retval;
5229                                 return BLOCK_ABORT;
5230                         }
5231                         retval = io_channel_write_blk(fs->io, new_block, 1,
5232                                                       cs->buf);
5233                         if (retval) {
5234                                 cs->errcode = retval;
5235                                 return BLOCK_ABORT;
5236                         }
5237                         decrement_badcount(ctx, *block_nr, p);
5238                         *block_nr = new_block;
5239                         ext2fs_mark_block_bitmap(ctx->block_found_map,
5240                                                  new_block);
5241                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
5242                         return BLOCK_CHANGED;
5243                 } else
5244                         bb_error_msg(_("internal error; can't find dup_blk for %d"),
5245                                 *block_nr);
5246         }
5247         return 0;
5248 }
5249
5250 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5251                       struct dup_inode *dp, char* block_buf)
5252 {
5253         ext2_filsys fs = ctx->fs;
5254         errcode_t       retval;
5255         struct clone_struct cs;
5256         struct problem_context  pctx;
5257         blk_t           blk;
5258         dnode_t         *n;
5259         struct inode_el *ino_el;
5260         struct dup_block        *db;
5261         struct dup_inode        *di;
5262
5263         clear_problem_context(&pctx);
5264         cs.errcode = 0;
5265         cs.dir = 0;
5266         cs.ctx = ctx;
5267         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5268         if (retval)
5269                 return retval;
5270
5271         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5272                 cs.dir = ino;
5273
5274         pctx.ino = ino;
5275         pctx.str = "clone_file";
5276         if (ext2fs_inode_has_valid_blocks(&dp->inode))
5277                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5278                                                      clone_file_block, &cs);
5279         ext2fs_mark_bb_dirty(fs);
5280         if (pctx.errcode) {
5281                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5282                 retval = pctx.errcode;
5283                 goto errout;
5284         }
5285         if (cs.errcode) {
5286                 bb_error_msg(_("returned from clone_file_block"));
5287                 retval = cs.errcode;
5288                 goto errout;
5289         }
5290         /* The inode may have changed on disk, so we have to re-read it */
5291         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5292         blk = dp->inode.i_file_acl;
5293         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5294                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5295                     BLOCK_CHANGED)) {
5296                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5297                 /*
5298                  * If we cloned the EA block, find all other inodes
5299                  * which refered to that EA block, and modify
5300                  * them to point to the new EA block.
5301                  */
5302                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5303                 db = (struct dup_block *) dnode_get(n);
5304                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5305                         if (ino_el->inode == ino)
5306                                 continue;
5307                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5308                         di = (struct dup_inode *) dnode_get(n);
5309                         if (di->inode.i_file_acl == blk) {
5310                                 di->inode.i_file_acl = dp->inode.i_file_acl;
5311                                 e2fsck_write_inode(ctx, ino_el->inode,
5312                                            &di->inode, "clone file EA");
5313                                 decrement_badcount(ctx, blk, db);
5314                         }
5315                 }
5316         }
5317         retval = 0;
5318 errout:
5319         ext2fs_free_mem(&cs.buf);
5320         return retval;
5321 }
5322
5323 /*
5324  * This routine returns 1 if a block overlaps with one of the superblocks,
5325  * group descriptors, inode bitmaps, or block bitmaps.
5326  */
5327 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5328 {
5329         ext2_filsys fs = ctx->fs;
5330         blk_t   block;
5331         dgrp_t  i;
5332
5333         block = fs->super->s_first_data_block;
5334         for (i = 0; i < fs->group_desc_count; i++) {
5335
5336                 /* Check superblocks/block group descriptros */
5337                 if (ext2fs_bg_has_super(fs, i)) {
5338                         if (test_block >= block &&
5339                             (test_block <= block + fs->desc_blocks))
5340                                 return 1;
5341                 }
5342
5343                 /* Check the inode table */
5344                 if ((fs->group_desc[i].bg_inode_table) &&
5345                     (test_block >= fs->group_desc[i].bg_inode_table) &&
5346                     (test_block < (fs->group_desc[i].bg_inode_table +
5347                                    fs->inode_blocks_per_group)))
5348                         return 1;
5349
5350                 /* Check the bitmap blocks */
5351                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5352                     (test_block == fs->group_desc[i].bg_inode_bitmap))
5353                         return 1;
5354
5355                 block += fs->super->s_blocks_per_group;
5356         }
5357         return 0;
5358 }
5359 /*
5360  * pass2.c --- check directory structure
5361  *
5362  * Pass 2 of e2fsck iterates through all active directory inodes, and
5363  * applies to following tests to each directory entry in the directory
5364  * blocks in the inodes:
5365  *
5366  *      - The length of the directory entry (rec_len) should be at
5367  *              least 8 bytes, and no more than the remaining space
5368  *              left in the directory block.
5369  *      - The length of the name in the directory entry (name_len)
5370  *              should be less than (rec_len - 8).
5371  *      - The inode number in the directory entry should be within
5372  *              legal bounds.
5373  *      - The inode number should refer to a in-use inode.
5374  *      - The first entry should be '.', and its inode should be
5375  *              the inode of the directory.
5376  *      - The second entry should be '..'.
5377  *
5378  * To minimize disk seek time, the directory blocks are processed in
5379  * sorted order of block numbers.
5380  *
5381  * Pass 2 also collects the following information:
5382  *      - The inode numbers of the subdirectories for each directory.
5383  *
5384  * Pass 2 relies on the following information from previous passes:
5385  *      - The directory information collected in pass 1.
5386  *      - The inode_used_map bitmap
5387  *      - The inode_bad_map bitmap
5388  *      - The inode_dir_map bitmap
5389  *
5390  * Pass 2 frees the following data structures
5391  *      - The inode_bad_map bitmap
5392  *      - The inode_reg_map bitmap
5393  */
5394
5395 /*
5396  * Keeps track of how many times an inode is referenced.
5397  */
5398 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5399 static int check_dir_block(ext2_filsys fs,
5400                            struct ext2_db_entry *dir_blocks_info,
5401                            void *priv_data);
5402 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5403                               struct problem_context *pctx);
5404 static int update_dir_block(ext2_filsys fs,
5405                             blk_t       *block_nr,
5406                             e2_blkcnt_t blockcnt,
5407                             blk_t       ref_block,
5408                             int         ref_offset,
5409                             void        *priv_data);
5410 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5411 static int htree_depth(struct dx_dir_info *dx_dir,
5412                        struct dx_dirblock_info *dx_db);
5413 static int special_dir_block_cmp(const void *a, const void *b);
5414
5415 struct check_dir_struct {
5416         char *buf;
5417         struct problem_context  pctx;
5418         int     count, max;
5419         e2fsck_t ctx;
5420 };
5421
5422 static void e2fsck_pass2(e2fsck_t ctx)
5423 {
5424         struct ext2_super_block *sb = ctx->fs->super;
5425         struct problem_context  pctx;
5426         ext2_filsys             fs = ctx->fs;
5427         char                    *buf;
5428         struct dir_info         *dir;
5429         struct check_dir_struct cd;
5430         struct dx_dir_info      *dx_dir;
5431         struct dx_dirblock_info *dx_db, *dx_parent;
5432         int                     b;
5433         int                     i, depth;
5434         problem_t               code;
5435         int                     bad_dir;
5436
5437         clear_problem_context(&cd.pctx);
5438
5439         /* Pass 2 */
5440
5441         if (!(ctx->options & E2F_OPT_PREEN))
5442                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5443
5444         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5445                                                 0, ctx->inode_link_info,
5446                                                 &ctx->inode_count);
5447         if (cd.pctx.errcode) {
5448                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5449                 ctx->flags |= E2F_FLAG_ABORT;
5450                 return;
5451         }
5452         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5453                                               "directory scan buffer");
5454
5455         /*
5456          * Set up the parent pointer for the root directory, if
5457          * present.  (If the root directory is not present, we will
5458          * create it in pass 3.)
5459          */
5460         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5461         if (dir)
5462                 dir->parent = EXT2_ROOT_INO;
5463
5464         cd.buf = buf;
5465         cd.ctx = ctx;
5466         cd.count = 1;
5467         cd.max = ext2fs_dblist_count(fs->dblist);
5468
5469         if (ctx->progress)
5470                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5471
5472         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5473                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5474
5475         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5476                                                 &cd);
5477         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478                 return;
5479         if (cd.pctx.errcode) {
5480                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5481                 ctx->flags |= E2F_FLAG_ABORT;
5482                 return;
5483         }
5484
5485 #ifdef ENABLE_HTREE
5486         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5487                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5488                         return;
5489                 if (dx_dir->numblocks == 0)
5490                         continue;
5491                 clear_problem_context(&pctx);
5492                 bad_dir = 0;
5493                 pctx.dir = dx_dir->ino;
5494                 dx_db = dx_dir->dx_block;
5495                 if (dx_db->flags & DX_FLAG_REFERENCED)
5496                         dx_db->flags |= DX_FLAG_DUP_REF;
5497                 else
5498                         dx_db->flags |= DX_FLAG_REFERENCED;
5499                 /*
5500                  * Find all of the first and last leaf blocks, and
5501                  * update their parent's min and max hash values
5502                  */
5503                 for (b=0, dx_db = dx_dir->dx_block;
5504                      b < dx_dir->numblocks;
5505                      b++, dx_db++) {
5506                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5507                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5508                                 continue;
5509                         dx_parent = &dx_dir->dx_block[dx_db->parent];
5510                         /*
5511                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5512                          */
5513                         if (dx_db->flags & DX_FLAG_FIRST)
5514                                 dx_parent->min_hash = dx_db->min_hash;
5515                         /*
5516                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5517                          */
5518                         if (dx_db->flags & DX_FLAG_LAST)
5519                                 dx_parent->max_hash = dx_db->max_hash;
5520                 }
5521
5522                 for (b=0, dx_db = dx_dir->dx_block;
5523                      b < dx_dir->numblocks;
5524                      b++, dx_db++) {
5525                         pctx.blkcount = b;
5526                         pctx.group = dx_db->parent;
5527                         code = 0;
5528                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
5529                             (dx_db->min_hash < dx_db->node_min_hash)) {
5530                                 pctx.blk = dx_db->min_hash;
5531                                 pctx.blk2 = dx_db->node_min_hash;
5532                                 code = PR_2_HTREE_MIN_HASH;
5533                                 fix_problem(ctx, code, &pctx);
5534                                 bad_dir++;
5535                         }
5536                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
5537                                 depth = htree_depth(dx_dir, dx_db);
5538                                 if (depth != dx_dir->depth) {
5539                                         code = PR_2_HTREE_BAD_DEPTH;
5540                                         fix_problem(ctx, code, &pctx);
5541                                         bad_dir++;
5542                                 }
5543                         }
5544                         /*
5545                          * This test doesn't apply for the root block
5546                          * at block #0
5547                          */
5548                         if (b &&
5549                             (dx_db->max_hash > dx_db->node_max_hash)) {
5550                                 pctx.blk = dx_db->max_hash;
5551                                 pctx.blk2 = dx_db->node_max_hash;
5552                                 code = PR_2_HTREE_MAX_HASH;
5553                                 fix_problem(ctx, code, &pctx);
5554                                 bad_dir++;
5555                         }
5556                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5557                                 code = PR_2_HTREE_NOTREF;
5558                                 fix_problem(ctx, code, &pctx);
5559                                 bad_dir++;
5560                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5561                                 code = PR_2_HTREE_DUPREF;
5562                                 fix_problem(ctx, code, &pctx);
5563                                 bad_dir++;
5564                         }
5565                         if (code == 0)
5566                                 continue;
5567                 }
5568                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5569                         clear_htree(ctx, dx_dir->ino);
5570                         dx_dir->numblocks = 0;
5571                 }
5572         }
5573 #endif
5574         ext2fs_free_mem(&buf);
5575         ext2fs_free_dblist(fs->dblist);
5576
5577         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5578         ctx->inode_bad_map = 0;
5579         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5580         ctx->inode_reg_map = 0;
5581
5582         clear_problem_context(&pctx);
5583         if (ctx->large_files) {
5584                 if (!(sb->s_feature_ro_compat &
5585                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5586                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5587                         sb->s_feature_ro_compat |=
5588                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5589                         ext2fs_mark_super_dirty(fs);
5590                 }
5591                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5592                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5593                         ext2fs_update_dynamic_rev(fs);
5594                         ext2fs_mark_super_dirty(fs);
5595                 }
5596         } else if (!ctx->large_files &&
5597             (sb->s_feature_ro_compat &
5598               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5599                 if (fs->flags & EXT2_FLAG_RW) {
5600                         sb->s_feature_ro_compat &=
5601                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5602                         ext2fs_mark_super_dirty(fs);
5603                 }
5604         }
5605
5606 }
5607
5608 #define MAX_DEPTH 32000
5609 static int htree_depth(struct dx_dir_info *dx_dir,
5610                        struct dx_dirblock_info *dx_db)
5611 {
5612         int     depth = 0;
5613
5614         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5615                 dx_db = &dx_dir->dx_block[dx_db->parent];
5616                 depth++;
5617         }
5618         return depth;
5619 }
5620
5621 static int dict_de_cmp(const void *a, const void *b)
5622 {
5623         const struct ext2_dir_entry *de_a, *de_b;
5624         int     a_len, b_len;
5625
5626         de_a = (const struct ext2_dir_entry *) a;
5627         a_len = de_a->name_len & 0xFF;
5628         de_b = (const struct ext2_dir_entry *) b;
5629         b_len = de_b->name_len & 0xFF;
5630
5631         if (a_len != b_len)
5632                 return (a_len - b_len);
5633
5634         return strncmp(de_a->name, de_b->name, a_len);
5635 }
5636
5637 /*
5638  * This is special sort function that makes sure that directory blocks
5639  * with a dirblock of zero are sorted to the beginning of the list.
5640  * This guarantees that the root node of the htree directories are
5641  * processed first, so we know what hash version to use.
5642  */
5643 static int special_dir_block_cmp(const void *a, const void *b)
5644 {
5645         const struct ext2_db_entry *db_a =
5646                 (const struct ext2_db_entry *) a;
5647         const struct ext2_db_entry *db_b =
5648                 (const struct ext2_db_entry *) b;
5649
5650         if (db_a->blockcnt && !db_b->blockcnt)
5651                 return 1;
5652
5653         if (!db_a->blockcnt && db_b->blockcnt)
5654                 return -1;
5655
5656         if (db_a->blk != db_b->blk)
5657                 return (int) (db_a->blk - db_b->blk);
5658
5659         if (db_a->ino != db_b->ino)
5660                 return (int) (db_a->ino - db_b->ino);
5661
5662         return (int) (db_a->blockcnt - db_b->blockcnt);
5663 }
5664
5665
5666 /*
5667  * Make sure the first entry in the directory is '.', and that the
5668  * directory entry is sane.
5669  */
5670 static int check_dot(e2fsck_t ctx,
5671                      struct ext2_dir_entry *dirent,
5672                      ext2_ino_t ino, struct problem_context *pctx)
5673 {
5674         struct ext2_dir_entry *nextdir;
5675         int     status = 0;
5676         int     created = 0;
5677         int     new_len;
5678         int     problem = 0;
5679
5680         if (!dirent->inode)
5681                 problem = PR_2_MISSING_DOT;
5682         else if (((dirent->name_len & 0xFF) != 1) ||
5683                  (dirent->name[0] != '.'))
5684                 problem = PR_2_1ST_NOT_DOT;
5685         else if (dirent->name[1] != '\0')
5686                 problem = PR_2_DOT_NULL_TERM;
5687
5688         if (problem) {
5689                 if (fix_problem(ctx, problem, pctx)) {
5690                         if (dirent->rec_len < 12)
5691                                 dirent->rec_len = 12;
5692                         dirent->inode = ino;
5693                         dirent->name_len = 1;
5694                         dirent->name[0] = '.';
5695                         dirent->name[1] = '\0';
5696                         status = 1;
5697                         created = 1;
5698                 }
5699         }
5700         if (dirent->inode != ino) {
5701                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5702                         dirent->inode = ino;
5703                         status = 1;
5704                 }
5705         }
5706         if (dirent->rec_len > 12) {
5707                 new_len = dirent->rec_len - 12;
5708                 if (new_len > 12) {
5709                         if (created ||
5710                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5711                                 nextdir = (struct ext2_dir_entry *)
5712                                         ((char *) dirent + 12);
5713                                 dirent->rec_len = 12;
5714                                 nextdir->rec_len = new_len;
5715                                 nextdir->inode = 0;
5716                                 nextdir->name_len = 0;
5717                                 status = 1;
5718                         }
5719                 }
5720         }
5721         return status;
5722 }
5723
5724 /*
5725  * Make sure the second entry in the directory is '..', and that the
5726  * directory entry is sane.  We do not check the inode number of '..'
5727  * here; this gets done in pass 3.
5728  */
5729 static int check_dotdot(e2fsck_t ctx,
5730                         struct ext2_dir_entry *dirent,
5731                         struct dir_info *dir, struct problem_context *pctx)
5732 {
5733         int             problem = 0;
5734
5735         if (!dirent->inode)
5736                 problem = PR_2_MISSING_DOT_DOT;
5737         else if (((dirent->name_len & 0xFF) != 2) ||
5738                  (dirent->name[0] != '.') ||
5739                  (dirent->name[1] != '.'))
5740                 problem = PR_2_2ND_NOT_DOT_DOT;
5741         else if (dirent->name[2] != '\0')
5742                 problem = PR_2_DOT_DOT_NULL_TERM;
5743
5744         if (problem) {
5745                 if (fix_problem(ctx, problem, pctx)) {
5746                         if (dirent->rec_len < 12)
5747                                 dirent->rec_len = 12;
5748                         /*
5749                          * Note: we don't have the parent inode just
5750                          * yet, so we will fill it in with the root
5751                          * inode.  This will get fixed in pass 3.
5752                          */
5753                         dirent->inode = EXT2_ROOT_INO;
5754                         dirent->name_len = 2;
5755                         dirent->name[0] = '.';
5756                         dirent->name[1] = '.';
5757                         dirent->name[2] = '\0';
5758                         return 1;
5759                 }
5760                 return 0;
5761         }
5762         dir->dotdot = dirent->inode;
5763         return 0;
5764 }
5765
5766 /*
5767  * Check to make sure a directory entry doesn't contain any illegal
5768  * characters.
5769  */
5770 static int check_name(e2fsck_t ctx,
5771                       struct ext2_dir_entry *dirent,
5772                       struct problem_context *pctx)
5773 {
5774         int     i;
5775         int     fixup = -1;
5776         int     ret = 0;
5777
5778         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5779                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5780                         if (fixup < 0) {
5781                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5782                         }
5783                         if (fixup) {
5784                                 dirent->name[i] = '.';
5785                                 ret = 1;
5786                         }
5787                 }
5788         }
5789         return ret;
5790 }
5791
5792 /*
5793  * Check the directory filetype (if present)
5794  */
5795
5796 /*
5797  * Given a mode, return the ext2 file type
5798  */
5799 static int ext2_file_type(unsigned int mode)
5800 {
5801         if (LINUX_S_ISREG(mode))
5802                 return EXT2_FT_REG_FILE;
5803
5804         if (LINUX_S_ISDIR(mode))
5805                 return EXT2_FT_DIR;
5806
5807         if (LINUX_S_ISCHR(mode))
5808                 return EXT2_FT_CHRDEV;
5809
5810         if (LINUX_S_ISBLK(mode))
5811                 return EXT2_FT_BLKDEV;
5812
5813         if (LINUX_S_ISLNK(mode))
5814                 return EXT2_FT_SYMLINK;
5815
5816         if (LINUX_S_ISFIFO(mode))
5817                 return EXT2_FT_FIFO;
5818
5819         if (LINUX_S_ISSOCK(mode))
5820                 return EXT2_FT_SOCK;
5821
5822         return 0;
5823 }
5824
5825 static int check_filetype(e2fsck_t ctx,
5826                                    struct ext2_dir_entry *dirent,
5827                                    struct problem_context *pctx)
5828 {
5829         int     filetype = dirent->name_len >> 8;
5830         int     should_be = EXT2_FT_UNKNOWN;
5831         struct ext2_inode       inode;
5832
5833         if (!(ctx->fs->super->s_feature_incompat &
5834               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5835                 if (filetype == 0 ||
5836                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5837                         return 0;
5838                 dirent->name_len = dirent->name_len & 0xFF;
5839                 return 1;
5840         }
5841
5842         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5843                 should_be = EXT2_FT_DIR;
5844         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5845                                             dirent->inode)) {
5846                 should_be = EXT2_FT_REG_FILE;
5847         } else if (ctx->inode_bad_map &&
5848                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5849                                             dirent->inode))
5850                 should_be = 0;
5851         else {
5852                 e2fsck_read_inode(ctx, dirent->inode, &inode,
5853                                   "check_filetype");
5854                 should_be = ext2_file_type(inode.i_mode);
5855         }
5856         if (filetype == should_be)
5857                 return 0;
5858         pctx->num = should_be;
5859
5860         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5861                         pctx) == 0)
5862                 return 0;
5863
5864         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5865         return 1;
5866 }
5867
5868 #ifdef ENABLE_HTREE
5869 static void parse_int_node(ext2_filsys fs,
5870                            struct ext2_db_entry *db,
5871                            struct check_dir_struct *cd,
5872                            struct dx_dir_info   *dx_dir,
5873                            char *block_buf)
5874 {
5875         struct          ext2_dx_root_info  *root;
5876         struct          ext2_dx_entry *ent;
5877         struct          ext2_dx_countlimit *limit;
5878         struct dx_dirblock_info *dx_db;
5879         int             i, expect_limit, count;
5880         blk_t           blk;
5881         ext2_dirhash_t  min_hash = 0xffffffff;
5882         ext2_dirhash_t  max_hash = 0;
5883         ext2_dirhash_t  hash = 0, prev_hash;
5884
5885         if (db->blockcnt == 0) {
5886                 root = (struct ext2_dx_root_info *) (block_buf + 24);
5887                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5888         } else {
5889                 ent = (struct ext2_dx_entry *) (block_buf+8);
5890         }
5891         limit = (struct ext2_dx_countlimit *) ent;
5892
5893         count = ext2fs_le16_to_cpu(limit->count);
5894         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5895                 sizeof(struct ext2_dx_entry);
5896         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5897                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5898                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5899                         goto clear_and_exit;
5900         }
5901         if (count > expect_limit) {
5902                 cd->pctx.num = count;
5903                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5904                         goto clear_and_exit;
5905                 count = expect_limit;
5906         }
5907
5908         for (i=0; i < count; i++) {
5909                 prev_hash = hash;
5910                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5911                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5912                 /* Check to make sure the block is valid */
5913                 if (blk > (blk_t) dx_dir->numblocks) {
5914                         cd->pctx.blk = blk;
5915                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5916                                         &cd->pctx))
5917                                 goto clear_and_exit;
5918                 }
5919                 if (hash < prev_hash &&
5920                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5921                         goto clear_and_exit;
5922                 dx_db = &dx_dir->dx_block[blk];
5923                 if (dx_db->flags & DX_FLAG_REFERENCED) {
5924                         dx_db->flags |= DX_FLAG_DUP_REF;
5925                 } else {
5926                         dx_db->flags |= DX_FLAG_REFERENCED;
5927                         dx_db->parent = db->blockcnt;
5928                 }
5929                 if (hash < min_hash)
5930                         min_hash = hash;
5931                 if (hash > max_hash)
5932                         max_hash = hash;
5933                 dx_db->node_min_hash = hash;
5934                 if ((i+1) < count)
5935                         dx_db->node_max_hash =
5936                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5937                 else {
5938                         dx_db->node_max_hash = 0xfffffffe;
5939                         dx_db->flags |= DX_FLAG_LAST;
5940                 }
5941                 if (i == 0)
5942                         dx_db->flags |= DX_FLAG_FIRST;
5943         }
5944         dx_db = &dx_dir->dx_block[db->blockcnt];
5945         dx_db->min_hash = min_hash;
5946         dx_db->max_hash = max_hash;
5947         return;
5948
5949 clear_and_exit:
5950         clear_htree(cd->ctx, cd->pctx.ino);
5951         dx_dir->numblocks = 0;
5952 }
5953 #endif /* ENABLE_HTREE */
5954
5955 /*
5956  * Given a busted directory, try to salvage it somehow.
5957  *
5958  */
5959 static void salvage_directory(ext2_filsys fs,
5960                               struct ext2_dir_entry *dirent,
5961                               struct ext2_dir_entry *prev,
5962                               unsigned int *offset)
5963 {
5964         char    *cp = (char *) dirent;
5965         int left = fs->blocksize - *offset - dirent->rec_len;
5966         int name_len = dirent->name_len & 0xFF;
5967
5968         /*
5969          * Special case of directory entry of size 8: copy what's left
5970          * of the directory block up to cover up the invalid hole.
5971          */
5972         if ((left >= 12) && (dirent->rec_len == 8)) {
5973                 memmove(cp, cp+8, left);
5974                 memset(cp + left, 0, 8);
5975                 return;
5976         }
5977         /*
5978          * If the directory entry overruns the end of the directory
5979          * block, and the name is small enough to fit, then adjust the
5980          * record length.
5981          */
5982         if ((left < 0) &&
5983             (name_len + 8 <= dirent->rec_len + left) &&
5984             dirent->inode <= fs->super->s_inodes_count &&
5985             strnlen(dirent->name, name_len) == name_len) {
5986                 dirent->rec_len += left;
5987                 return;
5988         }
5989         /*
5990          * If the directory entry is a multiple of four, so it is
5991          * valid, let the previous directory entry absorb the invalid
5992          * one.
5993          */
5994         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5995                 prev->rec_len += dirent->rec_len;
5996                 *offset += dirent->rec_len;
5997                 return;
5998         }
5999         /*
6000          * Default salvage method --- kill all of the directory
6001          * entries for the rest of the block.  We will either try to
6002          * absorb it into the previous directory entry, or create a
6003          * new empty directory entry the rest of the directory block.
6004          */
6005         if (prev) {
6006                 prev->rec_len += fs->blocksize - *offset;
6007                 *offset = fs->blocksize;
6008         } else {
6009                 dirent->rec_len = fs->blocksize - *offset;
6010                 dirent->name_len = 0;
6011                 dirent->inode = 0;
6012         }
6013 }
6014
6015 static int check_dir_block(ext2_filsys fs,
6016                            struct ext2_db_entry *db,
6017                            void *priv_data)
6018 {
6019         struct dir_info         *subdir, *dir;
6020         struct dx_dir_info      *dx_dir;
6021 #ifdef ENABLE_HTREE
6022         struct dx_dirblock_info *dx_db = 0;
6023 #endif /* ENABLE_HTREE */
6024         struct ext2_dir_entry   *dirent, *prev;
6025         ext2_dirhash_t          hash;
6026         unsigned int            offset = 0;
6027         int                     dir_modified = 0;
6028         int                     dot_state;
6029         blk_t                   block_nr = db->blk;
6030         ext2_ino_t              ino = db->ino;
6031         __u16                   links;
6032         struct check_dir_struct *cd;
6033         char                    *buf;
6034         e2fsck_t                ctx;
6035         int                     problem;
6036         struct ext2_dx_root_info *root;
6037         struct ext2_dx_countlimit *limit;
6038         static dict_t de_dict;
6039         struct problem_context  pctx;
6040         int     dups_found = 0;
6041
6042         cd = (struct check_dir_struct *) priv_data;
6043         buf = cd->buf;
6044         ctx = cd->ctx;
6045
6046         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6047                 return DIRENT_ABORT;
6048
6049         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6050                 return DIRENT_ABORT;
6051
6052         /*
6053          * Make sure the inode is still in use (could have been
6054          * deleted in the duplicate/bad blocks pass.
6055          */
6056         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6057                 return 0;
6058
6059         cd->pctx.ino = ino;
6060         cd->pctx.blk = block_nr;
6061         cd->pctx.blkcount = db->blockcnt;
6062         cd->pctx.ino2 = 0;
6063         cd->pctx.dirent = 0;
6064         cd->pctx.num = 0;
6065
6066         if (db->blk == 0) {
6067                 if (allocate_dir_block(ctx, db, &cd->pctx))
6068                         return 0;
6069                 block_nr = db->blk;
6070         }
6071
6072         if (db->blockcnt)
6073                 dot_state = 2;
6074         else
6075                 dot_state = 0;
6076
6077         if (ctx->dirs_to_hash &&
6078             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6079                 dups_found++;
6080
6081         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6082         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6083                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6084         if (cd->pctx.errcode) {
6085                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6086                         ctx->flags |= E2F_FLAG_ABORT;
6087                         return DIRENT_ABORT;
6088                 }
6089                 memset(buf, 0, fs->blocksize);
6090         }
6091 #ifdef ENABLE_HTREE
6092         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6093         if (dx_dir && dx_dir->numblocks) {
6094                 if (db->blockcnt >= dx_dir->numblocks) {
6095                         printf("XXX should never happen!!!\n");
6096                         abort();
6097                 }
6098                 dx_db = &dx_dir->dx_block[db->blockcnt];
6099                 dx_db->type = DX_DIRBLOCK_LEAF;
6100                 dx_db->phys = block_nr;
6101                 dx_db->min_hash = ~0;
6102                 dx_db->max_hash = 0;
6103
6104                 dirent = (struct ext2_dir_entry *) buf;
6105                 limit = (struct ext2_dx_countlimit *) (buf+8);
6106                 if (db->blockcnt == 0) {
6107                         root = (struct ext2_dx_root_info *) (buf + 24);
6108                         dx_db->type = DX_DIRBLOCK_ROOT;
6109                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6110                         if ((root->reserved_zero ||
6111                              root->info_length < 8 ||
6112                              root->indirect_levels > 1) &&
6113                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6114                                 clear_htree(ctx, ino);
6115                                 dx_dir->numblocks = 0;
6116                                 dx_db = 0;
6117                         }
6118                         dx_dir->hashversion = root->hash_version;
6119                         dx_dir->depth = root->indirect_levels + 1;
6120                 } else if ((dirent->inode == 0) &&
6121                            (dirent->rec_len == fs->blocksize) &&
6122                            (dirent->name_len == 0) &&
6123                            (ext2fs_le16_to_cpu(limit->limit) ==
6124                             ((fs->blocksize-8) /
6125                              sizeof(struct ext2_dx_entry))))
6126                         dx_db->type = DX_DIRBLOCK_NODE;
6127         }
6128 #endif /* ENABLE_HTREE */
6129
6130         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6131         prev = 0;
6132         do {
6133                 problem = 0;
6134                 dirent = (struct ext2_dir_entry *) (buf + offset);
6135                 cd->pctx.dirent = dirent;
6136                 cd->pctx.num = offset;
6137                 if (((offset + dirent->rec_len) > fs->blocksize) ||
6138                     (dirent->rec_len < 12) ||
6139                     ((dirent->rec_len % 4) != 0) ||
6140                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6141                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6142                                 salvage_directory(fs, dirent, prev, &offset);
6143                                 dir_modified++;
6144                                 continue;
6145                         } else
6146                                 goto abort_free_dict;
6147                 }
6148                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6149                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6150                                 dirent->name_len = EXT2_NAME_LEN;
6151                                 dir_modified++;
6152                         }
6153                 }
6154
6155                 if (dot_state == 0) {
6156                         if (check_dot(ctx, dirent, ino, &cd->pctx))
6157                                 dir_modified++;
6158                 } else if (dot_state == 1) {
6159                         dir = e2fsck_get_dir_info(ctx, ino);
6160                         if (!dir) {
6161                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6162                                 goto abort_free_dict;
6163                         }
6164                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6165                                 dir_modified++;
6166                 } else if (dirent->inode == ino) {
6167                         problem = PR_2_LINK_DOT;
6168                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6169                                 dirent->inode = 0;
6170                                 dir_modified++;
6171                                 goto next;
6172                         }
6173                 }
6174                 if (!dirent->inode)
6175                         goto next;
6176
6177                 /*
6178                  * Make sure the inode listed is a legal one.
6179                  */
6180                 if (((dirent->inode != EXT2_ROOT_INO) &&
6181                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6182                     (dirent->inode > fs->super->s_inodes_count)) {
6183                         problem = PR_2_BAD_INO;
6184                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6185                                                dirent->inode))) {
6186                         /*
6187                          * If the inode is unused, offer to clear it.
6188                          */
6189                         problem = PR_2_UNUSED_INODE;
6190                 } else if ((dot_state > 1) &&
6191                            ((dirent->name_len & 0xFF) == 1) &&
6192                            (dirent->name[0] == '.')) {
6193                         /*
6194                          * If there's a '.' entry in anything other
6195                          * than the first directory entry, it's a
6196                          * duplicate entry that should be removed.
6197                          */
6198                         problem = PR_2_DUP_DOT;
6199                 } else if ((dot_state > 1) &&
6200                            ((dirent->name_len & 0xFF) == 2) &&
6201                            (dirent->name[0] == '.') &&
6202                            (dirent->name[1] == '.')) {
6203                         /*
6204                          * If there's a '..' entry in anything other
6205                          * than the second directory entry, it's a
6206                          * duplicate entry that should be removed.
6207                          */
6208                         problem = PR_2_DUP_DOT_DOT;
6209                 } else if ((dot_state > 1) &&
6210                            (dirent->inode == EXT2_ROOT_INO)) {
6211                         /*
6212                          * Don't allow links to the root directory.
6213                          * We check this specially to make sure we
6214                          * catch this error case even if the root
6215                          * directory hasn't been created yet.
6216                          */
6217                         problem = PR_2_LINK_ROOT;
6218                 } else if ((dot_state > 1) &&
6219                            (dirent->name_len & 0xFF) == 0) {
6220                         /*
6221                          * Don't allow zero-length directory names.
6222                          */
6223                         problem = PR_2_NULL_NAME;
6224                 }
6225
6226                 if (problem) {
6227                         if (fix_problem(ctx, problem, &cd->pctx)) {
6228                                 dirent->inode = 0;
6229                                 dir_modified++;
6230                                 goto next;
6231                         } else {
6232                                 ext2fs_unmark_valid(fs);
6233                                 if (problem == PR_2_BAD_INO)
6234                                         goto next;
6235                         }
6236                 }
6237
6238                 /*
6239                  * If the inode was marked as having bad fields in
6240                  * pass1, process it and offer to fix/clear it.
6241                  * (We wait until now so that we can display the
6242                  * pathname to the user.)
6243                  */
6244                 if (ctx->inode_bad_map &&
6245                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6246                                              dirent->inode)) {
6247                         if (e2fsck_process_bad_inode(ctx, ino,
6248                                                      dirent->inode,
6249                                                      buf + fs->blocksize)) {
6250                                 dirent->inode = 0;
6251                                 dir_modified++;
6252                                 goto next;
6253                         }
6254                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6255                                 return DIRENT_ABORT;
6256                 }
6257
6258                 if (check_name(ctx, dirent, &cd->pctx))
6259                         dir_modified++;
6260
6261                 if (check_filetype(ctx, dirent, &cd->pctx))
6262                         dir_modified++;
6263
6264 #ifdef ENABLE_HTREE
6265                 if (dx_db) {
6266                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6267                                        (dirent->name_len & 0xFF),
6268                                        fs->super->s_hash_seed, &hash, 0);
6269                         if (hash < dx_db->min_hash)
6270                                 dx_db->min_hash = hash;
6271                         if (hash > dx_db->max_hash)
6272                                 dx_db->max_hash = hash;
6273                 }
6274 #endif
6275
6276                 /*
6277                  * If this is a directory, then mark its parent in its
6278                  * dir_info structure.  If the parent field is already
6279                  * filled in, then this directory has more than one
6280                  * hard link.  We assume the first link is correct,
6281                  * and ask the user if he/she wants to clear this one.
6282                  */
6283                 if ((dot_state > 1) &&
6284                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6285                                               dirent->inode))) {
6286                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6287                         if (!subdir) {
6288                                 cd->pctx.ino = dirent->inode;
6289                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6290                                 goto abort_free_dict;
6291                         }
6292                         if (subdir->parent) {
6293                                 cd->pctx.ino2 = subdir->parent;
6294                                 if (fix_problem(ctx, PR_2_LINK_DIR,
6295                                                 &cd->pctx)) {
6296                                         dirent->inode = 0;
6297                                         dir_modified++;
6298                                         goto next;
6299                                 }
6300                                 cd->pctx.ino2 = 0;
6301                         } else
6302                                 subdir->parent = ino;
6303                 }
6304
6305                 if (dups_found) {
6306                         ;
6307                 } else if (dict_lookup(&de_dict, dirent)) {
6308                         clear_problem_context(&pctx);
6309                         pctx.ino = ino;
6310                         pctx.dirent = dirent;
6311                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6312                         if (!ctx->dirs_to_hash)
6313                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6314                         if (ctx->dirs_to_hash)
6315                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6316                         dups_found++;
6317                 } else
6318                         dict_alloc_insert(&de_dict, dirent, dirent);
6319
6320                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6321                                         &links);
6322                 if (links > 1)
6323                         ctx->fs_links_count++;
6324                 ctx->fs_total_count++;
6325         next:
6326                 prev = dirent;
6327                 offset += dirent->rec_len;
6328                 dot_state++;
6329         } while (offset < fs->blocksize);
6330 #ifdef ENABLE_HTREE
6331         if (dx_db) {
6332                 cd->pctx.dir = cd->pctx.ino;
6333                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6334                     (dx_db->type == DX_DIRBLOCK_NODE))
6335                         parse_int_node(fs, db, cd, dx_dir, buf);
6336         }
6337 #endif /* ENABLE_HTREE */
6338         if (offset != fs->blocksize) {
6339                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6340                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6341                         dirent->rec_len = cd->pctx.num;
6342                         dir_modified++;
6343                 }
6344         }
6345         if (dir_modified) {
6346                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6347                 if (cd->pctx.errcode) {
6348                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6349                                          &cd->pctx))
6350                                 goto abort_free_dict;
6351                 }
6352                 ext2fs_mark_changed(fs);
6353         }
6354         dict_free_nodes(&de_dict);
6355         return 0;
6356 abort_free_dict:
6357         dict_free_nodes(&de_dict);
6358         ctx->flags |= E2F_FLAG_ABORT;
6359         return DIRENT_ABORT;
6360 }
6361
6362 /*
6363  * This function is called to deallocate a block, and is an interator
6364  * functioned called by deallocate inode via ext2fs_iterate_block().
6365  */
6366 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6367                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6368                                   blk_t ref_block FSCK_ATTR((unused)),
6369                                   int ref_offset FSCK_ATTR((unused)),
6370                                   void *priv_data)
6371 {
6372         e2fsck_t        ctx = (e2fsck_t) priv_data;
6373
6374         if (HOLE_BLKADDR(*block_nr))
6375                 return 0;
6376         if ((*block_nr < fs->super->s_first_data_block) ||
6377             (*block_nr >= fs->super->s_blocks_count))
6378                 return 0;
6379         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6380         ext2fs_block_alloc_stats(fs, *block_nr, -1);
6381         return 0;
6382 }
6383
6384 /*
6385  * This fuction deallocates an inode
6386  */
6387 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6388 {
6389         ext2_filsys fs = ctx->fs;
6390         struct ext2_inode       inode;
6391         struct problem_context  pctx;
6392         __u32                   count;
6393
6394         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6395         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6396         inode.i_links_count = 0;
6397         inode.i_dtime = time(0);
6398         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6399         clear_problem_context(&pctx);
6400         pctx.ino = ino;
6401
6402         /*
6403          * Fix up the bitmaps...
6404          */
6405         e2fsck_read_bitmaps(ctx);
6406         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6407         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6408         if (ctx->inode_bad_map)
6409                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6410         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6411
6412         if (inode.i_file_acl &&
6413             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6414                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6415                                                    block_buf, -1, &count);
6416                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6417                         pctx.errcode = 0;
6418                         count = 1;
6419                 }
6420                 if (pctx.errcode) {
6421                         pctx.blk = inode.i_file_acl;
6422                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6423                         ctx->flags |= E2F_FLAG_ABORT;
6424                         return;
6425                 }
6426                 if (count == 0) {
6427                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
6428                                                    inode.i_file_acl);
6429                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6430                 }
6431                 inode.i_file_acl = 0;
6432         }
6433
6434         if (!ext2fs_inode_has_valid_blocks(&inode))
6435                 return;
6436
6437         if (LINUX_S_ISREG(inode.i_mode) &&
6438             (inode.i_size_high || inode.i_size & 0x80000000UL))
6439                 ctx->large_files--;
6440
6441         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6442                                             deallocate_inode_block, ctx);
6443         if (pctx.errcode) {
6444                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6445                 ctx->flags |= E2F_FLAG_ABORT;
6446                 return;
6447         }
6448 }
6449
6450 /*
6451  * This fuction clears the htree flag on an inode
6452  */
6453 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6454 {
6455         struct ext2_inode       inode;
6456
6457         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6458         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6459         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6460         if (ctx->dirs_to_hash)
6461                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6462 }
6463
6464
6465 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6466                                     ext2_ino_t ino, char *buf)
6467 {
6468         ext2_filsys fs = ctx->fs;
6469         struct ext2_inode       inode;
6470         int                     inode_modified = 0;
6471         int                     not_fixed = 0;
6472         unsigned char           *frag, *fsize;
6473         struct problem_context  pctx;
6474         int     problem = 0;
6475
6476         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6477
6478         clear_problem_context(&pctx);
6479         pctx.ino = ino;
6480         pctx.dir = dir;
6481         pctx.inode = &inode;
6482
6483         if (inode.i_file_acl &&
6484             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6485             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6486                 inode.i_file_acl = 0;
6487 #if BB_BIG_ENDIAN
6488                 /*
6489                  * This is a special kludge to deal with long symlinks
6490                  * on big endian systems.  i_blocks had already been
6491                  * decremented earlier in pass 1, but since i_file_acl
6492                  * hadn't yet been cleared, ext2fs_read_inode()
6493                  * assumed that the file was short symlink and would
6494                  * not have byte swapped i_block[0].  Hence, we have
6495                  * to byte-swap it here.
6496                  */
6497                 if (LINUX_S_ISLNK(inode.i_mode) &&
6498                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6499                     (inode.i_blocks == fs->blocksize >> 9))
6500                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6501 #endif
6502                 inode_modified++;
6503         } else
6504                 not_fixed++;
6505
6506         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6507             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6508             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6509             !(LINUX_S_ISSOCK(inode.i_mode)))
6510                 problem = PR_2_BAD_MODE;
6511         else if (LINUX_S_ISCHR(inode.i_mode)
6512                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6513                 problem = PR_2_BAD_CHAR_DEV;
6514         else if (LINUX_S_ISBLK(inode.i_mode)
6515                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6516                 problem = PR_2_BAD_BLOCK_DEV;
6517         else if (LINUX_S_ISFIFO(inode.i_mode)
6518                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6519                 problem = PR_2_BAD_FIFO;
6520         else if (LINUX_S_ISSOCK(inode.i_mode)
6521                  && !e2fsck_pass1_check_device_inode(fs, &inode))
6522                 problem = PR_2_BAD_SOCKET;
6523         else if (LINUX_S_ISLNK(inode.i_mode)
6524                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6525                 problem = PR_2_INVALID_SYMLINK;
6526         }
6527
6528         if (problem) {
6529                 if (fix_problem(ctx, problem, &pctx)) {
6530                         deallocate_inode(ctx, ino, 0);
6531                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6532                                 return 0;
6533                         return 1;
6534                 } else
6535                         not_fixed++;
6536                 problem = 0;
6537         }
6538
6539         if (inode.i_faddr) {
6540                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6541                         inode.i_faddr = 0;
6542                         inode_modified++;
6543                 } else
6544                         not_fixed++;
6545         }
6546
6547         switch (fs->super->s_creator_os) {
6548             case EXT2_OS_LINUX:
6549                 frag = &inode.osd2.linux2.l_i_frag;
6550                 fsize = &inode.osd2.linux2.l_i_fsize;
6551                 break;
6552             case EXT2_OS_HURD:
6553                 frag = &inode.osd2.hurd2.h_i_frag;
6554                 fsize = &inode.osd2.hurd2.h_i_fsize;
6555                 break;
6556             case EXT2_OS_MASIX:
6557                 frag = &inode.osd2.masix2.m_i_frag;
6558                 fsize = &inode.osd2.masix2.m_i_fsize;
6559                 break;
6560             default:
6561                 frag = fsize = 0;
6562         }
6563         if (frag && *frag) {
6564                 pctx.num = *frag;
6565                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6566                         *frag = 0;
6567                         inode_modified++;
6568                 } else
6569                         not_fixed++;
6570                 pctx.num = 0;
6571         }
6572         if (fsize && *fsize) {
6573                 pctx.num = *fsize;
6574                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6575                         *fsize = 0;
6576                         inode_modified++;
6577                 } else
6578                         not_fixed++;
6579                 pctx.num = 0;
6580         }
6581
6582         if (inode.i_file_acl &&
6583             ((inode.i_file_acl < fs->super->s_first_data_block) ||
6584              (inode.i_file_acl >= fs->super->s_blocks_count))) {
6585                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6586                         inode.i_file_acl = 0;
6587                         inode_modified++;
6588                 } else
6589                         not_fixed++;
6590         }
6591         if (inode.i_dir_acl &&
6592             LINUX_S_ISDIR(inode.i_mode)) {
6593                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6594                         inode.i_dir_acl = 0;
6595                         inode_modified++;
6596                 } else
6597                         not_fixed++;
6598         }
6599
6600         if (inode_modified)
6601                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6602         if (!not_fixed)
6603                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6604         return 0;
6605 }
6606
6607
6608 /*
6609  * allocate_dir_block --- this function allocates a new directory
6610  *      block for a particular inode; this is done if a directory has
6611  *      a "hole" in it, or if a directory has a illegal block number
6612  *      that was zeroed out and now needs to be replaced.
6613  */
6614 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6615                               struct problem_context *pctx)
6616 {
6617         ext2_filsys fs = ctx->fs;
6618         blk_t                   blk;
6619         char                    *block;
6620         struct ext2_inode       inode;
6621
6622         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6623                 return 1;
6624
6625         /*
6626          * Read the inode and block bitmaps in; we'll be messing with
6627          * them.
6628          */
6629         e2fsck_read_bitmaps(ctx);
6630
6631         /*
6632          * First, find a free block
6633          */
6634         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6635         if (pctx->errcode) {
6636                 pctx->str = "ext2fs_new_block";
6637                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6638                 return 1;
6639         }
6640         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6641         ext2fs_mark_block_bitmap(fs->block_map, blk);
6642         ext2fs_mark_bb_dirty(fs);
6643
6644         /*
6645          * Now let's create the actual data block for the inode
6646          */
6647         if (db->blockcnt)
6648                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6649         else
6650                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6651                                                      EXT2_ROOT_INO, &block);
6652
6653         if (pctx->errcode) {
6654                 pctx->str = "ext2fs_new_dir_block";
6655                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6656                 return 1;
6657         }
6658
6659         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6660         ext2fs_free_mem(&block);
6661         if (pctx->errcode) {
6662                 pctx->str = "ext2fs_write_dir_block";
6663                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6664                 return 1;
6665         }
6666
6667         /*
6668          * Update the inode block count
6669          */
6670         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6671         inode.i_blocks += fs->blocksize / 512;
6672         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6673                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6674         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6675
6676         /*
6677          * Finally, update the block pointers for the inode
6678          */
6679         db->blk = blk;
6680         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6681                                       0, update_dir_block, db);
6682         if (pctx->errcode) {
6683                 pctx->str = "ext2fs_block_iterate";
6684                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6685                 return 1;
6686         }
6687
6688         return 0;
6689 }
6690
6691 /*
6692  * This is a helper function for allocate_dir_block().
6693  */
6694 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6695                             blk_t       *block_nr,
6696                             e2_blkcnt_t blockcnt,
6697                             blk_t ref_block FSCK_ATTR((unused)),
6698                             int ref_offset FSCK_ATTR((unused)),
6699                             void *priv_data)
6700 {
6701         struct ext2_db_entry *db;
6702
6703         db = (struct ext2_db_entry *) priv_data;
6704         if (db->blockcnt == (int) blockcnt) {
6705                 *block_nr = db->blk;
6706                 return BLOCK_CHANGED;
6707         }
6708         return 0;
6709 }
6710
6711 /*
6712  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6713  *
6714  * Pass #3 assures that all directories are connected to the
6715  * filesystem tree, using the following algorithm:
6716  *
6717  * First, the root directory is checked to make sure it exists; if
6718  * not, e2fsck will offer to create a new one.  It is then marked as
6719  * "done".
6720  *
6721  * Then, pass3 interates over all directory inodes; for each directory
6722  * it attempts to trace up the filesystem tree, using dirinfo.parent
6723  * until it reaches a directory which has been marked "done".  If it
6724  * cannot do so, then the directory must be disconnected, and e2fsck
6725  * will offer to reconnect it to /lost+found.  While it is chasing
6726  * parent pointers up the filesystem tree, if pass3 sees a directory
6727  * twice, then it has detected a filesystem loop, and it will again
6728  * offer to reconnect the directory to /lost+found in to break the
6729  * filesystem loop.
6730  *
6731  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6732  * reconnect inodes to /lost+found; this subroutine is also used by
6733  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6734  * is responsible for creating /lost+found if it does not exist.
6735  *
6736  * Pass 3 frees the following data structures:
6737  *      - The dirinfo directory information cache.
6738  */
6739
6740 static void check_root(e2fsck_t ctx);
6741 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6742                            struct problem_context *pctx);
6743 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6744
6745 static ext2fs_inode_bitmap inode_loop_detect;
6746 static ext2fs_inode_bitmap inode_done_map;
6747
6748 static void e2fsck_pass3(e2fsck_t ctx)
6749 {
6750         ext2_filsys fs = ctx->fs;
6751         int             i;
6752         struct problem_context  pctx;
6753         struct dir_info *dir;
6754         unsigned long maxdirs, count;
6755
6756         clear_problem_context(&pctx);
6757
6758         /* Pass 3 */
6759
6760         if (!(ctx->options & E2F_OPT_PREEN))
6761                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6762
6763         /*
6764          * Allocate some bitmaps to do loop detection.
6765          */
6766         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6767                                                     &inode_done_map);
6768         if (pctx.errcode) {
6769                 pctx.num = 2;
6770                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6771                 ctx->flags |= E2F_FLAG_ABORT;
6772                 goto abort_exit;
6773         }
6774         check_root(ctx);
6775         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6776                 goto abort_exit;
6777
6778         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6779
6780         maxdirs = e2fsck_get_num_dirinfo(ctx);
6781         count = 1;
6782
6783         if (ctx->progress)
6784                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6785                         goto abort_exit;
6786
6787         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6788                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6789                         goto abort_exit;
6790                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6791                         goto abort_exit;
6792                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6793                         if (check_directory(ctx, dir, &pctx))
6794                                 goto abort_exit;
6795         }
6796
6797         /*
6798          * Force the creation of /lost+found if not present
6799          */
6800         if ((ctx->flags & E2F_OPT_READONLY) == 0)
6801                 e2fsck_get_lost_and_found(ctx, 1);
6802
6803         /*
6804          * If there are any directories that need to be indexed or
6805          * optimized, do it here.
6806          */
6807         e2fsck_rehash_directories(ctx);
6808
6809 abort_exit:
6810         e2fsck_free_dir_info(ctx);
6811         ext2fs_free_inode_bitmap(inode_loop_detect);
6812         inode_loop_detect = 0;
6813         ext2fs_free_inode_bitmap(inode_done_map);
6814         inode_done_map = 0;
6815 }
6816
6817 /*
6818  * This makes sure the root inode is present; if not, we ask if the
6819  * user wants us to create it.  Not creating it is a fatal error.
6820  */
6821 static void check_root(e2fsck_t ctx)
6822 {
6823         ext2_filsys fs = ctx->fs;
6824         blk_t                   blk;
6825         struct ext2_inode       inode;
6826         char *                  block;
6827         struct problem_context  pctx;
6828
6829         clear_problem_context(&pctx);
6830
6831         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6832                 /*
6833                  * If the root inode is not a directory, die here.  The
6834                  * user must have answered 'no' in pass1 when we
6835                  * offered to clear it.
6836                  */
6837                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6838                                                EXT2_ROOT_INO))) {
6839                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6840                         ctx->flags |= E2F_FLAG_ABORT;
6841                 }
6842                 return;
6843         }
6844
6845         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6846                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6847                 ctx->flags |= E2F_FLAG_ABORT;
6848                 return;
6849         }
6850
6851         e2fsck_read_bitmaps(ctx);
6852
6853         /*
6854          * First, find a free block
6855          */
6856         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6857         if (pctx.errcode) {
6858                 pctx.str = "ext2fs_new_block";
6859                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6860                 ctx->flags |= E2F_FLAG_ABORT;
6861                 return;
6862         }
6863         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6864         ext2fs_mark_block_bitmap(fs->block_map, blk);
6865         ext2fs_mark_bb_dirty(fs);
6866
6867         /*
6868          * Now let's create the actual data block for the inode
6869          */
6870         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6871                                             &block);
6872         if (pctx.errcode) {
6873                 pctx.str = "ext2fs_new_dir_block";
6874                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6875                 ctx->flags |= E2F_FLAG_ABORT;
6876                 return;
6877         }
6878
6879         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6880         if (pctx.errcode) {
6881                 pctx.str = "ext2fs_write_dir_block";
6882                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6883                 ctx->flags |= E2F_FLAG_ABORT;
6884                 return;
6885         }
6886         ext2fs_free_mem(&block);
6887
6888         /*
6889          * Set up the inode structure
6890          */
6891         memset(&inode, 0, sizeof(inode));
6892         inode.i_mode = 040755;
6893         inode.i_size = fs->blocksize;
6894         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
6895         inode.i_links_count = 2;
6896         inode.i_blocks = fs->blocksize / 512;
6897         inode.i_block[0] = blk;
6898
6899         /*
6900          * Write out the inode.
6901          */
6902         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6903         if (pctx.errcode) {
6904                 pctx.str = "ext2fs_write_inode";
6905                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6906                 ctx->flags |= E2F_FLAG_ABORT;
6907                 return;
6908         }
6909
6910         /*
6911          * Miscellaneous bookkeeping...
6912          */
6913         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6914         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6915         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6916
6917         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6918         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6919         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6920         ext2fs_mark_ib_dirty(fs);
6921 }
6922
6923 /*
6924  * This subroutine is responsible for making sure that a particular
6925  * directory is connected to the root; if it isn't we trace it up as
6926  * far as we can go, and then offer to connect the resulting parent to
6927  * the lost+found.  We have to do loop detection; if we ever discover
6928  * a loop, we treat that as a disconnected directory and offer to
6929  * reparent it to lost+found.
6930  *
6931  * However, loop detection is expensive, because for very large
6932  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6933  * is non-trivial.  Loops in filesystems are also a rare error case,
6934  * and we shouldn't optimize for error cases.  So we try two passes of
6935  * the algorithm.  The first time, we ignore loop detection and merely
6936  * increment a counter; if the counter exceeds some extreme threshold,
6937  * then we try again with the loop detection bitmap enabled.
6938  */
6939 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6940                            struct problem_context *pctx)
6941 {
6942         ext2_filsys     fs = ctx->fs;
6943         struct dir_info *p = dir;
6944         int             loop_pass = 0, parent_count = 0;
6945
6946         if (!p)
6947                 return 0;
6948
6949         while (1) {
6950                 /*
6951                  * Mark this inode as being "done"; by the time we
6952                  * return from this function, the inode we either be
6953                  * verified as being connected to the directory tree,
6954                  * or we will have offered to reconnect this to
6955                  * lost+found.
6956                  *
6957                  * If it was marked done already, then we've reached a
6958                  * parent we've already checked.
6959                  */
6960                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6961                         break;
6962
6963                 /*
6964                  * If this directory doesn't have a parent, or we've
6965                  * seen the parent once already, then offer to
6966                  * reparent it to lost+found
6967                  */
6968                 if (!p->parent ||
6969                     (loop_pass &&
6970                      (ext2fs_test_inode_bitmap(inode_loop_detect,
6971                                               p->parent)))) {
6972                         pctx->ino = p->ino;
6973                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6974                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
6975                                         ext2fs_unmark_valid(fs);
6976                                 else {
6977                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
6978                                         p->parent = ctx->lost_and_found;
6979                                         fix_dotdot(ctx, p, ctx->lost_and_found);
6980                                 }
6981                         }
6982                         break;
6983                 }
6984                 p = e2fsck_get_dir_info(ctx, p->parent);
6985                 if (!p) {
6986                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6987                         return 0;
6988                 }
6989                 if (loop_pass) {
6990                         ext2fs_mark_inode_bitmap(inode_loop_detect,
6991                                                  p->ino);
6992                 } else if (parent_count++ > 2048) {
6993                         /*
6994                          * If we've run into a path depth that's
6995                          * greater than 2048, try again with the inode
6996                          * loop bitmap turned on and start from the
6997                          * top.
6998                          */
6999                         loop_pass = 1;
7000                         if (inode_loop_detect)
7001                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
7002                         else {
7003                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7004                                 if (pctx->errcode) {
7005                                         pctx->num = 1;
7006                                         fix_problem(ctx,
7007                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7008                                         ctx->flags |= E2F_FLAG_ABORT;
7009                                         return -1;
7010                                 }
7011                         }
7012                         p = dir;
7013                 }
7014         }
7015
7016         /*
7017          * Make sure that .. and the parent directory are the same;
7018          * offer to fix it if not.
7019          */
7020         if (dir->parent != dir->dotdot) {
7021                 pctx->ino = dir->ino;
7022                 pctx->ino2 = dir->dotdot;
7023                 pctx->dir = dir->parent;
7024                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7025                         fix_dotdot(ctx, dir, dir->parent);
7026         }
7027         return 0;
7028 }
7029
7030 /*
7031  * This routine gets the lost_and_found inode, making it a directory
7032  * if necessary
7033  */
7034 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7035 {
7036         ext2_filsys fs = ctx->fs;
7037         ext2_ino_t                      ino;
7038         blk_t                   blk;
7039         errcode_t               retval;
7040         struct ext2_inode       inode;
7041         char *                  block;
7042         static const char       name[] = "lost+found";
7043         struct  problem_context pctx;
7044         struct dir_info         *dirinfo;
7045
7046         if (ctx->lost_and_found)
7047                 return ctx->lost_and_found;
7048
7049         clear_problem_context(&pctx);
7050
7051         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7052                                sizeof(name)-1, 0, &ino);
7053         if (retval && !fix)
7054                 return 0;
7055         if (!retval) {
7056                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7057                         ctx->lost_and_found = ino;
7058                         return ino;
7059                 }
7060
7061                 /* Lost+found isn't a directory! */
7062                 if (!fix)
7063                         return 0;
7064                 pctx.ino = ino;
7065                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7066                         return 0;
7067
7068                 /* OK, unlink the old /lost+found file. */
7069                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7070                 if (pctx.errcode) {
7071                         pctx.str = "ext2fs_unlink";
7072                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7073                         return 0;
7074                 }
7075                 dirinfo = e2fsck_get_dir_info(ctx, ino);
7076                 if (dirinfo)
7077                         dirinfo->parent = 0;
7078                 e2fsck_adjust_inode_count(ctx, ino, -1);
7079         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7080                 pctx.errcode = retval;
7081                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7082         }
7083         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7084                 return 0;
7085
7086         /*
7087          * Read the inode and block bitmaps in; we'll be messing with
7088          * them.
7089          */
7090         e2fsck_read_bitmaps(ctx);
7091
7092         /*
7093          * First, find a free block
7094          */
7095         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7096         if (retval) {
7097                 pctx.errcode = retval;
7098                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7099                 return 0;
7100         }
7101         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7102         ext2fs_block_alloc_stats(fs, blk, +1);
7103
7104         /*
7105          * Next find a free inode.
7106          */
7107         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7108                                   ctx->inode_used_map, &ino);
7109         if (retval) {
7110                 pctx.errcode = retval;
7111                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7112                 return 0;
7113         }
7114         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7115         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7116         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7117
7118         /*
7119          * Now let's create the actual data block for the inode
7120          */
7121         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7122         if (retval) {
7123                 pctx.errcode = retval;
7124                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7125                 return 0;
7126         }
7127
7128         retval = ext2fs_write_dir_block(fs, blk, block);
7129         ext2fs_free_mem(&block);
7130         if (retval) {
7131                 pctx.errcode = retval;
7132                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7133                 return 0;
7134         }
7135
7136         /*
7137          * Set up the inode structure
7138          */
7139         memset(&inode, 0, sizeof(inode));
7140         inode.i_mode = 040700;
7141         inode.i_size = fs->blocksize;
7142         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
7143         inode.i_links_count = 2;
7144         inode.i_blocks = fs->blocksize / 512;
7145         inode.i_block[0] = blk;
7146
7147         /*
7148          * Next, write out the inode.
7149          */
7150         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7151         if (pctx.errcode) {
7152                 pctx.str = "ext2fs_write_inode";
7153                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7154                 return 0;
7155         }
7156         /*
7157          * Finally, create the directory link
7158          */
7159         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7160         if (pctx.errcode) {
7161                 pctx.str = "ext2fs_link";
7162                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7163                 return 0;
7164         }
7165
7166         /*
7167          * Miscellaneous bookkeeping that needs to be kept straight.
7168          */
7169         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7170         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7171         ext2fs_icount_store(ctx->inode_count, ino, 2);
7172         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7173         ctx->lost_and_found = ino;
7174         return ino;
7175 }
7176
7177 /*
7178  * This routine will connect a file to lost+found
7179  */
7180 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7181 {
7182         ext2_filsys fs = ctx->fs;
7183         errcode_t       retval;
7184         char            name[80];
7185         struct problem_context  pctx;
7186         struct ext2_inode       inode;
7187         int             file_type = 0;
7188
7189         clear_problem_context(&pctx);
7190         pctx.ino = ino;
7191
7192         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7193                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7194                         ctx->bad_lost_and_found++;
7195         }
7196         if (ctx->bad_lost_and_found) {
7197                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7198                 return 1;
7199         }
7200
7201         sprintf(name, "#%u", ino);
7202         if (ext2fs_read_inode(fs, ino, &inode) == 0)
7203                 file_type = ext2_file_type(inode.i_mode);
7204         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7205         if (retval == EXT2_ET_DIR_NO_SPACE) {
7206                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7207                         return 1;
7208                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7209                                                  1, 0);
7210                 if (retval) {
7211                         pctx.errcode = retval;
7212                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7213                         return 1;
7214                 }
7215                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7216                                      ino, file_type);
7217         }
7218         if (retval) {
7219                 pctx.errcode = retval;
7220                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7221                 return 1;
7222         }
7223         e2fsck_adjust_inode_count(ctx, ino, 1);
7224
7225         return 0;
7226 }
7227
7228 /*
7229  * Utility routine to adjust the inode counts on an inode.
7230  */
7231 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7232 {
7233         ext2_filsys fs = ctx->fs;
7234         errcode_t               retval;
7235         struct ext2_inode       inode;
7236
7237         if (!ino)
7238                 return 0;
7239
7240         retval = ext2fs_read_inode(fs, ino, &inode);
7241         if (retval)
7242                 return retval;
7243
7244         if (adj == 1) {
7245                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7246                 if (inode.i_links_count == (__u16) ~0)
7247                         return 0;
7248                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7249                 inode.i_links_count++;
7250         } else if (adj == -1) {
7251                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7252                 if (inode.i_links_count == 0)
7253                         return 0;
7254                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7255                 inode.i_links_count--;
7256         }
7257
7258         retval = ext2fs_write_inode(fs, ino, &inode);
7259         if (retval)
7260                 return retval;
7261
7262         return 0;
7263 }
7264
7265 /*
7266  * Fix parent --- this routine fixes up the parent of a directory.
7267  */
7268 struct fix_dotdot_struct {
7269         ext2_filsys     fs;
7270         ext2_ino_t      parent;
7271         int             done;
7272         e2fsck_t        ctx;
7273 };
7274
7275 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7276                            int  offset FSCK_ATTR((unused)),
7277                            int  blocksize FSCK_ATTR((unused)),
7278                            char *buf FSCK_ATTR((unused)),
7279                            void *priv_data)
7280 {
7281         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7282         errcode_t       retval;
7283         struct problem_context pctx;
7284
7285         if ((dirent->name_len & 0xFF) != 2)
7286                 return 0;
7287         if (strncmp(dirent->name, "..", 2))
7288                 return 0;
7289
7290         clear_problem_context(&pctx);
7291
7292         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7293         if (retval) {
7294                 pctx.errcode = retval;
7295                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7296         }
7297         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7298         if (retval) {
7299                 pctx.errcode = retval;
7300                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7301         }
7302         dirent->inode = fp->parent;
7303
7304         fp->done++;
7305         return DIRENT_ABORT | DIRENT_CHANGED;
7306 }
7307
7308 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7309 {
7310         ext2_filsys fs = ctx->fs;
7311         errcode_t       retval;
7312         struct fix_dotdot_struct fp;
7313         struct problem_context pctx;
7314
7315         fp.fs = fs;
7316         fp.parent = parent;
7317         fp.done = 0;
7318         fp.ctx = ctx;
7319
7320         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7321                                     0, fix_dotdot_proc, &fp);
7322         if (retval || !fp.done) {
7323                 clear_problem_context(&pctx);
7324                 pctx.ino = dir->ino;
7325                 pctx.errcode = retval;
7326                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7327                             PR_3_FIX_PARENT_NOFIND, &pctx);
7328                 ext2fs_unmark_valid(fs);
7329         }
7330         dir->dotdot = parent;
7331
7332         return;
7333 }
7334
7335 /*
7336  * These routines are responsible for expanding a /lost+found if it is
7337  * too small.
7338  */
7339
7340 struct expand_dir_struct {
7341         int                     num;
7342         int                     guaranteed_size;
7343         int                     newblocks;
7344         int                     last_block;
7345         errcode_t               err;
7346         e2fsck_t                ctx;
7347 };
7348
7349 static int expand_dir_proc(ext2_filsys fs,
7350                            blk_t        *blocknr,
7351                            e2_blkcnt_t  blockcnt,
7352                            blk_t ref_block FSCK_ATTR((unused)),
7353                            int ref_offset FSCK_ATTR((unused)),
7354                            void *priv_data)
7355 {
7356         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7357         blk_t   new_blk;
7358         static blk_t    last_blk = 0;
7359         char            *block;
7360         errcode_t       retval;
7361         e2fsck_t        ctx;
7362
7363         ctx = es->ctx;
7364
7365         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7366                 return BLOCK_ABORT;
7367
7368         if (blockcnt > 0)
7369                 es->last_block = blockcnt;
7370         if (*blocknr) {
7371                 last_blk = *blocknr;
7372                 return 0;
7373         }
7374         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7375                                   &new_blk);
7376         if (retval) {
7377                 es->err = retval;
7378                 return BLOCK_ABORT;
7379         }
7380         if (blockcnt > 0) {
7381                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7382                 if (retval) {
7383                         es->err = retval;
7384                         return BLOCK_ABORT;
7385                 }
7386                 es->num--;
7387                 retval = ext2fs_write_dir_block(fs, new_blk, block);
7388         } else {
7389                 retval = ext2fs_get_mem(fs->blocksize, &block);
7390                 if (retval) {
7391                         es->err = retval;
7392                         return BLOCK_ABORT;
7393                 }
7394                 memset(block, 0, fs->blocksize);
7395                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7396         }
7397         if (retval) {
7398                 es->err = retval;
7399                 return BLOCK_ABORT;
7400         }
7401         ext2fs_free_mem(&block);
7402         *blocknr = new_blk;
7403         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7404         ext2fs_block_alloc_stats(fs, new_blk, +1);
7405         es->newblocks++;
7406
7407         if (es->num == 0)
7408                 return (BLOCK_CHANGED | BLOCK_ABORT);
7409         else
7410                 return BLOCK_CHANGED;
7411 }
7412
7413 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7414                                   int num, int guaranteed_size)
7415 {
7416         ext2_filsys fs = ctx->fs;
7417         errcode_t       retval;
7418         struct expand_dir_struct es;
7419         struct ext2_inode       inode;
7420
7421         if (!(fs->flags & EXT2_FLAG_RW))
7422                 return EXT2_ET_RO_FILSYS;
7423
7424         /*
7425          * Read the inode and block bitmaps in; we'll be messing with
7426          * them.
7427          */
7428         e2fsck_read_bitmaps(ctx);
7429
7430         retval = ext2fs_check_directory(fs, dir);
7431         if (retval)
7432                 return retval;
7433
7434         es.num = num;
7435         es.guaranteed_size = guaranteed_size;
7436         es.last_block = 0;
7437         es.err = 0;
7438         es.newblocks = 0;
7439         es.ctx = ctx;
7440
7441         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7442                                        0, expand_dir_proc, &es);
7443
7444         if (es.err)
7445                 return es.err;
7446
7447         /*
7448          * Update the size and block count fields in the inode.
7449          */
7450         retval = ext2fs_read_inode(fs, dir, &inode);
7451         if (retval)
7452                 return retval;
7453
7454         inode.i_size = (es.last_block + 1) * fs->blocksize;
7455         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7456
7457         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7458
7459         return 0;
7460 }
7461
7462 /*
7463  * pass4.c -- pass #4 of e2fsck: Check reference counts
7464  *
7465  * Pass 4 frees the following data structures:
7466  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7467  */
7468
7469 /*
7470  * This routine is called when an inode is not connected to the
7471  * directory tree.
7472  *
7473  * This subroutine returns 1 then the caller shouldn't bother with the
7474  * rest of the pass 4 tests.
7475  */
7476 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7477 {
7478         ext2_filsys fs = ctx->fs;
7479         struct ext2_inode       inode;
7480         struct problem_context  pctx;
7481
7482         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7483         clear_problem_context(&pctx);
7484         pctx.ino = i;
7485         pctx.inode = &inode;
7486
7487         /*
7488          * Offer to delete any zero-length files that does not have
7489          * blocks.  If there is an EA block, it might have useful
7490          * information, so we won't prompt to delete it, but let it be
7491          * reconnected to lost+found.
7492          */
7493         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7494                                 LINUX_S_ISDIR(inode.i_mode))) {
7495                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7496                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
7497                         inode.i_links_count = 0;
7498                         inode.i_dtime = time(0);
7499                         e2fsck_write_inode(ctx, i, &inode,
7500                                            "disconnect_inode");
7501                         /*
7502                          * Fix up the bitmaps...
7503                          */
7504                         e2fsck_read_bitmaps(ctx);
7505                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7506                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7507                         ext2fs_inode_alloc_stats2(fs, i, -1,
7508                                                   LINUX_S_ISDIR(inode.i_mode));
7509                         return 0;
7510                 }
7511         }
7512
7513         /*
7514          * Prompt to reconnect.
7515          */
7516         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7517                 if (e2fsck_reconnect_file(ctx, i))
7518                         ext2fs_unmark_valid(fs);
7519         } else {
7520                 /*
7521                  * If we don't attach the inode, then skip the
7522                  * i_links_test since there's no point in trying to
7523                  * force i_links_count to zero.
7524                  */
7525                 ext2fs_unmark_valid(fs);
7526                 return 1;
7527         }
7528         return 0;
7529 }
7530
7531
7532 static void e2fsck_pass4(e2fsck_t ctx)
7533 {
7534         ext2_filsys fs = ctx->fs;
7535         ext2_ino_t      i;
7536         struct ext2_inode       inode;
7537         struct problem_context  pctx;
7538         __u16   link_count, link_counted;
7539         char    *buf = 0;
7540         int     group, maxgroup;
7541
7542         /* Pass 4 */
7543
7544         clear_problem_context(&pctx);
7545
7546         if (!(ctx->options & E2F_OPT_PREEN))
7547                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7548
7549         group = 0;
7550         maxgroup = fs->group_desc_count;
7551         if (ctx->progress)
7552                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7553                         return;
7554
7555         for (i=1; i <= fs->super->s_inodes_count; i++) {
7556                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7557                         return;
7558                 if ((i % fs->super->s_inodes_per_group) == 0) {
7559                         group++;
7560                         if (ctx->progress)
7561                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
7562                                         return;
7563                 }
7564                 if (i == EXT2_BAD_INO ||
7565                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7566                         continue;
7567                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7568                     (ctx->inode_imagic_map &&
7569                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7570                         continue;
7571                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7572                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7573                 if (link_counted == 0) {
7574                         if (!buf)
7575                                 buf = e2fsck_allocate_memory(ctx,
7576                                      fs->blocksize, "bad_inode buffer");
7577                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7578                                 continue;
7579                         if (disconnect_inode(ctx, i))
7580                                 continue;
7581                         ext2fs_icount_fetch(ctx->inode_link_info, i,
7582                                             &link_count);
7583                         ext2fs_icount_fetch(ctx->inode_count, i,
7584                                             &link_counted);
7585                 }
7586                 if (link_counted != link_count) {
7587                         e2fsck_read_inode(ctx, i, &inode, "pass4");
7588                         pctx.ino = i;
7589                         pctx.inode = &inode;
7590                         if (link_count != inode.i_links_count) {
7591                                 pctx.num = link_count;
7592                                 fix_problem(ctx,
7593                                             PR_4_INCONSISTENT_COUNT, &pctx);
7594                         }
7595                         pctx.num = link_counted;
7596                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7597                                 inode.i_links_count = link_counted;
7598                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
7599                         }
7600                 }
7601         }
7602         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7603         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7604         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7605         ctx->inode_imagic_map = 0;
7606         ext2fs_free_mem(&buf);
7607 }
7608
7609 /*
7610  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7611  */
7612
7613 #define NO_BLK ((blk_t) -1)
7614
7615 static void print_bitmap_problem(e2fsck_t ctx, int problem,
7616                             struct problem_context *pctx)
7617 {
7618         switch (problem) {
7619         case PR_5_BLOCK_UNUSED:
7620                 if (pctx->blk == pctx->blk2)
7621                         pctx->blk2 = 0;
7622                 else
7623                         problem = PR_5_BLOCK_RANGE_UNUSED;
7624                 break;
7625         case PR_5_BLOCK_USED:
7626                 if (pctx->blk == pctx->blk2)
7627                         pctx->blk2 = 0;
7628                 else
7629                         problem = PR_5_BLOCK_RANGE_USED;
7630                 break;
7631         case PR_5_INODE_UNUSED:
7632                 if (pctx->ino == pctx->ino2)
7633                         pctx->ino2 = 0;
7634                 else
7635                         problem = PR_5_INODE_RANGE_UNUSED;
7636                 break;
7637         case PR_5_INODE_USED:
7638                 if (pctx->ino == pctx->ino2)
7639                         pctx->ino2 = 0;
7640                 else
7641                         problem = PR_5_INODE_RANGE_USED;
7642                 break;
7643         }
7644         fix_problem(ctx, problem, pctx);
7645         pctx->blk = pctx->blk2 = NO_BLK;
7646         pctx->ino = pctx->ino2 = 0;
7647 }
7648
7649 static void check_block_bitmaps(e2fsck_t ctx)
7650 {
7651         ext2_filsys fs = ctx->fs;
7652         blk_t   i;
7653         int     *free_array;
7654         int     group = 0;
7655         unsigned int    blocks = 0;
7656         unsigned int    free_blocks = 0;
7657         int     group_free = 0;
7658         int     actual, bitmap;
7659         struct problem_context  pctx;
7660         int     problem, save_problem, fixit, had_problem;
7661         errcode_t       retval;
7662
7663         clear_problem_context(&pctx);
7664         free_array = (int *) e2fsck_allocate_memory(ctx,
7665             fs->group_desc_count * sizeof(int), "free block count array");
7666
7667         if ((fs->super->s_first_data_block <
7668              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7669             (fs->super->s_blocks_count-1 >
7670              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7671                 pctx.num = 1;
7672                 pctx.blk = fs->super->s_first_data_block;
7673                 pctx.blk2 = fs->super->s_blocks_count -1;
7674                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7675                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7676                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7677
7678                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7679                 return;
7680         }
7681
7682         if ((fs->super->s_first_data_block <
7683              ext2fs_get_block_bitmap_start(fs->block_map)) ||
7684             (fs->super->s_blocks_count-1 >
7685              ext2fs_get_block_bitmap_end(fs->block_map))) {
7686                 pctx.num = 2;
7687                 pctx.blk = fs->super->s_first_data_block;
7688                 pctx.blk2 = fs->super->s_blocks_count -1;
7689                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7690                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7691                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7692
7693                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7694                 return;
7695         }
7696
7697 redo_counts:
7698         had_problem = 0;
7699         save_problem = 0;
7700         pctx.blk = pctx.blk2 = NO_BLK;
7701         for (i = fs->super->s_first_data_block;
7702              i < fs->super->s_blocks_count;
7703              i++) {
7704                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7705                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7706
7707                 if (actual == bitmap)
7708                         goto do_counts;
7709
7710                 if (!actual && bitmap) {
7711                         /*
7712                          * Block not used, but marked in use in the bitmap.
7713                          */
7714                         problem = PR_5_BLOCK_UNUSED;
7715                 } else {
7716                         /*
7717                          * Block used, but not marked in use in the bitmap.
7718                          */
7719                         problem = PR_5_BLOCK_USED;
7720                 }
7721                 if (pctx.blk == NO_BLK) {
7722                         pctx.blk = pctx.blk2 = i;
7723                         save_problem = problem;
7724                 } else {
7725                         if ((problem == save_problem) &&
7726                             (pctx.blk2 == i-1))
7727                                 pctx.blk2++;
7728                         else {
7729                                 print_bitmap_problem(ctx, save_problem, &pctx);
7730                                 pctx.blk = pctx.blk2 = i;
7731                                 save_problem = problem;
7732                         }
7733                 }
7734                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7735                 had_problem++;
7736
7737         do_counts:
7738                 if (!bitmap) {
7739                         group_free++;
7740                         free_blocks++;
7741                 }
7742                 blocks ++;
7743                 if ((blocks == fs->super->s_blocks_per_group) ||
7744                     (i == fs->super->s_blocks_count-1)) {
7745                         free_array[group] = group_free;
7746                         group ++;
7747                         blocks = 0;
7748                         group_free = 0;
7749                         if (ctx->progress)
7750                                 if ((ctx->progress)(ctx, 5, group,
7751                                                     fs->group_desc_count*2))
7752                                         return;
7753                 }
7754         }
7755         if (pctx.blk != NO_BLK)
7756                 print_bitmap_problem(ctx, save_problem, &pctx);
7757         if (had_problem)
7758                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7759         else
7760                 fixit = -1;
7761         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7762
7763         if (fixit == 1) {
7764                 ext2fs_free_block_bitmap(fs->block_map);
7765                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7766                                                   &fs->block_map);
7767                 if (retval) {
7768                         clear_problem_context(&pctx);
7769                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7770                         ctx->flags |= E2F_FLAG_ABORT;
7771                         return;
7772                 }
7773                 ext2fs_set_bitmap_padding(fs->block_map);
7774                 ext2fs_mark_bb_dirty(fs);
7775
7776                 /* Redo the counts */
7777                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7778                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7779                 goto redo_counts;
7780         } else if (fixit == 0)
7781                 ext2fs_unmark_valid(fs);
7782
7783         for (i = 0; i < fs->group_desc_count; i++) {
7784                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7785                         pctx.group = i;
7786                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7787                         pctx.blk2 = free_array[i];
7788
7789                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7790                                         &pctx)) {
7791                                 fs->group_desc[i].bg_free_blocks_count =
7792                                         free_array[i];
7793                                 ext2fs_mark_super_dirty(fs);
7794                         } else
7795                                 ext2fs_unmark_valid(fs);
7796                 }
7797         }
7798         if (free_blocks != fs->super->s_free_blocks_count) {
7799                 pctx.group = 0;
7800                 pctx.blk = fs->super->s_free_blocks_count;
7801                 pctx.blk2 = free_blocks;
7802
7803                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7804                         fs->super->s_free_blocks_count = free_blocks;
7805                         ext2fs_mark_super_dirty(fs);
7806                 } else
7807                         ext2fs_unmark_valid(fs);
7808         }
7809         ext2fs_free_mem(&free_array);
7810 }
7811
7812 static void check_inode_bitmaps(e2fsck_t ctx)
7813 {
7814         ext2_filsys fs = ctx->fs;
7815         ext2_ino_t      i;
7816         unsigned int    free_inodes = 0;
7817         int             group_free = 0;
7818         int             dirs_count = 0;
7819         int             group = 0;
7820         unsigned int    inodes = 0;
7821         int             *free_array;
7822         int             *dir_array;
7823         int             actual, bitmap;
7824         errcode_t       retval;
7825         struct problem_context  pctx;
7826         int             problem, save_problem, fixit, had_problem;
7827
7828         clear_problem_context(&pctx);
7829         free_array = (int *) e2fsck_allocate_memory(ctx,
7830             fs->group_desc_count * sizeof(int), "free inode count array");
7831
7832         dir_array = (int *) e2fsck_allocate_memory(ctx,
7833            fs->group_desc_count * sizeof(int), "directory count array");
7834
7835         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7836             (fs->super->s_inodes_count >
7837              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7838                 pctx.num = 3;
7839                 pctx.blk = 1;
7840                 pctx.blk2 = fs->super->s_inodes_count;
7841                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7842                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7843                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7844
7845                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7846                 return;
7847         }
7848         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7849             (fs->super->s_inodes_count >
7850              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7851                 pctx.num = 4;
7852                 pctx.blk = 1;
7853                 pctx.blk2 = fs->super->s_inodes_count;
7854                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7855                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7856                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7857
7858                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7859                 return;
7860         }
7861
7862 redo_counts:
7863         had_problem = 0;
7864         save_problem = 0;
7865         pctx.ino = pctx.ino2 = 0;
7866         for (i = 1; i <= fs->super->s_inodes_count; i++) {
7867                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7868                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7869
7870                 if (actual == bitmap)
7871                         goto do_counts;
7872
7873                 if (!actual && bitmap) {
7874                         /*
7875                          * Inode wasn't used, but marked in bitmap
7876                          */
7877                         problem = PR_5_INODE_UNUSED;
7878                 } else /* if (actual && !bitmap) */ {
7879                         /*
7880                          * Inode used, but not in bitmap
7881                          */
7882                         problem = PR_5_INODE_USED;
7883                 }
7884                 if (pctx.ino == 0) {
7885                         pctx.ino = pctx.ino2 = i;
7886                         save_problem = problem;
7887                 } else {
7888                         if ((problem == save_problem) &&
7889                             (pctx.ino2 == i-1))
7890                                 pctx.ino2++;
7891                         else {
7892                                 print_bitmap_problem(ctx, save_problem, &pctx);
7893                                 pctx.ino = pctx.ino2 = i;
7894                                 save_problem = problem;
7895                         }
7896                 }
7897                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7898                 had_problem++;
7899
7900 do_counts:
7901                 if (!bitmap) {
7902                         group_free++;
7903                         free_inodes++;
7904                 } else {
7905                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7906                                 dirs_count++;
7907                 }
7908                 inodes++;
7909                 if ((inodes == fs->super->s_inodes_per_group) ||
7910                     (i == fs->super->s_inodes_count)) {
7911                         free_array[group] = group_free;
7912                         dir_array[group] = dirs_count;
7913                         group ++;
7914                         inodes = 0;
7915                         group_free = 0;
7916                         dirs_count = 0;
7917                         if (ctx->progress)
7918                                 if ((ctx->progress)(ctx, 5,
7919                                             group + fs->group_desc_count,
7920                                             fs->group_desc_count*2))
7921                                         return;
7922                 }
7923         }
7924         if (pctx.ino)
7925                 print_bitmap_problem(ctx, save_problem, &pctx);
7926
7927         if (had_problem)
7928                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7929         else
7930                 fixit = -1;
7931         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7932
7933         if (fixit == 1) {
7934                 ext2fs_free_inode_bitmap(fs->inode_map);
7935                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7936                                                   &fs->inode_map);
7937                 if (retval) {
7938                         clear_problem_context(&pctx);
7939                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7940                         ctx->flags |= E2F_FLAG_ABORT;
7941                         return;
7942                 }
7943                 ext2fs_set_bitmap_padding(fs->inode_map);
7944                 ext2fs_mark_ib_dirty(fs);
7945
7946                 /* redo counts */
7947                 inodes = 0; free_inodes = 0; group_free = 0;
7948                 dirs_count = 0; group = 0;
7949                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7950                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7951                 goto redo_counts;
7952         } else if (fixit == 0)
7953                 ext2fs_unmark_valid(fs);
7954
7955         for (i = 0; i < fs->group_desc_count; i++) {
7956                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7957                         pctx.group = i;
7958                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7959                         pctx.ino2 = free_array[i];
7960                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7961                                         &pctx)) {
7962                                 fs->group_desc[i].bg_free_inodes_count =
7963                                         free_array[i];
7964                                 ext2fs_mark_super_dirty(fs);
7965                         } else
7966                                 ext2fs_unmark_valid(fs);
7967                 }
7968                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7969                         pctx.group = i;
7970                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7971                         pctx.ino2 = dir_array[i];
7972
7973                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7974                                         &pctx)) {
7975                                 fs->group_desc[i].bg_used_dirs_count =
7976                                         dir_array[i];
7977                                 ext2fs_mark_super_dirty(fs);
7978                         } else
7979                                 ext2fs_unmark_valid(fs);
7980                 }
7981         }
7982         if (free_inodes != fs->super->s_free_inodes_count) {
7983                 pctx.group = -1;
7984                 pctx.ino = fs->super->s_free_inodes_count;
7985                 pctx.ino2 = free_inodes;
7986
7987                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7988                         fs->super->s_free_inodes_count = free_inodes;
7989                         ext2fs_mark_super_dirty(fs);
7990                 } else
7991                         ext2fs_unmark_valid(fs);
7992         }
7993         ext2fs_free_mem(&free_array);
7994         ext2fs_free_mem(&dir_array);
7995 }
7996
7997 static void check_inode_end(e2fsck_t ctx)
7998 {
7999         ext2_filsys fs = ctx->fs;
8000         ext2_ino_t      end, save_inodes_count, i;
8001         struct problem_context  pctx;
8002
8003         clear_problem_context(&pctx);
8004
8005         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8006         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8007                                                      &save_inodes_count);
8008         if (pctx.errcode) {
8009                 pctx.num = 1;
8010                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8011                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8012                 return;
8013         }
8014         if (save_inodes_count == end)
8015                 return;
8016
8017         for (i = save_inodes_count + 1; i <= end; i++) {
8018                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8019                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8020                                 for (i = save_inodes_count + 1; i <= end; i++)
8021                                         ext2fs_mark_inode_bitmap(fs->inode_map,
8022                                                                  i);
8023                                 ext2fs_mark_ib_dirty(fs);
8024                         } else
8025                                 ext2fs_unmark_valid(fs);
8026                         break;
8027                 }
8028         }
8029
8030         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8031                                                      save_inodes_count, 0);
8032         if (pctx.errcode) {
8033                 pctx.num = 2;
8034                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8035                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8036                 return;
8037         }
8038 }
8039
8040 static void check_block_end(e2fsck_t ctx)
8041 {
8042         ext2_filsys fs = ctx->fs;
8043         blk_t   end, save_blocks_count, i;
8044         struct problem_context  pctx;
8045
8046         clear_problem_context(&pctx);
8047
8048         end = fs->block_map->start +
8049                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8050         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8051                                                      &save_blocks_count);
8052         if (pctx.errcode) {
8053                 pctx.num = 3;
8054                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8055                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8056                 return;
8057         }
8058         if (save_blocks_count == end)
8059                 return;
8060
8061         for (i = save_blocks_count + 1; i <= end; i++) {
8062                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8063                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8064                                 for (i = save_blocks_count + 1; i <= end; i++)
8065                                         ext2fs_mark_block_bitmap(fs->block_map,
8066                                                                  i);
8067                                 ext2fs_mark_bb_dirty(fs);
8068                         } else
8069                                 ext2fs_unmark_valid(fs);
8070                         break;
8071                 }
8072         }
8073
8074         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8075                                                      save_blocks_count, 0);
8076         if (pctx.errcode) {
8077                 pctx.num = 4;
8078                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8079                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8080                 return;
8081         }
8082 }
8083
8084 static void e2fsck_pass5(e2fsck_t ctx)
8085 {
8086         struct problem_context  pctx;
8087
8088         /* Pass 5 */
8089
8090         clear_problem_context(&pctx);
8091
8092         if (!(ctx->options & E2F_OPT_PREEN))
8093                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8094
8095         if (ctx->progress)
8096                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8097                         return;
8098
8099         e2fsck_read_bitmaps(ctx);
8100
8101         check_block_bitmaps(ctx);
8102         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103                 return;
8104         check_inode_bitmaps(ctx);
8105         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106                 return;
8107         check_inode_end(ctx);
8108         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109                 return;
8110         check_block_end(ctx);
8111         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8112                 return;
8113
8114         ext2fs_free_inode_bitmap(ctx->inode_used_map);
8115         ctx->inode_used_map = 0;
8116         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8117         ctx->inode_dir_map = 0;
8118         ext2fs_free_block_bitmap(ctx->block_found_map);
8119         ctx->block_found_map = 0;
8120 }
8121
8122 /*
8123  * problem.c --- report filesystem problems to the user
8124  */
8125
8126 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8127 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8128 #define PR_NO_DEFAULT   0x000004 /* Default to no */
8129 #define PR_MSG_ONLY     0x000008 /* Print message only */
8130
8131 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8132
8133 #define PR_FATAL        0x001000 /* Fatal error */
8134 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8135                                  /* ask another */
8136 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8137 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8138 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8139 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8140 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8141
8142
8143 #define PROMPT_NONE     0
8144 #define PROMPT_FIX      1
8145 #define PROMPT_CLEAR    2
8146 #define PROMPT_RELOCATE 3
8147 #define PROMPT_ALLOCATE 4
8148 #define PROMPT_EXPAND   5
8149 #define PROMPT_CONNECT  6
8150 #define PROMPT_CREATE   7
8151 #define PROMPT_SALVAGE  8
8152 #define PROMPT_TRUNCATE 9
8153 #define PROMPT_CLEAR_INODE 10
8154 #define PROMPT_ABORT    11
8155 #define PROMPT_SPLIT    12
8156 #define PROMPT_CONTINUE 13
8157 #define PROMPT_CLONE    14
8158 #define PROMPT_DELETE   15
8159 #define PROMPT_SUPPRESS 16
8160 #define PROMPT_UNLINK   17
8161 #define PROMPT_CLEAR_HTREE 18
8162 #define PROMPT_RECREATE 19
8163 #define PROMPT_NULL     20
8164
8165 struct e2fsck_problem {
8166         problem_t       e2p_code;
8167         const char *    e2p_description;
8168         char            prompt;
8169         int             flags;
8170         problem_t       second_code;
8171 };
8172
8173 struct latch_descr {
8174         int             latch_code;
8175         problem_t       question;
8176         problem_t       end_message;
8177         int             flags;
8178 };
8179
8180 /*
8181  * These are the prompts which are used to ask the user if they want
8182  * to fix a problem.
8183  */
8184 static const char * const prompt[] = {
8185         N_("(no prompt)"),      /* 0 */
8186         N_("Fix"),              /* 1 */
8187         N_("Clear"),            /* 2 */
8188         N_("Relocate"),         /* 3 */
8189         N_("Allocate"),         /* 4 */
8190         N_("Expand"),           /* 5 */
8191         N_("Connect to /lost+found"), /* 6 */
8192         N_("Create"),           /* 7 */
8193         N_("Salvage"),          /* 8 */
8194         N_("Truncate"),         /* 9 */
8195         N_("Clear inode"),      /* 10 */
8196         N_("Abort"),            /* 11 */
8197         N_("Split"),            /* 12 */
8198         N_("Continue"),         /* 13 */
8199         N_("Clone multiply-claimed blocks"), /* 14 */
8200         N_("Delete file"),      /* 15 */
8201         N_("Suppress messages"),/* 16 */
8202         N_("Unlink"),           /* 17 */
8203         N_("Clear HTree index"),/* 18 */
8204         N_("Recreate"),         /* 19 */
8205         "",                     /* 20 */
8206 };
8207
8208 /*
8209  * These messages are printed when we are preen mode and we will be
8210  * automatically fixing the problem.
8211  */
8212 static const char * const preen_msg[] = {
8213         N_("(NONE)"),           /* 0 */
8214         N_("FIXED"),            /* 1 */
8215         N_("CLEARED"),          /* 2 */
8216         N_("RELOCATED"),        /* 3 */
8217         N_("ALLOCATED"),        /* 4 */
8218         N_("EXPANDED"),         /* 5 */
8219         N_("RECONNECTED"),      /* 6 */
8220         N_("CREATED"),          /* 7 */
8221         N_("SALVAGED"),         /* 8 */
8222         N_("TRUNCATED"),        /* 9 */
8223         N_("INODE CLEARED"),    /* 10 */
8224         N_("ABORTED"),          /* 11 */
8225         N_("SPLIT"),            /* 12 */
8226         N_("CONTINUING"),       /* 13 */
8227         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8228         N_("FILE DELETED"),     /* 15 */
8229         N_("SUPPRESSED"),       /* 16 */
8230         N_("UNLINKED"),         /* 17 */
8231         N_("HTREE INDEX CLEARED"),/* 18 */
8232         N_("WILL RECREATE"),    /* 19 */
8233         "",                     /* 20 */
8234 };
8235
8236 static const struct e2fsck_problem problem_table[] = {
8237
8238         /* Pre-Pass 1 errors */
8239
8240         /* Block bitmap not in group */
8241         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8242           PROMPT_RELOCATE, PR_LATCH_RELOC },
8243
8244         /* Inode bitmap not in group */
8245         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8246           PROMPT_RELOCATE, PR_LATCH_RELOC },
8247
8248         /* Inode table not in group */
8249         { PR_0_ITABLE_NOT_GROUP,
8250           N_("@i table for @g %g is not in @g.  (@b %b)\n"
8251           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8252           PROMPT_RELOCATE, PR_LATCH_RELOC },
8253
8254         /* Superblock corrupt */
8255         { PR_0_SB_CORRUPT,
8256           N_("\nThe @S could not be read or does not describe a correct ext2\n"
8257           "@f.  If the @v is valid and it really contains an ext2\n"
8258           "@f (and not swap or ufs or something else), then the @S\n"
8259           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8260           "    e2fsck -b %S <@v>\n\n"),
8261           PROMPT_NONE, PR_FATAL },
8262
8263         /* Filesystem size is wrong */
8264         { PR_0_FS_SIZE_WRONG,
8265           N_("The @f size (according to the @S) is %b @bs\n"
8266           "The physical size of the @v is %c @bs\n"
8267           "Either the @S or the partition table is likely to be corrupt!\n"),
8268           PROMPT_ABORT, 0 },
8269
8270         /* Fragments not supported */
8271         { PR_0_NO_FRAGMENTS,
8272           N_("@S @b_size = %b, fragsize = %c.\n"
8273           "This version of e2fsck does not support fragment sizes different\n"
8274           "from the @b size.\n"),
8275           PROMPT_NONE, PR_FATAL },
8276
8277           /* Bad blocks_per_group */
8278         { PR_0_BLOCKS_PER_GROUP,
8279           N_("@S @bs_per_group = %b, should have been %c\n"),
8280           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8281
8282         /* Bad first_data_block */
8283         { PR_0_FIRST_DATA_BLOCK,
8284           N_("@S first_data_@b = %b, should have been %c\n"),
8285           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8286
8287         /* Adding UUID to filesystem */
8288         { PR_0_ADD_UUID,
8289           N_("@f did not have a UUID; generating one.\n\n"),
8290           PROMPT_NONE, 0 },
8291
8292         /* Relocate hint */
8293         { PR_0_RELOCATE_HINT,
8294           N_("Note: if several inode or block bitmap blocks or part\n"
8295           "of the inode table require relocation, you may wish to try\n"
8296           "running e2fsck with the '-b %S' option first.  The problem\n"
8297           "may lie only with the primary block group descriptors, and\n"
8298           "the backup block group descriptors may be OK.\n\n"),
8299           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8300
8301         /* Miscellaneous superblock corruption */
8302         { PR_0_MISC_CORRUPT_SUPER,
8303           N_("Corruption found in @S.  (%s = %N).\n"),
8304           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8305
8306         /* Error determing physical device size of filesystem */
8307         { PR_0_GETSIZE_ERROR,
8308           N_("Error determining size of the physical @v: %m\n"),
8309           PROMPT_NONE, PR_FATAL },
8310
8311         /* Inode count in superblock is incorrect */
8312         { PR_0_INODE_COUNT_WRONG,
8313           N_("@i count in @S is %i, @s %j.\n"),
8314           PROMPT_FIX, 0 },
8315
8316         { PR_0_HURD_CLEAR_FILETYPE,
8317           N_("The Hurd does not support the filetype feature.\n"),
8318           PROMPT_CLEAR, 0 },
8319
8320         /* Journal inode is invalid */
8321         { PR_0_JOURNAL_BAD_INODE,
8322           N_("@S has an @n ext3 @j (@i %i).\n"),
8323           PROMPT_CLEAR, PR_PREEN_OK },
8324
8325         /* The external journal has (unsupported) multiple filesystems */
8326         { PR_0_JOURNAL_UNSUPP_MULTIFS,
8327           N_("External @j has multiple @f users (unsupported).\n"),
8328           PROMPT_NONE, PR_FATAL },
8329
8330         /* Can't find external journal */
8331         { PR_0_CANT_FIND_JOURNAL,
8332           N_("Can't find external @j\n"),
8333           PROMPT_NONE, PR_FATAL },
8334
8335         /* External journal has bad superblock */
8336         { PR_0_EXT_JOURNAL_BAD_SUPER,
8337           N_("External @j has bad @S\n"),
8338           PROMPT_NONE, PR_FATAL },
8339
8340         /* Superblock has a bad journal UUID */
8341         { PR_0_JOURNAL_BAD_UUID,
8342           N_("External @j does not support this @f\n"),
8343           PROMPT_NONE, PR_FATAL },
8344
8345         /* Journal has an unknown superblock type */
8346         { PR_0_JOURNAL_UNSUPP_SUPER,
8347           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8348              "It is likely that your copy of e2fsck is old and/or doesn't "
8349              "support this @j format.\n"
8350              "It is also possible the @j @S is corrupt.\n"),
8351           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8352
8353         /* Journal superblock is corrupt */
8354         { PR_0_JOURNAL_BAD_SUPER,
8355           N_("Ext3 @j @S is corrupt.\n"),
8356           PROMPT_FIX, PR_PREEN_OK },
8357
8358         /* Superblock flag should be cleared */
8359         { PR_0_JOURNAL_HAS_JOURNAL,
8360           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8361           PROMPT_CLEAR, PR_PREEN_OK },
8362
8363         /* Superblock flag is incorrect */
8364         { PR_0_JOURNAL_RECOVER_SET,
8365           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8366           PROMPT_CLEAR, PR_PREEN_OK },
8367
8368         /* Journal has data, but recovery flag is clear */
8369         { PR_0_JOURNAL_RECOVERY_CLEAR,
8370           N_("ext3 recovery flag is clear, but @j has data.\n"),
8371           PROMPT_NONE, 0 },
8372
8373         /* Ask if we should clear the journal */
8374         { PR_0_JOURNAL_RESET_JOURNAL,
8375           N_("Clear @j"),
8376           PROMPT_NULL, PR_PREEN_NOMSG },
8377
8378         /* Ask if we should run the journal anyway */
8379         { PR_0_JOURNAL_RUN,
8380           N_("Run @j anyway"),
8381           PROMPT_NULL, 0 },
8382
8383         /* Run the journal by default */
8384         { PR_0_JOURNAL_RUN_DEFAULT,
8385           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8386           PROMPT_NONE, 0 },
8387
8388         /* Clearing orphan inode */
8389         { PR_0_ORPHAN_CLEAR_INODE,
8390           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8391           PROMPT_NONE, 0 },
8392
8393         /* Illegal block found in orphaned inode */
8394         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8395            N_("@I @b #%B (%b) found in @o @i %i.\n"),
8396           PROMPT_NONE, 0 },
8397
8398         /* Already cleared block found in orphaned inode */
8399         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8400            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8401           PROMPT_NONE, 0 },
8402
8403         /* Illegal orphan inode in superblock */
8404         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8405           N_("@I @o @i %i in @S.\n"),
8406           PROMPT_NONE, 0 },
8407
8408         /* Illegal inode in orphaned inode list */
8409         { PR_0_ORPHAN_ILLEGAL_INODE,
8410           N_("@I @i %i in @o @i list.\n"),
8411           PROMPT_NONE, 0 },
8412
8413         /* Filesystem revision is 0, but feature flags are set */
8414         { PR_0_FS_REV_LEVEL,
8415           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8416           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8417
8418         /* Journal superblock has an unknown read-only feature flag set */
8419         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8420           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8421           PROMPT_ABORT, 0 },
8422
8423         /* Journal superblock has an unknown incompatible feature flag set */
8424         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8425           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8426           PROMPT_ABORT, 0 },
8427
8428         /* Journal has unsupported version number */
8429         { PR_0_JOURNAL_UNSUPP_VERSION,
8430           N_("@j version not supported by this e2fsck.\n"),
8431           PROMPT_ABORT, 0 },
8432
8433         /* Moving journal to hidden file */
8434         { PR_0_MOVE_JOURNAL,
8435           N_("Moving @j from /%s to hidden @i.\n\n"),
8436           PROMPT_NONE, 0 },
8437
8438         /* Error moving journal to hidden file */
8439         { PR_0_ERR_MOVE_JOURNAL,
8440           N_("Error moving @j: %m\n\n"),
8441           PROMPT_NONE, 0 },
8442
8443         /* Clearing V2 journal superblock */
8444         { PR_0_CLEAR_V2_JOURNAL,
8445           N_("Found @n V2 @j @S fields (from V1 @j).\n"
8446              "Clearing fields beyond the V1 @j @S...\n\n"),
8447           PROMPT_NONE, 0 },
8448
8449         /* Backup journal inode blocks */
8450         { PR_0_BACKUP_JNL,
8451           N_("Backing up @j @i @b information.\n\n"),
8452           PROMPT_NONE, 0 },
8453
8454         /* Reserved blocks w/o resize_inode */
8455         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8456           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8457              "is %N; @s zero.  "),
8458           PROMPT_FIX, 0 },
8459
8460         /* Resize_inode not enabled, but resize inode is non-zero */
8461         { PR_0_CLEAR_RESIZE_INODE,
8462           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8463           PROMPT_CLEAR, 0 },
8464
8465         /* Resize inode invalid */
8466         { PR_0_RESIZE_INODE_INVALID,
8467           N_("Resize @i not valid.  "),
8468           PROMPT_RECREATE, 0 },
8469
8470         /* Pass 1 errors */
8471
8472         /* Pass 1: Checking inodes, blocks, and sizes */
8473         { PR_1_PASS_HEADER,
8474           N_("Pass 1: Checking @is, @bs, and sizes\n"),
8475           PROMPT_NONE, 0 },
8476
8477         /* Root directory is not an inode */
8478         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8479           PROMPT_CLEAR, 0 },
8480
8481         /* Root directory has dtime set */
8482         { PR_1_ROOT_DTIME,
8483           N_("@r has dtime set (probably due to old mke2fs).  "),
8484           PROMPT_FIX, PR_PREEN_OK },
8485
8486         /* Reserved inode has bad mode */
8487         { PR_1_RESERVED_BAD_MODE,
8488           N_("Reserved @i %i (%Q) has @n mode.  "),
8489           PROMPT_CLEAR, PR_PREEN_OK },
8490
8491         /* Deleted inode has zero dtime */
8492         { PR_1_ZERO_DTIME,
8493           N_("@D @i %i has zero dtime.  "),
8494           PROMPT_FIX, PR_PREEN_OK },
8495
8496         /* Inode in use, but dtime set */
8497         { PR_1_SET_DTIME,
8498           N_("@i %i is in use, but has dtime set.  "),
8499           PROMPT_FIX, PR_PREEN_OK },
8500
8501         /* Zero-length directory */
8502         { PR_1_ZERO_LENGTH_DIR,
8503           N_("@i %i is a @z @d.  "),
8504           PROMPT_CLEAR, PR_PREEN_OK },
8505
8506         /* Block bitmap conflicts with some other fs block */
8507         { PR_1_BB_CONFLICT,
8508           N_("@g %g's @b @B at %b @C.\n"),
8509           PROMPT_RELOCATE, 0 },
8510
8511         /* Inode bitmap conflicts with some other fs block */
8512         { PR_1_IB_CONFLICT,
8513           N_("@g %g's @i @B at %b @C.\n"),
8514           PROMPT_RELOCATE, 0 },
8515
8516         /* Inode table conflicts with some other fs block */
8517         { PR_1_ITABLE_CONFLICT,
8518           N_("@g %g's @i table at %b @C.\n"),
8519           PROMPT_RELOCATE, 0 },
8520
8521         /* Block bitmap is on a bad block */
8522         { PR_1_BB_BAD_BLOCK,
8523           N_("@g %g's @b @B (%b) is bad.  "),
8524           PROMPT_RELOCATE, 0 },
8525
8526         /* Inode bitmap is on a bad block */
8527         { PR_1_IB_BAD_BLOCK,
8528           N_("@g %g's @i @B (%b) is bad.  "),
8529           PROMPT_RELOCATE, 0 },
8530
8531         /* Inode has incorrect i_size */
8532         { PR_1_BAD_I_SIZE,
8533           N_("@i %i, i_size is %Is, @s %N.  "),
8534           PROMPT_FIX, PR_PREEN_OK },
8535
8536         /* Inode has incorrect i_blocks */
8537         { PR_1_BAD_I_BLOCKS,
8538           N_("@i %i, i_@bs is %Ib, @s %N.  "),
8539           PROMPT_FIX, PR_PREEN_OK },
8540
8541         /* Illegal blocknumber in inode */
8542         { PR_1_ILLEGAL_BLOCK_NUM,
8543           N_("@I @b #%B (%b) in @i %i.  "),
8544           PROMPT_CLEAR, PR_LATCH_BLOCK },
8545
8546         /* Block number overlaps fs metadata */
8547         { PR_1_BLOCK_OVERLAPS_METADATA,
8548           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8549           PROMPT_CLEAR, PR_LATCH_BLOCK },
8550
8551         /* Inode has illegal blocks (latch question) */
8552         { PR_1_INODE_BLOCK_LATCH,
8553           N_("@i %i has illegal @b(s).  "),
8554           PROMPT_CLEAR, 0 },
8555
8556         /* Too many bad blocks in inode */
8557         { PR_1_TOO_MANY_BAD_BLOCKS,
8558           N_("Too many illegal @bs in @i %i.\n"),
8559           PROMPT_CLEAR_INODE, PR_NO_OK },
8560
8561         /* Illegal block number in bad block inode */
8562         { PR_1_BB_ILLEGAL_BLOCK_NUM,
8563           N_("@I @b #%B (%b) in bad @b @i.  "),
8564           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8565
8566         /* Bad block inode has illegal blocks (latch question) */
8567         { PR_1_INODE_BBLOCK_LATCH,
8568           N_("Bad @b @i has illegal @b(s).  "),
8569           PROMPT_CLEAR, 0 },
8570
8571         /* Duplicate or bad blocks in use! */
8572         { PR_1_DUP_BLOCKS_PREENSTOP,
8573           N_("Duplicate or bad @b in use!\n"),
8574           PROMPT_NONE, 0 },
8575
8576         /* Bad block used as bad block indirect block */
8577         { PR_1_BBINODE_BAD_METABLOCK,
8578           N_("Bad @b %b used as bad @b @i indirect @b.  "),
8579           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8580
8581         /* Inconsistency can't be fixed prompt */
8582         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8583           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8584              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8585              "in the @f.\n"),
8586           PROMPT_CONTINUE, PR_PREEN_NOMSG },
8587
8588         /* Bad primary block */
8589         { PR_1_BAD_PRIMARY_BLOCK,
8590           N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8591           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8592
8593         /* Bad primary block prompt */
8594         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8595           N_("You can remove this @b from the bad @b list and hope\n"
8596              "that the @b is really OK.  But there are no guarantees.\n\n"),
8597           PROMPT_CLEAR, PR_PREEN_NOMSG },
8598
8599         /* Bad primary superblock */
8600         { PR_1_BAD_PRIMARY_SUPERBLOCK,
8601           N_("The primary @S (%b) is on the bad @b list.\n"),
8602           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8603
8604         /* Bad primary block group descriptors */
8605         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8606           N_("Block %b in the primary @g descriptors "
8607           "is on the bad @b list\n"),
8608           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8609
8610         /* Bad superblock in group */
8611         { PR_1_BAD_SUPERBLOCK,
8612           N_("Warning: Group %g's @S (%b) is bad.\n"),
8613           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8614
8615         /* Bad block group descriptors in group */
8616         { PR_1_BAD_GROUP_DESCRIPTORS,
8617           N_("Warning: Group %g's copy of the @g descriptors has a bad "
8618           "@b (%b).\n"),
8619           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8620
8621         /* Block claimed for no reason */
8622         { PR_1_PROGERR_CLAIMED_BLOCK,
8623           N_("Programming error?  @b #%b claimed for no reason in "
8624           "process_bad_@b.\n"),
8625           PROMPT_NONE, PR_PREEN_OK },
8626
8627         /* Error allocating blocks for relocating metadata */
8628         { PR_1_RELOC_BLOCK_ALLOCATE,
8629           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8630           PROMPT_NONE, PR_PREEN_OK },
8631
8632         /* Error allocating block buffer during relocation process */
8633         { PR_1_RELOC_MEMORY_ALLOCATE,
8634           N_("@A @b buffer for relocating %s\n"),
8635           PROMPT_NONE, PR_PREEN_OK },
8636
8637         /* Relocating metadata group information from X to Y */
8638         { PR_1_RELOC_FROM_TO,
8639           N_("Relocating @g %g's %s from %b to %c...\n"),
8640           PROMPT_NONE, PR_PREEN_OK },
8641
8642         /* Relocating metatdata group information to X */
8643         { PR_1_RELOC_TO,
8644           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8645           PROMPT_NONE, PR_PREEN_OK },
8646
8647         /* Block read error during relocation process */
8648         { PR_1_RELOC_READ_ERR,
8649           N_("Warning: could not read @b %b of %s: %m\n"),
8650           PROMPT_NONE, PR_PREEN_OK },
8651
8652         /* Block write error during relocation process */
8653         { PR_1_RELOC_WRITE_ERR,
8654           N_("Warning: could not write @b %b for %s: %m\n"),
8655           PROMPT_NONE, PR_PREEN_OK },
8656
8657         /* Error allocating inode bitmap */
8658         { PR_1_ALLOCATE_IBITMAP_ERROR,
8659           N_("@A @i @B (%N): %m\n"),
8660           PROMPT_NONE, PR_FATAL },
8661
8662         /* Error allocating block bitmap */
8663         { PR_1_ALLOCATE_BBITMAP_ERROR,
8664           N_("@A @b @B (%N): %m\n"),
8665           PROMPT_NONE, PR_FATAL },
8666
8667         /* Error allocating icount structure */
8668         { PR_1_ALLOCATE_ICOUNT,
8669           N_("@A icount link information: %m\n"),
8670           PROMPT_NONE, PR_FATAL },
8671
8672         /* Error allocating dbcount */
8673         { PR_1_ALLOCATE_DBCOUNT,
8674           N_("@A @d @b array: %m\n"),
8675           PROMPT_NONE, PR_FATAL },
8676
8677         /* Error while scanning inodes */
8678         { PR_1_ISCAN_ERROR,
8679           N_("Error while scanning @is (%i): %m\n"),
8680           PROMPT_NONE, PR_FATAL },
8681
8682         /* Error while iterating over blocks */
8683         { PR_1_BLOCK_ITERATE,
8684           N_("Error while iterating over @bs in @i %i: %m\n"),
8685           PROMPT_NONE, PR_FATAL },
8686
8687         /* Error while storing inode count information */
8688         { PR_1_ICOUNT_STORE,
8689           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8690           PROMPT_NONE, PR_FATAL },
8691
8692         /* Error while storing directory block information */
8693         { PR_1_ADD_DBLOCK,
8694           N_("Error storing @d @b information "
8695           "(@i=%i, @b=%b, num=%N): %m\n"),
8696           PROMPT_NONE, PR_FATAL },
8697
8698         /* Error while reading inode (for clearing) */
8699         { PR_1_READ_INODE,
8700           N_("Error reading @i %i: %m\n"),
8701           PROMPT_NONE, PR_FATAL },
8702
8703         /* Suppress messages prompt */
8704         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8705
8706         /* Imagic flag set on an inode when filesystem doesn't support it */
8707         { PR_1_SET_IMAGIC,
8708           N_("@i %i has imagic flag set.  "),
8709           PROMPT_CLEAR, 0 },
8710
8711         /* Immutable flag set on a device or socket inode */
8712         { PR_1_SET_IMMUTABLE,
8713           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8714              "or append-only flag set.  "),
8715           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8716
8717         /* Compression flag set on an inode when filesystem doesn't support it */
8718         { PR_1_COMPR_SET,
8719           N_("@i %i has @cion flag set on @f without @cion support.  "),
8720           PROMPT_CLEAR, 0 },
8721
8722         /* Non-zero size for device, fifo or socket inode */
8723         { PR_1_SET_NONZSIZE,
8724           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8725           PROMPT_FIX, PR_PREEN_OK },
8726
8727         /* Filesystem revision is 0, but feature flags are set */
8728         { PR_1_FS_REV_LEVEL,
8729           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8730           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8731
8732         /* Journal inode is not in use, but contains data */
8733         { PR_1_JOURNAL_INODE_NOT_CLEAR,
8734           N_("@j @i is not in use, but contains data.  "),
8735           PROMPT_CLEAR, PR_PREEN_OK },
8736
8737         /* Journal has bad mode */
8738         { PR_1_JOURNAL_BAD_MODE,
8739           N_("@j is not regular file.  "),
8740           PROMPT_FIX, PR_PREEN_OK },
8741
8742         /* Deal with inodes that were part of orphan linked list */
8743         { PR_1_LOW_DTIME,
8744           N_("@i %i was part of the @o @i list.  "),
8745           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8746
8747         /* Deal with inodes that were part of corrupted orphan linked
8748            list (latch question) */
8749         { PR_1_ORPHAN_LIST_REFUGEES,
8750           N_("@is that were part of a corrupted orphan linked list found.  "),
8751           PROMPT_FIX, 0 },
8752
8753         /* Error allocating refcount structure */
8754         { PR_1_ALLOCATE_REFCOUNT,
8755           N_("@A refcount structure (%N): %m\n"),
8756           PROMPT_NONE, PR_FATAL },
8757
8758         /* Error reading extended attribute block */
8759         { PR_1_READ_EA_BLOCK,
8760           N_("Error reading @a @b %b for @i %i.  "),
8761           PROMPT_CLEAR, 0 },
8762
8763         /* Invalid extended attribute block */
8764         { PR_1_BAD_EA_BLOCK,
8765           N_("@i %i has a bad @a @b %b.  "),
8766           PROMPT_CLEAR, 0 },
8767
8768         /* Error reading Extended Attribute block while fixing refcount */
8769         { PR_1_EXTATTR_READ_ABORT,
8770           N_("Error reading @a @b %b (%m).  "),
8771           PROMPT_ABORT, 0 },
8772
8773         /* Extended attribute reference count incorrect */
8774         { PR_1_EXTATTR_REFCOUNT,
8775           N_("@a @b %b has reference count %B, @s %N.  "),
8776           PROMPT_FIX, 0 },
8777
8778         /* Error writing Extended Attribute block while fixing refcount */
8779         { PR_1_EXTATTR_WRITE,
8780           N_("Error writing @a @b %b (%m).  "),
8781           PROMPT_ABORT, 0 },
8782
8783         /* Multiple EA blocks not supported */
8784         { PR_1_EA_MULTI_BLOCK,
8785           N_("@a @b %b has h_@bs > 1.  "),
8786           PROMPT_CLEAR, 0},
8787
8788         /* Error allocating EA region allocation structure */
8789         { PR_1_EA_ALLOC_REGION,
8790           N_("@A @a @b %b.  "),
8791           PROMPT_ABORT, 0},
8792
8793         /* Error EA allocation collision */
8794         { PR_1_EA_ALLOC_COLLISION,
8795           N_("@a @b %b is corrupt (allocation collision).  "),
8796           PROMPT_CLEAR, 0},
8797
8798         /* Bad extended attribute name */
8799         { PR_1_EA_BAD_NAME,
8800           N_("@a @b %b is corrupt (@n name).  "),
8801           PROMPT_CLEAR, 0},
8802
8803         /* Bad extended attribute value */
8804         { PR_1_EA_BAD_VALUE,
8805           N_("@a @b %b is corrupt (@n value).  "),
8806           PROMPT_CLEAR, 0},
8807
8808         /* Inode too big (latch question) */
8809         { PR_1_INODE_TOOBIG,
8810           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8811
8812         /* Directory too big */
8813         { PR_1_TOOBIG_DIR,
8814           N_("@b #%B (%b) causes @d to be too big.  "),
8815           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8816
8817         /* Regular file too big */
8818         { PR_1_TOOBIG_REG,
8819           N_("@b #%B (%b) causes file to be too big.  "),
8820           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8821
8822         /* Symlink too big */
8823         { PR_1_TOOBIG_SYMLINK,
8824           N_("@b #%B (%b) causes symlink to be too big.  "),
8825           PROMPT_CLEAR, PR_LATCH_TOOBIG },
8826
8827         /* INDEX_FL flag set on a non-HTREE filesystem */
8828         { PR_1_HTREE_SET,
8829           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8830           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8831
8832         /* INDEX_FL flag set on a non-directory */
8833         { PR_1_HTREE_NODIR,
8834           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8835           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8836
8837         /* Invalid root node in HTREE directory */
8838         { PR_1_HTREE_BADROOT,
8839           N_("@h %i has an @n root node.\n"),
8840           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8841
8842         /* Unsupported hash version in HTREE directory */
8843         { PR_1_HTREE_HASHV,
8844           N_("@h %i has an unsupported hash version (%N)\n"),
8845           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8846
8847         /* Incompatible flag in HTREE root node */
8848         { PR_1_HTREE_INCOMPAT,
8849           N_("@h %i uses an incompatible htree root node flag.\n"),
8850           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8851
8852         /* HTREE too deep */
8853         { PR_1_HTREE_DEPTH,
8854           N_("@h %i has a tree depth (%N) which is too big\n"),
8855           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8856
8857         /* Bad block has indirect block that conflicts with filesystem block */
8858         { PR_1_BB_FS_BLOCK,
8859           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8860              "@f metadata.  "),
8861           PROMPT_CLEAR, PR_LATCH_BBLOCK },
8862
8863         /* Resize inode failed */
8864         { PR_1_RESIZE_INODE_CREATE,
8865           N_("Resize @i (re)creation failed: %m."),
8866           PROMPT_ABORT, 0 },
8867
8868         /* invalid inode->i_extra_isize */
8869         { PR_1_EXTRA_ISIZE,
8870           N_("@i %i has a extra size (%IS) which is @n\n"),
8871           PROMPT_FIX, PR_PREEN_OK },
8872
8873         /* invalid ea entry->e_name_len */
8874         { PR_1_ATTR_NAME_LEN,
8875           N_("@a in @i %i has a namelen (%N) which is @n\n"),
8876           PROMPT_CLEAR, PR_PREEN_OK },
8877
8878         /* invalid ea entry->e_value_size */
8879         { PR_1_ATTR_VALUE_SIZE,
8880           N_("@a in @i %i has a value size (%N) which is @n\n"),
8881           PROMPT_CLEAR, PR_PREEN_OK },
8882
8883         /* invalid ea entry->e_value_offs */
8884         { PR_1_ATTR_VALUE_OFFSET,
8885           N_("@a in @i %i has a value offset (%N) which is @n\n"),
8886           PROMPT_CLEAR, PR_PREEN_OK },
8887
8888         /* invalid ea entry->e_value_block */
8889         { PR_1_ATTR_VALUE_BLOCK,
8890           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8891           PROMPT_CLEAR, PR_PREEN_OK },
8892
8893         /* invalid ea entry->e_hash */
8894         { PR_1_ATTR_HASH,
8895           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8896           PROMPT_CLEAR, PR_PREEN_OK },
8897
8898         /* Pass 1b errors */
8899
8900         /* Pass 1B: Rescan for duplicate/bad blocks */
8901         { PR_1B_PASS_HEADER,
8902           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8903           "Pass 1B: Rescanning for @m @bs\n"),
8904           PROMPT_NONE, 0 },
8905
8906         /* Duplicate/bad block(s) header */
8907         { PR_1B_DUP_BLOCK_HEADER,
8908           N_("@m @b(s) in @i %i:"),
8909           PROMPT_NONE, 0 },
8910
8911         /* Duplicate/bad block(s) in inode */
8912         { PR_1B_DUP_BLOCK,
8913           " %b",
8914           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8915
8916         /* Duplicate/bad block(s) end */
8917         { PR_1B_DUP_BLOCK_END,
8918           "\n",
8919           PROMPT_NONE, PR_PREEN_NOHDR },
8920
8921         /* Error while scanning inodes */
8922         { PR_1B_ISCAN_ERROR,
8923           N_("Error while scanning inodes (%i): %m\n"),
8924           PROMPT_NONE, PR_FATAL },
8925
8926         /* Error allocating inode bitmap */
8927         { PR_1B_ALLOCATE_IBITMAP_ERROR,
8928           N_("@A @i @B (@i_dup_map): %m\n"),
8929           PROMPT_NONE, PR_FATAL },
8930
8931         /* Error while iterating over blocks */
8932         { PR_1B_BLOCK_ITERATE,
8933           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8934           PROMPT_NONE, 0 },
8935
8936         /* Error adjusting EA refcount */
8937         { PR_1B_ADJ_EA_REFCOUNT,
8938           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8939           PROMPT_NONE, 0 },
8940
8941
8942         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8943         { PR_1C_PASS_HEADER,
8944           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8945           PROMPT_NONE, 0 },
8946
8947
8948         /* Pass 1D: Reconciling multiply-claimed blocks */
8949         { PR_1D_PASS_HEADER,
8950           N_("Pass 1D: Reconciling @m @bs\n"),
8951           PROMPT_NONE, 0 },
8952
8953         /* File has duplicate blocks */
8954         { PR_1D_DUP_FILE,
8955           N_("File %Q (@i #%i, mod time %IM)\n"
8956           "  has %B @m @b(s), shared with %N file(s):\n"),
8957           PROMPT_NONE, 0 },
8958
8959         /* List of files sharing duplicate blocks */
8960         { PR_1D_DUP_FILE_LIST,
8961           N_("\t%Q (@i #%i, mod time %IM)\n"),
8962           PROMPT_NONE, 0 },
8963
8964         /* File sharing blocks with filesystem metadata  */
8965         { PR_1D_SHARE_METADATA,
8966           N_("\t<@f metadata>\n"),
8967           PROMPT_NONE, 0 },
8968
8969         /* Report of how many duplicate/bad inodes */
8970         { PR_1D_NUM_DUP_INODES,
8971           N_("(There are %N @is containing @m @bs.)\n\n"),
8972           PROMPT_NONE, 0 },
8973
8974         /* Duplicated blocks already reassigned or cloned. */
8975         { PR_1D_DUP_BLOCKS_DEALT,
8976           N_("@m @bs already reassigned or cloned.\n\n"),
8977           PROMPT_NONE, 0 },
8978
8979         /* Clone duplicate/bad blocks? */
8980         { PR_1D_CLONE_QUESTION,
8981           "", PROMPT_CLONE, PR_NO_OK },
8982
8983         /* Delete file? */
8984         { PR_1D_DELETE_QUESTION,
8985           "", PROMPT_DELETE, 0 },
8986
8987         /* Couldn't clone file (error) */
8988         { PR_1D_CLONE_ERROR,
8989           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8990
8991         /* Pass 2 errors */
8992
8993         /* Pass 2: Checking directory structure */
8994         { PR_2_PASS_HEADER,
8995           N_("Pass 2: Checking @d structure\n"),
8996           PROMPT_NONE, 0 },
8997
8998         /* Bad inode number for '.' */
8999         { PR_2_BAD_INODE_DOT,
9000           N_("@n @i number for '.' in @d @i %i.\n"),
9001           PROMPT_FIX, 0 },
9002
9003         /* Directory entry has bad inode number */
9004         { PR_2_BAD_INO,
9005           N_("@E has @n @i #: %Di.\n"),
9006           PROMPT_CLEAR, 0 },
9007
9008         /* Directory entry has deleted or unused inode */
9009         { PR_2_UNUSED_INODE,
9010           N_("@E has @D/unused @i %Di.  "),
9011           PROMPT_CLEAR, PR_PREEN_OK },
9012
9013         /* Directry entry is link to '.' */
9014         { PR_2_LINK_DOT,
9015           N_("@E @L to '.'  "),
9016           PROMPT_CLEAR, 0 },
9017
9018         /* Directory entry points to inode now located in a bad block */
9019         { PR_2_BB_INODE,
9020           N_("@E points to @i (%Di) located in a bad @b.\n"),
9021           PROMPT_CLEAR, 0 },
9022
9023         /* Directory entry contains a link to a directory */
9024         { PR_2_LINK_DIR,
9025           N_("@E @L to @d %P (%Di).\n"),
9026           PROMPT_CLEAR, 0 },
9027
9028         /* Directory entry contains a link to the root directry */
9029         { PR_2_LINK_ROOT,
9030           N_("@E @L to the @r.\n"),
9031           PROMPT_CLEAR, 0 },
9032
9033         /* Directory entry has illegal characters in its name */
9034         { PR_2_BAD_NAME,
9035           N_("@E has illegal characters in its name.\n"),
9036           PROMPT_FIX, 0 },
9037
9038         /* Missing '.' in directory inode */
9039         { PR_2_MISSING_DOT,
9040           N_("Missing '.' in @d @i %i.\n"),
9041           PROMPT_FIX, 0 },
9042
9043         /* Missing '..' in directory inode */
9044         { PR_2_MISSING_DOT_DOT,
9045           N_("Missing '..' in @d @i %i.\n"),
9046           PROMPT_FIX, 0 },
9047
9048         /* First entry in directory inode doesn't contain '.' */
9049         { PR_2_1ST_NOT_DOT,
9050           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9051           PROMPT_FIX, 0 },
9052
9053         /* Second entry in directory inode doesn't contain '..' */
9054         { PR_2_2ND_NOT_DOT_DOT,
9055           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9056           PROMPT_FIX, 0 },
9057
9058         /* i_faddr should be zero */
9059         { PR_2_FADDR_ZERO,
9060           N_("i_faddr @F %IF, @s zero.\n"),
9061           PROMPT_CLEAR, 0 },
9062
9063         /* i_file_acl should be zero */
9064         { PR_2_FILE_ACL_ZERO,
9065           N_("i_file_acl @F %If, @s zero.\n"),
9066           PROMPT_CLEAR, 0 },
9067
9068         /* i_dir_acl should be zero */
9069         { PR_2_DIR_ACL_ZERO,
9070           N_("i_dir_acl @F %Id, @s zero.\n"),
9071           PROMPT_CLEAR, 0 },
9072
9073         /* i_frag should be zero */
9074         { PR_2_FRAG_ZERO,
9075           N_("i_frag @F %N, @s zero.\n"),
9076           PROMPT_CLEAR, 0 },
9077
9078         /* i_fsize should be zero */
9079         { PR_2_FSIZE_ZERO,
9080           N_("i_fsize @F %N, @s zero.\n"),
9081           PROMPT_CLEAR, 0 },
9082
9083         /* inode has bad mode */
9084         { PR_2_BAD_MODE,
9085           N_("@i %i (%Q) has @n mode (%Im).\n"),
9086           PROMPT_CLEAR, 0 },
9087
9088         /* directory corrupted */
9089         { PR_2_DIR_CORRUPTED,
9090           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9091           PROMPT_SALVAGE, 0 },
9092
9093         /* filename too long */
9094         { PR_2_FILENAME_LONG,
9095           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9096           PROMPT_TRUNCATE, 0 },
9097
9098         /* Directory inode has a missing block (hole) */
9099         { PR_2_DIRECTORY_HOLE,
9100           N_("@d @i %i has an unallocated @b #%B.  "),
9101           PROMPT_ALLOCATE, 0 },
9102
9103         /* '.' is not NULL terminated */
9104         { PR_2_DOT_NULL_TERM,
9105           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9106           PROMPT_FIX, 0 },
9107
9108         /* '..' is not NULL terminated */
9109         { PR_2_DOT_DOT_NULL_TERM,
9110           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9111           PROMPT_FIX, 0 },
9112
9113         /* Illegal character device inode */
9114         { PR_2_BAD_CHAR_DEV,
9115           N_("@i %i (%Q) is an @I character @v.\n"),
9116           PROMPT_CLEAR, 0 },
9117
9118         /* Illegal block device inode */
9119         { PR_2_BAD_BLOCK_DEV,
9120           N_("@i %i (%Q) is an @I @b @v.\n"),
9121           PROMPT_CLEAR, 0 },
9122
9123         /* Duplicate '.' entry */
9124         { PR_2_DUP_DOT,
9125           N_("@E is duplicate '.' @e.\n"),
9126           PROMPT_FIX, 0 },
9127
9128         /* Duplicate '..' entry */
9129         { PR_2_DUP_DOT_DOT,
9130           N_("@E is duplicate '..' @e.\n"),
9131           PROMPT_FIX, 0 },
9132
9133         /* Internal error: couldn't find dir_info */
9134         { PR_2_NO_DIRINFO,
9135           N_("Internal error: cannot find dir_info for %i.\n"),
9136           PROMPT_NONE, PR_FATAL },
9137
9138         /* Final rec_len is wrong */
9139         { PR_2_FINAL_RECLEN,
9140           N_("@E has rec_len of %Dr, @s %N.\n"),
9141           PROMPT_FIX, 0 },
9142
9143         /* Error allocating icount structure */
9144         { PR_2_ALLOCATE_ICOUNT,
9145           N_("@A icount structure: %m\n"),
9146           PROMPT_NONE, PR_FATAL },
9147
9148         /* Error iterating over directory blocks */
9149         { PR_2_DBLIST_ITERATE,
9150           N_("Error iterating over @d @bs: %m\n"),
9151           PROMPT_NONE, PR_FATAL },
9152
9153         /* Error reading directory block */
9154         { PR_2_READ_DIRBLOCK,
9155           N_("Error reading @d @b %b (@i %i): %m\n"),
9156           PROMPT_CONTINUE, 0 },
9157
9158         /* Error writing directory block */
9159         { PR_2_WRITE_DIRBLOCK,
9160           N_("Error writing @d @b %b (@i %i): %m\n"),
9161           PROMPT_CONTINUE, 0 },
9162
9163         /* Error allocating new directory block */
9164         { PR_2_ALLOC_DIRBOCK,
9165           N_("@A new @d @b for @i %i (%s): %m\n"),
9166           PROMPT_NONE, 0 },
9167
9168         /* Error deallocating inode */
9169         { PR_2_DEALLOC_INODE,
9170           N_("Error deallocating @i %i: %m\n"),
9171           PROMPT_NONE, PR_FATAL },
9172
9173         /* Directory entry for '.' is big.  Split? */
9174         { PR_2_SPLIT_DOT,
9175           N_("@d @e for '.' is big.  "),
9176           PROMPT_SPLIT, PR_NO_OK },
9177
9178         /* Illegal FIFO inode */
9179         { PR_2_BAD_FIFO,
9180           N_("@i %i (%Q) is an @I FIFO.\n"),
9181           PROMPT_CLEAR, 0 },
9182
9183         /* Illegal socket inode */
9184         { PR_2_BAD_SOCKET,
9185           N_("@i %i (%Q) is an @I socket.\n"),
9186           PROMPT_CLEAR, 0 },
9187
9188         /* Directory filetype not set */
9189         { PR_2_SET_FILETYPE,
9190           N_("Setting filetype for @E to %N.\n"),
9191           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9192
9193         /* Directory filetype incorrect */
9194         { PR_2_BAD_FILETYPE,
9195           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9196           PROMPT_FIX, 0 },
9197
9198         /* Directory filetype set on filesystem */
9199         { PR_2_CLEAR_FILETYPE,
9200           N_("@E has filetype set.\n"),
9201           PROMPT_CLEAR, PR_PREEN_OK },
9202
9203         /* Directory filename is null */
9204         { PR_2_NULL_NAME,
9205           N_("@E has a @z name.\n"),
9206           PROMPT_CLEAR, 0 },
9207
9208         /* Invalid symlink */
9209         { PR_2_INVALID_SYMLINK,
9210           N_("Symlink %Q (@i #%i) is @n.\n"),
9211           PROMPT_CLEAR, 0 },
9212
9213         /* i_file_acl (extended attribute block) is bad */
9214         { PR_2_FILE_ACL_BAD,
9215           N_("@a @b @F @n (%If).\n"),
9216           PROMPT_CLEAR, 0 },
9217
9218         /* Filesystem contains large files, but has no such flag in sb */
9219         { PR_2_FEATURE_LARGE_FILES,
9220           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9221           PROMPT_FIX, 0 },
9222
9223         /* Node in HTREE directory not referenced */
9224         { PR_2_HTREE_NOTREF,
9225           N_("@p @h %d: node (%B) not referenced\n"),
9226           PROMPT_NONE, 0 },
9227
9228         /* Node in HTREE directory referenced twice */
9229         { PR_2_HTREE_DUPREF,
9230           N_("@p @h %d: node (%B) referenced twice\n"),
9231           PROMPT_NONE, 0 },
9232
9233         /* Node in HTREE directory has bad min hash */
9234         { PR_2_HTREE_MIN_HASH,
9235           N_("@p @h %d: node (%B) has bad min hash\n"),
9236           PROMPT_NONE, 0 },
9237
9238         /* Node in HTREE directory has bad max hash */
9239         { PR_2_HTREE_MAX_HASH,
9240           N_("@p @h %d: node (%B) has bad max hash\n"),
9241           PROMPT_NONE, 0 },
9242
9243         /* Clear invalid HTREE directory */
9244         { PR_2_HTREE_CLEAR,
9245           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9246
9247         /* Bad block in htree interior node */
9248         { PR_2_HTREE_BADBLK,
9249           N_("@p @h %d (%q): bad @b number %b.\n"),
9250           PROMPT_CLEAR_HTREE, 0 },
9251
9252         /* Error adjusting EA refcount */
9253         { PR_2_ADJ_EA_REFCOUNT,
9254           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9255           PROMPT_NONE, PR_FATAL },
9256
9257         /* Invalid HTREE root node */
9258         { PR_2_HTREE_BAD_ROOT,
9259           N_("@p @h %d: root node is @n\n"),
9260           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9261
9262         /* Invalid HTREE limit */
9263         { PR_2_HTREE_BAD_LIMIT,
9264           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9265           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9266
9267         /* Invalid HTREE count */
9268         { PR_2_HTREE_BAD_COUNT,
9269           N_("@p @h %d: node (%B) has @n count (%N)\n"),
9270           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9271
9272         /* HTREE interior node has out-of-order hashes in table */
9273         { PR_2_HTREE_HASH_ORDER,
9274           N_("@p @h %d: node (%B) has an unordered hash table\n"),
9275           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9276
9277         /* Node in HTREE directory has invalid depth */
9278         { PR_2_HTREE_BAD_DEPTH,
9279           N_("@p @h %d: node (%B) has @n depth\n"),
9280           PROMPT_NONE, 0 },
9281
9282         /* Duplicate directory entry found */
9283         { PR_2_DUPLICATE_DIRENT,
9284           N_("Duplicate @E found.  "),
9285           PROMPT_CLEAR, 0 },
9286
9287         /* Non-unique filename found */
9288         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9289           N_("@E has a non-unique filename.\nRename to %s"),
9290           PROMPT_NULL, 0 },
9291
9292         /* Duplicate directory entry found */
9293         { PR_2_REPORT_DUP_DIRENT,
9294           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9295           PROMPT_NONE, 0 },
9296
9297         /* Pass 3 errors */
9298
9299         /* Pass 3: Checking directory connectivity */
9300         { PR_3_PASS_HEADER,
9301           N_("Pass 3: Checking @d connectivity\n"),
9302           PROMPT_NONE, 0 },
9303
9304         /* Root inode not allocated */
9305         { PR_3_NO_ROOT_INODE,
9306           N_("@r not allocated.  "),
9307           PROMPT_ALLOCATE, 0 },
9308
9309         /* No room in lost+found */
9310         { PR_3_EXPAND_LF_DIR,
9311           N_("No room in @l @d.  "),
9312           PROMPT_EXPAND, 0 },
9313
9314         /* Unconnected directory inode */
9315         { PR_3_UNCONNECTED_DIR,
9316           N_("Unconnected @d @i %i (%p)\n"),
9317           PROMPT_CONNECT, 0 },
9318
9319         /* /lost+found not found */
9320         { PR_3_NO_LF_DIR,
9321           N_("/@l not found.  "),
9322           PROMPT_CREATE, PR_PREEN_OK },
9323
9324         /* .. entry is incorrect */
9325         { PR_3_BAD_DOT_DOT,
9326           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9327           PROMPT_FIX, 0 },
9328
9329         /* Bad or non-existent /lost+found.  Cannot reconnect */
9330         { PR_3_NO_LPF,
9331           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9332           PROMPT_NONE, 0 },
9333
9334         /* Could not expand /lost+found */
9335         { PR_3_CANT_EXPAND_LPF,
9336           N_("Could not expand /@l: %m\n"),
9337           PROMPT_NONE, 0 },
9338
9339         /* Could not reconnect inode */
9340         { PR_3_CANT_RECONNECT,
9341           N_("Could not reconnect %i: %m\n"),
9342           PROMPT_NONE, 0 },
9343
9344         /* Error while trying to find /lost+found */
9345         { PR_3_ERR_FIND_LPF,
9346           N_("Error while trying to find /@l: %m\n"),
9347           PROMPT_NONE, 0 },
9348
9349         /* Error in ext2fs_new_block while creating /lost+found */
9350         { PR_3_ERR_LPF_NEW_BLOCK,
9351           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9352           PROMPT_NONE, 0 },
9353
9354         /* Error in ext2fs_new_inode while creating /lost+found */
9355         { PR_3_ERR_LPF_NEW_INODE,
9356           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9357           PROMPT_NONE, 0 },
9358
9359         /* Error in ext2fs_new_dir_block while creating /lost+found */
9360         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9361           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9362           PROMPT_NONE, 0 },
9363
9364         /* Error while writing directory block for /lost+found */
9365         { PR_3_ERR_LPF_WRITE_BLOCK,
9366           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9367           PROMPT_NONE, 0 },
9368
9369         /* Error while adjusting inode count */
9370         { PR_3_ADJUST_INODE,
9371           N_("Error while adjusting @i count on @i %i\n"),
9372           PROMPT_NONE, 0 },
9373
9374         /* Couldn't fix parent directory -- error */
9375         { PR_3_FIX_PARENT_ERR,
9376           N_("Couldn't fix parent of @i %i: %m\n\n"),
9377           PROMPT_NONE, 0 },
9378
9379         /* Couldn't fix parent directory -- couldn't find it */
9380         { PR_3_FIX_PARENT_NOFIND,
9381           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9382           PROMPT_NONE, 0 },
9383
9384         /* Error allocating inode bitmap */
9385         { PR_3_ALLOCATE_IBITMAP_ERROR,
9386           N_("@A @i @B (%N): %m\n"),
9387           PROMPT_NONE, PR_FATAL },
9388
9389         /* Error creating root directory */
9390         { PR_3_CREATE_ROOT_ERROR,
9391           N_("Error creating root @d (%s): %m\n"),
9392           PROMPT_NONE, PR_FATAL },
9393
9394         /* Error creating lost and found directory */
9395         { PR_3_CREATE_LPF_ERROR,
9396           N_("Error creating /@l @d (%s): %m\n"),
9397           PROMPT_NONE, PR_FATAL },
9398
9399         /* Root inode is not directory; aborting */
9400         { PR_3_ROOT_NOT_DIR_ABORT,
9401           N_("@r is not a @d; aborting.\n"),
9402           PROMPT_NONE, PR_FATAL },
9403
9404         /* Cannot proceed without a root inode. */
9405         { PR_3_NO_ROOT_INODE_ABORT,
9406           N_("Cannot proceed without a @r.\n"),
9407           PROMPT_NONE, PR_FATAL },
9408
9409         /* Internal error: couldn't find dir_info */
9410         { PR_3_NO_DIRINFO,
9411           N_("Internal error: cannot find dir_info for %i.\n"),
9412           PROMPT_NONE, PR_FATAL },
9413
9414         /* Lost+found not a directory */
9415         { PR_3_LPF_NOTDIR,
9416           N_("/@l is not a @d (ino=%i)\n"),
9417           PROMPT_UNLINK, 0 },
9418
9419         /* Pass 3A Directory Optimization       */
9420
9421         /* Pass 3A: Optimizing directories */
9422         { PR_3A_PASS_HEADER,
9423           N_("Pass 3A: Optimizing directories\n"),
9424           PROMPT_NONE, PR_PREEN_NOMSG },
9425
9426         /* Error iterating over directories */
9427         { PR_3A_OPTIMIZE_ITER,
9428           N_("Failed to create dirs_to_hash iterator: %m"),
9429           PROMPT_NONE, 0 },
9430
9431         /* Error rehash directory */
9432         { PR_3A_OPTIMIZE_DIR_ERR,
9433           N_("Failed to optimize directory %q (%d): %m"),
9434           PROMPT_NONE, 0 },
9435
9436         /* Rehashing dir header */
9437         { PR_3A_OPTIMIZE_DIR_HEADER,
9438           N_("Optimizing directories: "),
9439           PROMPT_NONE, PR_MSG_ONLY },
9440
9441         /* Rehashing directory %d */
9442         { PR_3A_OPTIMIZE_DIR,
9443           " %d",
9444           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9445
9446         /* Rehashing dir end */
9447         { PR_3A_OPTIMIZE_DIR_END,
9448           "\n",
9449           PROMPT_NONE, PR_PREEN_NOHDR },
9450
9451         /* Pass 4 errors */
9452
9453         /* Pass 4: Checking reference counts */
9454         { PR_4_PASS_HEADER,
9455           N_("Pass 4: Checking reference counts\n"),
9456           PROMPT_NONE, 0 },
9457
9458         /* Unattached zero-length inode */
9459         { PR_4_ZERO_LEN_INODE,
9460           N_("@u @z @i %i.  "),
9461           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9462
9463         /* Unattached inode */
9464         { PR_4_UNATTACHED_INODE,
9465           N_("@u @i %i\n"),
9466           PROMPT_CONNECT, 0 },
9467
9468         /* Inode ref count wrong */
9469         { PR_4_BAD_REF_COUNT,
9470           N_("@i %i ref count is %Il, @s %N.  "),
9471           PROMPT_FIX, PR_PREEN_OK },
9472
9473         { PR_4_INCONSISTENT_COUNT,
9474           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9475           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9476           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9477           "They @s the same!\n"),
9478           PROMPT_NONE, 0 },
9479
9480         /* Pass 5 errors */
9481
9482         /* Pass 5: Checking group summary information */
9483         { PR_5_PASS_HEADER,
9484           N_("Pass 5: Checking @g summary information\n"),
9485           PROMPT_NONE, 0 },
9486
9487         /* Padding at end of inode bitmap is not set. */
9488         { PR_5_INODE_BMAP_PADDING,
9489           N_("Padding at end of @i @B is not set. "),
9490           PROMPT_FIX, PR_PREEN_OK },
9491
9492         /* Padding at end of block bitmap is not set. */
9493         { PR_5_BLOCK_BMAP_PADDING,
9494           N_("Padding at end of @b @B is not set. "),
9495           PROMPT_FIX, PR_PREEN_OK },
9496
9497         /* Block bitmap differences header */
9498         { PR_5_BLOCK_BITMAP_HEADER,
9499           N_("@b @B differences: "),
9500           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9501
9502         /* Block not used, but marked in bitmap */
9503         { PR_5_BLOCK_UNUSED,
9504           " -%b",
9505           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9506
9507         /* Block used, but not marked used in bitmap */
9508         { PR_5_BLOCK_USED,
9509           " +%b",
9510           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9511
9512         /* Block bitmap differences end */
9513         { PR_5_BLOCK_BITMAP_END,
9514           "\n",
9515           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9516
9517         /* Inode bitmap differences header */
9518         { PR_5_INODE_BITMAP_HEADER,
9519           N_("@i @B differences: "),
9520           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9521
9522         /* Inode not used, but marked in bitmap */
9523         { PR_5_INODE_UNUSED,
9524           " -%i",
9525           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9526
9527         /* Inode used, but not marked used in bitmap */
9528         { PR_5_INODE_USED,
9529           " +%i",
9530           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9531
9532         /* Inode bitmap differences end */
9533         { PR_5_INODE_BITMAP_END,
9534           "\n",
9535           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9536
9537         /* Free inodes count for group wrong */
9538         { PR_5_FREE_INODE_COUNT_GROUP,
9539           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9540           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9541
9542         /* Directories count for group wrong */
9543         { PR_5_FREE_DIR_COUNT_GROUP,
9544           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9545           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9546
9547         /* Free inodes count wrong */
9548         { PR_5_FREE_INODE_COUNT,
9549           N_("Free @is count wrong (%i, counted=%j).\n"),
9550           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9551
9552         /* Free blocks count for group wrong */
9553         { PR_5_FREE_BLOCK_COUNT_GROUP,
9554           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9555           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9556
9557         /* Free blocks count wrong */
9558         { PR_5_FREE_BLOCK_COUNT,
9559           N_("Free @bs count wrong (%b, counted=%c).\n"),
9560           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9561
9562         /* Programming error: bitmap endpoints don't match */
9563         { PR_5_BMAP_ENDPOINTS,
9564           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9565           "match calculated @B endpoints (%i, %j)\n"),
9566           PROMPT_NONE, PR_FATAL },
9567
9568         /* Internal error: fudging end of bitmap */
9569         { PR_5_FUDGE_BITMAP_ERROR,
9570           N_("Internal error: fudging end of bitmap (%N)\n"),
9571           PROMPT_NONE, PR_FATAL },
9572
9573         /* Error copying in replacement inode bitmap */
9574         { PR_5_COPY_IBITMAP_ERROR,
9575           N_("Error copying in replacement @i @B: %m\n"),
9576           PROMPT_NONE, PR_FATAL },
9577
9578         /* Error copying in replacement block bitmap */
9579         { PR_5_COPY_BBITMAP_ERROR,
9580           N_("Error copying in replacement @b @B: %m\n"),
9581           PROMPT_NONE, PR_FATAL },
9582
9583         /* Block range not used, but marked in bitmap */
9584         { PR_5_BLOCK_RANGE_UNUSED,
9585           " -(%b--%c)",
9586           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9587
9588         /* Block range used, but not marked used in bitmap */
9589         { PR_5_BLOCK_RANGE_USED,
9590           " +(%b--%c)",
9591           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9592
9593         /* Inode range not used, but marked in bitmap */
9594         { PR_5_INODE_RANGE_UNUSED,
9595           " -(%i--%j)",
9596           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9597
9598         /* Inode range used, but not marked used in bitmap */
9599         { PR_5_INODE_RANGE_USED,
9600           " +(%i--%j)",
9601           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9602
9603         { 0 }
9604 };
9605
9606 /*
9607  * This is the latch flags register.  It allows several problems to be
9608  * "latched" together.  This means that the user has to answer but one
9609  * question for the set of problems, and all of the associated
9610  * problems will be either fixed or not fixed.
9611  */
9612 static struct latch_descr pr_latch_info[] = {
9613         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9614         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9615         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9616         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9617         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9618         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9619         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9620         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9621         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9622         { -1, 0, 0 },
9623 };
9624
9625 static const struct e2fsck_problem *find_problem(problem_t code)
9626 {
9627         int     i;
9628
9629         for (i=0; problem_table[i].e2p_code; i++) {
9630                 if (problem_table[i].e2p_code == code)
9631                         return &problem_table[i];
9632         }
9633         return 0;
9634 }
9635
9636 static struct latch_descr *find_latch(int code)
9637 {
9638         int     i;
9639
9640         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9641                 if (pr_latch_info[i].latch_code == code)
9642                         return &pr_latch_info[i];
9643         }
9644         return 0;
9645 }
9646
9647 int end_problem_latch(e2fsck_t ctx, int mask)
9648 {
9649         struct latch_descr *ldesc;
9650         struct problem_context pctx;
9651         int answer = -1;
9652
9653         ldesc = find_latch(mask);
9654         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9655                 clear_problem_context(&pctx);
9656                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9657         }
9658         ldesc->flags &= ~(PRL_VARIABLE);
9659         return answer;
9660 }
9661
9662 int set_latch_flags(int mask, int setflags, int clearflags)
9663 {
9664         struct latch_descr *ldesc;
9665
9666         ldesc = find_latch(mask);
9667         if (!ldesc)
9668                 return -1;
9669         ldesc->flags |= setflags;
9670         ldesc->flags &= ~clearflags;
9671         return 0;
9672 }
9673
9674 void clear_problem_context(struct problem_context *ctx)
9675 {
9676         memset(ctx, 0, sizeof(struct problem_context));
9677         ctx->blkcount = -1;
9678         ctx->group = -1;
9679 }
9680
9681 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9682 {
9683         ext2_filsys fs = ctx->fs;
9684         const struct e2fsck_problem *ptr;
9685         struct latch_descr *ldesc = 0;
9686         const char *message;
9687         int             def_yn, answer, ans;
9688         int             print_answer = 0;
9689         int             suppress = 0;
9690
9691         ptr = find_problem(code);
9692         if (!ptr) {
9693                 printf(_("Unhandled error code (0x%x)!\n"), code);
9694                 return 0;
9695         }
9696         def_yn = 1;
9697         if ((ptr->flags & PR_NO_DEFAULT) ||
9698             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9699             (ctx->options & E2F_OPT_NO))
9700                 def_yn= 0;
9701
9702         /*
9703          * Do special latch processing.  This is where we ask the
9704          * latch question, if it exists
9705          */
9706         if (ptr->flags & PR_LATCH_MASK) {
9707                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9708                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9709                         ans = fix_problem(ctx, ldesc->question, pctx);
9710                         if (ans == 1)
9711                                 ldesc->flags |= PRL_YES;
9712                         if (ans == 0)
9713                                 ldesc->flags |= PRL_NO;
9714                         ldesc->flags |= PRL_LATCHED;
9715                 }
9716                 if (ldesc->flags & PRL_SUPPRESS)
9717                         suppress++;
9718         }
9719         if ((ptr->flags & PR_PREEN_NOMSG) &&
9720             (ctx->options & E2F_OPT_PREEN))
9721                 suppress++;
9722         if ((ptr->flags & PR_NO_NOMSG) &&
9723             (ctx->options & E2F_OPT_NO))
9724                 suppress++;
9725         if (!suppress) {
9726                 message = ptr->e2p_description;
9727                 if ((ctx->options & E2F_OPT_PREEN) &&
9728                     !(ptr->flags & PR_PREEN_NOHDR)) {
9729                         printf("%s: ", ctx->device_name ?
9730                                ctx->device_name : ctx->filesystem_name);
9731                 }
9732                 if (*message)
9733                         print_e2fsck_message(ctx, _(message), pctx, 1);
9734         }
9735         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9736                 preenhalt(ctx);
9737
9738         if (ptr->flags & PR_FATAL)
9739                 bb_error_msg_and_die(0);
9740
9741         if (ptr->prompt == PROMPT_NONE) {
9742                 if (ptr->flags & PR_NOCOLLATE)
9743                         answer = -1;
9744                 else
9745                         answer = def_yn;
9746         } else {
9747                 if (ctx->options & E2F_OPT_PREEN) {
9748                         answer = def_yn;
9749                         if (!(ptr->flags & PR_PREEN_NOMSG))
9750                                 print_answer = 1;
9751                 } else if ((ptr->flags & PR_LATCH_MASK) &&
9752                            (ldesc->flags & (PRL_YES | PRL_NO))) {
9753                         if (!suppress)
9754                                 print_answer = 1;
9755                         if (ldesc->flags & PRL_YES)
9756                                 answer = 1;
9757                         else
9758                                 answer = 0;
9759                 } else
9760                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9761                 if (!answer && !(ptr->flags & PR_NO_OK))
9762                         ext2fs_unmark_valid(fs);
9763
9764                 if (print_answer)
9765                         printf("%s.\n", answer ?
9766                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9767
9768         }
9769
9770         if ((ptr->prompt == PROMPT_ABORT) && answer)
9771                 bb_error_msg_and_die(0);
9772
9773         if (ptr->flags & PR_AFTER_CODE)
9774                 answer = fix_problem(ctx, ptr->second_code, pctx);
9775
9776         return answer;
9777 }
9778
9779 /*
9780  * linux/fs/recovery.c
9781  *
9782  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9783  */
9784
9785 /*
9786  * Maintain information about the progress of the recovery job, so that
9787  * the different passes can carry information between them.
9788  */
9789 struct recovery_info
9790 {
9791         tid_t           start_transaction;
9792         tid_t           end_transaction;
9793
9794         int             nr_replays;
9795         int             nr_revokes;
9796         int             nr_revoke_hits;
9797 };
9798
9799 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9800 static int do_one_pass(journal_t *journal,
9801                                 struct recovery_info *info, enum passtype pass);
9802 static int scan_revoke_records(journal_t *, struct buffer_head *,
9803                                 tid_t, struct recovery_info *);
9804
9805 /*
9806  * Read a block from the journal
9807  */
9808
9809 static int jread(struct buffer_head **bhp, journal_t *journal,
9810                  unsigned int offset)
9811 {
9812         int err;
9813         unsigned long blocknr;
9814         struct buffer_head *bh;
9815
9816         *bhp = NULL;
9817
9818         err = journal_bmap(journal, offset, &blocknr);
9819
9820         if (err) {
9821                 printf ("JBD: bad block at offset %u\n", offset);
9822                 return err;
9823         }
9824
9825         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9826         if (!bh)
9827                 return -ENOMEM;
9828
9829         if (!buffer_uptodate(bh)) {
9830                 /* If this is a brand new buffer, start readahead.
9831                    Otherwise, we assume we are already reading it.  */
9832                 if (!buffer_req(bh))
9833                         do_readahead(journal, offset);
9834                 wait_on_buffer(bh);
9835         }
9836
9837         if (!buffer_uptodate(bh)) {
9838                 printf ("JBD: Failed to read block at offset %u\n", offset);
9839                 brelse(bh);
9840                 return -EIO;
9841         }
9842
9843         *bhp = bh;
9844         return 0;
9845 }
9846
9847
9848 /*
9849  * Count the number of in-use tags in a journal descriptor block.
9850  */
9851
9852 static int count_tags(struct buffer_head *bh, int size)
9853 {
9854         char *                  tagp;
9855         journal_block_tag_t *   tag;
9856         int                     nr = 0;
9857
9858         tagp = &bh->b_data[sizeof(journal_header_t)];
9859
9860         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9861                 tag = (journal_block_tag_t *) tagp;
9862
9863                 nr++;
9864                 tagp += sizeof(journal_block_tag_t);
9865                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9866                         tagp += 16;
9867
9868                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9869                         break;
9870         }
9871
9872         return nr;
9873 }
9874
9875
9876 /* Make sure we wrap around the log correctly! */
9877 #define wrap(journal, var)                                            \
9878 do {                                                                \
9879         if (var >= (journal)->j_last)                                   \
9880                 var -= ((journal)->j_last - (journal)->j_first);        \
9881 } while (0)
9882
9883 /**
9884  * int journal_recover(journal_t *journal) - recovers a on-disk journal
9885  * @journal: the journal to recover
9886  *
9887  * The primary function for recovering the log contents when mounting a
9888  * journaled device.
9889  *
9890  * Recovery is done in three passes.  In the first pass, we look for the
9891  * end of the log.  In the second, we assemble the list of revoke
9892  * blocks.  In the third and final pass, we replay any un-revoked blocks
9893  * in the log.
9894  */
9895 int journal_recover(journal_t *journal)
9896 {
9897         int                     err;
9898         journal_superblock_t *  sb;
9899
9900         struct recovery_info    info;
9901
9902         memset(&info, 0, sizeof(info));
9903         sb = journal->j_superblock;
9904
9905         /*
9906          * The journal superblock's s_start field (the current log head)
9907          * is always zero if, and only if, the journal was cleanly
9908          * unmounted.
9909          */
9910
9911         if (!sb->s_start) {
9912                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9913                 return 0;
9914         }
9915
9916         err = do_one_pass(journal, &info, PASS_SCAN);
9917         if (!err)
9918                 err = do_one_pass(journal, &info, PASS_REVOKE);
9919         if (!err)
9920                 err = do_one_pass(journal, &info, PASS_REPLAY);
9921
9922         /* Restart the log at the next transaction ID, thus invalidating
9923          * any existing commit records in the log. */
9924         journal->j_transaction_sequence = ++info.end_transaction;
9925
9926         journal_clear_revoke(journal);
9927         sync_blockdev(journal->j_fs_dev);
9928         return err;
9929 }
9930
9931 static int do_one_pass(journal_t *journal,
9932                         struct recovery_info *info, enum passtype pass)
9933 {
9934         unsigned int            first_commit_ID, next_commit_ID;
9935         unsigned long           next_log_block;
9936         int                     err, success = 0;
9937         journal_superblock_t *  sb;
9938         journal_header_t *      tmp;
9939         struct buffer_head *    bh;
9940         unsigned int            sequence;
9941         int                     blocktype;
9942
9943         /* Precompute the maximum metadata descriptors in a descriptor block */
9944         int                     MAX_BLOCKS_PER_DESC;
9945         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9946                                / sizeof(journal_block_tag_t));
9947
9948         /*
9949          * First thing is to establish what we expect to find in the log
9950          * (in terms of transaction IDs), and where (in terms of log
9951          * block offsets): query the superblock.
9952          */
9953
9954         sb = journal->j_superblock;
9955         next_commit_ID = ntohl(sb->s_sequence);
9956         next_log_block = ntohl(sb->s_start);
9957
9958         first_commit_ID = next_commit_ID;
9959         if (pass == PASS_SCAN)
9960                 info->start_transaction = first_commit_ID;
9961
9962         /*
9963          * Now we walk through the log, transaction by transaction,
9964          * making sure that each transaction has a commit block in the
9965          * expected place.  Each complete transaction gets replayed back
9966          * into the main filesystem.
9967          */
9968
9969         while (1) {
9970                 int                     flags;
9971                 char *                  tagp;
9972                 journal_block_tag_t *   tag;
9973                 struct buffer_head *    obh;
9974                 struct buffer_head *    nbh;
9975
9976                 /* If we already know where to stop the log traversal,
9977                  * check right now that we haven't gone past the end of
9978                  * the log. */
9979
9980                 if (pass != PASS_SCAN)
9981                         if (tid_geq(next_commit_ID, info->end_transaction))
9982                                 break;
9983
9984                 /* Skip over each chunk of the transaction looking
9985                  * either the next descriptor block or the final commit
9986                  * record. */
9987
9988                 err = jread(&bh, journal, next_log_block);
9989                 if (err)
9990                         goto failed;
9991
9992                 next_log_block++;
9993                 wrap(journal, next_log_block);
9994
9995                 /* What kind of buffer is it?
9996                  *
9997                  * If it is a descriptor block, check that it has the
9998                  * expected sequence number.  Otherwise, we're all done
9999                  * here. */
10000
10001                 tmp = (journal_header_t *)bh->b_data;
10002
10003                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10004                         brelse(bh);
10005                         break;
10006                 }
10007
10008                 blocktype = ntohl(tmp->h_blocktype);
10009                 sequence = ntohl(tmp->h_sequence);
10010
10011                 if (sequence != next_commit_ID) {
10012                         brelse(bh);
10013                         break;
10014                 }
10015
10016                 /* OK, we have a valid descriptor block which matches
10017                  * all of the sequence number checks.  What are we going
10018                  * to do with it?  That depends on the pass... */
10019
10020                 switch(blocktype) {
10021                 case JFS_DESCRIPTOR_BLOCK:
10022                         /* If it is a valid descriptor block, replay it
10023                          * in pass REPLAY; otherwise, just skip over the
10024                          * blocks it describes. */
10025                         if (pass != PASS_REPLAY) {
10026                                 next_log_block +=
10027                                         count_tags(bh, journal->j_blocksize);
10028                                 wrap(journal, next_log_block);
10029                                 brelse(bh);
10030                                 continue;
10031                         }
10032
10033                         /* A descriptor block: we can now write all of
10034                          * the data blocks.  Yay, useful work is finally
10035                          * getting done here! */
10036
10037                         tagp = &bh->b_data[sizeof(journal_header_t)];
10038                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10039                                <= journal->j_blocksize) {
10040                                 unsigned long io_block;
10041
10042                                 tag = (journal_block_tag_t *) tagp;
10043                                 flags = ntohl(tag->t_flags);
10044
10045                                 io_block = next_log_block++;
10046                                 wrap(journal, next_log_block);
10047                                 err = jread(&obh, journal, io_block);
10048                                 if (err) {
10049                                         /* Recover what we can, but
10050                                          * report failure at the end. */
10051                                         success = err;
10052                                         printf ("JBD: IO error %d recovering "
10053                                                 "block %ld in log\n",
10054                                                 err, io_block);
10055                                 } else {
10056                                         unsigned long blocknr;
10057
10058                                         blocknr = ntohl(tag->t_blocknr);
10059
10060                                         /* If the block has been
10061                                          * revoked, then we're all done
10062                                          * here. */
10063                                         if (journal_test_revoke
10064                                             (journal, blocknr,
10065                                              next_commit_ID)) {
10066                                                 brelse(obh);
10067                                                 ++info->nr_revoke_hits;
10068                                                 goto skip_write;
10069                                         }
10070
10071                                         /* Find a buffer for the new
10072                                          * data being restored */
10073                                         nbh = getblk(journal->j_fs_dev,
10074                                                        blocknr,
10075                                                      journal->j_blocksize);
10076                                         if (nbh == NULL) {
10077                                                 printf ("JBD: Out of memory "
10078                                                        "during recovery.\n");
10079                                                 err = -ENOMEM;
10080                                                 brelse(bh);
10081                                                 brelse(obh);
10082                                                 goto failed;
10083                                         }
10084
10085                                         lock_buffer(nbh);
10086                                         memcpy(nbh->b_data, obh->b_data,
10087                                                         journal->j_blocksize);
10088                                         if (flags & JFS_FLAG_ESCAPE) {
10089                                                 *((unsigned int *)bh->b_data) =
10090                                                         htonl(JFS_MAGIC_NUMBER);
10091                                         }
10092
10093                                         mark_buffer_uptodate(nbh, 1);
10094                                         mark_buffer_dirty(nbh);
10095                                         ++info->nr_replays;
10096                                         /* ll_rw_block(WRITE, 1, &nbh); */
10097                                         unlock_buffer(nbh);
10098                                         brelse(obh);
10099                                         brelse(nbh);
10100                                 }
10101
10102                         skip_write:
10103                                 tagp += sizeof(journal_block_tag_t);
10104                                 if (!(flags & JFS_FLAG_SAME_UUID))
10105                                         tagp += 16;
10106
10107                                 if (flags & JFS_FLAG_LAST_TAG)
10108                                         break;
10109                         }
10110
10111                         brelse(bh);
10112                         continue;
10113
10114                 case JFS_COMMIT_BLOCK:
10115                         /* Found an expected commit block: not much to
10116                          * do other than move on to the next sequence
10117                          * number. */
10118                         brelse(bh);
10119                         next_commit_ID++;
10120                         continue;
10121
10122                 case JFS_REVOKE_BLOCK:
10123                         /* If we aren't in the REVOKE pass, then we can
10124                          * just skip over this block. */
10125                         if (pass != PASS_REVOKE) {
10126                                 brelse(bh);
10127                                 continue;
10128                         }
10129
10130                         err = scan_revoke_records(journal, bh,
10131                                                   next_commit_ID, info);
10132                         brelse(bh);
10133                         if (err)
10134                                 goto failed;
10135                         continue;
10136
10137                 default:
10138                         goto done;
10139                 }
10140         }
10141
10142  done:
10143         /*
10144          * We broke out of the log scan loop: either we came to the
10145          * known end of the log or we found an unexpected block in the
10146          * log.  If the latter happened, then we know that the "current"
10147          * transaction marks the end of the valid log.
10148          */
10149
10150         if (pass == PASS_SCAN)
10151                 info->end_transaction = next_commit_ID;
10152         else {
10153                 /* It's really bad news if different passes end up at
10154                  * different places (but possible due to IO errors). */
10155                 if (info->end_transaction != next_commit_ID) {
10156                         printf ("JBD: recovery pass %d ended at "
10157                                 "transaction %u, expected %u\n",
10158                                 pass, next_commit_ID, info->end_transaction);
10159                         if (!success)
10160                                 success = -EIO;
10161                 }
10162         }
10163
10164         return success;
10165
10166  failed:
10167         return err;
10168 }
10169
10170
10171 /* Scan a revoke record, marking all blocks mentioned as revoked. */
10172
10173 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10174                                tid_t sequence, struct recovery_info *info)
10175 {
10176         journal_revoke_header_t *header;
10177         int offset, max;
10178
10179         header = (journal_revoke_header_t *) bh->b_data;
10180         offset = sizeof(journal_revoke_header_t);
10181         max = ntohl(header->r_count);
10182
10183         while (offset < max) {
10184                 unsigned long blocknr;
10185                 int err;
10186
10187                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10188                 offset += 4;
10189                 err = journal_set_revoke(journal, blocknr, sequence);
10190                 if (err)
10191                         return err;
10192                 ++info->nr_revokes;
10193         }
10194         return 0;
10195 }
10196
10197
10198 /*
10199  * rehash.c --- rebuild hash tree directories
10200  *
10201  * This algorithm is designed for simplicity of implementation and to
10202  * pack the directory as much as possible.  It however requires twice
10203  * as much memory as the size of the directory.  The maximum size
10204  * directory supported using a 4k blocksize is roughly a gigabyte, and
10205  * so there may very well be problems with machines that don't have
10206  * virtual memory, and obscenely large directories.
10207  *
10208  * An alternate algorithm which is much more disk intensive could be
10209  * written, and probably will need to be written in the future.  The
10210  * design goals of such an algorithm are: (a) use (roughly) constant
10211  * amounts of memory, no matter how large the directory, (b) the
10212  * directory must be safe at all times, even if e2fsck is interrupted
10213  * in the middle, (c) we must use minimal amounts of extra disk
10214  * blocks.  This pretty much requires an incremental approach, where
10215  * we are reading from one part of the directory, and inserting into
10216  * the front half.  So the algorithm will have to keep track of a
10217  * moving block boundary between the new tree and the old tree, and
10218  * files will need to be moved from the old directory and inserted
10219  * into the new tree.  If the new directory requires space which isn't
10220  * yet available, blocks from the beginning part of the old directory
10221  * may need to be moved to the end of the directory to make room for
10222  * the new tree:
10223  *
10224  *    --------------------------------------------------------
10225  *    |  new tree   |        | old tree                      |
10226  *    --------------------------------------------------------
10227  *                  ^ ptr    ^ptr
10228  *                tail new   head old
10229  *
10230  * This is going to be a pain in the tuckus to implement, and will
10231  * require a lot more disk accesses.  So I'm going to skip it for now;
10232  * it's only really going to be an issue for really, really big
10233  * filesystems (when we reach the level of tens of millions of files
10234  * in a single directory).  It will probably be easier to simply
10235  * require that e2fsck use VM first.
10236  */
10237
10238 struct fill_dir_struct {
10239         char *buf;
10240         struct ext2_inode *inode;
10241         int err;
10242         e2fsck_t ctx;
10243         struct hash_entry *harray;
10244         int max_array, num_array;
10245         int dir_size;
10246         int compress;
10247         ino_t parent;
10248 };
10249
10250 struct hash_entry {
10251         ext2_dirhash_t  hash;
10252         ext2_dirhash_t  minor_hash;
10253         struct ext2_dir_entry   *dir;
10254 };
10255
10256 struct out_dir {
10257         int             num;
10258         int             max;
10259         char            *buf;
10260         ext2_dirhash_t  *hashes;
10261 };
10262
10263 static int fill_dir_block(ext2_filsys fs,
10264                           blk_t *block_nr,
10265                           e2_blkcnt_t blockcnt,
10266                           blk_t ref_block FSCK_ATTR((unused)),
10267                           int ref_offset FSCK_ATTR((unused)),
10268                           void *priv_data)
10269 {
10270         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10271         struct hash_entry       *new_array, *ent;
10272         struct ext2_dir_entry   *dirent;
10273         char                    *dir;
10274         unsigned int            offset, dir_offset;
10275
10276         if (blockcnt < 0)
10277                 return 0;
10278
10279         offset = blockcnt * fs->blocksize;
10280         if (offset + fs->blocksize > fd->inode->i_size) {
10281                 fd->err = EXT2_ET_DIR_CORRUPTED;
10282                 return BLOCK_ABORT;
10283         }
10284         dir = (fd->buf+offset);
10285         if (HOLE_BLKADDR(*block_nr)) {
10286                 memset(dir, 0, fs->blocksize);
10287                 dirent = (struct ext2_dir_entry *) dir;
10288                 dirent->rec_len = fs->blocksize;
10289         } else {
10290                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10291                 if (fd->err)
10292                         return BLOCK_ABORT;
10293         }
10294         /* While the directory block is "hot", index it. */
10295         dir_offset = 0;
10296         while (dir_offset < fs->blocksize) {
10297                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10298                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10299                     (dirent->rec_len < 8) ||
10300                     ((dirent->rec_len % 4) != 0) ||
10301                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10302                         fd->err = EXT2_ET_DIR_CORRUPTED;
10303                         return BLOCK_ABORT;
10304                 }
10305                 dir_offset += dirent->rec_len;
10306                 if (dirent->inode == 0)
10307                         continue;
10308                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10309                     (dirent->name[0] == '.'))
10310                         continue;
10311                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10312                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10313                         fd->parent = dirent->inode;
10314                         continue;
10315                 }
10316                 if (fd->num_array >= fd->max_array) {
10317                         new_array = realloc(fd->harray,
10318                             sizeof(struct hash_entry) * (fd->max_array+500));
10319                         if (!new_array) {
10320                                 fd->err = ENOMEM;
10321                                 return BLOCK_ABORT;
10322                         }
10323                         fd->harray = new_array;
10324                         fd->max_array += 500;
10325                 }
10326                 ent = fd->harray + fd->num_array++;
10327                 ent->dir = dirent;
10328                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10329                 if (fd->compress)
10330                         ent->hash = ent->minor_hash = 0;
10331                 else {
10332                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10333                                                  dirent->name,
10334                                                  dirent->name_len & 0xFF,
10335                                                  fs->super->s_hash_seed,
10336                                                  &ent->hash, &ent->minor_hash);
10337                         if (fd->err)
10338                                 return BLOCK_ABORT;
10339                 }
10340         }
10341
10342         return 0;
10343 }
10344
10345 /* Used for sorting the hash entry */
10346 static int name_cmp(const void *a, const void *b)
10347 {
10348         const struct hash_entry *he_a = (const struct hash_entry *) a;
10349         const struct hash_entry *he_b = (const struct hash_entry *) b;
10350         int     ret;
10351         int     min_len;
10352
10353         min_len = he_a->dir->name_len;
10354         if (min_len > he_b->dir->name_len)
10355                 min_len = he_b->dir->name_len;
10356
10357         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10358         if (ret == 0) {
10359                 if (he_a->dir->name_len > he_b->dir->name_len)
10360                         ret = 1;
10361                 else if (he_a->dir->name_len < he_b->dir->name_len)
10362                         ret = -1;
10363                 else
10364                         ret = he_b->dir->inode - he_a->dir->inode;
10365         }
10366         return ret;
10367 }
10368
10369 /* Used for sorting the hash entry */
10370 static int hash_cmp(const void *a, const void *b)
10371 {
10372         const struct hash_entry *he_a = (const struct hash_entry *) a;
10373         const struct hash_entry *he_b = (const struct hash_entry *) b;
10374         int     ret;
10375
10376         if (he_a->hash > he_b->hash)
10377                 ret = 1;
10378         else if (he_a->hash < he_b->hash)
10379                 ret = -1;
10380         else {
10381                 if (he_a->minor_hash > he_b->minor_hash)
10382                         ret = 1;
10383                 else if (he_a->minor_hash < he_b->minor_hash)
10384                         ret = -1;
10385                 else
10386                         ret = name_cmp(a, b);
10387         }
10388         return ret;
10389 }
10390
10391 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10392                                 int blocks)
10393 {
10394         void                    *new_mem;
10395
10396         if (outdir->max) {
10397                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
10398                 if (!new_mem)
10399                         return ENOMEM;
10400                 outdir->buf = new_mem;
10401                 new_mem = realloc(outdir->hashes,
10402                                   blocks * sizeof(ext2_dirhash_t));
10403                 if (!new_mem)
10404                         return ENOMEM;
10405                 outdir->hashes = new_mem;
10406         } else {
10407                 outdir->buf = malloc(blocks * fs->blocksize);
10408                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
10409                 outdir->num = 0;
10410         }
10411         outdir->max = blocks;
10412         return 0;
10413 }
10414
10415 static void free_out_dir(struct out_dir *outdir)
10416 {
10417         free(outdir->buf);
10418         free(outdir->hashes);
10419         outdir->max = 0;
10420         outdir->num =0;
10421 }
10422
10423 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10424                          char ** ret)
10425 {
10426         errcode_t       retval;
10427
10428         if (outdir->num >= outdir->max) {
10429                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10430                 if (retval)
10431                         return retval;
10432         }
10433         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10434         memset(*ret, 0, fs->blocksize);
10435         return 0;
10436 }
10437
10438 /*
10439  * This function is used to make a unique filename.  We do this by
10440  * appending ~0, and then incrementing the number.  However, we cannot
10441  * expand the length of the filename beyond the padding available in
10442  * the directory entry.
10443  */
10444 static void mutate_name(char *str, __u16 *len)
10445 {
10446         int     i;
10447         __u16   l = *len & 0xFF, h = *len & 0xff00;
10448
10449         /*
10450          * First check to see if it looks the name has been mutated
10451          * already
10452          */
10453         for (i = l-1; i > 0; i--) {
10454                 if (!isdigit(str[i]))
10455                         break;
10456         }
10457         if ((i == l-1) || (str[i] != '~')) {
10458                 if (((l-1) & 3) < 2)
10459                         l += 2;
10460                 else
10461                         l = (l+3) & ~3;
10462                 str[l-2] = '~';
10463                 str[l-1] = '0';
10464                 *len = l | h;
10465                 return;
10466         }
10467         for (i = l-1; i >= 0; i--) {
10468                 if (isdigit(str[i])) {
10469                         if (str[i] == '9')
10470                                 str[i] = '0';
10471                         else {
10472                                 str[i]++;
10473                                 return;
10474                         }
10475                         continue;
10476                 }
10477                 if (i == 1) {
10478                         if (str[0] == 'z')
10479                                 str[0] = 'A';
10480                         else if (str[0] == 'Z') {
10481                                 str[0] = '~';
10482                                 str[1] = '0';
10483                         } else
10484                                 str[0]++;
10485                 } else if (i > 0) {
10486                         str[i] = '1';
10487                         str[i-1] = '~';
10488                 } else {
10489                         if (str[0] == '~')
10490                                 str[0] = 'a';
10491                         else
10492                                 str[0]++;
10493                 }
10494                 break;
10495         }
10496 }
10497
10498 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10499                                     ext2_ino_t ino,
10500                                     struct fill_dir_struct *fd)
10501 {
10502         struct problem_context  pctx;
10503         struct hash_entry       *ent, *prev;
10504         int                     i, j;
10505         int                     fixed = 0;
10506         char                    new_name[256];
10507         __u16                   new_len;
10508
10509         clear_problem_context(&pctx);
10510         pctx.ino = ino;
10511
10512         for (i=1; i < fd->num_array; i++) {
10513                 ent = fd->harray + i;
10514                 prev = ent - 1;
10515                 if (!ent->dir->inode ||
10516                     ((ent->dir->name_len & 0xFF) !=
10517                      (prev->dir->name_len & 0xFF)) ||
10518                     (strncmp(ent->dir->name, prev->dir->name,
10519                              ent->dir->name_len & 0xFF)))
10520                         continue;
10521                 pctx.dirent = ent->dir;
10522                 if ((ent->dir->inode == prev->dir->inode) &&
10523                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10524                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10525                         ent->dir->inode = 0;
10526                         fixed++;
10527                         continue;
10528                 }
10529                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10530                 new_len = ent->dir->name_len;
10531                 mutate_name(new_name, &new_len);
10532                 for (j=0; j < fd->num_array; j++) {
10533                         if ((i==j) ||
10534                             ((ent->dir->name_len & 0xFF) !=
10535                              (fd->harray[j].dir->name_len & 0xFF)) ||
10536                             (strncmp(new_name, fd->harray[j].dir->name,
10537                                      new_len & 0xFF)))
10538                                 continue;
10539                         mutate_name(new_name, &new_len);
10540
10541                         j = -1;
10542                 }
10543                 new_name[new_len & 0xFF] = 0;
10544                 pctx.str = new_name;
10545                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10546                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
10547                         ent->dir->name_len = new_len;
10548                         ext2fs_dirhash(fs->super->s_def_hash_version,
10549                                        ent->dir->name,
10550                                        ent->dir->name_len & 0xFF,
10551                                        fs->super->s_hash_seed,
10552                                        &ent->hash, &ent->minor_hash);
10553                         fixed++;
10554                 }
10555         }
10556         return fixed;
10557 }
10558
10559
10560 static errcode_t copy_dir_entries(ext2_filsys fs,
10561                                   struct fill_dir_struct *fd,
10562                                   struct out_dir *outdir)
10563 {
10564         errcode_t               retval;
10565         char                    *block_start;
10566         struct hash_entry       *ent;
10567         struct ext2_dir_entry   *dirent;
10568         int                     i, rec_len, left;
10569         ext2_dirhash_t          prev_hash;
10570         int                     offset;
10571
10572         outdir->max = 0;
10573         retval = alloc_size_dir(fs, outdir,
10574                                 (fd->dir_size / fs->blocksize) + 2);
10575         if (retval)
10576                 return retval;
10577         outdir->num = fd->compress ? 0 : 1;
10578         offset = 0;
10579         outdir->hashes[0] = 0;
10580         prev_hash = 1;
10581         if ((retval = get_next_block(fs, outdir, &block_start)))
10582                 return retval;
10583         dirent = (struct ext2_dir_entry *) block_start;
10584         left = fs->blocksize;
10585         for (i=0; i < fd->num_array; i++) {
10586                 ent = fd->harray + i;
10587                 if (ent->dir->inode == 0)
10588                         continue;
10589                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10590                 if (rec_len > left) {
10591                         if (left)
10592                                 dirent->rec_len += left;
10593                         if ((retval = get_next_block(fs, outdir,
10594                                                       &block_start)))
10595                                 return retval;
10596                         offset = 0;
10597                 }
10598                 left = fs->blocksize - offset;
10599                 dirent = (struct ext2_dir_entry *) (block_start + offset);
10600                 if (offset == 0) {
10601                         if (ent->hash == prev_hash)
10602                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
10603                         else
10604                                 outdir->hashes[outdir->num-1] = ent->hash;
10605                 }
10606                 dirent->inode = ent->dir->inode;
10607                 dirent->name_len = ent->dir->name_len;
10608                 dirent->rec_len = rec_len;
10609                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10610                 offset += rec_len;
10611                 left -= rec_len;
10612                 if (left < 12) {
10613                         dirent->rec_len += left;
10614                         offset += left;
10615                         left = 0;
10616                 }
10617                 prev_hash = ent->hash;
10618         }
10619         if (left)
10620                 dirent->rec_len += left;
10621
10622         return 0;
10623 }
10624
10625
10626 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10627                                     ext2_ino_t ino, ext2_ino_t parent)
10628 {
10629         struct ext2_dir_entry           *dir;
10630         struct ext2_dx_root_info        *root;
10631         struct ext2_dx_countlimit       *limits;
10632         int                             filetype = 0;
10633
10634         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10635                 filetype = EXT2_FT_DIR << 8;
10636
10637         memset(buf, 0, fs->blocksize);
10638         dir = (struct ext2_dir_entry *) buf;
10639         dir->inode = ino;
10640         dir->name[0] = '.';
10641         dir->name_len = 1 | filetype;
10642         dir->rec_len = 12;
10643         dir = (struct ext2_dir_entry *) (buf + 12);
10644         dir->inode = parent;
10645         dir->name[0] = '.';
10646         dir->name[1] = '.';
10647         dir->name_len = 2 | filetype;
10648         dir->rec_len = fs->blocksize - 12;
10649
10650         root = (struct ext2_dx_root_info *) (buf+24);
10651         root->reserved_zero = 0;
10652         root->hash_version = fs->super->s_def_hash_version;
10653         root->info_length = 8;
10654         root->indirect_levels = 0;
10655         root->unused_flags = 0;
10656
10657         limits = (struct ext2_dx_countlimit *) (buf+32);
10658         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10659         limits->count = 0;
10660
10661         return root;
10662 }
10663
10664
10665 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10666 {
10667         struct ext2_dir_entry           *dir;
10668         struct ext2_dx_countlimit       *limits;
10669
10670         memset(buf, 0, fs->blocksize);
10671         dir = (struct ext2_dir_entry *) buf;
10672         dir->inode = 0;
10673         dir->rec_len = fs->blocksize;
10674
10675         limits = (struct ext2_dx_countlimit *) (buf+8);
10676         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10677         limits->count = 0;
10678
10679         return (struct ext2_dx_entry *) limits;
10680 }
10681
10682 /*
10683  * This function takes the leaf nodes which have been written in
10684  * outdir, and populates the root node and any necessary interior nodes.
10685  */
10686 static errcode_t calculate_tree(ext2_filsys fs,
10687                                 struct out_dir *outdir,
10688                                 ext2_ino_t ino,
10689                                 ext2_ino_t parent)
10690 {
10691         struct ext2_dx_root_info        *root_info;
10692         struct ext2_dx_entry            *root, *dx_ent = 0;
10693         struct ext2_dx_countlimit       *root_limit, *limit;
10694         errcode_t                       retval;
10695         char                            * block_start;
10696         int                             i, c1, c2, nblks;
10697         int                             limit_offset, root_offset;
10698
10699         root_info = set_root_node(fs, outdir->buf, ino, parent);
10700         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10701                 root_info->info_length;
10702         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10703         c1 = root_limit->limit;
10704         nblks = outdir->num;
10705
10706         /* Write out the pointer blocks */
10707         if (nblks-1 <= c1) {
10708                 /* Just write out the root block, and we're done */
10709                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10710                 for (i=1; i < nblks; i++) {
10711                         root->block = ext2fs_cpu_to_le32(i);
10712                         if (i != 1)
10713                                 root->hash =
10714                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10715                         root++;
10716                         c1--;
10717                 }
10718         } else {
10719                 c2 = 0;
10720                 limit = 0;
10721                 root_info->indirect_levels = 1;
10722                 for (i=1; i < nblks; i++) {
10723                         if (c1 == 0)
10724                                 return ENOSPC;
10725                         if (c2 == 0) {
10726                                 if (limit)
10727                                         limit->limit = limit->count =
10728                 ext2fs_cpu_to_le16(limit->limit);
10729                                 root = (struct ext2_dx_entry *)
10730                                         (outdir->buf + root_offset);
10731                                 root->block = ext2fs_cpu_to_le32(outdir->num);
10732                                 if (i != 1)
10733                                         root->hash =
10734                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10735                                 if ((retval =  get_next_block(fs, outdir,
10736                                                               &block_start)))
10737                                         return retval;
10738                                 dx_ent = set_int_node(fs, block_start);
10739                                 limit = (struct ext2_dx_countlimit *) dx_ent;
10740                                 c2 = limit->limit;
10741                                 root_offset += sizeof(struct ext2_dx_entry);
10742                                 c1--;
10743                         }
10744                         dx_ent->block = ext2fs_cpu_to_le32(i);
10745                         if (c2 != limit->limit)
10746                                 dx_ent->hash =
10747                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
10748                         dx_ent++;
10749                         c2--;
10750                 }
10751                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10752                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10753         }
10754         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10755         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10756         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10757
10758         return 0;
10759 }
10760
10761 struct write_dir_struct {
10762         struct out_dir *outdir;
10763         errcode_t       err;
10764         e2fsck_t        ctx;
10765         int             cleared;
10766 };
10767
10768 /*
10769  * Helper function which writes out a directory block.
10770  */
10771 static int write_dir_block(ext2_filsys fs,
10772                            blk_t        *block_nr,
10773                            e2_blkcnt_t blockcnt,
10774                            blk_t ref_block FSCK_ATTR((unused)),
10775                            int ref_offset FSCK_ATTR((unused)),
10776                            void *priv_data)
10777 {
10778         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10779         blk_t   blk;
10780         char    *dir;
10781
10782         if (*block_nr == 0)
10783                 return 0;
10784         if (blockcnt >= wd->outdir->num) {
10785                 e2fsck_read_bitmaps(wd->ctx);
10786                 blk = *block_nr;
10787                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10788                 ext2fs_block_alloc_stats(fs, blk, -1);
10789                 *block_nr = 0;
10790                 wd->cleared++;
10791                 return BLOCK_CHANGED;
10792         }
10793         if (blockcnt < 0)
10794                 return 0;
10795
10796         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10797         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10798         if (wd->err)
10799                 return BLOCK_ABORT;
10800         return 0;
10801 }
10802
10803 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10804                                  struct out_dir *outdir,
10805                                  ext2_ino_t ino, int compress)
10806 {
10807         struct write_dir_struct wd;
10808         errcode_t       retval;
10809         struct ext2_inode       inode;
10810
10811         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10812         if (retval)
10813                 return retval;
10814
10815         wd.outdir = outdir;
10816         wd.err = 0;
10817         wd.ctx = ctx;
10818         wd.cleared = 0;
10819
10820         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10821                                        write_dir_block, &wd);
10822         if (retval)
10823                 return retval;
10824         if (wd.err)
10825                 return wd.err;
10826
10827         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10828         if (compress)
10829                 inode.i_flags &= ~EXT2_INDEX_FL;
10830         else
10831                 inode.i_flags |= EXT2_INDEX_FL;
10832         inode.i_size = outdir->num * fs->blocksize;
10833         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10834         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10835
10836         return 0;
10837 }
10838
10839 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10840 {
10841         ext2_filsys             fs = ctx->fs;
10842         errcode_t               retval;
10843         struct ext2_inode       inode;
10844         char                    *dir_buf = 0;
10845         struct fill_dir_struct  fd;
10846         struct out_dir          outdir;
10847
10848         outdir.max = outdir.num = 0;
10849         outdir.buf = 0;
10850         outdir.hashes = 0;
10851         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10852
10853         retval = ENOMEM;
10854         fd.harray = 0;
10855         dir_buf = malloc(inode.i_size);
10856         if (!dir_buf)
10857                 goto errout;
10858
10859         fd.max_array = inode.i_size / 32;
10860         fd.num_array = 0;
10861         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
10862         if (!fd.harray)
10863                 goto errout;
10864
10865         fd.ctx = ctx;
10866         fd.buf = dir_buf;
10867         fd.inode = &inode;
10868         fd.err = 0;
10869         fd.dir_size = 0;
10870         fd.compress = 0;
10871         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10872             (inode.i_size / fs->blocksize) < 2)
10873                 fd.compress = 1;
10874         fd.parent = 0;
10875
10876         /* Read in the entire directory into memory */
10877         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10878                                        fill_dir_block, &fd);
10879         if (fd.err) {
10880                 retval = fd.err;
10881                 goto errout;
10882         }
10883
10884         /* Sort the list */
10885 resort:
10886         if (fd.compress)
10887                 qsort(fd.harray+2, fd.num_array-2,
10888                       sizeof(struct hash_entry), name_cmp);
10889         else
10890                 qsort(fd.harray, fd.num_array,
10891                       sizeof(struct hash_entry), hash_cmp);
10892
10893         /*
10894          * Look for duplicates
10895          */
10896         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10897                 goto resort;
10898
10899         if (ctx->options & E2F_OPT_NO) {
10900                 retval = 0;
10901                 goto errout;
10902         }
10903
10904         /*
10905          * Copy the directory entries.  In a htree directory these
10906          * will become the leaf nodes.
10907          */
10908         retval = copy_dir_entries(fs, &fd, &outdir);
10909         if (retval)
10910                 goto errout;
10911
10912         free(dir_buf); dir_buf = 0;
10913
10914         if (!fd.compress) {
10915                 /* Calculate the interior nodes */
10916                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10917                 if (retval)
10918                         goto errout;
10919         }
10920
10921         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10922
10923 errout:
10924         free(dir_buf);
10925         free(fd.harray);
10926
10927         free_out_dir(&outdir);
10928         return retval;
10929 }
10930
10931 void e2fsck_rehash_directories(e2fsck_t ctx)
10932 {
10933         struct problem_context  pctx;
10934         struct dir_info         *dir;
10935         ext2_u32_iterate        iter;
10936         ext2_ino_t              ino;
10937         errcode_t               retval;
10938         int                     i, cur, max, all_dirs, dir_index, first = 1;
10939
10940         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10941
10942         if (!ctx->dirs_to_hash && !all_dirs)
10943                 return;
10944
10945         e2fsck_get_lost_and_found(ctx, 0);
10946
10947         clear_problem_context(&pctx);
10948
10949         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10950         cur = 0;
10951         if (all_dirs) {
10952                 i = 0;
10953                 max = e2fsck_get_num_dirinfo(ctx);
10954         } else {
10955                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10956                                                        &iter);
10957                 if (retval) {
10958                         pctx.errcode = retval;
10959                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10960                         return;
10961                 }
10962                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10963         }
10964         while (1) {
10965                 if (all_dirs) {
10966                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10967                                 break;
10968                         ino = dir->ino;
10969                 } else {
10970                         if (!ext2fs_u32_list_iterate(iter, &ino))
10971                                 break;
10972                 }
10973                 if (ino == ctx->lost_and_found)
10974                         continue;
10975                 pctx.dir = ino;
10976                 if (first) {
10977                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10978                         first = 0;
10979                 }
10980                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10981                 if (pctx.errcode) {
10982                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10983                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10984                 }
10985                 if (ctx->progress && !ctx->progress_fd)
10986                         e2fsck_simple_progress(ctx, "Rebuilding directory",
10987                                100.0 * (float) (++cur) / (float) max, ino);
10988         }
10989         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10990         if (!all_dirs)
10991                 ext2fs_u32_list_iterate_end(iter);
10992
10993         ext2fs_u32_list_free(ctx->dirs_to_hash);
10994         ctx->dirs_to_hash = 0;
10995 }
10996
10997 /*
10998  * linux/fs/revoke.c
10999  *
11000  * Journal revoke routines for the generic filesystem journaling code;
11001  * part of the ext2fs journaling system.
11002  *
11003  * Revoke is the mechanism used to prevent old log records for deleted
11004  * metadata from being replayed on top of newer data using the same
11005  * blocks.  The revoke mechanism is used in two separate places:
11006  *
11007  * + Commit: during commit we write the entire list of the current
11008  *   transaction's revoked blocks to the journal
11009  *
11010  * + Recovery: during recovery we record the transaction ID of all
11011  *   revoked blocks.  If there are multiple revoke records in the log
11012  *   for a single block, only the last one counts, and if there is a log
11013  *   entry for a block beyond the last revoke, then that log entry still
11014  *   gets replayed.
11015  *
11016  * We can get interactions between revokes and new log data within a
11017  * single transaction:
11018  *
11019  * Block is revoked and then journaled:
11020  *   The desired end result is the journaling of the new block, so we
11021  *   cancel the revoke before the transaction commits.
11022  *
11023  * Block is journaled and then revoked:
11024  *   The revoke must take precedence over the write of the block, so we
11025  *   need either to cancel the journal entry or to write the revoke
11026  *   later in the log than the log block.  In this case, we choose the
11027  *   latter: journaling a block cancels any revoke record for that block
11028  *   in the current transaction, so any revoke for that block in the
11029  *   transaction must have happened after the block was journaled and so
11030  *   the revoke must take precedence.
11031  *
11032  * Block is revoked and then written as data:
11033  *   The data write is allowed to succeed, but the revoke is _not_
11034  *   cancelled.  We still need to prevent old log records from
11035  *   overwriting the new data.  We don't even need to clear the revoke
11036  *   bit here.
11037  *
11038  * Revoke information on buffers is a tri-state value:
11039  *
11040  * RevokeValid clear:   no cached revoke status, need to look it up
11041  * RevokeValid set, Revoked clear:
11042  *                      buffer has not been revoked, and cancel_revoke
11043  *                      need do nothing.
11044  * RevokeValid set, Revoked set:
11045  *                      buffer has been revoked.
11046  */
11047
11048 static kmem_cache_t *revoke_record_cache;
11049 static kmem_cache_t *revoke_table_cache;
11050
11051 /* Each revoke record represents one single revoked block.  During
11052    journal replay, this involves recording the transaction ID of the
11053    last transaction to revoke this block. */
11054
11055 struct jbd_revoke_record_s
11056 {
11057         struct list_head  hash;
11058         tid_t             sequence;     /* Used for recovery only */
11059         unsigned long     blocknr;
11060 };
11061
11062
11063 /* The revoke table is just a simple hash table of revoke records. */
11064 struct jbd_revoke_table_s
11065 {
11066         /* It is conceivable that we might want a larger hash table
11067          * for recovery.  Must be a power of two. */
11068         int               hash_size;
11069         int               hash_shift;
11070         struct list_head *hash_table;
11071 };
11072
11073
11074 /* Utility functions to maintain the revoke table */
11075
11076 /* Borrowed from buffer.c: this is a tried and tested block hash function */
11077 static int hash(journal_t *journal, unsigned long block)
11078 {
11079         struct jbd_revoke_table_s *table = journal->j_revoke;
11080         int hash_shift = table->hash_shift;
11081
11082         return ((block << (hash_shift - 6)) ^
11083                 (block >> 13) ^
11084                 (block << (hash_shift - 12))) & (table->hash_size - 1);
11085 }
11086
11087 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11088                               tid_t seq)
11089 {
11090         struct list_head *hash_list;
11091         struct jbd_revoke_record_s *record;
11092
11093         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11094         if (!record)
11095                 goto oom;
11096
11097         record->sequence = seq;
11098         record->blocknr = blocknr;
11099         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11100         list_add(&record->hash, hash_list);
11101         return 0;
11102
11103 oom:
11104         return -ENOMEM;
11105 }
11106
11107 /* Find a revoke record in the journal's hash table. */
11108
11109 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11110                                                       unsigned long blocknr)
11111 {
11112         struct list_head *hash_list;
11113         struct jbd_revoke_record_s *record;
11114
11115         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11116
11117         record = (struct jbd_revoke_record_s *) hash_list->next;
11118         while (&(record->hash) != hash_list) {
11119                 if (record->blocknr == blocknr)
11120                         return record;
11121                 record = (struct jbd_revoke_record_s *) record->hash.next;
11122         }
11123         return NULL;
11124 }
11125
11126 int journal_init_revoke_caches(void)
11127 {
11128         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11129         if (revoke_record_cache == 0)
11130                 return -ENOMEM;
11131
11132         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11133         if (revoke_table_cache == 0) {
11134                 do_cache_destroy(revoke_record_cache);
11135                 revoke_record_cache = NULL;
11136                 return -ENOMEM;
11137         }
11138         return 0;
11139 }
11140
11141 void journal_destroy_revoke_caches(void)
11142 {
11143         do_cache_destroy(revoke_record_cache);
11144         revoke_record_cache = 0;
11145         do_cache_destroy(revoke_table_cache);
11146         revoke_table_cache = 0;
11147 }
11148
11149 /* Initialise the revoke table for a given journal to a given size. */
11150
11151 int journal_init_revoke(journal_t *journal, int hash_size)
11152 {
11153         int shift, tmp;
11154
11155         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11156         if (!journal->j_revoke)
11157                 return -ENOMEM;
11158
11159         /* Check that the hash_size is a power of two */
11160         journal->j_revoke->hash_size = hash_size;
11161
11162         shift = 0;
11163         tmp = hash_size;
11164         while((tmp >>= 1UL) != 0UL)
11165                 shift++;
11166         journal->j_revoke->hash_shift = shift;
11167
11168         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
11169         if (!journal->j_revoke->hash_table) {
11170                 free(journal->j_revoke);
11171                 journal->j_revoke = NULL;
11172                 return -ENOMEM;
11173         }
11174
11175         for (tmp = 0; tmp < hash_size; tmp++)
11176                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11177
11178         return 0;
11179 }
11180
11181 /* Destoy a journal's revoke table.  The table must already be empty! */
11182
11183 void journal_destroy_revoke(journal_t *journal)
11184 {
11185         struct jbd_revoke_table_s *table;
11186         struct list_head *hash_list;
11187         int i;
11188
11189         table = journal->j_revoke;
11190         if (!table)
11191                 return;
11192
11193         for (i=0; i<table->hash_size; i++) {
11194                 hash_list = &table->hash_table[i];
11195         }
11196
11197         free(table->hash_table);
11198         free(table);
11199         journal->j_revoke = NULL;
11200 }
11201
11202 /*
11203  * Revoke support for recovery.
11204  *
11205  * Recovery needs to be able to:
11206  *
11207  *  record all revoke records, including the tid of the latest instance
11208  *  of each revoke in the journal
11209  *
11210  *  check whether a given block in a given transaction should be replayed
11211  *  (ie. has not been revoked by a revoke record in that or a subsequent
11212  *  transaction)
11213  *
11214  *  empty the revoke table after recovery.
11215  */
11216
11217 /*
11218  * First, setting revoke records.  We create a new revoke record for
11219  * every block ever revoked in the log as we scan it for recovery, and
11220  * we update the existing records if we find multiple revokes for a
11221  * single block.
11222  */
11223
11224 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11225                        tid_t sequence)
11226 {
11227         struct jbd_revoke_record_s *record;
11228
11229         record = find_revoke_record(journal, blocknr);
11230         if (record) {
11231                 /* If we have multiple occurences, only record the
11232                  * latest sequence number in the hashed record */
11233                 if (tid_gt(sequence, record->sequence))
11234                         record->sequence = sequence;
11235                 return 0;
11236         }
11237         return insert_revoke_hash(journal, blocknr, sequence);
11238 }
11239
11240 /*
11241  * Test revoke records.  For a given block referenced in the log, has
11242  * that block been revoked?  A revoke record with a given transaction
11243  * sequence number revokes all blocks in that transaction and earlier
11244  * ones, but later transactions still need replayed.
11245  */
11246
11247 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11248                         tid_t sequence)
11249 {
11250         struct jbd_revoke_record_s *record;
11251
11252         record = find_revoke_record(journal, blocknr);
11253         if (!record)
11254                 return 0;
11255         if (tid_gt(sequence, record->sequence))
11256                 return 0;
11257         return 1;
11258 }
11259
11260 /*
11261  * Finally, once recovery is over, we need to clear the revoke table so
11262  * that it can be reused by the running filesystem.
11263  */
11264
11265 void journal_clear_revoke(journal_t *journal)
11266 {
11267         int i;
11268         struct list_head *hash_list;
11269         struct jbd_revoke_record_s *record;
11270         struct jbd_revoke_table_s *revoke_var;
11271
11272         revoke_var = journal->j_revoke;
11273
11274         for (i = 0; i < revoke_var->hash_size; i++) {
11275                 hash_list = &revoke_var->hash_table[i];
11276                 while (!list_empty(hash_list)) {
11277                         record = (struct jbd_revoke_record_s*) hash_list->next;
11278                         list_del(&record->hash);
11279                         free(record);
11280                 }
11281         }
11282 }
11283
11284 /*
11285  * e2fsck.c - superblock checks
11286  */
11287
11288 #define MIN_CHECK 1
11289 #define MAX_CHECK 2
11290
11291 static void check_super_value(e2fsck_t ctx, const char *descr,
11292                               unsigned long value, int flags,
11293                               unsigned long min_val, unsigned long max_val)
11294 {
11295         struct          problem_context pctx;
11296
11297         if (((flags & MIN_CHECK) && (value < min_val)) ||
11298             ((flags & MAX_CHECK) && (value > max_val))) {
11299                 clear_problem_context(&pctx);
11300                 pctx.num = value;
11301                 pctx.str = descr;
11302                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11303                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11304         }
11305 }
11306
11307 /*
11308  * This routine may get stubbed out in special compilations of the
11309  * e2fsck code..
11310  */
11311 #ifndef EXT2_SPECIAL_DEVICE_SIZE
11312 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11313 {
11314         return (ext2fs_get_device_size(ctx->filesystem_name,
11315                                        EXT2_BLOCK_SIZE(ctx->fs->super),
11316                                        &ctx->num_blocks));
11317 }
11318 #endif
11319
11320 /*
11321  * helper function to release an inode
11322  */
11323 struct process_block_struct {
11324         e2fsck_t        ctx;
11325         char            *buf;
11326         struct problem_context *pctx;
11327         int             truncating;
11328         int             truncate_offset;
11329         e2_blkcnt_t     truncate_block;
11330         int             truncated_blocks;
11331         int             abort;
11332         errcode_t       errcode;
11333 };
11334
11335 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11336                                e2_blkcnt_t blockcnt,
11337                                blk_t    ref_blk FSCK_ATTR((unused)),
11338                                int      ref_offset FSCK_ATTR((unused)),
11339                                void *priv_data)
11340 {
11341         struct process_block_struct *pb;
11342         e2fsck_t                ctx;
11343         struct problem_context  *pctx;
11344         blk_t                   blk = *block_nr;
11345         int                     retval = 0;
11346
11347         pb = (struct process_block_struct *) priv_data;
11348         ctx = pb->ctx;
11349         pctx = pb->pctx;
11350
11351         pctx->blk = blk;
11352         pctx->blkcount = blockcnt;
11353
11354         if (HOLE_BLKADDR(blk))
11355                 return 0;
11356
11357         if ((blk < fs->super->s_first_data_block) ||
11358             (blk >= fs->super->s_blocks_count)) {
11359                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11360         return_abort:
11361                 pb->abort = 1;
11362                 return BLOCK_ABORT;
11363         }
11364
11365         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11366                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11367                 goto return_abort;
11368         }
11369
11370         /*
11371          * If we are deleting an orphan, then we leave the fields alone.
11372          * If we are truncating an orphan, then update the inode fields
11373          * and clean up any partial block data.
11374          */
11375         if (pb->truncating) {
11376                 /*
11377                  * We only remove indirect blocks if they are
11378                  * completely empty.
11379                  */
11380                 if (blockcnt < 0) {
11381                         int     i, limit;
11382                         blk_t   *bp;
11383
11384                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11385                                                         pb->buf);
11386                         if (pb->errcode)
11387                                 goto return_abort;
11388
11389                         limit = fs->blocksize >> 2;
11390                         for (i = 0, bp = (blk_t *) pb->buf;
11391                              i < limit;  i++, bp++)
11392                                 if (*bp)
11393                                         return 0;
11394                 }
11395                 /*
11396                  * We don't remove direct blocks until we've reached
11397                  * the truncation block.
11398                  */
11399                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11400                         return 0;
11401                 /*
11402                  * If part of the last block needs truncating, we do
11403                  * it here.
11404                  */
11405                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11406                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11407                                                         pb->buf);
11408                         if (pb->errcode)
11409                                 goto return_abort;
11410                         memset(pb->buf + pb->truncate_offset, 0,
11411                                fs->blocksize - pb->truncate_offset);
11412                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11413                                                          pb->buf);
11414                         if (pb->errcode)
11415                                 goto return_abort;
11416                 }
11417                 pb->truncated_blocks++;
11418                 *block_nr = 0;
11419                 retval |= BLOCK_CHANGED;
11420         }
11421
11422         ext2fs_block_alloc_stats(fs, blk, -1);
11423         return retval;
11424 }
11425
11426 /*
11427  * This function releases an inode.  Returns 1 if an inconsistency was
11428  * found.  If the inode has a link count, then it is being truncated and
11429  * not deleted.
11430  */
11431 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11432                                 struct ext2_inode *inode, char *block_buf,
11433                                 struct problem_context *pctx)
11434 {
11435         struct process_block_struct     pb;
11436         ext2_filsys                     fs = ctx->fs;
11437         errcode_t                       retval;
11438         __u32                           count;
11439
11440         if (!ext2fs_inode_has_valid_blocks(inode))
11441                 return 0;
11442
11443         pb.buf = block_buf + 3 * ctx->fs->blocksize;
11444         pb.ctx = ctx;
11445         pb.abort = 0;
11446         pb.errcode = 0;
11447         pb.pctx = pctx;
11448         if (inode->i_links_count) {
11449                 pb.truncating = 1;
11450                 pb.truncate_block = (e2_blkcnt_t)
11451                         ((((long long)inode->i_size_high << 32) +
11452                           inode->i_size + fs->blocksize - 1) /
11453                          fs->blocksize);
11454                 pb.truncate_offset = inode->i_size % fs->blocksize;
11455         } else {
11456                 pb.truncating = 0;
11457                 pb.truncate_block = 0;
11458                 pb.truncate_offset = 0;
11459         }
11460         pb.truncated_blocks = 0;
11461         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11462                                       block_buf, release_inode_block, &pb);
11463         if (retval) {
11464                 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11465                         ino);
11466                 return 1;
11467         }
11468         if (pb.abort)
11469                 return 1;
11470
11471         /* Refresh the inode since ext2fs_block_iterate may have changed it */
11472         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11473
11474         if (pb.truncated_blocks)
11475                 inode->i_blocks -= pb.truncated_blocks *
11476                         (fs->blocksize / 512);
11477
11478         if (inode->i_file_acl) {
11479                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11480                                                    block_buf, -1, &count);
11481                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11482                         retval = 0;
11483                         count = 1;
11484                 }
11485                 if (retval) {
11486                         bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11487                                 ino);
11488                         return 1;
11489                 }
11490                 if (count == 0)
11491                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11492                 inode->i_file_acl = 0;
11493         }
11494         return 0;
11495 }
11496
11497 /*
11498  * This function releases all of the orphan inodes.  It returns 1 if
11499  * it hit some error, and 0 on success.
11500  */
11501 static int release_orphan_inodes(e2fsck_t ctx)
11502 {
11503         ext2_filsys fs = ctx->fs;
11504         ext2_ino_t      ino, next_ino;
11505         struct ext2_inode inode;
11506         struct problem_context pctx;
11507         char *block_buf;
11508
11509         if ((ino = fs->super->s_last_orphan) == 0)
11510                 return 0;
11511
11512         /*
11513          * Win or lose, we won't be using the head of the orphan inode
11514          * list again.
11515          */
11516         fs->super->s_last_orphan = 0;
11517         ext2fs_mark_super_dirty(fs);
11518
11519         /*
11520          * If the filesystem contains errors, don't run the orphan
11521          * list, since the orphan list can't be trusted; and we're
11522          * going to be running a full e2fsck run anyway...
11523          */
11524         if (fs->super->s_state & EXT2_ERROR_FS)
11525                 return 0;
11526
11527         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11528             (ino > fs->super->s_inodes_count)) {
11529                 clear_problem_context(&pctx);
11530                 pctx.ino = ino;
11531                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11532                 return 1;
11533         }
11534
11535         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11536                                                     "block iterate buffer");
11537         e2fsck_read_bitmaps(ctx);
11538
11539         while (ino) {
11540                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11541                 clear_problem_context(&pctx);
11542                 pctx.ino = ino;
11543                 pctx.inode = &inode;
11544                 pctx.str = inode.i_links_count ? _("Truncating") :
11545                         _("Clearing");
11546
11547                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11548
11549                 next_ino = inode.i_dtime;
11550                 if (next_ino &&
11551                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11552                      (next_ino > fs->super->s_inodes_count))) {
11553                         pctx.ino = next_ino;
11554                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11555                         goto return_abort;
11556                 }
11557
11558                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11559                         goto return_abort;
11560
11561                 if (!inode.i_links_count) {
11562                         ext2fs_inode_alloc_stats2(fs, ino, -1,
11563                                                   LINUX_S_ISDIR(inode.i_mode));
11564                         inode.i_dtime = time(0);
11565                 } else {
11566                         inode.i_dtime = 0;
11567                 }
11568                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11569                 ino = next_ino;
11570         }
11571         ext2fs_free_mem(&block_buf);
11572         return 0;
11573 return_abort:
11574         ext2fs_free_mem(&block_buf);
11575         return 1;
11576 }
11577
11578 /*
11579  * Check the resize inode to make sure it is sane.  We check both for
11580  * the case where on-line resizing is not enabled (in which case the
11581  * resize inode should be cleared) as well as the case where on-line
11582  * resizing is enabled.
11583  */
11584 static void check_resize_inode(e2fsck_t ctx)
11585 {
11586         ext2_filsys fs = ctx->fs;
11587         struct ext2_inode inode;
11588         struct problem_context  pctx;
11589         int             i, j, gdt_off, ind_off;
11590         blk_t           blk, pblk, expect;
11591         __u32           *dind_buf = 0, *ind_buf;
11592         errcode_t       retval;
11593
11594         clear_problem_context(&pctx);
11595
11596         /*
11597          * If the resize inode feature isn't set, then
11598          * s_reserved_gdt_blocks must be zero.
11599          */
11600         if (!(fs->super->s_feature_compat &
11601               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11602                 if (fs->super->s_reserved_gdt_blocks) {
11603                         pctx.num = fs->super->s_reserved_gdt_blocks;
11604                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11605                                         &pctx)) {
11606                                 fs->super->s_reserved_gdt_blocks = 0;
11607                                 ext2fs_mark_super_dirty(fs);
11608                         }
11609                 }
11610         }
11611
11612         /* Read the resize inode */
11613         pctx.ino = EXT2_RESIZE_INO;
11614         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11615         if (retval) {
11616                 if (fs->super->s_feature_compat &
11617                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11618                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11619                 return;
11620         }
11621
11622         /*
11623          * If the resize inode feature isn't set, check to make sure
11624          * the resize inode is cleared; then we're done.
11625          */
11626         if (!(fs->super->s_feature_compat &
11627               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11628                 for (i=0; i < EXT2_N_BLOCKS; i++) {
11629                         if (inode.i_block[i])
11630                                 break;
11631                 }
11632                 if ((i < EXT2_N_BLOCKS) &&
11633                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11634                         memset(&inode, 0, sizeof(inode));
11635                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11636                                            "clear_resize");
11637                 }
11638                 return;
11639         }
11640
11641         /*
11642          * The resize inode feature is enabled; check to make sure the
11643          * only block in use is the double indirect block
11644          */
11645         blk = inode.i_block[EXT2_DIND_BLOCK];
11646         for (i=0; i < EXT2_N_BLOCKS; i++) {
11647                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11648                         break;
11649         }
11650         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11651             !(inode.i_mode & LINUX_S_IFREG) ||
11652             (blk < fs->super->s_first_data_block ||
11653              blk >= fs->super->s_blocks_count)) {
11654         resize_inode_invalid:
11655                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11656                         memset(&inode, 0, sizeof(inode));
11657                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11658                                            "clear_resize");
11659                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
11660                 }
11661                 if (!(ctx->options & E2F_OPT_READONLY)) {
11662                         fs->super->s_state &= ~EXT2_VALID_FS;
11663                         ext2fs_mark_super_dirty(fs);
11664                 }
11665                 goto cleanup;
11666         }
11667         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11668                                                     "resize dind buffer");
11669         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11670
11671         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11672         if (retval)
11673                 goto resize_inode_invalid;
11674
11675         gdt_off = fs->desc_blocks;
11676         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11677         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11678              i++, gdt_off++, pblk++) {
11679                 gdt_off %= fs->blocksize/4;
11680                 if (dind_buf[gdt_off] != pblk)
11681                         goto resize_inode_invalid;
11682                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11683                 if (retval)
11684                         goto resize_inode_invalid;
11685                 ind_off = 0;
11686                 for (j = 1; j < fs->group_desc_count; j++) {
11687                         if (!ext2fs_bg_has_super(fs, j))
11688                                 continue;
11689                         expect = pblk + (j * fs->super->s_blocks_per_group);
11690                         if (ind_buf[ind_off] != expect)
11691                                 goto resize_inode_invalid;
11692                         ind_off++;
11693                 }
11694         }
11695
11696 cleanup:
11697         ext2fs_free_mem(&dind_buf);
11698
11699  }
11700
11701 static void check_super_block(e2fsck_t ctx)
11702 {
11703         ext2_filsys fs = ctx->fs;
11704         blk_t   first_block, last_block;
11705         struct ext2_super_block *sb = fs->super;
11706         struct ext2_group_desc *gd;
11707         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11708         blk_t   bpg_max;
11709         int     inodes_per_block;
11710         int     ipg_max;
11711         int     inode_size;
11712         dgrp_t  i;
11713         blk_t   should_be;
11714         struct problem_context  pctx;
11715         __u32   free_blocks = 0, free_inodes = 0;
11716
11717         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11718         ipg_max = inodes_per_block * (blocks_per_group - 4);
11719         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11720                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11721         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11722         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11723                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11724
11725         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11726                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11727         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11728                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11729         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11730                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11731
11732         clear_problem_context(&pctx);
11733
11734         /*
11735          * Verify the super block constants...
11736          */
11737         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11738                           MIN_CHECK, 1, 0);
11739         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11740                           MIN_CHECK, 1, 0);
11741         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11742                           MAX_CHECK, 0, sb->s_blocks_count);
11743         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11744                           MIN_CHECK | MAX_CHECK, 0,
11745                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11746         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11747                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11748         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11749                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11750                           bpg_max);
11751         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11752                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
11753         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11754                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11755         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11756                           MAX_CHECK, 0, sb->s_blocks_count / 2);
11757         check_super_value(ctx, "reserved_gdt_blocks",
11758                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11759                           fs->blocksize/4);
11760         inode_size = EXT2_INODE_SIZE(sb);
11761         check_super_value(ctx, "inode_size",
11762                           inode_size, MIN_CHECK | MAX_CHECK,
11763                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11764         if (inode_size & (inode_size - 1)) {
11765                 pctx.num = inode_size;
11766                 pctx.str = "inode_size";
11767                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11768                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11769                 return;
11770         }
11771
11772         if (!ctx->num_blocks) {
11773                 pctx.errcode = e2fsck_get_device_size(ctx);
11774                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11775                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11776                         ctx->flags |= E2F_FLAG_ABORT;
11777                         return;
11778                 }
11779                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11780                     (ctx->num_blocks < sb->s_blocks_count)) {
11781                         pctx.blk = sb->s_blocks_count;
11782                         pctx.blk2 = ctx->num_blocks;
11783                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11784                                 ctx->flags |= E2F_FLAG_ABORT;
11785                                 return;
11786                         }
11787                 }
11788         }
11789
11790         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11791                 pctx.blk = EXT2_BLOCK_SIZE(sb);
11792                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11793                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11794                 ctx->flags |= E2F_FLAG_ABORT;
11795                 return;
11796         }
11797
11798         should_be = sb->s_frags_per_group >>
11799                 (sb->s_log_block_size - sb->s_log_frag_size);
11800         if (sb->s_blocks_per_group != should_be) {
11801                 pctx.blk = sb->s_blocks_per_group;
11802                 pctx.blk2 = should_be;
11803                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11804                 ctx->flags |= E2F_FLAG_ABORT;
11805                 return;
11806         }
11807
11808         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11809         if (sb->s_first_data_block != should_be) {
11810                 pctx.blk = sb->s_first_data_block;
11811                 pctx.blk2 = should_be;
11812                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11813                 ctx->flags |= E2F_FLAG_ABORT;
11814                 return;
11815         }
11816
11817         should_be = sb->s_inodes_per_group * fs->group_desc_count;
11818         if (sb->s_inodes_count != should_be) {
11819                 pctx.ino = sb->s_inodes_count;
11820                 pctx.ino2 = should_be;
11821                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11822                         sb->s_inodes_count = should_be;
11823                         ext2fs_mark_super_dirty(fs);
11824                 }
11825         }
11826
11827         /*
11828          * Verify the group descriptors....
11829          */
11830         first_block =  sb->s_first_data_block;
11831         last_block = first_block + blocks_per_group;
11832
11833         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11834                 pctx.group = i;
11835
11836                 if (i == fs->group_desc_count - 1)
11837                         last_block = sb->s_blocks_count;
11838                 if ((gd->bg_block_bitmap < first_block) ||
11839                     (gd->bg_block_bitmap >= last_block)) {
11840                         pctx.blk = gd->bg_block_bitmap;
11841                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11842                                 gd->bg_block_bitmap = 0;
11843                 }
11844                 if (gd->bg_block_bitmap == 0) {
11845                         ctx->invalid_block_bitmap_flag[i]++;
11846                         ctx->invalid_bitmaps++;
11847                 }
11848                 if ((gd->bg_inode_bitmap < first_block) ||
11849                     (gd->bg_inode_bitmap >= last_block)) {
11850                         pctx.blk = gd->bg_inode_bitmap;
11851                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11852                                 gd->bg_inode_bitmap = 0;
11853                 }
11854                 if (gd->bg_inode_bitmap == 0) {
11855                         ctx->invalid_inode_bitmap_flag[i]++;
11856                         ctx->invalid_bitmaps++;
11857                 }
11858                 if ((gd->bg_inode_table < first_block) ||
11859                     ((gd->bg_inode_table +
11860                       fs->inode_blocks_per_group - 1) >= last_block)) {
11861                         pctx.blk = gd->bg_inode_table;
11862                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11863                                 gd->bg_inode_table = 0;
11864                 }
11865                 if (gd->bg_inode_table == 0) {
11866                         ctx->invalid_inode_table_flag[i]++;
11867                         ctx->invalid_bitmaps++;
11868                 }
11869                 free_blocks += gd->bg_free_blocks_count;
11870                 free_inodes += gd->bg_free_inodes_count;
11871                 first_block += sb->s_blocks_per_group;
11872                 last_block += sb->s_blocks_per_group;
11873
11874                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11875                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11876                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11877                         ext2fs_unmark_valid(fs);
11878
11879         }
11880
11881         /*
11882          * Update the global counts from the block group counts.  This
11883          * is needed for an experimental patch which eliminates
11884          * locking the entire filesystem when allocating blocks or
11885          * inodes; if the filesystem is not unmounted cleanly, the
11886          * global counts may not be accurate.
11887          */
11888         if ((free_blocks != sb->s_free_blocks_count) ||
11889             (free_inodes != sb->s_free_inodes_count)) {
11890                 if (ctx->options & E2F_OPT_READONLY)
11891                         ext2fs_unmark_valid(fs);
11892                 else {
11893                         sb->s_free_blocks_count = free_blocks;
11894                         sb->s_free_inodes_count = free_inodes;
11895                         ext2fs_mark_super_dirty(fs);
11896                 }
11897         }
11898
11899         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11900             (sb->s_free_inodes_count > sb->s_inodes_count))
11901                 ext2fs_unmark_valid(fs);
11902
11903
11904         /*
11905          * If we have invalid bitmaps, set the error state of the
11906          * filesystem.
11907          */
11908         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11909                 sb->s_state &= ~EXT2_VALID_FS;
11910                 ext2fs_mark_super_dirty(fs);
11911         }
11912
11913         clear_problem_context(&pctx);
11914
11915         /*
11916          * If the UUID field isn't assigned, assign it.
11917          */
11918         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11919                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11920                         uuid_generate(sb->s_uuid);
11921                         ext2fs_mark_super_dirty(fs);
11922                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11923                 }
11924         }
11925
11926         /* FIXME - HURD support?
11927          * For the Hurd, check to see if the filetype option is set,
11928          * since it doesn't support it.
11929          */
11930         if (!(ctx->options & E2F_OPT_READONLY) &&
11931             fs->super->s_creator_os == EXT2_OS_HURD &&
11932             (fs->super->s_feature_incompat &
11933              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11934                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11935                         fs->super->s_feature_incompat &=
11936                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11937                         ext2fs_mark_super_dirty(fs);
11938
11939                 }
11940         }
11941
11942         /*
11943          * If we have any of the compatibility flags set, we need to have a
11944          * revision 1 filesystem.  Most kernels will not check the flags on
11945          * a rev 0 filesystem and we may have corruption issues because of
11946          * the incompatible changes to the filesystem.
11947          */
11948         if (!(ctx->options & E2F_OPT_READONLY) &&
11949             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11950             (fs->super->s_feature_compat ||
11951              fs->super->s_feature_ro_compat ||
11952              fs->super->s_feature_incompat) &&
11953             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11954                 ext2fs_update_dynamic_rev(fs);
11955                 ext2fs_mark_super_dirty(fs);
11956         }
11957
11958         check_resize_inode(ctx);
11959
11960         /*
11961          * Clean up any orphan inodes, if present.
11962          */
11963         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11964                 fs->super->s_state &= ~EXT2_VALID_FS;
11965                 ext2fs_mark_super_dirty(fs);
11966         }
11967
11968         /*
11969          * Move the ext3 journal file, if necessary.
11970          */
11971         e2fsck_move_ext3_journal(ctx);
11972         return;
11973 }
11974
11975 /*
11976  * swapfs.c --- byte-swap an ext2 filesystem
11977  */
11978
11979 #ifdef ENABLE_SWAPFS
11980
11981 struct swap_block_struct {
11982         ext2_ino_t      ino;
11983         int             isdir;
11984         errcode_t       errcode;
11985         char            *dir_buf;
11986         struct ext2_inode *inode;
11987 };
11988
11989 /*
11990  * This is a helper function for block_iterate.  We mark all of the
11991  * indirect and direct blocks as changed, so that block_iterate will
11992  * write them out.
11993  */
11994 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11995                       void *priv_data)
11996 {
11997         errcode_t       retval;
11998
11999         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
12000
12001         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
12002                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
12003                 if (retval) {
12004                         sb->errcode = retval;
12005                         return BLOCK_ABORT;
12006                 }
12007                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
12008                 if (retval) {
12009                         sb->errcode = retval;
12010                         return BLOCK_ABORT;
12011                 }
12012         }
12013         if (blockcnt >= 0) {
12014                 if (blockcnt < EXT2_NDIR_BLOCKS)
12015                         return 0;
12016                 return BLOCK_CHANGED;
12017         }
12018         if (blockcnt == BLOCK_COUNT_IND) {
12019                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
12020                         return 0;
12021                 return BLOCK_CHANGED;
12022         }
12023         if (blockcnt == BLOCK_COUNT_DIND) {
12024                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12025                         return 0;
12026                 return BLOCK_CHANGED;
12027         }
12028         if (blockcnt == BLOCK_COUNT_TIND) {
12029                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12030                         return 0;
12031                 return BLOCK_CHANGED;
12032         }
12033         return BLOCK_CHANGED;
12034 }
12035
12036 /*
12037  * This function is responsible for byte-swapping all of the indirect,
12038  * block pointers.  It is also responsible for byte-swapping directories.
12039  */
12040 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12041                               struct ext2_inode *inode)
12042 {
12043         errcode_t                       retval;
12044         struct swap_block_struct        sb;
12045
12046         sb.ino = ino;
12047         sb.inode = inode;
12048         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12049         sb.errcode = 0;
12050         sb.isdir = 0;
12051         if (LINUX_S_ISDIR(inode->i_mode))
12052                 sb.isdir = 1;
12053
12054         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12055                                       swap_block, &sb);
12056         if (retval) {
12057                 bb_error_msg(_("while calling ext2fs_block_iterate"));
12058                 ctx->flags |= E2F_FLAG_ABORT;
12059                 return;
12060         }
12061         if (sb.errcode) {
12062                 bb_error_msg(_("while calling iterator function"));
12063                 ctx->flags |= E2F_FLAG_ABORT;
12064                 return;
12065         }
12066 }
12067
12068 static void swap_inodes(e2fsck_t ctx)
12069 {
12070         ext2_filsys fs = ctx->fs;
12071         dgrp_t                  group;
12072         unsigned int            i;
12073         ext2_ino_t              ino = 1;
12074         char                    *buf, *block_buf;
12075         errcode_t               retval;
12076         struct ext2_inode *     inode;
12077
12078         e2fsck_use_inode_shortcuts(ctx, 1);
12079
12080         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12081                                 &buf);
12082         if (retval) {
12083                 bb_error_msg(_("while allocating inode buffer"));
12084                 ctx->flags |= E2F_FLAG_ABORT;
12085                 return;
12086         }
12087         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12088                                                     "block interate buffer");
12089         for (group = 0; group < fs->group_desc_count; group++) {
12090                 retval = io_channel_read_blk(fs->io,
12091                       fs->group_desc[group].bg_inode_table,
12092                       fs->inode_blocks_per_group, buf);
12093                 if (retval) {
12094                         bb_error_msg(_("while reading inode table (group %d)"),
12095                                 group);
12096                         ctx->flags |= E2F_FLAG_ABORT;
12097                         return;
12098                 }
12099                 inode = (struct ext2_inode *) buf;
12100                 for (i=0; i < fs->super->s_inodes_per_group;
12101                      i++, ino++, inode++) {
12102                         ctx->stashed_ino = ino;
12103                         ctx->stashed_inode = inode;
12104
12105                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12106                                 ext2fs_swap_inode(fs, inode, inode, 0);
12107
12108                         /*
12109                          * Skip deleted files.
12110                          */
12111                         if (inode->i_links_count == 0)
12112                                 continue;
12113
12114                         if (LINUX_S_ISDIR(inode->i_mode) ||
12115                             ((inode->i_block[EXT2_IND_BLOCK] ||
12116                               inode->i_block[EXT2_DIND_BLOCK] ||
12117                               inode->i_block[EXT2_TIND_BLOCK]) &&
12118                              ext2fs_inode_has_valid_blocks(inode)))
12119                                 swap_inode_blocks(ctx, ino, block_buf, inode);
12120
12121                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12122                                 return;
12123
12124                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12125                                 ext2fs_swap_inode(fs, inode, inode, 1);
12126                 }
12127                 retval = io_channel_write_blk(fs->io,
12128                       fs->group_desc[group].bg_inode_table,
12129                       fs->inode_blocks_per_group, buf);
12130                 if (retval) {
12131                         bb_error_msg(_("while writing inode table (group %d)"),
12132                                 group);
12133                         ctx->flags |= E2F_FLAG_ABORT;
12134                         return;
12135                 }
12136         }
12137         ext2fs_free_mem(&buf);
12138         ext2fs_free_mem(&block_buf);
12139         e2fsck_use_inode_shortcuts(ctx, 0);
12140         ext2fs_flush_icache(fs);
12141 }
12142
12143 #if defined(__powerpc__) && BB_BIG_ENDIAN
12144 /*
12145  * On the PowerPC, the big-endian variant of the ext2 filesystem
12146  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12147  * of each word.  Thus a bitmap with only bit 0 set would be, as
12148  * a string of bytes, 00 00 00 01 00 ...
12149  * To cope with this, we byte-reverse each word of a bitmap if
12150  * we have a big-endian filesystem, that is, if we are *not*
12151  * byte-swapping other word-sized numbers.
12152  */
12153 #define EXT2_BIG_ENDIAN_BITMAPS
12154 #endif
12155
12156 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12157 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12158 {
12159         __u32 *p = (__u32 *) bmap->bitmap;
12160         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12161
12162         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12163                 *p = ext2fs_swab32(*p);
12164 }
12165 #endif
12166
12167
12168 #ifdef ENABLE_SWAPFS
12169 static void swap_filesys(e2fsck_t ctx)
12170 {
12171         ext2_filsys fs = ctx->fs;
12172         if (!(ctx->options & E2F_OPT_PREEN))
12173                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12174
12175         /* Byte swap */
12176
12177         if (fs->super->s_mnt_count) {
12178                 fprintf(stderr, _("%s: the filesystem must be freshly "
12179                         "checked using fsck\n"
12180                         "and not mounted before trying to "
12181                         "byte-swap it.\n"), ctx->device_name);
12182                 ctx->flags |= E2F_FLAG_ABORT;
12183                 return;
12184         }
12185         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12186                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12187                                EXT2_FLAG_SWAP_BYTES_WRITE);
12188                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12189         } else {
12190                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12191                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12192         }
12193         swap_inodes(ctx);
12194         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12195                 return;
12196         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12197                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12198         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12199                        EXT2_FLAG_SWAP_BYTES_WRITE);
12200
12201 #ifdef EXT2_BIG_ENDIAN_BITMAPS
12202         e2fsck_read_bitmaps(ctx);
12203         ext2fs_swap_bitmap(fs->inode_map);
12204         ext2fs_swap_bitmap(fs->block_map);
12205         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12206 #endif
12207         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12208         ext2fs_flush(fs);
12209         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12210 }
12211 #endif  /* ENABLE_SWAPFS */
12212
12213 #endif
12214
12215 /*
12216  * util.c --- miscellaneous utilities
12217  */
12218
12219
12220 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12221                              const char *description)
12222 {
12223         void *ret;
12224         char buf[256];
12225
12226         ret = malloc(size);
12227         if (!ret) {
12228                 sprintf(buf, "Can't allocate %s\n", description);
12229                 bb_error_msg_and_die(buf);
12230         }
12231         memset(ret, 0, size);
12232         return ret;
12233 }
12234
12235 static char *string_copy(const char *str, int len)
12236 {
12237         char    *ret;
12238
12239         if (!str)
12240                 return NULL;
12241         if (!len)
12242                 len = strlen(str);
12243         ret = malloc(len+1);
12244         if (ret) {
12245                 strncpy(ret, str, len);
12246                 ret[len] = 0;
12247         }
12248         return ret;
12249 }
12250
12251 #ifndef HAVE_CONIO_H
12252 static int read_a_char(void)
12253 {
12254         char    c;
12255         int     r;
12256         int     fail = 0;
12257
12258         while(1) {
12259                 if (e2fsck_global_ctx &&
12260                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12261                         return 3;
12262                 }
12263                 r = read(0, &c, 1);
12264                 if (r == 1)
12265                         return c;
12266                 if (fail++ > 100)
12267                         break;
12268         }
12269         return EOF;
12270 }
12271 #endif
12272
12273 static int ask_yn(const char * string, int def)
12274 {
12275         int             c;
12276         const char      *defstr;
12277         static const char short_yes[] = "yY";
12278         static const char short_no[] = "nN";
12279
12280 #ifdef HAVE_TERMIOS_H
12281         struct termios  termios, tmp;
12282
12283         tcgetattr (0, &termios);
12284         tmp = termios;
12285         tmp.c_lflag &= ~(ICANON | ECHO);
12286         tmp.c_cc[VMIN] = 1;
12287         tmp.c_cc[VTIME] = 0;
12288         tcsetattr (0, TCSANOW, &tmp);
12289 #endif
12290
12291         if (def == 1)
12292                 defstr = "<y>";
12293         else if (def == 0)
12294                 defstr = "<n>";
12295         else
12296                 defstr = " (y/n)";
12297         printf("%s%s? ", string, defstr);
12298         while (1) {
12299                 fflush (stdout);
12300                 if ((c = read_a_char()) == EOF)
12301                         break;
12302                 if (c == 3) {
12303 #ifdef HAVE_TERMIOS_H
12304                         tcsetattr (0, TCSANOW, &termios);
12305 #endif
12306                         if (e2fsck_global_ctx &&
12307                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12308                                 puts("\n");
12309                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
12310                         }
12311                         puts(_("cancelled!\n"));
12312                         return 0;
12313                 }
12314                 if (strchr(short_yes, (char) c)) {
12315                         def = 1;
12316                         break;
12317                 }
12318                 else if (strchr(short_no, (char) c)) {
12319                         def = 0;
12320                         break;
12321                 }
12322                 else if ((c == ' ' || c == '\n') && (def != -1))
12323                         break;
12324         }
12325         if (def)
12326                 puts("yes\n");
12327         else
12328                 puts ("no\n");
12329 #ifdef HAVE_TERMIOS_H
12330         tcsetattr (0, TCSANOW, &termios);
12331 #endif
12332         return def;
12333 }
12334
12335 int ask (e2fsck_t ctx, const char * string, int def)
12336 {
12337         if (ctx->options & E2F_OPT_NO) {
12338                 printf (_("%s? no\n\n"), string);
12339                 return 0;
12340         }
12341         if (ctx->options & E2F_OPT_YES) {
12342                 printf (_("%s? yes\n\n"), string);
12343                 return 1;
12344         }
12345         if (ctx->options & E2F_OPT_PREEN) {
12346                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
12347                 return def;
12348         }
12349         return ask_yn(string, def);
12350 }
12351
12352 void e2fsck_read_bitmaps(e2fsck_t ctx)
12353 {
12354         ext2_filsys fs = ctx->fs;
12355         errcode_t       retval;
12356
12357         if (ctx->invalid_bitmaps) {
12358                 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12359                         ctx->device_name);
12360                 bb_error_msg_and_die(0);
12361         }
12362
12363         ehandler_operation(_("reading inode and block bitmaps"));
12364         retval = ext2fs_read_bitmaps(fs);
12365         ehandler_operation(0);
12366         if (retval) {
12367                 bb_error_msg(_("while retrying to read bitmaps for %s"),
12368                         ctx->device_name);
12369                 bb_error_msg_and_die(0);
12370         }
12371 }
12372
12373 static void e2fsck_write_bitmaps(e2fsck_t ctx)
12374 {
12375         ext2_filsys fs = ctx->fs;
12376         errcode_t       retval;
12377
12378         if (ext2fs_test_bb_dirty(fs)) {
12379                 ehandler_operation(_("writing block bitmaps"));
12380                 retval = ext2fs_write_block_bitmap(fs);
12381                 ehandler_operation(0);
12382                 if (retval) {
12383                         bb_error_msg(_("while retrying to write block bitmaps for %s"),
12384                                 ctx->device_name);
12385                         bb_error_msg_and_die(0);
12386                 }
12387         }
12388
12389         if (ext2fs_test_ib_dirty(fs)) {
12390                 ehandler_operation(_("writing inode bitmaps"));
12391                 retval = ext2fs_write_inode_bitmap(fs);
12392                 ehandler_operation(0);
12393                 if (retval) {
12394                         bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12395                                 ctx->device_name);
12396                         bb_error_msg_and_die(0);
12397                 }
12398         }
12399 }
12400
12401 void preenhalt(e2fsck_t ctx)
12402 {
12403         ext2_filsys fs = ctx->fs;
12404
12405         if (!(ctx->options & E2F_OPT_PREEN))
12406                 return;
12407         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12408                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12409                ctx->device_name);
12410         if (fs != NULL) {
12411                 fs->super->s_state |= EXT2_ERROR_FS;
12412                 ext2fs_mark_super_dirty(fs);
12413                 ext2fs_close(fs);
12414         }
12415         exit(EXIT_UNCORRECTED);
12416 }
12417
12418 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12419                               struct ext2_inode * inode, const char *proc)
12420 {
12421         int retval;
12422
12423         retval = ext2fs_read_inode(ctx->fs, ino, inode);
12424         if (retval) {
12425                 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12426                 bb_error_msg_and_die(0);
12427         }
12428 }
12429
12430 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12431                                struct ext2_inode * inode, int bufsize,
12432                                const char *proc)
12433 {
12434         int retval;
12435
12436         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12437         if (retval) {
12438                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12439                 bb_error_msg_and_die(0);
12440         }
12441 }
12442
12443 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12444                                struct ext2_inode * inode, const char *proc)
12445 {
12446         int retval;
12447
12448         retval = ext2fs_write_inode(ctx->fs, ino, inode);
12449         if (retval) {
12450                 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12451                 bb_error_msg_and_die(0);
12452         }
12453 }
12454
12455 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12456                    io_manager manager)
12457 {
12458         struct ext2_super_block *sb;
12459         io_channel              io = NULL;
12460         void                    *buf = NULL;
12461         int                     blocksize;
12462         blk_t                   superblock, ret_sb = 8193;
12463
12464         if (fs && fs->super) {
12465                 ret_sb = (fs->super->s_blocks_per_group +
12466                           fs->super->s_first_data_block);
12467                 if (ctx) {
12468                         ctx->superblock = ret_sb;
12469                         ctx->blocksize = fs->blocksize;
12470                 }
12471                 return ret_sb;
12472         }
12473
12474         if (ctx) {
12475                 if (ctx->blocksize) {
12476                         ret_sb = ctx->blocksize * 8;
12477                         if (ctx->blocksize == 1024)
12478                                 ret_sb++;
12479                         ctx->superblock = ret_sb;
12480                         return ret_sb;
12481                 }
12482                 ctx->superblock = ret_sb;
12483                 ctx->blocksize = 1024;
12484         }
12485
12486         if (!name || !manager)
12487                 goto cleanup;
12488
12489         if (manager->open(name, 0, &io) != 0)
12490                 goto cleanup;
12491
12492         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12493                 goto cleanup;
12494         sb = (struct ext2_super_block *) buf;
12495
12496         for (blocksize = EXT2_MIN_BLOCK_SIZE;
12497              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
12498                 superblock = blocksize*8;
12499                 if (blocksize == 1024)
12500                         superblock++;
12501                 io_channel_set_blksize(io, blocksize);
12502                 if (io_channel_read_blk(io, superblock,
12503                                         -SUPERBLOCK_SIZE, buf))
12504                         continue;
12505 #if BB_BIG_ENDIAN
12506                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12507                         ext2fs_swap_super(sb);
12508 #endif
12509                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12510                         ret_sb = superblock;
12511                         if (ctx) {
12512                                 ctx->superblock = superblock;
12513                                 ctx->blocksize = blocksize;
12514                         }
12515                         break;
12516                 }
12517         }
12518
12519 cleanup:
12520         if (io)
12521                 io_channel_close(io);
12522         ext2fs_free_mem(&buf);
12523         return (ret_sb);
12524 }
12525
12526
12527 /*
12528  * This function runs through the e2fsck passes and calls them all,
12529  * returning restart, abort, or cancel as necessary...
12530  */
12531 typedef void (*pass_t)(e2fsck_t ctx);
12532
12533 static const pass_t e2fsck_passes[] = {
12534         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12535         e2fsck_pass5, 0 };
12536
12537 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12538
12539 static int e2fsck_run(e2fsck_t ctx)
12540 {
12541         int     i;
12542         pass_t  e2fsck_pass;
12543
12544         if (setjmp(ctx->abort_loc)) {
12545                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12546                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12547         }
12548         ctx->flags |= E2F_FLAG_SETJMP_OK;
12549
12550         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12551                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12552                         break;
12553                 e2fsck_pass(ctx);
12554                 if (ctx->progress)
12555                         (void) (ctx->progress)(ctx, 0, 0, 0);
12556         }
12557         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12558
12559         if (ctx->flags & E2F_FLAG_RUN_RETURN)
12560                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12561         return 0;
12562 }
12563
12564
12565 /*
12566  * unix.c - The unix-specific code for e2fsck
12567  */
12568
12569
12570 /* Command line options */
12571 static int swapfs;
12572 #ifdef ENABLE_SWAPFS
12573 static int normalize_swapfs;
12574 #endif
12575 static int cflag;               /* check disk */
12576 static int show_version_only;
12577 static int verbose;
12578
12579 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12580
12581 static void show_stats(e2fsck_t ctx)
12582 {
12583         ext2_filsys fs = ctx->fs;
12584         int inodes, inodes_used, blocks, blocks_used;
12585         int dir_links;
12586         int num_files, num_links;
12587         int frag_percent;
12588
12589         dir_links = 2 * ctx->fs_directory_count - 1;
12590         num_files = ctx->fs_total_count - dir_links;
12591         num_links = ctx->fs_links_count - dir_links;
12592         inodes = fs->super->s_inodes_count;
12593         inodes_used = (fs->super->s_inodes_count -
12594                        fs->super->s_free_inodes_count);
12595         blocks = fs->super->s_blocks_count;
12596         blocks_used = (fs->super->s_blocks_count -
12597                        fs->super->s_free_blocks_count);
12598
12599         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12600         frag_percent = (frag_percent + 5) / 10;
12601
12602         if (!verbose) {
12603                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12604                        ctx->device_name, inodes_used, inodes,
12605                        frag_percent / 10, frag_percent % 10,
12606                        blocks_used, blocks);
12607                 return;
12608         }
12609         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12610                 100 * inodes_used / inodes);
12611         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
12612                 P_E2("", "s", ctx->fs_fragmented),
12613                 frag_percent / 10, frag_percent % 10);
12614         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12615                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12616         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12617                 (int) ((long long) 100 * blocks_used / blocks));
12618         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12619         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12620         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12621         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12622         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12623         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12624         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12625         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12626         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12627         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12628         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12629 }
12630
12631 static void check_mount(e2fsck_t ctx)
12632 {
12633         errcode_t       retval;
12634         int             cont;
12635
12636         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12637                                          &ctx->mount_flags);
12638         if (retval) {
12639                 bb_error_msg(_("while determining whether %s is mounted."),
12640                         ctx->filesystem_name);
12641                 return;
12642         }
12643
12644         /*
12645          * If the filesystem isn't mounted, or it's the root filesystem
12646          * and it's mounted read-only, then everything's fine.
12647          */
12648         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12649             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12650              (ctx->mount_flags & EXT2_MF_READONLY)))
12651                 return;
12652
12653         if (ctx->options & E2F_OPT_READONLY) {
12654                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12655                 return;
12656         }
12657
12658         printf(_("%s is mounted.  "), ctx->filesystem_name);
12659         if (!ctx->interactive)
12660                 bb_error_msg_and_die(_("Cannot continue, aborting."));
12661         printf(_("\n\n\007\007\007\007WARNING!!!  "
12662                "Running e2fsck on a mounted filesystem may cause\n"
12663                "SEVERE filesystem damage.\007\007\007\n\n"));
12664         cont = ask_yn(_("Do you really want to continue"), -1);
12665         if (!cont) {
12666                 printf (_("check aborted.\n"));
12667                 exit (0);
12668         }
12669         return;
12670 }
12671
12672 static int is_on_batt(void)
12673 {
12674         FILE    *f;
12675         DIR     *d;
12676         char    tmp[80], tmp2[80], fname[80];
12677         unsigned int    acflag;
12678         struct dirent*  de;
12679
12680         f = fopen("/proc/apm", "r");
12681         if (f) {
12682                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12683                         acflag = 1;
12684                 fclose(f);
12685                 return (acflag != 1);
12686         }
12687         d = opendir("/proc/acpi/ac_adapter");
12688         if (d) {
12689                 while ((de=readdir(d)) != NULL) {
12690                         if (!strncmp(".", de->d_name, 1))
12691                                 continue;
12692                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12693                                  de->d_name);
12694                         f = fopen(fname, "r");
12695                         if (!f)
12696                                 continue;
12697                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12698                                 tmp[0] = 0;
12699                         fclose(f);
12700                         if (strncmp(tmp, "off-line", 8) == 0) {
12701                                 closedir(d);
12702                                 return 1;
12703                         }
12704                 }
12705                 closedir(d);
12706         }
12707         return 0;
12708 }
12709
12710 /*
12711  * This routine checks to see if a filesystem can be skipped; if so,
12712  * it will exit with EXIT_OK.  Under some conditions it will print a
12713  * message explaining why a check is being forced.
12714  */
12715 static void check_if_skip(e2fsck_t ctx)
12716 {
12717         ext2_filsys fs = ctx->fs;
12718         const char *reason = NULL;
12719         unsigned int reason_arg = 0;
12720         long next_check;
12721         int batt = is_on_batt();
12722         time_t now = time(0);
12723
12724         if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12725                 return;
12726
12727         if ((fs->super->s_state & EXT2_ERROR_FS) ||
12728             !ext2fs_test_valid(fs))
12729                 reason = _(" contains a file system with errors");
12730         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12731                 reason = _(" was not cleanly unmounted");
12732         else if ((fs->super->s_max_mnt_count > 0) &&
12733                  (fs->super->s_mnt_count >=
12734                   (unsigned) fs->super->s_max_mnt_count)) {
12735                 reason = _(" has been mounted %u times without being checked");
12736                 reason_arg = fs->super->s_mnt_count;
12737                 if (batt && (fs->super->s_mnt_count <
12738                              (unsigned) fs->super->s_max_mnt_count*2))
12739                         reason = 0;
12740         } else if (fs->super->s_checkinterval &&
12741                    ((now - fs->super->s_lastcheck) >=
12742                     fs->super->s_checkinterval)) {
12743                 reason = _(" has gone %u days without being checked");
12744                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12745                 if (batt && ((now - fs->super->s_lastcheck) <
12746                              fs->super->s_checkinterval*2))
12747                         reason = 0;
12748         }
12749         if (reason) {
12750                 fputs(ctx->device_name, stdout);
12751                 printf(reason, reason_arg);
12752                 fputs(_(", check forced.\n"), stdout);
12753                 return;
12754         }
12755         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12756                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12757                fs->super->s_inodes_count,
12758                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12759                fs->super->s_blocks_count);
12760         next_check = 100000;
12761         if (fs->super->s_max_mnt_count > 0) {
12762                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12763                 if (next_check <= 0)
12764                         next_check = 1;
12765         }
12766         if (fs->super->s_checkinterval &&
12767             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12768                 next_check = 1;
12769         if (next_check <= 5) {
12770                 if (next_check == 1)
12771                         fputs(_(" (check after next mount)"), stdout);
12772                 else
12773                         printf(_(" (check in %ld mounts)"), next_check);
12774         }
12775         fputc('\n', stdout);
12776         ext2fs_close(fs);
12777         ctx->fs = NULL;
12778         e2fsck_free_context(ctx);
12779         exit(EXIT_OK);
12780 }
12781
12782 /*
12783  * For completion notice
12784  */
12785 struct percent_tbl {
12786         int     max_pass;
12787         int     table[32];
12788 };
12789 static const struct percent_tbl e2fsck_tbl = {
12790         5, { 0, 70, 90, 92,  95, 100 }
12791 };
12792
12793 static char bar[128], spaces[128];
12794
12795 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12796                           int max)
12797 {
12798         float   percent;
12799
12800         if (pass <= 0)
12801                 return 0.0;
12802         if (pass > tbl->max_pass || max == 0)
12803                 return 100.0;
12804         percent = ((float) curr) / ((float) max);
12805         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12806                 + tbl->table[pass-1]);
12807 }
12808
12809 void e2fsck_clear_progbar(e2fsck_t ctx)
12810 {
12811         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12812                 return;
12813
12814         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12815                ctx->stop_meta);
12816         fflush(stdout);
12817         ctx->flags &= ~E2F_FLAG_PROG_BAR;
12818 }
12819
12820 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12821                            unsigned int dpynum)
12822 {
12823         static const char spinner[] = "\\|/-";
12824         int     i;
12825         unsigned int    tick;
12826         struct timeval  tv;
12827         int dpywidth;
12828         int fixed_percent;
12829
12830         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12831                 return 0;
12832
12833         /*
12834          * Calculate the new progress position.  If the
12835          * percentage hasn't changed, then we skip out right
12836          * away.
12837          */
12838         fixed_percent = (int) ((10 * percent) + 0.5);
12839         if (ctx->progress_last_percent == fixed_percent)
12840                 return 0;
12841         ctx->progress_last_percent = fixed_percent;
12842
12843         /*
12844          * If we've already updated the spinner once within
12845          * the last 1/8th of a second, no point doing it
12846          * again.
12847          */
12848         gettimeofday(&tv, NULL);
12849         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12850         if ((tick == ctx->progress_last_time) &&
12851             (fixed_percent != 0) && (fixed_percent != 1000))
12852                 return 0;
12853         ctx->progress_last_time = tick;
12854
12855         /*
12856          * Advance the spinner, and note that the progress bar
12857          * will be on the screen
12858          */
12859         ctx->progress_pos = (ctx->progress_pos+1) & 3;
12860         ctx->flags |= E2F_FLAG_PROG_BAR;
12861
12862         dpywidth = 66 - strlen(label);
12863         dpywidth = 8 * (dpywidth / 8);
12864         if (dpynum)
12865                 dpywidth -= 8;
12866
12867         i = ((percent * dpywidth) + 50) / 100;
12868         printf("%s%s: |%s%s", ctx->start_meta, label,
12869                bar + (sizeof(bar) - (i+1)),
12870                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12871         if (fixed_percent == 1000)
12872                 fputc('|', stdout);
12873         else
12874                 fputc(spinner[ctx->progress_pos & 3], stdout);
12875         printf(" %4.1f%%  ", percent);
12876         if (dpynum)
12877                 printf("%u\r", dpynum);
12878         else
12879                 fputs(" \r", stdout);
12880         fputs(ctx->stop_meta, stdout);
12881
12882         if (fixed_percent == 1000)
12883                 e2fsck_clear_progbar(ctx);
12884         fflush(stdout);
12885
12886         return 0;
12887 }
12888
12889 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12890                                   unsigned long cur, unsigned long max)
12891 {
12892         char buf[80];
12893         float percent;
12894
12895         if (pass == 0)
12896                 return 0;
12897
12898         if (ctx->progress_fd) {
12899                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12900                 write(ctx->progress_fd, buf, strlen(buf));
12901         } else {
12902                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12903                 e2fsck_simple_progress(ctx, ctx->device_name,
12904                                        percent, 0);
12905         }
12906         return 0;
12907 }
12908
12909 static void reserve_stdio_fds(void)
12910 {
12911         int     fd;
12912
12913         while (1) {
12914                 fd = open(bb_dev_null, O_RDWR);
12915                 if (fd > 2)
12916                         break;
12917                 if (fd < 0) {
12918                         fprintf(stderr, _("ERROR: Cannot open "
12919                                 "/dev/null (%s)\n"),
12920                                 strerror(errno));
12921                         break;
12922                 }
12923         }
12924         close(fd);
12925 }
12926
12927 static void signal_progress_on(int sig FSCK_ATTR((unused)))
12928 {
12929         e2fsck_t ctx = e2fsck_global_ctx;
12930
12931         if (!ctx)
12932                 return;
12933
12934         ctx->progress = e2fsck_update_progress;
12935         ctx->progress_fd = 0;
12936 }
12937
12938 static void signal_progress_off(int sig FSCK_ATTR((unused)))
12939 {
12940         e2fsck_t ctx = e2fsck_global_ctx;
12941
12942         if (!ctx)
12943                 return;
12944
12945         e2fsck_clear_progbar(ctx);
12946         ctx->progress = 0;
12947 }
12948
12949 static void signal_cancel(int sig FSCK_ATTR((unused)))
12950 {
12951         e2fsck_t ctx = e2fsck_global_ctx;
12952
12953         if (!ctx)
12954                 exit(FSCK_CANCELED);
12955
12956         ctx->flags |= E2F_FLAG_CANCEL;
12957 }
12958
12959 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12960 {
12961         char    *buf, *token, *next, *p, *arg;
12962         int     ea_ver;
12963         int     extended_usage = 0;
12964
12965         buf = string_copy(opts, 0);
12966         for (token = buf; token && *token; token = next) {
12967                 p = strchr(token, ',');
12968                 next = 0;
12969                 if (p) {
12970                         *p = 0;
12971                         next = p+1;
12972                 }
12973                 arg = strchr(token, '=');
12974                 if (arg) {
12975                         *arg = 0;
12976                         arg++;
12977                 }
12978                 if (strcmp(token, "ea_ver") == 0) {
12979                         if (!arg) {
12980                                 extended_usage++;
12981                                 continue;
12982                         }
12983                         ea_ver = strtoul(arg, &p, 0);
12984                         if (*p ||
12985                             ((ea_ver != 1) && (ea_ver != 2))) {
12986                                 fprintf(stderr,
12987                                         _("Invalid EA version.\n"));
12988                                 extended_usage++;
12989                                 continue;
12990                         }
12991                         ctx->ext_attr_ver = ea_ver;
12992                 } else {
12993                         fprintf(stderr, _("Unknown extended option: %s\n"),
12994                                 token);
12995                         extended_usage++;
12996                 }
12997         }
12998         if (extended_usage) {
12999                 bb_error_msg_and_die(
13000                         "Extended options are separated by commas, "
13001                         "and may take an argument which\n"
13002                         "is set off by an equals ('=') sign.  "
13003                         "Valid extended options are:\n"
13004                         "\tea_ver=<ea_version (1 or 2)>\n\n");
13005         }
13006 }
13007
13008
13009 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
13010 {
13011         int             flush = 0;
13012         int             c, fd;
13013         e2fsck_t        ctx;
13014         errcode_t       retval;
13015         struct sigaction        sa;
13016         char            *extended_opts = 0;
13017
13018         retval = e2fsck_allocate_context(&ctx);
13019         if (retval)
13020                 return retval;
13021
13022         *ret_ctx = ctx;
13023
13024         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
13025         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
13026         if (isatty(0) && isatty(1)) {
13027                 ctx->interactive = 1;
13028         } else {
13029                 ctx->start_meta[0] = '\001';
13030                 ctx->stop_meta[0] = '\002';
13031         }
13032         memset(bar, '=', sizeof(bar)-1);
13033         memset(spaces, ' ', sizeof(spaces)-1);
13034         blkid_get_cache(&ctx->blkid, NULL);
13035
13036         if (argc && *argv)
13037                 ctx->program_name = *argv;
13038         else
13039                 ctx->program_name = "e2fsck";
13040         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13041                 switch (c) {
13042                 case 'C':
13043                         ctx->progress = e2fsck_update_progress;
13044                         ctx->progress_fd = atoi(optarg);
13045                         if (!ctx->progress_fd)
13046                                 break;
13047                         /* Validate the file descriptor to avoid disasters */
13048                         fd = dup(ctx->progress_fd);
13049                         if (fd < 0) {
13050                                 fprintf(stderr,
13051                                 _("Error validating file descriptor %d: %s\n"),
13052                                         ctx->progress_fd,
13053                                         error_message(errno));
13054                                 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13055                         } else
13056                                 close(fd);
13057                         break;
13058                 case 'D':
13059                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
13060                         break;
13061                 case 'E':
13062                         extended_opts = optarg;
13063                         break;
13064                 case 'p':
13065                 case 'a':
13066                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13067                         conflict_opt:
13068                                 bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
13069                         }
13070                         ctx->options |= E2F_OPT_PREEN;
13071                         break;
13072                 case 'n':
13073                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13074                                 goto conflict_opt;
13075                         ctx->options |= E2F_OPT_NO;
13076                         break;
13077                 case 'y':
13078                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13079                                 goto conflict_opt;
13080                         ctx->options |= E2F_OPT_YES;
13081                         break;
13082                 case 't':
13083                         /* FIXME - This needs to go away in a future path - will change binary */
13084                         fprintf(stderr, _("The -t option is not "
13085                                 "supported on this version of e2fsck.\n"));
13086                         break;
13087                 case 'c':
13088                         if (cflag++)
13089                                 ctx->options |= E2F_OPT_WRITECHECK;
13090                         ctx->options |= E2F_OPT_CHECKBLOCKS;
13091                         break;
13092                 case 'r':
13093                         /* What we do by default, anyway! */
13094                         break;
13095                 case 'b':
13096                         ctx->use_superblock = atoi(optarg);
13097                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13098                         break;
13099                 case 'B':
13100                         ctx->blocksize = atoi(optarg);
13101                         break;
13102                 case 'I':
13103                         ctx->inode_buffer_blocks = atoi(optarg);
13104                         break;
13105                 case 'j':
13106                         ctx->journal_name = string_copy(optarg, 0);
13107                         break;
13108                 case 'P':
13109                         ctx->process_inode_size = atoi(optarg);
13110                         break;
13111                 case 'd':
13112                         ctx->options |= E2F_OPT_DEBUG;
13113                         break;
13114                 case 'f':
13115                         ctx->options |= E2F_OPT_FORCE;
13116                         break;
13117                 case 'F':
13118                         flush = 1;
13119                         break;
13120                 case 'v':
13121                         verbose = 1;
13122                         break;
13123                 case 'V':
13124                         show_version_only = 1;
13125                         break;
13126                 case 'N':
13127                         ctx->device_name = optarg;
13128                         break;
13129 #ifdef ENABLE_SWAPFS
13130                 case 's':
13131                         normalize_swapfs = 1;
13132                 case 'S':
13133                         swapfs = 1;
13134                         break;
13135 #else
13136                 case 's':
13137                 case 'S':
13138                         fprintf(stderr, _("Byte-swapping filesystems "
13139                                           "not compiled in this version "
13140                                           "of e2fsck\n"));
13141                         exit(1);
13142 #endif
13143                 default:
13144                         bb_show_usage();
13145                 }
13146         if (show_version_only)
13147                 return 0;
13148         if (optind != argc - 1)
13149                 bb_show_usage();
13150         if ((ctx->options & E2F_OPT_NO) &&
13151             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13152                 ctx->options |= E2F_OPT_READONLY;
13153         ctx->io_options = strchr(argv[optind], '?');
13154         if (ctx->io_options)
13155                 *ctx->io_options++ = 0;
13156         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13157         if (!ctx->filesystem_name) {
13158                 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13159                 bb_error_msg_and_die(0);
13160         }
13161         if (extended_opts)
13162                 parse_extended_opts(ctx, extended_opts);
13163
13164         if (flush) {
13165                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13166                 if (fd < 0) {
13167                         bb_error_msg(_("while opening %s for flushing"),
13168                                 ctx->filesystem_name);
13169                         bb_error_msg_and_die(0);
13170                 }
13171                 if ((retval = ext2fs_sync_device(fd, 1))) {
13172                         bb_error_msg(_("while trying to flush %s"),
13173                                 ctx->filesystem_name);
13174                         bb_error_msg_and_die(0);
13175                 }
13176                 close(fd);
13177         }
13178 #ifdef ENABLE_SWAPFS
13179         if (swapfs && cflag) {
13180                         fprintf(stderr, _("Incompatible options not "
13181                                           "allowed when byte-swapping.\n"));
13182                         exit(EXIT_USAGE);
13183         }
13184 #endif
13185         /*
13186          * Set up signal action
13187          */
13188         memset(&sa, 0, sizeof(struct sigaction));
13189         sa.sa_handler = signal_cancel;
13190         sigaction(SIGINT, &sa, 0);
13191         sigaction(SIGTERM, &sa, 0);
13192 #ifdef SA_RESTART
13193         sa.sa_flags = SA_RESTART;
13194 #endif
13195         e2fsck_global_ctx = ctx;
13196         sa.sa_handler = signal_progress_on;
13197         sigaction(SIGUSR1, &sa, 0);
13198         sa.sa_handler = signal_progress_off;
13199         sigaction(SIGUSR2, &sa, 0);
13200
13201         /* Update our PATH to include /sbin if we need to run badblocks  */
13202         if (cflag)
13203                 e2fs_set_sbin_path();
13204         return 0;
13205 }
13206
13207 static const char my_ver_string[] = E2FSPROGS_VERSION;
13208 static const char my_ver_date[] = E2FSPROGS_DATE;
13209
13210 int e2fsck_main (int argc, char *argv[])
13211 {
13212         errcode_t       retval;
13213         int             exit_value = EXIT_OK;
13214         ext2_filsys     fs = 0;
13215         io_manager      io_ptr;
13216         struct ext2_super_block *sb;
13217         const char      *lib_ver_date;
13218         int             my_ver, lib_ver;
13219         e2fsck_t        ctx;
13220         struct problem_context pctx;
13221         int flags, run_result;
13222
13223         clear_problem_context(&pctx);
13224
13225         my_ver = ext2fs_parse_version_string(my_ver_string);
13226         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13227         if (my_ver > lib_ver) {
13228                 fprintf( stderr, _("Error: ext2fs library version "
13229                         "out of date!\n"));
13230                 show_version_only++;
13231         }
13232
13233         retval = PRS(argc, argv, &ctx);
13234         if (retval) {
13235                 bb_error_msg(_("while trying to initialize program"));
13236                 exit(EXIT_ERROR);
13237         }
13238         reserve_stdio_fds();
13239
13240         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13241                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13242                          my_ver_date);
13243
13244         if (show_version_only) {
13245                 fprintf(stderr, _("\tUsing %s, %s\n"),
13246                         error_message(EXT2_ET_BASE), lib_ver_date);
13247                 exit(EXIT_OK);
13248         }
13249
13250         check_mount(ctx);
13251
13252         if (!(ctx->options & E2F_OPT_PREEN) &&
13253             !(ctx->options & E2F_OPT_NO) &&
13254             !(ctx->options & E2F_OPT_YES)) {
13255                 if (!ctx->interactive)
13256                         bb_error_msg_and_die(_("need terminal for interactive repairs"));
13257         }
13258         ctx->superblock = ctx->use_superblock;
13259 restart:
13260 #ifdef CONFIG_TESTIO_DEBUG
13261         io_ptr = test_io_manager;
13262         test_io_backing_manager = unix_io_manager;
13263 #else
13264         io_ptr = unix_io_manager;
13265 #endif
13266         flags = 0;
13267         if ((ctx->options & E2F_OPT_READONLY) == 0)
13268                 flags |= EXT2_FLAG_RW;
13269
13270         if (ctx->superblock && ctx->blocksize) {
13271                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13272                                       flags, ctx->superblock, ctx->blocksize,
13273                                       io_ptr, &fs);
13274         } else if (ctx->superblock) {
13275                 int blocksize;
13276                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13277                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13278                         retval = ext2fs_open2(ctx->filesystem_name,
13279                                               ctx->io_options, flags,
13280                                               ctx->superblock, blocksize,
13281                                               io_ptr, &fs);
13282                         if (!retval)
13283                                 break;
13284                 }
13285         } else
13286                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13287                                       flags, 0, 0, io_ptr, &fs);
13288         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13289             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13290             ((retval == EXT2_ET_BAD_MAGIC) ||
13291              ((retval == 0) && ext2fs_check_desc(fs)))) {
13292                 if (!fs || (fs->group_desc_count > 1)) {
13293                         printf(_("%s trying backup blocks...\n"),
13294                                retval ? _("Couldn't find ext2 superblock,") :
13295                                _("Group descriptors look bad..."));
13296                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13297                         if (fs)
13298                                 ext2fs_close(fs);
13299                         goto restart;
13300                 }
13301         }
13302         if (retval) {
13303                 bb_error_msg(_("while trying to open %s"),
13304                         ctx->filesystem_name);
13305                 if (retval == EXT2_ET_REV_TOO_HIGH) {
13306                         printf(_("The filesystem revision is apparently "
13307                                "too high for this version of e2fsck.\n"
13308                                "(Or the filesystem superblock "
13309                                "is corrupt)\n\n"));
13310                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13311                 } else if (retval == EXT2_ET_SHORT_READ)
13312                         printf(_("Could this be a zero-length partition?\n"));
13313                 else if ((retval == EPERM) || (retval == EACCES))
13314                         printf(_("You must have %s access to the "
13315                                "filesystem or be root\n"),
13316                                (ctx->options & E2F_OPT_READONLY) ?
13317                                "r/o" : "r/w");
13318                 else if (retval == ENXIO)
13319                         printf(_("Possibly non-existent or swap device?\n"));
13320 #ifdef EROFS
13321                 else if (retval == EROFS)
13322                         printf(_("Disk write-protected; use the -n option "
13323                                "to do a read-only\n"
13324                                "check of the device.\n"));
13325 #endif
13326                 else
13327                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13328                 bb_error_msg_and_die(0);
13329         }
13330         ctx->fs = fs;
13331         fs->priv_data = ctx;
13332         sb = fs->super;
13333         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13334                 bb_error_msg(_("while trying to open %s"),
13335                         ctx->filesystem_name);
13336         get_newer:
13337                 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13338         }
13339
13340         /*
13341          * Set the device name, which is used whenever we print error
13342          * or informational messages to the user.
13343          */
13344         if (ctx->device_name == 0 &&
13345             (sb->s_volume_name[0] != 0)) {
13346                 ctx->device_name = string_copy(sb->s_volume_name,
13347                                                sizeof(sb->s_volume_name));
13348         }
13349         if (ctx->device_name == 0)
13350                 ctx->device_name = ctx->filesystem_name;
13351
13352         /*
13353          * Make sure the ext3 superblock fields are consistent.
13354          */
13355         retval = e2fsck_check_ext3_journal(ctx);
13356         if (retval) {
13357                 bb_error_msg(_("while checking ext3 journal for %s"),
13358                         ctx->device_name);
13359                 bb_error_msg_and_die(0);
13360         }
13361
13362         /*
13363          * Check to see if we need to do ext3-style recovery.  If so,
13364          * do it, and then restart the fsck.
13365          */
13366         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13367                 if (ctx->options & E2F_OPT_READONLY) {
13368                         printf(_("Warning: skipping journal recovery "
13369                                  "because doing a read-only filesystem "
13370                                  "check.\n"));
13371                         io_channel_flush(ctx->fs->io);
13372                 } else {
13373                         if (ctx->flags & E2F_FLAG_RESTARTED) {
13374                                 /*
13375                                  * Whoops, we attempted to run the
13376                                  * journal twice.  This should never
13377                                  * happen, unless the hardware or
13378                                  * device driver is being bogus.
13379                                  */
13380                                 bb_error_msg(_("unable to set superblock flags on %s"), ctx->device_name);
13381                                 bb_error_msg_and_die(0);
13382                         }
13383                         retval = e2fsck_run_ext3_journal(ctx);
13384                         if (retval) {
13385                                 bb_error_msg(_("while recovering ext3 journal of %s"),
13386                                         ctx->device_name);
13387                                 bb_error_msg_and_die(0);
13388                         }
13389                         ext2fs_close(ctx->fs);
13390                         ctx->fs = 0;
13391                         ctx->flags |= E2F_FLAG_RESTARTED;
13392                         goto restart;
13393                 }
13394         }
13395
13396         /*
13397          * Check for compatibility with the feature sets.  We need to
13398          * be more stringent than ext2fs_open().
13399          */
13400         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13401             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13402                 bb_error_msg("(%s)", ctx->device_name);
13403                 goto get_newer;
13404         }
13405         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13406                 bb_error_msg("(%s)", ctx->device_name);
13407                 goto get_newer;
13408         }
13409 #ifdef ENABLE_COMPRESSION
13410         /* FIXME - do we support this at all? */
13411         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13412                 bb_error_msg(_("Warning: compression support is experimental."));
13413 #endif
13414 #ifndef ENABLE_HTREE
13415         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13416                 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13417                           "but filesystem %s has HTREE directories."),
13418                         ctx->device_name);
13419                 goto get_newer;
13420         }
13421 #endif
13422
13423         /*
13424          * If the user specified a specific superblock, presumably the
13425          * master superblock has been trashed.  So we mark the
13426          * superblock as dirty, so it can be written out.
13427          */
13428         if (ctx->superblock &&
13429             !(ctx->options & E2F_OPT_READONLY))
13430                 ext2fs_mark_super_dirty(fs);
13431
13432         /*
13433          * We only update the master superblock because (a) paranoia;
13434          * we don't want to corrupt the backup superblocks, and (b) we
13435          * don't need to update the mount count and last checked
13436          * fields in the backup superblock (the kernel doesn't
13437          * update the backup superblocks anyway).
13438          */
13439         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13440
13441         ehandler_init(fs->io);
13442
13443         if (ctx->superblock)
13444                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13445         ext2fs_mark_valid(fs);
13446         check_super_block(ctx);
13447         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13448                 bb_error_msg_and_die(0);
13449         check_if_skip(ctx);
13450         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13451                 bb_error_msg_and_die(0);
13452 #ifdef ENABLE_SWAPFS
13453
13454 #ifdef WORDS_BIGENDIAN
13455 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13456 #else
13457 #define NATIVE_FLAG 0
13458 #endif
13459
13460
13461         if (normalize_swapfs) {
13462                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13463                         fprintf(stderr, _("%s: Filesystem byte order "
13464                                 "already normalized.\n"), ctx->device_name);
13465                         bb_error_msg_and_die(0);
13466                 }
13467         }
13468         if (swapfs) {
13469                 swap_filesys(ctx);
13470                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13471                         bb_error_msg_and_die(0);
13472         }
13473 #endif
13474
13475         /*
13476          * Mark the system as valid, 'til proven otherwise
13477          */
13478         ext2fs_mark_valid(fs);
13479
13480         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13481         if (retval) {
13482                 bb_error_msg(_("while reading bad blocks inode"));
13483                 preenhalt(ctx);
13484                 printf(_("This doesn't bode well,"
13485                          " but we'll try to go on...\n"));
13486         }
13487
13488         run_result = e2fsck_run(ctx);
13489         e2fsck_clear_progbar(ctx);
13490         if (run_result == E2F_FLAG_RESTART) {
13491                 printf(_("Restarting e2fsck from the beginning...\n"));
13492                 retval = e2fsck_reset_context(ctx);
13493                 if (retval) {
13494                         bb_error_msg(_("while resetting context"));
13495                         bb_error_msg_and_die(0);
13496                 }
13497                 ext2fs_close(fs);
13498                 goto restart;
13499         }
13500         if (run_result & E2F_FLAG_CANCEL) {
13501                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13502                        ctx->device_name : ctx->filesystem_name);
13503                 exit_value |= FSCK_CANCELED;
13504         }
13505         if (run_result & E2F_FLAG_ABORT)
13506                 bb_error_msg_and_die(_("aborted"));
13507
13508         /* Cleanup */
13509         if (ext2fs_test_changed(fs)) {
13510                 exit_value |= EXIT_NONDESTRUCT;
13511                 if (!(ctx->options & E2F_OPT_PREEN))
13512                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13513                                ctx->device_name);
13514                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13515                         printf(_("%s: ***** REBOOT LINUX *****\n"),
13516                                ctx->device_name);
13517                         exit_value |= EXIT_DESTRUCT;
13518                 }
13519         }
13520         if (!ext2fs_test_valid(fs)) {
13521                 printf(_("\n%s: ********** WARNING: Filesystem still has "
13522                          "errors **********\n\n"), ctx->device_name);
13523                 exit_value |= EXIT_UNCORRECTED;
13524                 exit_value &= ~EXIT_NONDESTRUCT;
13525         }
13526         if (exit_value & FSCK_CANCELED)
13527                 exit_value &= ~EXIT_NONDESTRUCT;
13528         else {
13529                 show_stats(ctx);
13530                 if (!(ctx->options & E2F_OPT_READONLY)) {
13531                         if (ext2fs_test_valid(fs)) {
13532                                 if (!(sb->s_state & EXT2_VALID_FS))
13533                                         exit_value |= EXIT_NONDESTRUCT;
13534                                 sb->s_state = EXT2_VALID_FS;
13535                         } else
13536                                 sb->s_state &= ~EXT2_VALID_FS;
13537                         sb->s_mnt_count = 0;
13538                         sb->s_lastcheck = time(NULL);
13539                         ext2fs_mark_super_dirty(fs);
13540                 }
13541         }
13542
13543         e2fsck_write_bitmaps(ctx);
13544
13545         ext2fs_close(fs);
13546         ctx->fs = NULL;
13547         free(ctx->filesystem_name);
13548         free(ctx->journal_name);
13549         e2fsck_free_context(ctx);
13550
13551         return exit_value;
13552 }