Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 363589 byte(s)
-updated to busybox-1.13.4
1 niro 532 /* 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 niro 816 #define lock_buffer(bh) do {} while (0)
196     #define unlock_buffer(bh) do {} while (0)
197 niro 532 #define buffer_req(bh) 1
198 niro 816 #define do_readahead(journal, start) do {} while (0)
199 niro 532
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 niro 816 static const char *const journal_names[] = {
2172 niro 532 ".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 niro 816 const char *const * cpp;
2183 niro 532 int group, mount_flags;
2184    
2185     clear_problem_context(&pctx);
2186    
2187     /*
2188     * If the filesystem is opened read-only, or there is no
2189     * journal, then do nothing.
2190     */
2191     if ((ctx->options & E2F_OPT_READONLY) ||
2192     (sb->s_journal_inum == 0) ||
2193     !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2194     return;
2195    
2196     /*
2197     * Read in the journal inode
2198     */
2199     if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2200     return;
2201    
2202     /*
2203     * If it's necessary to backup the journal inode, do so.
2204     */
2205     if ((sb->s_jnl_backup_type == 0) ||
2206     ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2207     memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2208     if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2209     memcpy(sb->s_jnl_blocks, inode.i_block,
2210     EXT2_N_BLOCKS*4);
2211     sb->s_jnl_blocks[16] = inode.i_size;
2212     sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2213     ext2fs_mark_super_dirty(fs);
2214     fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2215     }
2216     }
2217    
2218     /*
2219     * If the journal is already the hidden inode, then do nothing
2220     */
2221     if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2222     return;
2223    
2224     /*
2225     * The journal inode had better have only one link and not be readable.
2226     */
2227     if (inode.i_links_count != 1)
2228     return;
2229    
2230     /*
2231     * If the filesystem is mounted, or we can't tell whether
2232     * or not it's mounted, do nothing.
2233     */
2234     retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2235     if (retval || (mount_flags & EXT2_MF_MOUNTED))
2236     return;
2237    
2238     /*
2239     * If we can't find the name of the journal inode, then do
2240     * nothing.
2241     */
2242     for (cpp = journal_names; *cpp; cpp++) {
2243     retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2244     strlen(*cpp), 0, &ino);
2245     if ((retval == 0) && (ino == sb->s_journal_inum))
2246     break;
2247     }
2248     if (*cpp == 0)
2249     return;
2250    
2251     /* We need the inode bitmap to be loaded */
2252     retval = ext2fs_read_bitmaps(fs);
2253     if (retval)
2254     return;
2255    
2256     pctx.str = *cpp;
2257     if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2258     return;
2259    
2260     /*
2261     * OK, we've done all the checks, let's actually move the
2262     * journal inode. Errors at this point mean we need to force
2263     * an ext2 filesystem check.
2264     */
2265     if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2266     goto err_out;
2267     if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2268     goto err_out;
2269     sb->s_journal_inum = EXT2_JOURNAL_INO;
2270     ext2fs_mark_super_dirty(fs);
2271     fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2272     inode.i_links_count = 0;
2273     inode.i_dtime = time(0);
2274     if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2275     goto err_out;
2276    
2277     group = ext2fs_group_of_ino(fs, ino);
2278     ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2279     ext2fs_mark_ib_dirty(fs);
2280     fs->group_desc[group].bg_free_inodes_count++;
2281     fs->super->s_free_inodes_count++;
2282     return;
2283    
2284     err_out:
2285     pctx.errcode = retval;
2286     fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2287     fs->super->s_state &= ~EXT2_VALID_FS;
2288     ext2fs_mark_super_dirty(fs);
2289     }
2290    
2291     /*
2292     * message.c --- print e2fsck messages (with compression)
2293     *
2294     * print_e2fsck_message() prints a message to the user, using
2295     * compression techniques and expansions of abbreviations.
2296     *
2297     * The following % expansions are supported:
2298     *
2299     * %b <blk> block number
2300     * %B <blkcount> integer
2301     * %c <blk2> block number
2302     * %Di <dirent>->ino inode number
2303     * %Dn <dirent>->name string
2304     * %Dr <dirent>->rec_len
2305     * %Dl <dirent>->name_len
2306     * %Dt <dirent>->filetype
2307     * %d <dir> inode number
2308     * %g <group> integer
2309     * %i <ino> inode number
2310     * %Is <inode> -> i_size
2311     * %IS <inode> -> i_extra_isize
2312     * %Ib <inode> -> i_blocks
2313     * %Il <inode> -> i_links_count
2314     * %Im <inode> -> i_mode
2315     * %IM <inode> -> i_mtime
2316     * %IF <inode> -> i_faddr
2317     * %If <inode> -> i_file_acl
2318     * %Id <inode> -> i_dir_acl
2319     * %Iu <inode> -> i_uid
2320     * %Ig <inode> -> i_gid
2321     * %j <ino2> inode number
2322     * %m <com_err error message>
2323     * %N <num>
2324     * %p ext2fs_get_pathname of directory <ino>
2325     * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2326     * the containing directory. (If dirent is NULL
2327     * then return the pathname of directory <ino2>)
2328     * %q ext2fs_get_pathname of directory <dir>
2329     * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2330     * the containing directory.
2331     * %s <str> miscellaneous string
2332     * %S backup superblock
2333     * %X <num> hexadecimal format
2334     *
2335     * The following '@' expansions are supported:
2336     *
2337     * @a extended attribute
2338     * @A error allocating
2339     * @b block
2340     * @B bitmap
2341     * @c compress
2342     * @C conflicts with some other fs block
2343     * @D deleted
2344     * @d directory
2345     * @e entry
2346     * @E Entry '%Dn' in %p (%i)
2347     * @f filesystem
2348     * @F for @i %i (%Q) is
2349     * @g group
2350     * @h HTREE directory inode
2351     * @i inode
2352     * @I illegal
2353     * @j journal
2354     * @l lost+found
2355     * @L is a link
2356     * @m multiply-claimed
2357     * @n invalid
2358     * @o orphaned
2359     * @p problem in
2360     * @r root inode
2361     * @s should be
2362     * @S superblock
2363     * @u unattached
2364     * @v device
2365     * @z zero-length
2366     */
2367    
2368    
2369     /*
2370     * This structure defines the abbreviations used by the text strings
2371     * below. The first character in the string is the index letter. An
2372     * abbreviation of the form '@<i>' is expanded by looking up the index
2373     * letter <i> in the table below.
2374     */
2375 niro 816 static const char *const abbrevs[] = {
2376 niro 532 N_("aextended attribute"),
2377     N_("Aerror allocating"),
2378     N_("bblock"),
2379     N_("Bbitmap"),
2380     N_("ccompress"),
2381     N_("Cconflicts with some other fs @b"),
2382     N_("iinode"),
2383     N_("Iillegal"),
2384     N_("jjournal"),
2385     N_("Ddeleted"),
2386     N_("ddirectory"),
2387     N_("eentry"),
2388     N_("E@e '%Dn' in %p (%i)"),
2389     N_("ffilesystem"),
2390     N_("Ffor @i %i (%Q) is"),
2391     N_("ggroup"),
2392     N_("hHTREE @d @i"),
2393     N_("llost+found"),
2394     N_("Lis a link"),
2395     N_("mmultiply-claimed"),
2396     N_("ninvalid"),
2397     N_("oorphaned"),
2398     N_("pproblem in"),
2399     N_("rroot @i"),
2400     N_("sshould be"),
2401     N_("Ssuper@b"),
2402     N_("uunattached"),
2403     N_("vdevice"),
2404     N_("zzero-length"),
2405     "@@",
2406     0
2407     };
2408    
2409     /*
2410     * Give more user friendly names to the "special" inodes.
2411     */
2412     #define num_special_inodes 11
2413 niro 816 static const char *const special_inode_name[] =
2414 niro 532 {
2415     N_("<The NULL inode>"), /* 0 */
2416     N_("<The bad blocks inode>"), /* 1 */
2417     "/", /* 2 */
2418     N_("<The ACL index inode>"), /* 3 */
2419     N_("<The ACL data inode>"), /* 4 */
2420     N_("<The boot loader inode>"), /* 5 */
2421     N_("<The undelete directory inode>"), /* 6 */
2422     N_("<The group descriptor inode>"), /* 7 */
2423     N_("<The journal inode>"), /* 8 */
2424     N_("<Reserved inode 9>"), /* 9 */
2425     N_("<Reserved inode 10>"), /* 10 */
2426     };
2427    
2428     /*
2429     * This function does "safe" printing. It will convert non-printable
2430     * ASCII characters using '^' and M- notation.
2431     */
2432     static void safe_print(const char *cp, int len)
2433     {
2434     unsigned char ch;
2435    
2436     if (len < 0)
2437     len = strlen(cp);
2438    
2439     while (len--) {
2440     ch = *cp++;
2441     if (ch > 128) {
2442     fputs("M-", stdout);
2443     ch -= 128;
2444     }
2445     if ((ch < 32) || (ch == 0x7f)) {
2446 niro 816 bb_putchar('^');
2447 niro 532 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2448     }
2449 niro 816 bb_putchar(ch);
2450 niro 532 }
2451     }
2452    
2453    
2454     /*
2455     * This function prints a pathname, using the ext2fs_get_pathname
2456     * function
2457     */
2458     static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2459     {
2460     errcode_t retval;
2461     char *path;
2462    
2463     if (!dir && (ino < num_special_inodes)) {
2464     fputs(_(special_inode_name[ino]), stdout);
2465     return;
2466     }
2467    
2468     retval = ext2fs_get_pathname(fs, dir, ino, &path);
2469     if (retval)
2470     fputs("???", stdout);
2471     else {
2472     safe_print(path, -1);
2473     ext2fs_free_mem(&path);
2474     }
2475     }
2476    
2477     static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2478     struct problem_context *pctx, int first);
2479     /*
2480     * This function handles the '@' expansion. We allow recursive
2481     * expansion; an @ expression can contain further '@' and '%'
2482     * expressions.
2483     */
2484     static void expand_at_expression(e2fsck_t ctx, char ch,
2485     struct problem_context *pctx,
2486     int *first)
2487     {
2488 niro 816 const char *const *cpp;
2489 niro 532 const char *str;
2490    
2491     /* Search for the abbreviation */
2492     for (cpp = abbrevs; *cpp; cpp++) {
2493     if (ch == *cpp[0])
2494     break;
2495     }
2496     if (*cpp) {
2497     str = _(*cpp) + 1;
2498     if (*first && islower(*str)) {
2499     *first = 0;
2500 niro 816 bb_putchar(toupper(*str++));
2501 niro 532 }
2502     print_e2fsck_message(ctx, str, pctx, *first);
2503     } else
2504     printf("@%c", ch);
2505     }
2506    
2507     /*
2508     * This function expands '%IX' expressions
2509     */
2510     static void expand_inode_expression(char ch,
2511     struct problem_context *ctx)
2512     {
2513     struct ext2_inode *inode;
2514     struct ext2_inode_large *large_inode;
2515     char * time_str;
2516     time_t t;
2517     int do_gmt = -1;
2518    
2519     if (!ctx || !ctx->inode)
2520     goto no_inode;
2521    
2522     inode = ctx->inode;
2523     large_inode = (struct ext2_inode_large *) inode;
2524    
2525     switch (ch) {
2526     case 's':
2527     if (LINUX_S_ISDIR(inode->i_mode))
2528     printf("%u", inode->i_size);
2529     else {
2530     printf("%"PRIu64, (inode->i_size |
2531     ((uint64_t) inode->i_size_high << 32)));
2532     }
2533     break;
2534     case 'S':
2535     printf("%u", large_inode->i_extra_isize);
2536     break;
2537     case 'b':
2538     printf("%u", inode->i_blocks);
2539     break;
2540     case 'l':
2541     printf("%d", inode->i_links_count);
2542     break;
2543     case 'm':
2544     printf("0%o", inode->i_mode);
2545     break;
2546     case 'M':
2547     /* The diet libc doesn't respect the TZ environemnt variable */
2548     if (do_gmt == -1) {
2549     time_str = getenv("TZ");
2550     if (!time_str)
2551     time_str = "";
2552     do_gmt = !strcmp(time_str, "GMT");
2553     }
2554     t = inode->i_mtime;
2555     time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2556     printf("%.24s", time_str);
2557     break;
2558     case 'F':
2559     printf("%u", inode->i_faddr);
2560     break;
2561     case 'f':
2562     printf("%u", inode->i_file_acl);
2563     break;
2564     case 'd':
2565     printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2566     inode->i_dir_acl : 0));
2567     break;
2568     case 'u':
2569     printf("%d", (inode->i_uid |
2570     (inode->osd2.linux2.l_i_uid_high << 16)));
2571     break;
2572     case 'g':
2573     printf("%d", (inode->i_gid |
2574     (inode->osd2.linux2.l_i_gid_high << 16)));
2575     break;
2576     default:
2577     no_inode:
2578     printf("%%I%c", ch);
2579     break;
2580     }
2581     }
2582    
2583     /*
2584     * This function expands '%dX' expressions
2585     */
2586     static void expand_dirent_expression(char ch,
2587     struct problem_context *ctx)
2588     {
2589     struct ext2_dir_entry *dirent;
2590     int len;
2591    
2592     if (!ctx || !ctx->dirent)
2593     goto no_dirent;
2594    
2595     dirent = ctx->dirent;
2596    
2597     switch (ch) {
2598     case 'i':
2599     printf("%u", dirent->inode);
2600     break;
2601     case 'n':
2602     len = dirent->name_len & 0xFF;
2603     if (len > EXT2_NAME_LEN)
2604     len = EXT2_NAME_LEN;
2605     if (len > dirent->rec_len)
2606     len = dirent->rec_len;
2607     safe_print(dirent->name, len);
2608     break;
2609     case 'r':
2610     printf("%u", dirent->rec_len);
2611     break;
2612     case 'l':
2613     printf("%u", dirent->name_len & 0xFF);
2614     break;
2615     case 't':
2616     printf("%u", dirent->name_len >> 8);
2617     break;
2618     default:
2619     no_dirent:
2620     printf("%%D%c", ch);
2621     break;
2622     }
2623     }
2624    
2625     static void expand_percent_expression(ext2_filsys fs, char ch,
2626     struct problem_context *ctx)
2627     {
2628     if (!ctx)
2629     goto no_context;
2630    
2631     switch (ch) {
2632     case '%':
2633 niro 816 bb_putchar('%');
2634 niro 532 break;
2635     case 'b':
2636     printf("%u", ctx->blk);
2637     break;
2638     case 'B':
2639     printf("%"PRIi64, ctx->blkcount);
2640     break;
2641     case 'c':
2642     printf("%u", ctx->blk2);
2643     break;
2644     case 'd':
2645     printf("%u", ctx->dir);
2646     break;
2647     case 'g':
2648     printf("%d", ctx->group);
2649     break;
2650     case 'i':
2651     printf("%u", ctx->ino);
2652     break;
2653     case 'j':
2654     printf("%u", ctx->ino2);
2655     break;
2656     case 'm':
2657 niro 816 fputs(error_message(ctx->errcode), stdout);
2658 niro 532 break;
2659     case 'N':
2660     printf("%"PRIi64, ctx->num);
2661     break;
2662     case 'p':
2663     print_pathname(fs, ctx->ino, 0);
2664     break;
2665     case 'P':
2666     print_pathname(fs, ctx->ino2,
2667     ctx->dirent ? ctx->dirent->inode : 0);
2668     break;
2669     case 'q':
2670     print_pathname(fs, ctx->dir, 0);
2671     break;
2672     case 'Q':
2673     print_pathname(fs, ctx->dir, ctx->ino);
2674     break;
2675     case 'S':
2676     printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2677     break;
2678     case 's':
2679 niro 816 fputs((ctx->str ? ctx->str : "NULL"), stdout);
2680 niro 532 break;
2681     case 'X':
2682     printf("0x%"PRIi64, ctx->num);
2683     break;
2684     default:
2685     no_context:
2686     printf("%%%c", ch);
2687     break;
2688     }
2689     }
2690    
2691    
2692     static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2693     struct problem_context *pctx, int first)
2694     {
2695     ext2_filsys fs = ctx->fs;
2696     const char * cp;
2697     int i;
2698    
2699     e2fsck_clear_progbar(ctx);
2700     for (cp = msg; *cp; cp++) {
2701     if (cp[0] == '@') {
2702     cp++;
2703     expand_at_expression(ctx, *cp, pctx, &first);
2704     } else if (cp[0] == '%' && cp[1] == 'I') {
2705     cp += 2;
2706     expand_inode_expression(*cp, pctx);
2707     } else if (cp[0] == '%' && cp[1] == 'D') {
2708     cp += 2;
2709     expand_dirent_expression(*cp, pctx);
2710     } else if ((cp[0] == '%')) {
2711     cp++;
2712     expand_percent_expression(fs, *cp, pctx);
2713     } else {
2714     for (i=0; cp[i]; i++)
2715     if ((cp[i] == '@') || cp[i] == '%')
2716     break;
2717     printf("%.*s", i, cp);
2718     cp += i-1;
2719     }
2720     first = 0;
2721     }
2722     }
2723    
2724    
2725     /*
2726     * region.c --- code which manages allocations within a region.
2727     */
2728    
2729     struct region_el {
2730     region_addr_t start;
2731     region_addr_t end;
2732     struct region_el *next;
2733     };
2734    
2735     struct region_struct {
2736     region_addr_t min;
2737     region_addr_t max;
2738     struct region_el *allocated;
2739     };
2740    
2741     static region_t region_create(region_addr_t min, region_addr_t max)
2742     {
2743     region_t region;
2744    
2745     region = malloc(sizeof(struct region_struct));
2746     if (!region)
2747     return NULL;
2748     memset(region, 0, sizeof(struct region_struct));
2749     region->min = min;
2750     region->max = max;
2751     return region;
2752     }
2753    
2754     static void region_free(region_t region)
2755     {
2756     struct region_el *r, *next;
2757    
2758     for (r = region->allocated; r; r = next) {
2759     next = r->next;
2760     free(r);
2761     }
2762     memset(region, 0, sizeof(struct region_struct));
2763     free(region);
2764     }
2765    
2766     static int region_allocate(region_t region, region_addr_t start, int n)
2767     {
2768     struct region_el *r, *new_region, *prev, *next;
2769     region_addr_t end;
2770    
2771     end = start+n;
2772     if ((start < region->min) || (end > region->max))
2773     return -1;
2774     if (n == 0)
2775     return 1;
2776    
2777     /*
2778     * Search through the linked list. If we find that it
2779     * conflicts witih something that's already allocated, return
2780     * 1; if we can find an existing region which we can grow, do
2781     * so. Otherwise, stop when we find the appropriate place
2782     * insert a new region element into the linked list.
2783     */
2784     for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2785     if (((start >= r->start) && (start < r->end)) ||
2786     ((end > r->start) && (end <= r->end)) ||
2787     ((start <= r->start) && (end >= r->end)))
2788     return 1;
2789     if (end == r->start) {
2790     r->start = start;
2791     return 0;
2792     }
2793     if (start == r->end) {
2794     if ((next = r->next)) {
2795     if (end > next->start)
2796     return 1;
2797     if (end == next->start) {
2798     r->end = next->end;
2799     r->next = next->next;
2800     free(next);
2801     return 0;
2802     }
2803     }
2804     r->end = end;
2805     return 0;
2806     }
2807     if (start < r->start)
2808     break;
2809     }
2810     /*
2811     * Insert a new region element structure into the linked list
2812     */
2813     new_region = malloc(sizeof(struct region_el));
2814     if (!new_region)
2815     return -1;
2816     new_region->start = start;
2817     new_region->end = start + n;
2818     new_region->next = r;
2819     if (prev)
2820     prev->next = new_region;
2821     else
2822     region->allocated = new_region;
2823     return 0;
2824     }
2825    
2826     /*
2827     * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2828     *
2829     * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2830     * and applies the following tests to each inode:
2831     *
2832     * - The mode field of the inode must be legal.
2833     * - The size and block count fields of the inode are correct.
2834     * - A data block must not be used by another inode
2835     *
2836     * Pass 1 also gathers the collects the following information:
2837     *
2838     * - A bitmap of which inodes are in use. (inode_used_map)
2839     * - A bitmap of which inodes are directories. (inode_dir_map)
2840     * - A bitmap of which inodes are regular files. (inode_reg_map)
2841     * - A bitmap of which inodes have bad fields. (inode_bad_map)
2842     * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2843     * - A bitmap of which blocks are in use. (block_found_map)
2844     * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2845     * - The data blocks of the directory inodes. (dir_map)
2846     *
2847     * Pass 1 is designed to stash away enough information so that the
2848     * other passes should not need to read in the inode information
2849     * during the normal course of a filesystem check. (Althogh if an
2850     * inconsistency is detected, other passes may need to read in an
2851     * inode to fix it.)
2852     *
2853     * Note that pass 1B will be invoked if there are any duplicate blocks
2854     * found.
2855     */
2856    
2857    
2858     static int process_block(ext2_filsys fs, blk_t *blocknr,
2859     e2_blkcnt_t blockcnt, blk_t ref_blk,
2860     int ref_offset, void *priv_data);
2861     static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2862     e2_blkcnt_t blockcnt, blk_t ref_blk,
2863     int ref_offset, void *priv_data);
2864     static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2865     char *block_buf);
2866     static void mark_table_blocks(e2fsck_t ctx);
2867     static void alloc_imagic_map(e2fsck_t ctx);
2868     static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2869     static void handle_fs_bad_blocks(e2fsck_t ctx);
2870     static void process_inodes(e2fsck_t ctx, char *block_buf);
2871     static int process_inode_cmp(const void *a, const void *b);
2872     static errcode_t scan_callback(ext2_filsys fs,
2873     dgrp_t group, void * priv_data);
2874     static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2875     char *block_buf, int adjust_sign);
2876     /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2877    
2878     static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2879     struct ext2_inode * inode, int bufsize,
2880     const char *proc);
2881    
2882     struct process_block_struct_1 {
2883     ext2_ino_t ino;
2884     unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2885     fragmented:1, compressed:1, bbcheck:1;
2886     blk_t num_blocks;
2887     blk_t max_blocks;
2888     e2_blkcnt_t last_block;
2889     int num_illegal_blocks;
2890     blk_t previous_block;
2891     struct ext2_inode *inode;
2892     struct problem_context *pctx;
2893     ext2fs_block_bitmap fs_meta_blocks;
2894     e2fsck_t ctx;
2895     };
2896    
2897     struct process_inode_block {
2898     ext2_ino_t ino;
2899     struct ext2_inode inode;
2900     };
2901    
2902     struct scan_callback_struct {
2903     e2fsck_t ctx;
2904     char *block_buf;
2905     };
2906    
2907     /*
2908     * For the inodes to process list.
2909     */
2910     static struct process_inode_block *inodes_to_process;
2911     static int process_inode_count;
2912    
2913     static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2914     EXT2_MIN_BLOCK_LOG_SIZE + 1];
2915    
2916     /*
2917     * Free all memory allocated by pass1 in preparation for restarting
2918     * things.
2919     */
2920     static void unwind_pass1(void)
2921     {
2922     ext2fs_free_mem(&inodes_to_process);
2923     }
2924    
2925     /*
2926     * Check to make sure a device inode is real. Returns 1 if the device
2927     * checks out, 0 if not.
2928     *
2929     * Note: this routine is now also used to check FIFO's and Sockets,
2930     * since they have the same requirement; the i_block fields should be
2931     * zero.
2932     */
2933     static int
2934     e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2935     {
2936     int i;
2937    
2938     /*
2939     * If i_blocks is non-zero, or the index flag is set, then
2940     * this is a bogus device/fifo/socket
2941     */
2942     if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2943     (inode->i_flags & EXT2_INDEX_FL))
2944     return 0;
2945    
2946     /*
2947     * We should be able to do the test below all the time, but
2948     * because the kernel doesn't forcibly clear the device
2949     * inode's additional i_block fields, there are some rare
2950     * occasions when a legitimate device inode will have non-zero
2951     * additional i_block fields. So for now, we only complain
2952     * when the immutable flag is set, which should never happen
2953     * for devices. (And that's when the problem is caused, since
2954     * you can't set or clear immutable flags for devices.) Once
2955     * the kernel has been fixed we can change this...
2956     */
2957     if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2958     for (i=4; i < EXT2_N_BLOCKS; i++)
2959     if (inode->i_block[i])
2960     return 0;
2961     }
2962     return 1;
2963     }
2964    
2965     /*
2966     * Check to make sure a symlink inode is real. Returns 1 if the symlink
2967     * checks out, 0 if not.
2968     */
2969     static int
2970     e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2971     {
2972     unsigned int len;
2973     int i;
2974     blk_t blocks;
2975    
2976     if ((inode->i_size_high || inode->i_size == 0) ||
2977     (inode->i_flags & EXT2_INDEX_FL))
2978     return 0;
2979    
2980     blocks = ext2fs_inode_data_blocks(fs, inode);
2981     if (blocks) {
2982     if ((inode->i_size >= fs->blocksize) ||
2983     (blocks != fs->blocksize >> 9) ||
2984     (inode->i_block[0] < fs->super->s_first_data_block) ||
2985     (inode->i_block[0] >= fs->super->s_blocks_count))
2986     return 0;
2987    
2988     for (i = 1; i < EXT2_N_BLOCKS; i++)
2989     if (inode->i_block[i])
2990     return 0;
2991    
2992     if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2993     return 0;
2994    
2995     len = strnlen(buf, fs->blocksize);
2996     if (len == fs->blocksize)
2997     return 0;
2998     } else {
2999     if (inode->i_size >= sizeof(inode->i_block))
3000     return 0;
3001    
3002     len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3003     if (len == sizeof(inode->i_block))
3004     return 0;
3005     }
3006     if (len != inode->i_size)
3007     return 0;
3008     return 1;
3009     }
3010    
3011     /*
3012     * If the immutable (or append-only) flag is set on the inode, offer
3013     * to clear it.
3014     */
3015     #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3016     static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3017     {
3018     if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3019     return;
3020    
3021     if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3022     return;
3023    
3024     pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3025     e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3026     }
3027    
3028     /*
3029     * If device, fifo or socket, check size is zero -- if not offer to
3030     * clear it
3031     */
3032     static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3033     {
3034     struct ext2_inode *inode = pctx->inode;
3035    
3036     if ((inode->i_size == 0) && (inode->i_size_high == 0))
3037     return;
3038    
3039     if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3040     return;
3041    
3042     inode->i_size = 0;
3043     inode->i_size_high = 0;
3044     e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3045     }
3046    
3047     static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3048     {
3049     struct ext2_super_block *sb = ctx->fs->super;
3050     struct ext2_inode_large *inode;
3051     struct ext2_ext_attr_entry *entry;
3052     char *start, *end;
3053     int storage_size, remain, offs;
3054     int problem = 0;
3055    
3056     inode = (struct ext2_inode_large *) pctx->inode;
3057     storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3058     inode->i_extra_isize;
3059     start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3060     inode->i_extra_isize + sizeof(__u32);
3061     end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3062     entry = (struct ext2_ext_attr_entry *) start;
3063    
3064     /* scan all entry's headers first */
3065    
3066     /* take finish entry 0UL into account */
3067     remain = storage_size - sizeof(__u32);
3068     offs = end - start;
3069    
3070     while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3071    
3072     /* header eats this space */
3073     remain -= sizeof(struct ext2_ext_attr_entry);
3074    
3075     /* is attribute name valid? */
3076     if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3077     pctx->num = entry->e_name_len;
3078     problem = PR_1_ATTR_NAME_LEN;
3079     goto fix;
3080     }
3081    
3082     /* attribute len eats this space */
3083     remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3084    
3085     /* check value size */
3086     if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3087     pctx->num = entry->e_value_size;
3088     problem = PR_1_ATTR_VALUE_SIZE;
3089     goto fix;
3090     }
3091    
3092     /* check value placement */
3093     if (entry->e_value_offs +
3094     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3095     printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3096     pctx->num = entry->e_value_offs;
3097     problem = PR_1_ATTR_VALUE_OFFSET;
3098     goto fix;
3099     }
3100    
3101     /* e_value_block must be 0 in inode's ea */
3102     if (entry->e_value_block != 0) {
3103     pctx->num = entry->e_value_block;
3104     problem = PR_1_ATTR_VALUE_BLOCK;
3105     goto fix;
3106     }
3107    
3108     /* e_hash must be 0 in inode's ea */
3109     if (entry->e_hash != 0) {
3110     pctx->num = entry->e_hash;
3111     problem = PR_1_ATTR_HASH;
3112     goto fix;
3113     }
3114    
3115     remain -= entry->e_value_size;
3116     offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3117    
3118     entry = EXT2_EXT_ATTR_NEXT(entry);
3119     }
3120     fix:
3121     /*
3122     * it seems like a corruption. it's very unlikely we could repair
3123     * EA(s) in automatic fashion -bzzz
3124     */
3125     if (problem == 0 || !fix_problem(ctx, problem, pctx))
3126     return;
3127    
3128     /* simple remove all possible EA(s) */
3129     *((__u32 *)start) = 0UL;
3130     e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3131     EXT2_INODE_SIZE(sb), "pass1");
3132     }
3133    
3134     static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3135     {
3136     struct ext2_super_block *sb = ctx->fs->super;
3137     struct ext2_inode_large *inode;
3138     __u32 *eamagic;
3139     int min, max;
3140    
3141     inode = (struct ext2_inode_large *) pctx->inode;
3142     if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3143     /* this isn't large inode. so, nothing to check */
3144     return;
3145     }
3146    
3147     /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3148     min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3149     max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3150     /*
3151     * For now we will allow i_extra_isize to be 0, but really
3152     * implementations should never allow i_extra_isize to be 0
3153     */
3154     if (inode->i_extra_isize &&
3155     (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3156     if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3157     return;
3158     inode->i_extra_isize = min;
3159     e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3160     EXT2_INODE_SIZE(sb), "pass1");
3161     return;
3162     }
3163    
3164     eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3165     inode->i_extra_isize);
3166     if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3167     /* it seems inode has an extended attribute(s) in body */
3168     check_ea_in_inode(ctx, pctx);
3169     }
3170     }
3171    
3172     static void e2fsck_pass1(e2fsck_t ctx)
3173     {
3174     int i;
3175     __u64 max_sizes;
3176     ext2_filsys fs = ctx->fs;
3177     ext2_ino_t ino;
3178     struct ext2_inode *inode;
3179     ext2_inode_scan scan;
3180     char *block_buf;
3181     unsigned char frag, fsize;
3182     struct problem_context pctx;
3183     struct scan_callback_struct scan_struct;
3184     struct ext2_super_block *sb = ctx->fs->super;
3185     int imagic_fs;
3186     int busted_fs_time = 0;
3187     int inode_size;
3188    
3189     clear_problem_context(&pctx);
3190    
3191     if (!(ctx->options & E2F_OPT_PREEN))
3192     fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3193    
3194     if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3195     !(ctx->options & E2F_OPT_NO)) {
3196     if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3197     ctx->dirs_to_hash = 0;
3198     }
3199    
3200     /* Pass 1 */
3201    
3202     #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3203    
3204     for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3205     max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3206     max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3207     max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3208     max_sizes = (max_sizes * (1UL << i)) - 1;
3209     ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3210     }
3211     #undef EXT2_BPP
3212    
3213     imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3214    
3215     /*
3216     * Allocate bitmaps structures
3217     */
3218     pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3219     &ctx->inode_used_map);
3220     if (pctx.errcode) {
3221     pctx.num = 1;
3222     fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3223     ctx->flags |= E2F_FLAG_ABORT;
3224     return;
3225     }
3226     pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3227     _("directory inode map"), &ctx->inode_dir_map);
3228     if (pctx.errcode) {
3229     pctx.num = 2;
3230     fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3231     ctx->flags |= E2F_FLAG_ABORT;
3232     return;
3233     }
3234     pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3235     _("regular file inode map"), &ctx->inode_reg_map);
3236     if (pctx.errcode) {
3237     pctx.num = 6;
3238     fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3239     ctx->flags |= E2F_FLAG_ABORT;
3240     return;
3241     }
3242     pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3243     &ctx->block_found_map);
3244     if (pctx.errcode) {
3245     pctx.num = 1;
3246     fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3247     ctx->flags |= E2F_FLAG_ABORT;
3248     return;
3249     }
3250     pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3251     &ctx->inode_link_info);
3252     if (pctx.errcode) {
3253     fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3254     ctx->flags |= E2F_FLAG_ABORT;
3255     return;
3256     }
3257     inode_size = EXT2_INODE_SIZE(fs->super);
3258     inode = (struct ext2_inode *)
3259     e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3260    
3261     inodes_to_process = (struct process_inode_block *)
3262     e2fsck_allocate_memory(ctx,
3263     (ctx->process_inode_size *
3264     sizeof(struct process_inode_block)),
3265     "array of inodes to process");
3266     process_inode_count = 0;
3267    
3268     pctx.errcode = ext2fs_init_dblist(fs, 0);
3269     if (pctx.errcode) {
3270     fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3271     ctx->flags |= E2F_FLAG_ABORT;
3272     return;
3273     }
3274    
3275     /*
3276     * If the last orphan field is set, clear it, since the pass1
3277     * processing will automatically find and clear the orphans.
3278     * In the future, we may want to try using the last_orphan
3279     * linked list ourselves, but for now, we clear it so that the
3280     * ext3 mount code won't get confused.
3281     */
3282     if (!(ctx->options & E2F_OPT_READONLY)) {
3283     if (fs->super->s_last_orphan) {
3284     fs->super->s_last_orphan = 0;
3285     ext2fs_mark_super_dirty(fs);
3286     }
3287     }
3288    
3289     mark_table_blocks(ctx);
3290     block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3291     "block interate buffer");
3292     e2fsck_use_inode_shortcuts(ctx, 1);
3293     ehandler_operation(_("doing inode scan"));
3294     pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3295     &scan);
3296     if (pctx.errcode) {
3297     fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3298     ctx->flags |= E2F_FLAG_ABORT;
3299     return;
3300     }
3301     ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3302     ctx->stashed_inode = inode;
3303     scan_struct.ctx = ctx;
3304     scan_struct.block_buf = block_buf;
3305     ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3306     if (ctx->progress)
3307     if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3308     return;
3309     if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3310     (fs->super->s_mtime < fs->super->s_inodes_count))
3311     busted_fs_time = 1;
3312    
3313     while (1) {
3314     pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3315     inode, inode_size);
3316     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3317     return;
3318     if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3319     continue;
3320     }
3321     if (pctx.errcode) {
3322     fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3323     ctx->flags |= E2F_FLAG_ABORT;
3324     return;
3325     }
3326     if (!ino)
3327     break;
3328     pctx.ino = ino;
3329     pctx.inode = inode;
3330     ctx->stashed_ino = ino;
3331     if (inode->i_links_count) {
3332     pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3333     ino, inode->i_links_count);
3334     if (pctx.errcode) {
3335     pctx.num = inode->i_links_count;
3336     fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3337     ctx->flags |= E2F_FLAG_ABORT;
3338     return;
3339     }
3340     }
3341     if (ino == EXT2_BAD_INO) {
3342     struct process_block_struct_1 pb;
3343    
3344     pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3345     &pb.fs_meta_blocks);
3346     if (pctx.errcode) {
3347     pctx.num = 4;
3348     fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3349     ctx->flags |= E2F_FLAG_ABORT;
3350     return;
3351     }
3352     pb.ino = EXT2_BAD_INO;
3353     pb.num_blocks = pb.last_block = 0;
3354     pb.num_illegal_blocks = 0;
3355     pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3356     pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3357     pb.inode = inode;
3358     pb.pctx = &pctx;
3359     pb.ctx = ctx;
3360     pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3361     block_buf, process_bad_block, &pb);
3362     ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3363     if (pctx.errcode) {
3364     fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3365     ctx->flags |= E2F_FLAG_ABORT;
3366     return;
3367     }
3368     if (pb.bbcheck)
3369     if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3370     ctx->flags |= E2F_FLAG_ABORT;
3371     return;
3372     }
3373     ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3374     clear_problem_context(&pctx);
3375     continue;
3376     } else if (ino == EXT2_ROOT_INO) {
3377     /*
3378     * Make sure the root inode is a directory; if
3379     * not, offer to clear it. It will be
3380     * regnerated in pass #3.
3381     */
3382     if (!LINUX_S_ISDIR(inode->i_mode)) {
3383     if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3384     inode->i_dtime = time(0);
3385     inode->i_links_count = 0;
3386     ext2fs_icount_store(ctx->inode_link_info,
3387     ino, 0);
3388     e2fsck_write_inode(ctx, ino, inode,
3389     "pass1");
3390     }
3391    
3392     }
3393     /*
3394     * If dtime is set, offer to clear it. mke2fs
3395     * version 0.2b created filesystems with the
3396     * dtime field set for the root and lost+found
3397     * directories. We won't worry about
3398     * /lost+found, since that can be regenerated
3399     * easily. But we will fix the root directory
3400     * as a special case.
3401     */
3402     if (inode->i_dtime && inode->i_links_count) {
3403     if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3404     inode->i_dtime = 0;
3405     e2fsck_write_inode(ctx, ino, inode,
3406     "pass1");
3407     }
3408     }
3409     } else if (ino == EXT2_JOURNAL_INO) {
3410     ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3411     if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3412     if (!LINUX_S_ISREG(inode->i_mode) &&
3413     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3414     &pctx)) {
3415     inode->i_mode = LINUX_S_IFREG;
3416     e2fsck_write_inode(ctx, ino, inode,
3417     "pass1");
3418     }
3419     check_blocks(ctx, &pctx, block_buf);
3420     continue;
3421     }
3422     if ((inode->i_links_count || inode->i_blocks ||
3423     inode->i_blocks || inode->i_block[0]) &&
3424     fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3425     &pctx)) {
3426     memset(inode, 0, inode_size);
3427     ext2fs_icount_store(ctx->inode_link_info,
3428     ino, 0);
3429     e2fsck_write_inode_full(ctx, ino, inode,
3430     inode_size, "pass1");
3431     }
3432     } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3433     int problem = 0;
3434    
3435     ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3436     if (ino == EXT2_BOOT_LOADER_INO) {
3437     if (LINUX_S_ISDIR(inode->i_mode))
3438     problem = PR_1_RESERVED_BAD_MODE;
3439     } else if (ino == EXT2_RESIZE_INO) {
3440     if (inode->i_mode &&
3441     !LINUX_S_ISREG(inode->i_mode))
3442     problem = PR_1_RESERVED_BAD_MODE;
3443     } else {
3444     if (inode->i_mode != 0)
3445     problem = PR_1_RESERVED_BAD_MODE;
3446     }
3447     if (problem) {
3448     if (fix_problem(ctx, problem, &pctx)) {
3449     inode->i_mode = 0;
3450     e2fsck_write_inode(ctx, ino, inode,
3451     "pass1");
3452     }
3453     }
3454     check_blocks(ctx, &pctx, block_buf);
3455     continue;
3456     }
3457     /*
3458     * Check for inodes who might have been part of the
3459     * orphaned list linked list. They should have gotten
3460     * dealt with by now, unless the list had somehow been
3461     * corrupted.
3462     *
3463     * FIXME: In the future, inodes which are still in use
3464     * (and which are therefore) pending truncation should
3465     * be handled specially. Right now we just clear the
3466     * dtime field, and the normal e2fsck handling of
3467     * inodes where i_size and the inode blocks are
3468     * inconsistent is to fix i_size, instead of releasing
3469     * the extra blocks. This won't catch the inodes that
3470     * was at the end of the orphan list, but it's better
3471     * than nothing. The right answer is that there
3472     * shouldn't be any bugs in the orphan list handling. :-)
3473     */
3474     if (inode->i_dtime && !busted_fs_time &&
3475     inode->i_dtime < ctx->fs->super->s_inodes_count) {
3476     if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3477     inode->i_dtime = inode->i_links_count ?
3478     0 : time(0);
3479     e2fsck_write_inode(ctx, ino, inode,
3480     "pass1");
3481     }
3482     }
3483    
3484     /*
3485     * This code assumes that deleted inodes have
3486     * i_links_count set to 0.
3487     */
3488     if (!inode->i_links_count) {
3489     if (!inode->i_dtime && inode->i_mode) {
3490     if (fix_problem(ctx,
3491     PR_1_ZERO_DTIME, &pctx)) {
3492     inode->i_dtime = time(0);
3493     e2fsck_write_inode(ctx, ino, inode,
3494     "pass1");
3495     }
3496     }
3497     continue;
3498     }
3499     /*
3500     * n.b. 0.3c ext2fs code didn't clear i_links_count for
3501     * deleted files. Oops.
3502     *
3503     * Since all new ext2 implementations get this right,
3504     * we now assume that the case of non-zero
3505     * i_links_count and non-zero dtime means that we
3506     * should keep the file, not delete it.
3507     *
3508     */
3509     if (inode->i_dtime) {
3510     if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3511     inode->i_dtime = 0;
3512     e2fsck_write_inode(ctx, ino, inode, "pass1");
3513     }
3514     }
3515    
3516     ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3517     switch (fs->super->s_creator_os) {
3518     case EXT2_OS_LINUX:
3519     frag = inode->osd2.linux2.l_i_frag;
3520     fsize = inode->osd2.linux2.l_i_fsize;
3521     break;
3522     case EXT2_OS_HURD:
3523     frag = inode->osd2.hurd2.h_i_frag;
3524     fsize = inode->osd2.hurd2.h_i_fsize;
3525     break;
3526     case EXT2_OS_MASIX:
3527     frag = inode->osd2.masix2.m_i_frag;
3528     fsize = inode->osd2.masix2.m_i_fsize;
3529     break;
3530     default:
3531     frag = fsize = 0;
3532     }
3533    
3534     if (inode->i_faddr || frag || fsize ||
3535     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3536     mark_inode_bad(ctx, ino);
3537     if (inode->i_flags & EXT2_IMAGIC_FL) {
3538     if (imagic_fs) {
3539     if (!ctx->inode_imagic_map)
3540     alloc_imagic_map(ctx);
3541     ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3542     ino);
3543     } else {
3544     if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3545     inode->i_flags &= ~EXT2_IMAGIC_FL;
3546     e2fsck_write_inode(ctx, ino,
3547     inode, "pass1");
3548     }
3549     }
3550     }
3551    
3552     check_inode_extra_space(ctx, &pctx);
3553    
3554     if (LINUX_S_ISDIR(inode->i_mode)) {
3555     ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3556     e2fsck_add_dir_info(ctx, ino, 0);
3557     ctx->fs_directory_count++;
3558     } else if (LINUX_S_ISREG (inode->i_mode)) {
3559     ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3560     ctx->fs_regular_count++;
3561     } else if (LINUX_S_ISCHR (inode->i_mode) &&
3562     e2fsck_pass1_check_device_inode(fs, inode)) {
3563     check_immutable(ctx, &pctx);
3564     check_size(ctx, &pctx);
3565     ctx->fs_chardev_count++;
3566     } else if (LINUX_S_ISBLK (inode->i_mode) &&
3567     e2fsck_pass1_check_device_inode(fs, inode)) {
3568     check_immutable(ctx, &pctx);
3569     check_size(ctx, &pctx);
3570     ctx->fs_blockdev_count++;
3571     } else if (LINUX_S_ISLNK (inode->i_mode) &&
3572     e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3573     check_immutable(ctx, &pctx);
3574     ctx->fs_symlinks_count++;
3575     if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3576     ctx->fs_fast_symlinks_count++;
3577     check_blocks(ctx, &pctx, block_buf);
3578     continue;
3579     }
3580     }
3581     else if (LINUX_S_ISFIFO (inode->i_mode) &&
3582     e2fsck_pass1_check_device_inode(fs, inode)) {
3583     check_immutable(ctx, &pctx);
3584     check_size(ctx, &pctx);
3585     ctx->fs_fifo_count++;
3586     } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3587     e2fsck_pass1_check_device_inode(fs, inode)) {
3588     check_immutable(ctx, &pctx);
3589     check_size(ctx, &pctx);
3590     ctx->fs_sockets_count++;
3591     } else
3592     mark_inode_bad(ctx, ino);
3593     if (inode->i_block[EXT2_IND_BLOCK])
3594     ctx->fs_ind_count++;
3595     if (inode->i_block[EXT2_DIND_BLOCK])
3596     ctx->fs_dind_count++;
3597     if (inode->i_block[EXT2_TIND_BLOCK])
3598     ctx->fs_tind_count++;
3599     if (inode->i_block[EXT2_IND_BLOCK] ||
3600     inode->i_block[EXT2_DIND_BLOCK] ||
3601     inode->i_block[EXT2_TIND_BLOCK] ||
3602     inode->i_file_acl) {
3603     inodes_to_process[process_inode_count].ino = ino;
3604     inodes_to_process[process_inode_count].inode = *inode;
3605     process_inode_count++;
3606     } else
3607     check_blocks(ctx, &pctx, block_buf);
3608    
3609     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3610     return;
3611    
3612     if (process_inode_count >= ctx->process_inode_size) {
3613     process_inodes(ctx, block_buf);
3614    
3615     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3616     return;
3617     }
3618     }
3619     process_inodes(ctx, block_buf);
3620     ext2fs_close_inode_scan(scan);
3621     ehandler_operation(0);
3622    
3623     /*
3624     * If any extended attribute blocks' reference counts need to
3625     * be adjusted, either up (ctx->refcount_extra), or down
3626     * (ctx->refcount), then fix them.
3627     */
3628     if (ctx->refcount) {
3629     adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3630     ea_refcount_free(ctx->refcount);
3631     ctx->refcount = 0;
3632     }
3633     if (ctx->refcount_extra) {
3634     adjust_extattr_refcount(ctx, ctx->refcount_extra,
3635     block_buf, +1);
3636     ea_refcount_free(ctx->refcount_extra);
3637     ctx->refcount_extra = 0;
3638     }
3639    
3640     if (ctx->invalid_bitmaps)
3641     handle_fs_bad_blocks(ctx);
3642    
3643     /* We don't need the block_ea_map any more */
3644     ext2fs_free_block_bitmap(ctx->block_ea_map);
3645     ctx->block_ea_map = 0;
3646    
3647     if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3648     ext2fs_block_bitmap save_bmap;
3649    
3650     save_bmap = fs->block_map;
3651     fs->block_map = ctx->block_found_map;
3652     clear_problem_context(&pctx);
3653     pctx.errcode = ext2fs_create_resize_inode(fs);
3654     if (pctx.errcode) {
3655     fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3656     /* Should never get here */
3657     ctx->flags |= E2F_FLAG_ABORT;
3658     return;
3659     }
3660     e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3661     "recreate inode");
3662     inode->i_mtime = time(0);
3663     e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3664     "recreate inode");
3665     fs->block_map = save_bmap;
3666     ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3667     }
3668    
3669     if (ctx->flags & E2F_FLAG_RESTART) {
3670     /*
3671     * Only the master copy of the superblock and block
3672     * group descriptors are going to be written during a
3673     * restart, so set the superblock to be used to be the
3674     * master superblock.
3675     */
3676     ctx->use_superblock = 0;
3677     unwind_pass1();
3678     goto endit;
3679     }
3680    
3681     if (ctx->block_dup_map) {
3682     if (ctx->options & E2F_OPT_PREEN) {
3683     clear_problem_context(&pctx);
3684     fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3685     }
3686     e2fsck_pass1_dupblocks(ctx, block_buf);
3687     }
3688     ext2fs_free_mem(&inodes_to_process);
3689     endit:
3690     e2fsck_use_inode_shortcuts(ctx, 0);
3691    
3692     ext2fs_free_mem(&block_buf);
3693     ext2fs_free_mem(&inode);
3694    
3695     }
3696    
3697     /*
3698     * When the inode_scan routines call this callback at the end of the
3699     * glock group, call process_inodes.
3700     */
3701     static errcode_t scan_callback(ext2_filsys fs,
3702     dgrp_t group, void * priv_data)
3703     {
3704     struct scan_callback_struct *scan_struct;
3705     e2fsck_t ctx;
3706    
3707     scan_struct = (struct scan_callback_struct *) priv_data;
3708     ctx = scan_struct->ctx;
3709    
3710     process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3711    
3712     if (ctx->progress)
3713     if ((ctx->progress)(ctx, 1, group+1,
3714     ctx->fs->group_desc_count))
3715     return EXT2_ET_CANCEL_REQUESTED;
3716    
3717     return 0;
3718     }
3719    
3720     /*
3721     * Process the inodes in the "inodes to process" list.
3722     */
3723     static void process_inodes(e2fsck_t ctx, char *block_buf)
3724     {
3725     int i;
3726     struct ext2_inode *old_stashed_inode;
3727     ext2_ino_t old_stashed_ino;
3728     const char *old_operation;
3729     char buf[80];
3730     struct problem_context pctx;
3731    
3732     /* begin process_inodes */
3733     if (process_inode_count == 0)
3734     return;
3735     old_operation = ehandler_operation(0);
3736     old_stashed_inode = ctx->stashed_inode;
3737     old_stashed_ino = ctx->stashed_ino;
3738     qsort(inodes_to_process, process_inode_count,
3739     sizeof(struct process_inode_block), process_inode_cmp);
3740     clear_problem_context(&pctx);
3741     for (i=0; i < process_inode_count; i++) {
3742     pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3743     pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3744     sprintf(buf, _("reading indirect blocks of inode %u"),
3745     pctx.ino);
3746     ehandler_operation(buf);
3747     check_blocks(ctx, &pctx, block_buf);
3748     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3749     break;
3750     }
3751     ctx->stashed_inode = old_stashed_inode;
3752     ctx->stashed_ino = old_stashed_ino;
3753     process_inode_count = 0;
3754     /* end process inodes */
3755    
3756     ehandler_operation(old_operation);
3757     }
3758    
3759     static int process_inode_cmp(const void *a, const void *b)
3760     {
3761     const struct process_inode_block *ib_a =
3762     (const struct process_inode_block *) a;
3763     const struct process_inode_block *ib_b =
3764     (const struct process_inode_block *) b;
3765     int ret;
3766    
3767     ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3768     ib_b->inode.i_block[EXT2_IND_BLOCK]);
3769     if (ret == 0)
3770     ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3771     return ret;
3772     }
3773    
3774     /*
3775     * Mark an inode as being bad in some what
3776     */
3777     static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3778     {
3779     struct problem_context pctx;
3780    
3781     if (!ctx->inode_bad_map) {
3782     clear_problem_context(&pctx);
3783    
3784     pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3785     _("bad inode map"), &ctx->inode_bad_map);
3786     if (pctx.errcode) {
3787     pctx.num = 3;
3788     fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3789     /* Should never get here */
3790     ctx->flags |= E2F_FLAG_ABORT;
3791     return;
3792     }
3793     }
3794     ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3795     }
3796    
3797    
3798     /*
3799     * This procedure will allocate the inode imagic table
3800     */
3801     static void alloc_imagic_map(e2fsck_t ctx)
3802     {
3803     struct problem_context pctx;
3804    
3805     clear_problem_context(&pctx);
3806     pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3807     _("imagic inode map"),
3808     &ctx->inode_imagic_map);
3809     if (pctx.errcode) {
3810     pctx.num = 5;
3811     fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3812     /* Should never get here */
3813     ctx->flags |= E2F_FLAG_ABORT;
3814     return;
3815     }
3816     }
3817    
3818     /*
3819     * Marks a block as in use, setting the dup_map if it's been set
3820     * already. Called by process_block and process_bad_block.
3821     *
3822     * WARNING: Assumes checks have already been done to make sure block
3823     * is valid. This is true in both process_block and process_bad_block.
3824     */
3825     static void mark_block_used(e2fsck_t ctx, blk_t block)
3826     {
3827     struct problem_context pctx;
3828    
3829     clear_problem_context(&pctx);
3830    
3831     if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3832     if (!ctx->block_dup_map) {
3833     pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3834     _("multiply claimed block map"),
3835     &ctx->block_dup_map);
3836     if (pctx.errcode) {
3837     pctx.num = 3;
3838     fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3839     &pctx);
3840     /* Should never get here */
3841     ctx->flags |= E2F_FLAG_ABORT;
3842     return;
3843     }
3844     }
3845     ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3846     } else {
3847     ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3848     }
3849     }
3850    
3851     /*
3852     * Adjust the extended attribute block's reference counts at the end
3853     * of pass 1, either by subtracting out references for EA blocks that
3854     * are still referenced in ctx->refcount, or by adding references for
3855     * EA blocks that had extra references as accounted for in
3856     * ctx->refcount_extra.
3857     */
3858     static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3859     char *block_buf, int adjust_sign)
3860     {
3861     struct ext2_ext_attr_header *header;
3862     struct problem_context pctx;
3863     ext2_filsys fs = ctx->fs;
3864     blk_t blk;
3865     __u32 should_be;
3866     int count;
3867    
3868     clear_problem_context(&pctx);
3869    
3870     ea_refcount_intr_begin(refcount);
3871     while (1) {
3872     if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3873     break;
3874     pctx.blk = blk;
3875     pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3876     if (pctx.errcode) {
3877     fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3878     return;
3879     }
3880     header = (struct ext2_ext_attr_header *) block_buf;
3881     pctx.blkcount = header->h_refcount;
3882     should_be = header->h_refcount + adjust_sign * count;
3883     pctx.num = should_be;
3884     if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3885     header->h_refcount = should_be;
3886     pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3887     block_buf);
3888     if (pctx.errcode) {
3889     fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3890     continue;
3891     }
3892     }
3893     }
3894     }
3895    
3896     /*
3897     * Handle processing the extended attribute blocks
3898     */
3899     static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3900     char *block_buf)
3901     {
3902     ext2_filsys fs = ctx->fs;
3903     ext2_ino_t ino = pctx->ino;
3904     struct ext2_inode *inode = pctx->inode;
3905     blk_t blk;
3906     char * end;
3907     struct ext2_ext_attr_header *header;
3908     struct ext2_ext_attr_entry *entry;
3909     int count;
3910     region_t region;
3911    
3912     blk = inode->i_file_acl;
3913     if (blk == 0)
3914     return 0;
3915    
3916     /*
3917     * If the Extended attribute flag isn't set, then a non-zero
3918     * file acl means that the inode is corrupted.
3919     *
3920     * Or if the extended attribute block is an invalid block,
3921     * then the inode is also corrupted.
3922     */
3923     if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3924     (blk < fs->super->s_first_data_block) ||
3925     (blk >= fs->super->s_blocks_count)) {
3926     mark_inode_bad(ctx, ino);
3927     return 0;
3928     }
3929    
3930     /* If ea bitmap hasn't been allocated, create it */
3931     if (!ctx->block_ea_map) {
3932     pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3933     _("ext attr block map"),
3934     &ctx->block_ea_map);
3935     if (pctx->errcode) {
3936     pctx->num = 2;
3937     fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3938     ctx->flags |= E2F_FLAG_ABORT;
3939     return 0;
3940     }
3941     }
3942    
3943     /* Create the EA refcount structure if necessary */
3944     if (!ctx->refcount) {
3945     pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3946     if (pctx->errcode) {
3947     pctx->num = 1;
3948     fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3949     ctx->flags |= E2F_FLAG_ABORT;
3950     return 0;
3951     }
3952     }
3953    
3954     /* Have we seen this EA block before? */
3955     if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3956     if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3957     return 1;
3958     /* Ooops, this EA was referenced more than it stated */
3959     if (!ctx->refcount_extra) {
3960     pctx->errcode = ea_refcount_create(0,
3961     &ctx->refcount_extra);
3962     if (pctx->errcode) {
3963     pctx->num = 2;
3964     fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3965     ctx->flags |= E2F_FLAG_ABORT;
3966     return 0;
3967     }
3968     }
3969     ea_refcount_increment(ctx->refcount_extra, blk, 0);
3970     return 1;
3971     }
3972    
3973     /*
3974     * OK, we haven't seen this EA block yet. So we need to
3975     * validate it
3976     */
3977     pctx->blk = blk;
3978     pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3979     if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3980     goto clear_extattr;
3981     header = (struct ext2_ext_attr_header *) block_buf;
3982     pctx->blk = inode->i_file_acl;
3983     if (((ctx->ext_attr_ver == 1) &&
3984     (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3985     ((ctx->ext_attr_ver == 2) &&
3986     (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3987     if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3988     goto clear_extattr;
3989     }
3990    
3991     if (header->h_blocks != 1) {
3992     if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3993     goto clear_extattr;
3994     }
3995    
3996     region = region_create(0, fs->blocksize);
3997     if (!region) {
3998     fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3999     ctx->flags |= E2F_FLAG_ABORT;
4000     return 0;
4001     }
4002     if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4003     if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4004     goto clear_extattr;
4005     }
4006    
4007     entry = (struct ext2_ext_attr_entry *)(header+1);
4008     end = block_buf + fs->blocksize;
4009     while ((char *)entry < end && *(__u32 *)entry) {
4010     if (region_allocate(region, (char *)entry - (char *)header,
4011     EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4012     if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4013     goto clear_extattr;
4014     }
4015     if ((ctx->ext_attr_ver == 1 &&
4016     (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4017     (ctx->ext_attr_ver == 2 &&
4018     entry->e_name_index == 0)) {
4019     if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4020     goto clear_extattr;
4021     }
4022     if (entry->e_value_block != 0) {
4023     if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4024     goto clear_extattr;
4025     }
4026     if (entry->e_value_size &&
4027     region_allocate(region, entry->e_value_offs,
4028     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4029     if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4030     goto clear_extattr;
4031     }
4032     entry = EXT2_EXT_ATTR_NEXT(entry);
4033     }
4034     if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4035     if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4036     goto clear_extattr;
4037     }
4038     region_free(region);
4039    
4040     count = header->h_refcount - 1;
4041     if (count)
4042     ea_refcount_store(ctx->refcount, blk, count);
4043     mark_block_used(ctx, blk);
4044     ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4045    
4046     return 1;
4047    
4048     clear_extattr:
4049     inode->i_file_acl = 0;
4050     e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4051     return 0;
4052     }
4053    
4054     /* Returns 1 if bad htree, 0 if OK */
4055     static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4056     ext2_ino_t ino FSCK_ATTR((unused)),
4057     struct ext2_inode *inode,
4058     char *block_buf)
4059     {
4060     struct ext2_dx_root_info *root;
4061     ext2_filsys fs = ctx->fs;
4062     errcode_t retval;
4063     blk_t blk;
4064    
4065     if ((!LINUX_S_ISDIR(inode->i_mode) &&
4066     fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4067     (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4068     fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4069     return 1;
4070    
4071     blk = inode->i_block[0];
4072     if (((blk == 0) ||
4073     (blk < fs->super->s_first_data_block) ||
4074     (blk >= fs->super->s_blocks_count)) &&
4075     fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4076     return 1;
4077    
4078     retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4079     if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4080     return 1;
4081    
4082     /* XXX should check that beginning matches a directory */
4083     root = (struct ext2_dx_root_info *) (block_buf + 24);
4084    
4085     if ((root->reserved_zero || root->info_length < 8) &&
4086     fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4087     return 1;
4088    
4089     pctx->num = root->hash_version;
4090     if ((root->hash_version != EXT2_HASH_LEGACY) &&
4091     (root->hash_version != EXT2_HASH_HALF_MD4) &&
4092     (root->hash_version != EXT2_HASH_TEA) &&
4093     fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4094     return 1;
4095    
4096     if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4097     fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4098     return 1;
4099    
4100     pctx->num = root->indirect_levels;
4101     if ((root->indirect_levels > 1) &&
4102     fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4103     return 1;
4104    
4105     return 0;
4106     }
4107    
4108     /*
4109     * This subroutine is called on each inode to account for all of the
4110     * blocks used by that inode.
4111     */
4112     static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4113     char *block_buf)
4114     {
4115     ext2_filsys fs = ctx->fs;
4116     struct process_block_struct_1 pb;
4117     ext2_ino_t ino = pctx->ino;
4118     struct ext2_inode *inode = pctx->inode;
4119     int bad_size = 0;
4120     int dirty_inode = 0;
4121     __u64 size;
4122    
4123     pb.ino = ino;
4124     pb.num_blocks = 0;
4125     pb.last_block = -1;
4126     pb.num_illegal_blocks = 0;
4127     pb.suppress = 0; pb.clear = 0;
4128     pb.fragmented = 0;
4129     pb.compressed = 0;
4130     pb.previous_block = 0;
4131     pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4132     pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4133     pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4134     pb.inode = inode;
4135     pb.pctx = pctx;
4136     pb.ctx = ctx;
4137     pctx->ino = ino;
4138     pctx->errcode = 0;
4139    
4140     if (inode->i_flags & EXT2_COMPRBLK_FL) {
4141     if (fs->super->s_feature_incompat &
4142     EXT2_FEATURE_INCOMPAT_COMPRESSION)
4143     pb.compressed = 1;
4144     else {
4145     if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4146     inode->i_flags &= ~EXT2_COMPRBLK_FL;
4147     dirty_inode++;
4148     }
4149     }
4150     }
4151    
4152     if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4153     pb.num_blocks++;
4154    
4155     if (ext2fs_inode_has_valid_blocks(inode))
4156     pctx->errcode = ext2fs_block_iterate2(fs, ino,
4157     pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4158     block_buf, process_block, &pb);
4159     end_problem_latch(ctx, PR_LATCH_BLOCK);
4160     end_problem_latch(ctx, PR_LATCH_TOOBIG);
4161     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4162     goto out;
4163     if (pctx->errcode)
4164     fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4165    
4166     if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4167     ctx->fs_fragmented++;
4168    
4169     if (pb.clear) {
4170     inode->i_links_count = 0;
4171     ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4172     inode->i_dtime = time(0);
4173     dirty_inode++;
4174     ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4175     ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4176     ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4177     /*
4178     * The inode was probably partially accounted for
4179     * before processing was aborted, so we need to
4180     * restart the pass 1 scan.
4181     */
4182     ctx->flags |= E2F_FLAG_RESTART;
4183     goto out;
4184     }
4185    
4186     if (inode->i_flags & EXT2_INDEX_FL) {
4187     if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4188     inode->i_flags &= ~EXT2_INDEX_FL;
4189     dirty_inode++;
4190     } else {
4191     #ifdef ENABLE_HTREE
4192     e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4193     #endif
4194     }
4195     }
4196     if (ctx->dirs_to_hash && pb.is_dir &&
4197     !(inode->i_flags & EXT2_INDEX_FL) &&
4198     ((inode->i_size / fs->blocksize) >= 3))
4199     ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4200    
4201     if (!pb.num_blocks && pb.is_dir) {
4202     if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4203     inode->i_links_count = 0;
4204     ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4205     inode->i_dtime = time(0);
4206     dirty_inode++;
4207     ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4208     ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4209     ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4210     ctx->fs_directory_count--;
4211     goto out;
4212     }
4213     }
4214    
4215     pb.num_blocks *= (fs->blocksize / 512);
4216    
4217     if (pb.is_dir) {
4218     int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4219     if (nblock > (pb.last_block + 1))
4220     bad_size = 1;
4221     else if (nblock < (pb.last_block + 1)) {
4222     if (((pb.last_block + 1) - nblock) >
4223     fs->super->s_prealloc_dir_blocks)
4224     bad_size = 2;
4225     }
4226     } else {
4227     size = EXT2_I_SIZE(inode);
4228     if ((pb.last_block >= 0) &&
4229     (size < (__u64) pb.last_block * fs->blocksize))
4230     bad_size = 3;
4231     else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4232     bad_size = 4;
4233     }
4234     /* i_size for symlinks is checked elsewhere */
4235     if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4236     pctx->num = (pb.last_block+1) * fs->blocksize;
4237     if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4238     inode->i_size = pctx->num;
4239     if (!LINUX_S_ISDIR(inode->i_mode))
4240     inode->i_size_high = pctx->num >> 32;
4241     dirty_inode++;
4242     }
4243     pctx->num = 0;
4244     }
4245     if (LINUX_S_ISREG(inode->i_mode) &&
4246     (inode->i_size_high || inode->i_size & 0x80000000UL))
4247     ctx->large_files++;
4248     if (pb.num_blocks != inode->i_blocks) {
4249     pctx->num = pb.num_blocks;
4250     if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4251     inode->i_blocks = pb.num_blocks;
4252     dirty_inode++;
4253     }
4254     pctx->num = 0;
4255     }
4256     out:
4257     if (dirty_inode)
4258     e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4259     }
4260    
4261    
4262     /*
4263     * This is a helper function for check_blocks().
4264     */
4265     static int process_block(ext2_filsys fs,
4266     blk_t *block_nr,
4267     e2_blkcnt_t blockcnt,
4268     blk_t ref_block FSCK_ATTR((unused)),
4269     int ref_offset FSCK_ATTR((unused)),
4270     void *priv_data)
4271     {
4272     struct process_block_struct_1 *p;
4273     struct problem_context *pctx;
4274     blk_t blk = *block_nr;
4275     int ret_code = 0;
4276     int problem = 0;
4277     e2fsck_t ctx;
4278    
4279     p = (struct process_block_struct_1 *) priv_data;
4280     pctx = p->pctx;
4281     ctx = p->ctx;
4282    
4283     if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4284     /* todo: Check that the comprblk_fl is high, that the
4285     blkaddr pattern looks right (all non-holes up to
4286     first EXT2FS_COMPRESSED_BLKADDR, then all
4287     EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4288     that the feature_incompat bit is high, and that the
4289     inode is a regular file. If we're doing a "full
4290     check" (a concept introduced to e2fsck by e2compr,
4291     meaning that we look at data blocks as well as
4292     metadata) then call some library routine that
4293     checks the compressed data. I'll have to think
4294     about this, because one particularly important
4295     problem to be able to fix is to recalculate the
4296     cluster size if necessary. I think that perhaps
4297     we'd better do most/all e2compr-specific checks
4298     separately, after the non-e2compr checks. If not
4299     doing a full check, it may be useful to test that
4300     the personality is linux; e.g. if it isn't then
4301     perhaps this really is just an illegal block. */
4302     return 0;
4303     }
4304    
4305     if (blk == 0) {
4306     if (p->is_dir == 0) {
4307     /*
4308     * Should never happen, since only directories
4309     * get called with BLOCK_FLAG_HOLE
4310     */
4311     #ifdef DEBUG_E2FSCK
4312     printf("process_block() called with blk == 0, "
4313     "blockcnt=%d, inode %lu???\n",
4314     blockcnt, p->ino);
4315     #endif
4316     return 0;
4317     }
4318     if (blockcnt < 0)
4319     return 0;
4320     if (blockcnt * fs->blocksize < p->inode->i_size) {
4321     goto mark_dir;
4322     }
4323     return 0;
4324     }
4325    
4326     /*
4327     * Simplistic fragmentation check. We merely require that the
4328     * file be contiguous. (Which can never be true for really
4329     * big files that are greater than a block group.)
4330     */
4331     if (!HOLE_BLKADDR(p->previous_block)) {
4332     if (p->previous_block+1 != blk)
4333     p->fragmented = 1;
4334     }
4335     p->previous_block = blk;
4336    
4337     if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4338     problem = PR_1_TOOBIG_DIR;
4339     if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4340     problem = PR_1_TOOBIG_REG;
4341     if (!p->is_dir && !p->is_reg && blockcnt > 0)
4342     problem = PR_1_TOOBIG_SYMLINK;
4343    
4344     if (blk < fs->super->s_first_data_block ||
4345     blk >= fs->super->s_blocks_count)
4346     problem = PR_1_ILLEGAL_BLOCK_NUM;
4347    
4348     if (problem) {
4349     p->num_illegal_blocks++;
4350     if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4351     if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4352     p->clear = 1;
4353     return BLOCK_ABORT;
4354     }
4355     if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4356     p->suppress = 1;
4357     set_latch_flags(PR_LATCH_BLOCK,
4358     PRL_SUPPRESS, 0);
4359     }
4360     }
4361     pctx->blk = blk;
4362     pctx->blkcount = blockcnt;
4363     if (fix_problem(ctx, problem, pctx)) {
4364     blk = *block_nr = 0;
4365     ret_code = BLOCK_CHANGED;
4366     goto mark_dir;
4367     } else
4368     return 0;
4369     }
4370    
4371     if (p->ino == EXT2_RESIZE_INO) {
4372     /*
4373     * The resize inode has already be sanity checked
4374     * during pass #0 (the superblock checks). All we
4375     * have to do is mark the double indirect block as
4376     * being in use; all of the other blocks are handled
4377     * by mark_table_blocks()).
4378     */
4379     if (blockcnt == BLOCK_COUNT_DIND)
4380     mark_block_used(ctx, blk);
4381     } else
4382     mark_block_used(ctx, blk);
4383     p->num_blocks++;
4384     if (blockcnt >= 0)
4385     p->last_block = blockcnt;
4386     mark_dir:
4387     if (p->is_dir && (blockcnt >= 0)) {
4388     pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4389     blk, blockcnt);
4390     if (pctx->errcode) {
4391     pctx->blk = blk;
4392     pctx->num = blockcnt;
4393     fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4394     /* Should never get here */
4395     ctx->flags |= E2F_FLAG_ABORT;
4396     return BLOCK_ABORT;
4397     }
4398     }
4399     return ret_code;
4400     }
4401    
4402     static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4403     blk_t *block_nr,
4404     e2_blkcnt_t blockcnt,
4405     blk_t ref_block FSCK_ATTR((unused)),
4406     int ref_offset FSCK_ATTR((unused)),
4407     void *priv_data EXT2FS_ATTR((unused)))
4408     {
4409     /*
4410     * Note: This function processes blocks for the bad blocks
4411     * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4412     */
4413    
4414     printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4415     return BLOCK_ERROR;
4416     }
4417    
4418     /*
4419     * This routine gets called at the end of pass 1 if bad blocks are
4420     * detected in the superblock, group descriptors, inode_bitmaps, or
4421     * block bitmaps. At this point, all of the blocks have been mapped
4422     * out, so we can try to allocate new block(s) to replace the bad
4423     * blocks.
4424     */
4425     static void handle_fs_bad_blocks(e2fsck_t ctx)
4426     {
4427     printf("Bad blocks detected on your filesystem\n"
4428     "You should get your data off as the device will soon die\n");
4429     }
4430    
4431     /*
4432     * This routine marks all blocks which are used by the superblock,
4433     * group descriptors, inode bitmaps, and block bitmaps.
4434     */
4435     static void mark_table_blocks(e2fsck_t ctx)
4436     {
4437     ext2_filsys fs = ctx->fs;
4438     blk_t block, b;
4439     dgrp_t i;
4440     int j;
4441     struct problem_context pctx;
4442    
4443     clear_problem_context(&pctx);
4444    
4445     block = fs->super->s_first_data_block;
4446     for (i = 0; i < fs->group_desc_count; i++) {
4447     pctx.group = i;
4448    
4449     ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4450    
4451     /*
4452     * Mark the blocks used for the inode table
4453     */
4454     if (fs->group_desc[i].bg_inode_table) {
4455     for (j = 0, b = fs->group_desc[i].bg_inode_table;
4456     j < fs->inode_blocks_per_group;
4457     j++, b++) {
4458     if (ext2fs_test_block_bitmap(ctx->block_found_map,
4459     b)) {
4460     pctx.blk = b;
4461     if (fix_problem(ctx,
4462     PR_1_ITABLE_CONFLICT, &pctx)) {
4463     ctx->invalid_inode_table_flag[i]++;
4464     ctx->invalid_bitmaps++;
4465     }
4466     } else {
4467     ext2fs_mark_block_bitmap(ctx->block_found_map,
4468     b);
4469     }
4470     }
4471     }
4472    
4473     /*
4474     * Mark block used for the block bitmap
4475     */
4476     if (fs->group_desc[i].bg_block_bitmap) {
4477     if (ext2fs_test_block_bitmap(ctx->block_found_map,
4478     fs->group_desc[i].bg_block_bitmap)) {
4479     pctx.blk = fs->group_desc[i].bg_block_bitmap;
4480     if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4481     ctx->invalid_block_bitmap_flag[i]++;
4482     ctx->invalid_bitmaps++;
4483     }
4484     } else {
4485     ext2fs_mark_block_bitmap(ctx->block_found_map,
4486     fs->group_desc[i].bg_block_bitmap);
4487     }
4488    
4489     }
4490     /*
4491     * Mark block used for the inode bitmap
4492     */
4493     if (fs->group_desc[i].bg_inode_bitmap) {
4494     if (ext2fs_test_block_bitmap(ctx->block_found_map,
4495     fs->group_desc[i].bg_inode_bitmap)) {
4496     pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4497     if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4498     ctx->invalid_inode_bitmap_flag[i]++;
4499     ctx->invalid_bitmaps++;
4500     }
4501     } else {
4502     ext2fs_mark_block_bitmap(ctx->block_found_map,
4503     fs->group_desc[i].bg_inode_bitmap);
4504     }
4505     }
4506     block += fs->super->s_blocks_per_group;
4507     }
4508     }
4509    
4510     /*
4511     * Thes subroutines short circuits ext2fs_get_blocks and
4512     * ext2fs_check_directory; we use them since we already have the inode
4513     * structure, so there's no point in letting the ext2fs library read
4514     * the inode again.
4515     */
4516     static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4517     blk_t *blocks)
4518     {
4519     e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4520     int i;
4521    
4522     if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4523     return EXT2_ET_CALLBACK_NOTHANDLED;
4524    
4525     for (i=0; i < EXT2_N_BLOCKS; i++)
4526     blocks[i] = ctx->stashed_inode->i_block[i];
4527     return 0;
4528     }
4529    
4530     static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4531     struct ext2_inode *inode)
4532     {
4533     e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4534    
4535     if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4536     return EXT2_ET_CALLBACK_NOTHANDLED;
4537     *inode = *ctx->stashed_inode;
4538     return 0;
4539     }
4540    
4541     static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4542     struct ext2_inode *inode)
4543     {
4544     e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545    
4546     if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4547     *ctx->stashed_inode = *inode;
4548     return EXT2_ET_CALLBACK_NOTHANDLED;
4549     }
4550    
4551     static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4552     {
4553     e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4554    
4555     if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4556     return EXT2_ET_CALLBACK_NOTHANDLED;
4557    
4558     if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4559     return EXT2_ET_NO_DIRECTORY;
4560     return 0;
4561     }
4562    
4563     void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4564     {
4565     ext2_filsys fs = ctx->fs;
4566    
4567     if (bool) {
4568     fs->get_blocks = pass1_get_blocks;
4569     fs->check_directory = pass1_check_directory;
4570     fs->read_inode = pass1_read_inode;
4571     fs->write_inode = pass1_write_inode;
4572     ctx->stashed_ino = 0;
4573     } else {
4574     fs->get_blocks = 0;
4575     fs->check_directory = 0;
4576     fs->read_inode = 0;
4577     fs->write_inode = 0;
4578     }
4579     }
4580    
4581     /*
4582     * pass1b.c --- Pass #1b of e2fsck
4583     *
4584     * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4585     * only invoked if pass 1 discovered blocks which are in use by more
4586     * than one inode.
4587     *
4588     * Pass1B scans the data blocks of all the inodes again, generating a
4589     * complete list of duplicate blocks and which inodes have claimed
4590     * them.
4591     *
4592     * Pass1C does a tree-traversal of the filesystem, to determine the
4593     * parent directories of these inodes. This step is necessary so that
4594     * e2fsck can print out the pathnames of affected inodes.
4595     *
4596     * Pass1D is a reconciliation pass. For each inode with duplicate
4597     * blocks, the user is prompted if s/he would like to clone the file
4598     * (so that the file gets a fresh copy of the duplicated blocks) or
4599     * simply to delete the file.
4600     *
4601     */
4602    
4603    
4604     /* Needed for architectures where sizeof(int) != sizeof(void *) */
4605     #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4606     #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4607    
4608     /* Define an extension to the ext2 library's block count information */
4609     #define BLOCK_COUNT_EXTATTR (-5)
4610    
4611     struct block_el {
4612     blk_t block;
4613     struct block_el *next;
4614     };
4615    
4616     struct inode_el {
4617     ext2_ino_t inode;
4618     struct inode_el *next;
4619     };
4620    
4621     struct dup_block {
4622     int num_bad;
4623     struct inode_el *inode_list;
4624     };
4625    
4626     /*
4627     * This structure stores information about a particular inode which
4628     * is sharing blocks with other inodes. This information is collected
4629     * to display to the user, so that the user knows what files he or she
4630     * is dealing with, when trying to decide how to resolve the conflict
4631     * of multiply-claimed blocks.
4632     */
4633     struct dup_inode {
4634     ext2_ino_t dir;
4635     int num_dupblocks;
4636     struct ext2_inode inode;
4637     struct block_el *block_list;
4638     };
4639    
4640     static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4641     e2_blkcnt_t blockcnt, blk_t ref_blk,
4642     int ref_offset, void *priv_data);
4643     static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4644     struct dup_inode *dp, char *block_buf);
4645     static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4646     struct dup_inode *dp, char* block_buf);
4647     static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4648    
4649     static void pass1b(e2fsck_t ctx, char *block_buf);
4650     static void pass1c(e2fsck_t ctx, char *block_buf);
4651     static void pass1d(e2fsck_t ctx, char *block_buf);
4652    
4653     static int dup_inode_count = 0;
4654    
4655     static dict_t blk_dict, ino_dict;
4656    
4657     static ext2fs_inode_bitmap inode_dup_map;
4658    
4659     static int dict_int_cmp(const void *a, const void *b)
4660     {
4661     intptr_t ia, ib;
4662    
4663     ia = (intptr_t)a;
4664     ib = (intptr_t)b;
4665    
4666     return (ia-ib);
4667     }
4668    
4669     /*
4670     * Add a duplicate block record
4671     */
4672     static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4673     struct ext2_inode *inode)
4674     {
4675     dnode_t *n;
4676     struct dup_block *db;
4677     struct dup_inode *di;
4678     struct block_el *blk_el;
4679     struct inode_el *ino_el;
4680    
4681     n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4682     if (n)
4683     db = (struct dup_block *) dnode_get(n);
4684     else {
4685     db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4686     sizeof(struct dup_block), "duplicate block header");
4687     db->num_bad = 0;
4688     db->inode_list = 0;
4689     dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4690     }
4691     ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4692     sizeof(struct inode_el), "inode element");
4693     ino_el->inode = ino;
4694     ino_el->next = db->inode_list;
4695     db->inode_list = ino_el;
4696     db->num_bad++;
4697    
4698     n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4699     if (n)
4700     di = (struct dup_inode *) dnode_get(n);
4701     else {
4702     di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4703     sizeof(struct dup_inode), "duplicate inode header");
4704 niro 816 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4705 niro 532 di->num_dupblocks = 0;
4706     di->block_list = 0;
4707     di->inode = *inode;
4708     dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4709     }
4710     blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4711     sizeof(struct block_el), "block element");
4712     blk_el->block = blk;
4713     blk_el->next = di->block_list;
4714     di->block_list = blk_el;
4715     di->num_dupblocks++;
4716     }
4717    
4718     /*
4719     * Free a duplicate inode record
4720     */
4721     static void inode_dnode_free(dnode_t *node)
4722     {
4723     struct dup_inode *di;
4724     struct block_el *p, *next;
4725    
4726     di = (struct dup_inode *) dnode_get(node);
4727     for (p = di->block_list; p; p = next) {
4728     next = p->next;
4729     free(p);
4730     }
4731     free(node);
4732     }
4733    
4734     /*
4735     * Free a duplicate block record
4736     */
4737     static void block_dnode_free(dnode_t *node)
4738     {
4739     struct dup_block *db;
4740     struct inode_el *p, *next;
4741    
4742     db = (struct dup_block *) dnode_get(node);
4743     for (p = db->inode_list; p; p = next) {
4744     next = p->next;
4745     free(p);
4746     }
4747     free(node);
4748     }
4749    
4750    
4751     /*
4752     * Main procedure for handling duplicate blocks
4753     */
4754     void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4755     {
4756     ext2_filsys fs = ctx->fs;
4757     struct problem_context pctx;
4758    
4759     clear_problem_context(&pctx);
4760    
4761     pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4762     _("multiply claimed inode map"), &inode_dup_map);
4763     if (pctx.errcode) {
4764     fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4765     ctx->flags |= E2F_FLAG_ABORT;
4766     return;
4767     }
4768    
4769     dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4770     dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771     dict_set_allocator(&ino_dict, inode_dnode_free);
4772     dict_set_allocator(&blk_dict, block_dnode_free);
4773    
4774     pass1b(ctx, block_buf);
4775     pass1c(ctx, block_buf);
4776     pass1d(ctx, block_buf);
4777    
4778     /*
4779     * Time to free all of the accumulated data structures that we
4780     * don't need anymore.
4781     */
4782     dict_free_nodes(&ino_dict);
4783     dict_free_nodes(&blk_dict);
4784     }
4785    
4786     /*
4787     * Scan the inodes looking for inodes that contain duplicate blocks.
4788     */
4789     struct process_block_struct_1b {
4790     e2fsck_t ctx;
4791     ext2_ino_t ino;
4792     int dup_blocks;
4793     struct ext2_inode *inode;
4794     struct problem_context *pctx;
4795     };
4796    
4797     static void pass1b(e2fsck_t ctx, char *block_buf)
4798     {
4799     ext2_filsys fs = ctx->fs;
4800     ext2_ino_t ino;
4801     struct ext2_inode inode;
4802     ext2_inode_scan scan;
4803     struct process_block_struct_1b pb;
4804     struct problem_context pctx;
4805    
4806     clear_problem_context(&pctx);
4807    
4808     if (!(ctx->options & E2F_OPT_PREEN))
4809     fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4810     pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4811     &scan);
4812     if (pctx.errcode) {
4813     fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4814     ctx->flags |= E2F_FLAG_ABORT;
4815     return;
4816     }
4817     ctx->stashed_inode = &inode;
4818     pb.ctx = ctx;
4819     pb.pctx = &pctx;
4820     pctx.str = "pass1b";
4821     while (1) {
4822     pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4823     if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4824     continue;
4825     if (pctx.errcode) {
4826     fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4827     ctx->flags |= E2F_FLAG_ABORT;
4828     return;
4829     }
4830     if (!ino)
4831     break;
4832     pctx.ino = ctx->stashed_ino = ino;
4833     if ((ino != EXT2_BAD_INO) &&
4834     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4835     continue;
4836    
4837     pb.ino = ino;
4838     pb.dup_blocks = 0;
4839     pb.inode = &inode;
4840    
4841     if (ext2fs_inode_has_valid_blocks(&inode) ||
4842     (ino == EXT2_BAD_INO))
4843     pctx.errcode = ext2fs_block_iterate2(fs, ino,
4844     0, block_buf, process_pass1b_block, &pb);
4845     if (inode.i_file_acl)
4846     process_pass1b_block(fs, &inode.i_file_acl,
4847     BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4848     if (pb.dup_blocks) {
4849     end_problem_latch(ctx, PR_LATCH_DBLOCK);
4850     if (ino >= EXT2_FIRST_INODE(fs->super) ||
4851     ino == EXT2_ROOT_INO)
4852     dup_inode_count++;
4853     }
4854     if (pctx.errcode)
4855     fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4856     }
4857     ext2fs_close_inode_scan(scan);
4858     e2fsck_use_inode_shortcuts(ctx, 0);
4859     }
4860    
4861     static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4862     blk_t *block_nr,
4863     e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4864     blk_t ref_blk FSCK_ATTR((unused)),
4865     int ref_offset FSCK_ATTR((unused)),
4866     void *priv_data)
4867     {
4868     struct process_block_struct_1b *p;
4869     e2fsck_t ctx;
4870    
4871     if (HOLE_BLKADDR(*block_nr))
4872     return 0;
4873     p = (struct process_block_struct_1b *) priv_data;
4874     ctx = p->ctx;
4875    
4876     if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4877     return 0;
4878    
4879     /* OK, this is a duplicate block */
4880     if (p->ino != EXT2_BAD_INO) {
4881     p->pctx->blk = *block_nr;
4882     fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4883     }
4884     p->dup_blocks++;
4885     ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4886    
4887     add_dupe(ctx, p->ino, *block_nr, p->inode);
4888    
4889     return 0;
4890     }
4891    
4892     /*
4893     * Pass 1c: Scan directories for inodes with duplicate blocks. This
4894     * is used so that we can print pathnames when prompting the user for
4895     * what to do.
4896     */
4897     struct search_dir_struct {
4898     int count;
4899     ext2_ino_t first_inode;
4900     ext2_ino_t max_inode;
4901     };
4902    
4903     static int search_dirent_proc(ext2_ino_t dir, int entry,
4904     struct ext2_dir_entry *dirent,
4905     int offset FSCK_ATTR((unused)),
4906     int blocksize FSCK_ATTR((unused)),
4907     char *buf FSCK_ATTR((unused)),
4908     void *priv_data)
4909     {
4910     struct search_dir_struct *sd;
4911     struct dup_inode *p;
4912     dnode_t *n;
4913    
4914     sd = (struct search_dir_struct *) priv_data;
4915    
4916     if (dirent->inode > sd->max_inode)
4917     /* Should abort this inode, but not everything */
4918     return 0;
4919    
4920     if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4921     !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4922     return 0;
4923    
4924     n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4925     if (!n)
4926     return 0;
4927     p = (struct dup_inode *) dnode_get(n);
4928     p->dir = dir;
4929     sd->count--;
4930    
4931     return sd->count ? 0 : DIRENT_ABORT;
4932     }
4933    
4934    
4935     static void pass1c(e2fsck_t ctx, char *block_buf)
4936     {
4937     ext2_filsys fs = ctx->fs;
4938     struct search_dir_struct sd;
4939     struct problem_context pctx;
4940    
4941     clear_problem_context(&pctx);
4942    
4943     if (!(ctx->options & E2F_OPT_PREEN))
4944     fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4945    
4946     /*
4947     * Search through all directories to translate inodes to names
4948     * (by searching for the containing directory for that inode.)
4949     */
4950     sd.count = dup_inode_count;
4951     sd.first_inode = EXT2_FIRST_INODE(fs->super);
4952     sd.max_inode = fs->super->s_inodes_count;
4953     ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4954     search_dirent_proc, &sd);
4955     }
4956    
4957     static void pass1d(e2fsck_t ctx, char *block_buf)
4958     {
4959     ext2_filsys fs = ctx->fs;
4960     struct dup_inode *p, *t;
4961     struct dup_block *q;
4962     ext2_ino_t *shared, ino;
4963     int shared_len;
4964     int i;
4965     int file_ok;
4966     int meta_data = 0;
4967     struct problem_context pctx;
4968     dnode_t *n, *m;
4969     struct block_el *s;
4970     struct inode_el *r;
4971    
4972     clear_problem_context(&pctx);
4973    
4974     if (!(ctx->options & E2F_OPT_PREEN))
4975     fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4976     e2fsck_read_bitmaps(ctx);
4977    
4978     pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4979     fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4980     shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4981     sizeof(ext2_ino_t) * dict_count(&ino_dict),
4982     "Shared inode list");
4983     for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4984     p = (struct dup_inode *) dnode_get(n);
4985     shared_len = 0;
4986     file_ok = 1;
4987     ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4988     if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4989     continue;
4990    
4991     /*
4992     * Find all of the inodes which share blocks with this
4993     * one. First we find all of the duplicate blocks
4994     * belonging to this inode, and then search each block
4995     * get the list of inodes, and merge them together.
4996     */
4997     for (s = p->block_list; s; s = s->next) {
4998     m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4999     if (!m)
5000     continue; /* Should never happen... */
5001     q = (struct dup_block *) dnode_get(m);
5002     if (q->num_bad > 1)
5003     file_ok = 0;
5004     if (check_if_fs_block(ctx, s->block)) {
5005     file_ok = 0;
5006     meta_data = 1;
5007     }
5008    
5009     /*
5010     * Add all inodes used by this block to the
5011     * shared[] --- which is a unique list, so
5012     * if an inode is already in shared[], don't
5013     * add it again.
5014     */
5015     for (r = q->inode_list; r; r = r->next) {
5016     if (r->inode == ino)
5017     continue;
5018     for (i = 0; i < shared_len; i++)
5019     if (shared[i] == r->inode)
5020     break;
5021     if (i == shared_len) {
5022     shared[shared_len++] = r->inode;
5023     }
5024     }
5025     }
5026    
5027     /*
5028     * Report the inode that we are working on
5029     */
5030     pctx.inode = &p->inode;
5031     pctx.ino = ino;
5032     pctx.dir = p->dir;
5033     pctx.blkcount = p->num_dupblocks;
5034     pctx.num = meta_data ? shared_len+1 : shared_len;
5035     fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5036     pctx.blkcount = 0;
5037     pctx.num = 0;
5038    
5039     if (meta_data)
5040     fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5041    
5042     for (i = 0; i < shared_len; i++) {
5043     m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5044     if (!m)
5045     continue; /* should never happen */
5046     t = (struct dup_inode *) dnode_get(m);
5047     /*
5048     * Report the inode that we are sharing with
5049     */
5050     pctx.inode = &t->inode;
5051     pctx.ino = shared[i];
5052     pctx.dir = t->dir;
5053     fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5054     }
5055     if (file_ok) {
5056     fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5057     continue;
5058     }
5059     if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5060     pctx.errcode = clone_file(ctx, ino, p, block_buf);
5061     if (pctx.errcode)
5062     fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5063     else
5064     continue;
5065     }
5066     if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5067     delete_file(ctx, ino, p, block_buf);
5068     else
5069     ext2fs_unmark_valid(fs);
5070     }
5071     ext2fs_free_mem(&shared);
5072     }
5073    
5074     /*
5075     * Drop the refcount on the dup_block structure, and clear the entry
5076     * in the block_dup_map if appropriate.
5077     */
5078     static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5079     {
5080     p->num_bad--;
5081     if (p->num_bad <= 0 ||
5082     (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5083     ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5084     }
5085    
5086     static int delete_file_block(ext2_filsys fs,
5087     blk_t *block_nr,
5088     e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5089     blk_t ref_block FSCK_ATTR((unused)),
5090     int ref_offset FSCK_ATTR((unused)),
5091     void *priv_data)
5092     {
5093     struct process_block_struct_1b *pb;
5094     struct dup_block *p;
5095     dnode_t *n;
5096     e2fsck_t ctx;
5097    
5098     pb = (struct process_block_struct_1b *) priv_data;
5099     ctx = pb->ctx;
5100    
5101     if (HOLE_BLKADDR(*block_nr))
5102     return 0;
5103    
5104     if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5105     n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5106     if (n) {
5107     p = (struct dup_block *) dnode_get(n);
5108     decrement_badcount(ctx, *block_nr, p);
5109     } else
5110     bb_error_msg(_("internal error; can't find dup_blk for %d"),
5111     *block_nr);
5112     } else {
5113     ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5114     ext2fs_block_alloc_stats(fs, *block_nr, -1);
5115     }
5116    
5117     return 0;
5118     }
5119    
5120     static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5121     struct dup_inode *dp, char* block_buf)
5122     {
5123     ext2_filsys fs = ctx->fs;
5124     struct process_block_struct_1b pb;
5125     struct ext2_inode inode;
5126     struct problem_context pctx;
5127     unsigned int count;
5128    
5129     clear_problem_context(&pctx);
5130     pctx.ino = pb.ino = ino;
5131     pb.dup_blocks = dp->num_dupblocks;
5132     pb.ctx = ctx;
5133     pctx.str = "delete_file";
5134    
5135     e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5136     if (ext2fs_inode_has_valid_blocks(&inode))
5137     pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5138     delete_file_block, &pb);
5139     if (pctx.errcode)
5140     fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5141     ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5142     ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5143     if (ctx->inode_bad_map)
5144     ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5145     ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5146    
5147     /* Inode may have changed by block_iterate, so reread it */
5148     e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5149     inode.i_links_count = 0;
5150     inode.i_dtime = time(0);
5151     if (inode.i_file_acl &&
5152     (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5153     count = 1;
5154     pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5155     block_buf, -1, &count);
5156     if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5157     pctx.errcode = 0;
5158     count = 1;
5159     }
5160     if (pctx.errcode) {
5161     pctx.blk = inode.i_file_acl;
5162     fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5163     }
5164     /*
5165     * If the count is zero, then arrange to have the
5166     * block deleted. If the block is in the block_dup_map,
5167     * also call delete_file_block since it will take care
5168     * of keeping the accounting straight.
5169     */
5170     if ((count == 0) ||
5171     ext2fs_test_block_bitmap(ctx->block_dup_map,
5172     inode.i_file_acl))
5173     delete_file_block(fs, &inode.i_file_acl,
5174     BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5175     }
5176     e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5177     }
5178    
5179     struct clone_struct {
5180     errcode_t errcode;
5181     ext2_ino_t dir;
5182     char *buf;
5183     e2fsck_t ctx;
5184     };
5185    
5186     static int clone_file_block(ext2_filsys fs,
5187     blk_t *block_nr,
5188     e2_blkcnt_t blockcnt,
5189     blk_t ref_block FSCK_ATTR((unused)),
5190     int ref_offset FSCK_ATTR((unused)),
5191     void *priv_data)
5192     {
5193     struct dup_block *p;
5194     blk_t new_block;
5195     errcode_t retval;
5196     struct clone_struct *cs = (struct clone_struct *) priv_data;
5197     dnode_t *n;
5198     e2fsck_t ctx;
5199    
5200     ctx = cs->ctx;
5201    
5202     if (HOLE_BLKADDR(*block_nr))
5203     return 0;
5204    
5205     if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5206     n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5207     if (n) {
5208     p = (struct dup_block *) dnode_get(n);
5209     retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5210     &new_block);
5211     if (retval) {
5212     cs->errcode = retval;
5213     return BLOCK_ABORT;
5214     }
5215     if (cs->dir && (blockcnt >= 0)) {
5216     retval = ext2fs_set_dir_block(fs->dblist,
5217     cs->dir, new_block, blockcnt);
5218     if (retval) {
5219     cs->errcode = retval;
5220     return BLOCK_ABORT;
5221     }
5222     }
5223    
5224     retval = io_channel_read_blk(fs->io, *block_nr, 1,
5225     cs->buf);
5226     if (retval) {
5227     cs->errcode = retval;
5228     return BLOCK_ABORT;
5229     }
5230     retval = io_channel_write_blk(fs->io, new_block, 1,
5231     cs->buf);
5232     if (retval) {
5233     cs->errcode = retval;
5234     return BLOCK_ABORT;
5235     }
5236     decrement_badcount(ctx, *block_nr, p);
5237     *block_nr = new_block;
5238     ext2fs_mark_block_bitmap(ctx->block_found_map,
5239     new_block);
5240     ext2fs_mark_block_bitmap(fs->block_map, new_block);
5241     return BLOCK_CHANGED;
5242     } else
5243     bb_error_msg(_("internal error; can't find dup_blk for %d"),
5244     *block_nr);
5245     }
5246     return 0;
5247     }
5248    
5249     static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5250     struct dup_inode *dp, char* block_buf)
5251     {
5252     ext2_filsys fs = ctx->fs;
5253     errcode_t retval;
5254     struct clone_struct cs;
5255     struct problem_context pctx;
5256     blk_t blk;
5257     dnode_t *n;
5258     struct inode_el *ino_el;
5259     struct dup_block *db;
5260     struct dup_inode *di;
5261    
5262     clear_problem_context(&pctx);
5263     cs.errcode = 0;
5264     cs.dir = 0;
5265     cs.ctx = ctx;
5266     retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5267     if (retval)
5268     return retval;
5269    
5270     if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5271     cs.dir = ino;
5272    
5273     pctx.ino = ino;
5274     pctx.str = "clone_file";
5275     if (ext2fs_inode_has_valid_blocks(&dp->inode))
5276     pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5277     clone_file_block, &cs);
5278     ext2fs_mark_bb_dirty(fs);
5279     if (pctx.errcode) {
5280     fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5281     retval = pctx.errcode;
5282     goto errout;
5283     }
5284     if (cs.errcode) {
5285     bb_error_msg(_("returned from clone_file_block"));
5286     retval = cs.errcode;
5287     goto errout;
5288     }
5289     /* The inode may have changed on disk, so we have to re-read it */
5290     e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5291     blk = dp->inode.i_file_acl;
5292     if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5293     BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5294     BLOCK_CHANGED)) {
5295     e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5296     /*
5297     * If we cloned the EA block, find all other inodes
5298     * which refered to that EA block, and modify
5299     * them to point to the new EA block.
5300     */
5301     n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5302     db = (struct dup_block *) dnode_get(n);
5303     for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5304     if (ino_el->inode == ino)
5305     continue;
5306     n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5307     di = (struct dup_inode *) dnode_get(n);
5308     if (di->inode.i_file_acl == blk) {
5309     di->inode.i_file_acl = dp->inode.i_file_acl;
5310     e2fsck_write_inode(ctx, ino_el->inode,
5311     &di->inode, "clone file EA");
5312     decrement_badcount(ctx, blk, db);
5313     }
5314     }
5315     }
5316     retval = 0;
5317     errout:
5318     ext2fs_free_mem(&cs.buf);
5319     return retval;
5320     }
5321    
5322     /*
5323     * This routine returns 1 if a block overlaps with one of the superblocks,
5324     * group descriptors, inode bitmaps, or block bitmaps.
5325     */
5326     static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5327     {
5328     ext2_filsys fs = ctx->fs;
5329     blk_t block;
5330     dgrp_t i;
5331    
5332     block = fs->super->s_first_data_block;
5333     for (i = 0; i < fs->group_desc_count; i++) {
5334    
5335     /* Check superblocks/block group descriptros */
5336     if (ext2fs_bg_has_super(fs, i)) {
5337     if (test_block >= block &&
5338     (test_block <= block + fs->desc_blocks))
5339     return 1;
5340     }
5341    
5342     /* Check the inode table */
5343     if ((fs->group_desc[i].bg_inode_table) &&
5344     (test_block >= fs->group_desc[i].bg_inode_table) &&
5345     (test_block < (fs->group_desc[i].bg_inode_table +
5346     fs->inode_blocks_per_group)))
5347     return 1;
5348    
5349     /* Check the bitmap blocks */
5350     if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5351     (test_block == fs->group_desc[i].bg_inode_bitmap))
5352     return 1;
5353    
5354     block += fs->super->s_blocks_per_group;
5355     }
5356     return 0;
5357     }
5358     /*
5359     * pass2.c --- check directory structure
5360     *
5361     * Pass 2 of e2fsck iterates through all active directory inodes, and
5362     * applies to following tests to each directory entry in the directory
5363     * blocks in the inodes:
5364     *
5365     * - The length of the directory entry (rec_len) should be at
5366     * least 8 bytes, and no more than the remaining space
5367     * left in the directory block.
5368     * - The length of the name in the directory entry (name_len)
5369     * should be less than (rec_len - 8).
5370     * - The inode number in the directory entry should be within
5371     * legal bounds.
5372     * - The inode number should refer to a in-use inode.
5373     * - The first entry should be '.', and its inode should be
5374     * the inode of the directory.
5375     * - The second entry should be '..'.
5376     *
5377     * To minimize disk seek time, the directory blocks are processed in
5378     * sorted order of block numbers.
5379     *
5380     * Pass 2 also collects the following information:
5381     * - The inode numbers of the subdirectories for each directory.
5382     *
5383     * Pass 2 relies on the following information from previous passes:
5384     * - The directory information collected in pass 1.
5385     * - The inode_used_map bitmap
5386     * - The inode_bad_map bitmap
5387     * - The inode_dir_map bitmap
5388     *
5389     * Pass 2 frees the following data structures
5390     * - The inode_bad_map bitmap
5391     * - The inode_reg_map bitmap
5392     */
5393    
5394     /*
5395     * Keeps track of how many times an inode is referenced.
5396     */
5397     static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5398     static int check_dir_block(ext2_filsys fs,
5399     struct ext2_db_entry *dir_blocks_info,
5400     void *priv_data);
5401     static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5402     struct problem_context *pctx);
5403     static int update_dir_block(ext2_filsys fs,
5404     blk_t *block_nr,
5405     e2_blkcnt_t blockcnt,
5406     blk_t ref_block,
5407     int ref_offset,
5408     void *priv_data);
5409     static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5410     static int htree_depth(struct dx_dir_info *dx_dir,
5411     struct dx_dirblock_info *dx_db);
5412     static int special_dir_block_cmp(const void *a, const void *b);
5413    
5414     struct check_dir_struct {
5415     char *buf;
5416     struct problem_context pctx;
5417     int count, max;
5418     e2fsck_t ctx;
5419     };
5420    
5421     static void e2fsck_pass2(e2fsck_t ctx)
5422     {
5423     struct ext2_super_block *sb = ctx->fs->super;
5424     struct problem_context pctx;
5425     ext2_filsys fs = ctx->fs;
5426     char *buf;
5427     struct dir_info *dir;
5428     struct check_dir_struct cd;
5429     struct dx_dir_info *dx_dir;
5430     struct dx_dirblock_info *dx_db, *dx_parent;
5431     int b;
5432     int i, depth;
5433     problem_t code;
5434     int bad_dir;
5435    
5436     clear_problem_context(&cd.pctx);
5437    
5438     /* Pass 2 */
5439    
5440     if (!(ctx->options & E2F_OPT_PREEN))
5441     fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5442    
5443     cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5444     0, ctx->inode_link_info,
5445     &ctx->inode_count);
5446     if (cd.pctx.errcode) {
5447     fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5448     ctx->flags |= E2F_FLAG_ABORT;
5449     return;
5450     }
5451     buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5452     "directory scan buffer");
5453    
5454     /*
5455     * Set up the parent pointer for the root directory, if
5456     * present. (If the root directory is not present, we will
5457     * create it in pass 3.)
5458     */
5459     dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5460     if (dir)
5461     dir->parent = EXT2_ROOT_INO;
5462    
5463     cd.buf = buf;
5464     cd.ctx = ctx;
5465     cd.count = 1;
5466     cd.max = ext2fs_dblist_count(fs->dblist);
5467    
5468     if (ctx->progress)
5469     (void) (ctx->progress)(ctx, 2, 0, cd.max);
5470    
5471     if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5472     ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5473    
5474     cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5475     &cd);
5476     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5477     return;
5478     if (cd.pctx.errcode) {
5479     fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5480     ctx->flags |= E2F_FLAG_ABORT;
5481     return;
5482     }
5483    
5484     #ifdef ENABLE_HTREE
5485     for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5486     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5487     return;
5488     if (dx_dir->numblocks == 0)
5489     continue;
5490     clear_problem_context(&pctx);
5491     bad_dir = 0;
5492     pctx.dir = dx_dir->ino;
5493     dx_db = dx_dir->dx_block;
5494     if (dx_db->flags & DX_FLAG_REFERENCED)
5495     dx_db->flags |= DX_FLAG_DUP_REF;
5496     else
5497     dx_db->flags |= DX_FLAG_REFERENCED;
5498     /*
5499     * Find all of the first and last leaf blocks, and
5500     * update their parent's min and max hash values
5501     */
5502     for (b=0, dx_db = dx_dir->dx_block;
5503     b < dx_dir->numblocks;
5504     b++, dx_db++) {
5505     if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5506     !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5507     continue;
5508     dx_parent = &dx_dir->dx_block[dx_db->parent];
5509     /*
5510     * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5511     */
5512     if (dx_db->flags & DX_FLAG_FIRST)
5513     dx_parent->min_hash = dx_db->min_hash;
5514     /*
5515     * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5516     */
5517     if (dx_db->flags & DX_FLAG_LAST)
5518     dx_parent->max_hash = dx_db->max_hash;
5519     }
5520    
5521     for (b=0, dx_db = dx_dir->dx_block;
5522     b < dx_dir->numblocks;
5523     b++, dx_db++) {
5524     pctx.blkcount = b;
5525     pctx.group = dx_db->parent;
5526     code = 0;
5527     if (!(dx_db->flags & DX_FLAG_FIRST) &&
5528     (dx_db->min_hash < dx_db->node_min_hash)) {
5529     pctx.blk = dx_db->min_hash;
5530     pctx.blk2 = dx_db->node_min_hash;
5531     code = PR_2_HTREE_MIN_HASH;
5532     fix_problem(ctx, code, &pctx);
5533     bad_dir++;
5534     }
5535     if (dx_db->type == DX_DIRBLOCK_LEAF) {
5536     depth = htree_depth(dx_dir, dx_db);
5537     if (depth != dx_dir->depth) {
5538     code = PR_2_HTREE_BAD_DEPTH;
5539     fix_problem(ctx, code, &pctx);
5540     bad_dir++;
5541     }
5542     }
5543     /*
5544     * This test doesn't apply for the root block
5545     * at block #0
5546     */
5547     if (b &&
5548     (dx_db->max_hash > dx_db->node_max_hash)) {
5549     pctx.blk = dx_db->max_hash;
5550     pctx.blk2 = dx_db->node_max_hash;
5551     code = PR_2_HTREE_MAX_HASH;
5552     fix_problem(ctx, code, &pctx);
5553     bad_dir++;
5554     }
5555     if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5556     code = PR_2_HTREE_NOTREF;
5557     fix_problem(ctx, code, &pctx);
5558     bad_dir++;
5559     } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5560     code = PR_2_HTREE_DUPREF;
5561     fix_problem(ctx, code, &pctx);
5562     bad_dir++;
5563     }
5564     if (code == 0)
5565     continue;
5566     }
5567     if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5568     clear_htree(ctx, dx_dir->ino);
5569     dx_dir->numblocks = 0;
5570     }
5571     }
5572     #endif
5573     ext2fs_free_mem(&buf);
5574     ext2fs_free_dblist(fs->dblist);
5575    
5576     ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5577     ctx->inode_bad_map = 0;
5578     ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5579     ctx->inode_reg_map = 0;
5580    
5581     clear_problem_context(&pctx);
5582     if (ctx->large_files) {
5583     if (!(sb->s_feature_ro_compat &
5584     EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5585     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5586     sb->s_feature_ro_compat |=
5587     EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5588     ext2fs_mark_super_dirty(fs);
5589     }
5590     if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5591     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5592     ext2fs_update_dynamic_rev(fs);
5593     ext2fs_mark_super_dirty(fs);
5594     }
5595     } else if (!ctx->large_files &&
5596     (sb->s_feature_ro_compat &
5597     EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5598     if (fs->flags & EXT2_FLAG_RW) {
5599     sb->s_feature_ro_compat &=
5600     ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5601     ext2fs_mark_super_dirty(fs);
5602     }
5603     }
5604    
5605     }
5606    
5607     #define MAX_DEPTH 32000
5608     static int htree_depth(struct dx_dir_info *dx_dir,
5609     struct dx_dirblock_info *dx_db)
5610     {
5611     int depth = 0;
5612    
5613     while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614     dx_db = &dx_dir->dx_block[dx_db->parent];
5615     depth++;
5616     }
5617     return depth;
5618     }
5619    
5620     static int dict_de_cmp(const void *a, const void *b)
5621     {
5622     const struct ext2_dir_entry *de_a, *de_b;
5623     int a_len, b_len;
5624    
5625     de_a = (const struct ext2_dir_entry *) a;
5626     a_len = de_a->name_len & 0xFF;
5627     de_b = (const struct ext2_dir_entry *) b;
5628     b_len = de_b->name_len & 0xFF;
5629    
5630     if (a_len != b_len)
5631     return (a_len - b_len);
5632    
5633     return strncmp(de_a->name, de_b->name, a_len);
5634     }
5635    
5636     /*
5637     * This is special sort function that makes sure that directory blocks
5638     * with a dirblock of zero are sorted to the beginning of the list.
5639     * This guarantees that the root node of the htree directories are
5640     * processed first, so we know what hash version to use.
5641     */
5642     static int special_dir_block_cmp(const void *a, const void *b)
5643     {
5644     const struct ext2_db_entry *db_a =
5645     (const struct ext2_db_entry *) a;
5646     const struct ext2_db_entry *db_b =
5647     (const struct ext2_db_entry *) b;
5648    
5649     if (db_a->blockcnt && !db_b->blockcnt)
5650     return 1;
5651    
5652     if (!db_a->blockcnt && db_b->blockcnt)
5653     return -1;
5654    
5655     if (db_a->blk != db_b->blk)
5656     return (int) (db_a->blk - db_b->blk);
5657    
5658     if (db_a->ino != db_b->ino)
5659     return (int) (db_a->ino - db_b->ino);
5660    
5661     return (int) (db_a->blockcnt - db_b->blockcnt);
5662     }
5663    
5664    
5665     /*
5666     * Make sure the first entry in the directory is '.', and that the
5667     * directory entry is sane.
5668     */
5669     static int check_dot(e2fsck_t ctx,
5670     struct ext2_dir_entry *dirent,
5671     ext2_ino_t ino, struct problem_context *pctx)
5672     {
5673     struct ext2_dir_entry *nextdir;
5674     int status = 0;
5675     int created = 0;
5676     int new_len;
5677     int problem = 0;
5678    
5679     if (!dirent->inode)
5680     problem = PR_2_MISSING_DOT;
5681     else if (((dirent->name_len & 0xFF) != 1) ||
5682     (dirent->name[0] != '.'))
5683     problem = PR_2_1ST_NOT_DOT;
5684     else if (dirent->name[1] != '\0')
5685     problem = PR_2_DOT_NULL_TERM;
5686    
5687     if (problem) {
5688     if (fix_problem(ctx, problem, pctx)) {
5689     if (dirent->rec_len < 12)
5690     dirent->rec_len = 12;
5691     dirent->inode = ino;
5692     dirent->name_len = 1;
5693     dirent->name[0] = '.';
5694     dirent->name[1] = '\0';
5695     status = 1;
5696     created = 1;
5697     }
5698     }
5699     if (dirent->inode != ino) {
5700     if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701     dirent->inode = ino;
5702     status = 1;
5703     }
5704     }
5705     if (dirent->rec_len > 12) {
5706     new_len = dirent->rec_len - 12;
5707     if (new_len > 12) {
5708     if (created ||
5709     fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710     nextdir = (struct ext2_dir_entry *)
5711     ((char *) dirent + 12);
5712     dirent->rec_len = 12;
5713     nextdir->rec_len = new_len;
5714     nextdir->inode = 0;
5715     nextdir->name_len = 0;
5716     status = 1;
5717     }
5718     }
5719     }
5720     return status;
5721     }
5722    
5723     /*
5724     * Make sure the second entry in the directory is '..', and that the
5725     * directory entry is sane. We do not check the inode number of '..'
5726     * here; this gets done in pass 3.
5727     */
5728     static int check_dotdot(e2fsck_t ctx,
5729     struct ext2_dir_entry *dirent,
5730     struct dir_info *dir, struct problem_context *pctx)
5731     {
5732     int problem = 0;
5733    
5734     if (!dirent->inode)
5735     problem = PR_2_MISSING_DOT_DOT;
5736     else if (((dirent->name_len & 0xFF) != 2) ||
5737     (dirent->name[0] != '.') ||
5738     (dirent->name[1] != '.'))
5739     problem = PR_2_2ND_NOT_DOT_DOT;
5740     else if (dirent->name[2] != '\0')
5741     problem = PR_2_DOT_DOT_NULL_TERM;
5742    
5743     if (problem) {
5744     if (fix_problem(ctx, problem, pctx)) {
5745     if (dirent->rec_len < 12)
5746     dirent->rec_len = 12;
5747     /*
5748     * Note: we don't have the parent inode just
5749     * yet, so we will fill it in with the root
5750     * inode. This will get fixed in pass 3.
5751     */
5752     dirent->inode = EXT2_ROOT_INO;
5753     dirent->name_len = 2;
5754     dirent->name[0] = '.';
5755     dirent->name[1] = '.';
5756     dirent->name[2] = '\0';
5757     return 1;
5758     }
5759     return 0;
5760     }
5761     dir->dotdot = dirent->inode;
5762     return 0;
5763     }
5764    
5765     /*
5766     * Check to make sure a directory entry doesn't contain any illegal
5767     * characters.
5768     */
5769     static int check_name(e2fsck_t ctx,
5770     struct ext2_dir_entry *dirent,
5771     struct problem_context *pctx)
5772     {
5773     int i;
5774     int fixup = -1;
5775     int ret = 0;
5776    
5777     for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778     if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779     if (fixup < 0) {
5780     fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5781     }
5782     if (fixup) {
5783     dirent->name[i] = '.';
5784     ret = 1;
5785     }
5786     }
5787     }
5788     return ret;
5789     }
5790    
5791     /*
5792     * Check the directory filetype (if present)
5793     */
5794    
5795     /*
5796     * Given a mode, return the ext2 file type
5797     */
5798     static int ext2_file_type(unsigned int mode)
5799     {
5800     if (LINUX_S_ISREG(mode))
5801     return EXT2_FT_REG_FILE;
5802    
5803     if (LINUX_S_ISDIR(mode))
5804     return EXT2_FT_DIR;
5805    
5806     if (LINUX_S_ISCHR(mode))
5807     return EXT2_FT_CHRDEV;
5808    
5809     if (LINUX_S_ISBLK(mode))
5810     return EXT2_FT_BLKDEV;
5811    
5812     if (LINUX_S_ISLNK(mode))
5813     return EXT2_FT_SYMLINK;
5814    
5815     if (LINUX_S_ISFIFO(mode))
5816     return EXT2_FT_FIFO;
5817    
5818     if (LINUX_S_ISSOCK(mode))
5819     return EXT2_FT_SOCK;
5820    
5821     return 0;
5822     }
5823    
5824     static int check_filetype(e2fsck_t ctx,
5825     struct ext2_dir_entry *dirent,
5826     struct problem_context *pctx)
5827     {
5828     int filetype = dirent->name_len >> 8;
5829     int should_be = EXT2_FT_UNKNOWN;
5830     struct ext2_inode inode;
5831    
5832     if (!(ctx->fs->super->s_feature_incompat &
5833     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834     if (filetype == 0 ||
5835     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836     return 0;
5837     dirent->name_len = dirent->name_len & 0xFF;
5838     return 1;
5839     }
5840    
5841     if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842     should_be = EXT2_FT_DIR;
5843     } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844     dirent->inode)) {
5845     should_be = EXT2_FT_REG_FILE;
5846     } else if (ctx->inode_bad_map &&
5847     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848     dirent->inode))
5849     should_be = 0;
5850     else {
5851     e2fsck_read_inode(ctx, dirent->inode, &inode,
5852     "check_filetype");
5853     should_be = ext2_file_type(inode.i_mode);
5854     }
5855     if (filetype == should_be)
5856     return 0;
5857     pctx->num = should_be;
5858    
5859     if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860     pctx) == 0)
5861     return 0;
5862    
5863     dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864     return 1;
5865     }
5866    
5867     #ifdef ENABLE_HTREE
5868     static void parse_int_node(ext2_filsys fs,
5869     struct ext2_db_entry *db,
5870     struct check_dir_struct *cd,
5871     struct dx_dir_info *dx_dir,
5872     char *block_buf)
5873     {
5874     struct ext2_dx_root_info *root;
5875     struct ext2_dx_entry *ent;
5876     struct ext2_dx_countlimit *limit;
5877     struct dx_dirblock_info *dx_db;
5878     int i, expect_limit, count;
5879     blk_t blk;
5880     ext2_dirhash_t min_hash = 0xffffffff;
5881     ext2_dirhash_t max_hash = 0;
5882     ext2_dirhash_t hash = 0, prev_hash;
5883    
5884     if (db->blockcnt == 0) {
5885     root = (struct ext2_dx_root_info *) (block_buf + 24);
5886     ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887     } else {
5888     ent = (struct ext2_dx_entry *) (block_buf+8);
5889     }
5890     limit = (struct ext2_dx_countlimit *) ent;
5891    
5892     count = ext2fs_le16_to_cpu(limit->count);
5893     expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894     sizeof(struct ext2_dx_entry);
5895     if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896     cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897     if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898     goto clear_and_exit;
5899     }
5900     if (count > expect_limit) {
5901     cd->pctx.num = count;
5902     if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903     goto clear_and_exit;
5904     count = expect_limit;
5905     }
5906    
5907     for (i=0; i < count; i++) {
5908     prev_hash = hash;
5909     hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910     blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911     /* Check to make sure the block is valid */
5912     if (blk > (blk_t) dx_dir->numblocks) {
5913     cd->pctx.blk = blk;
5914     if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915     &cd->pctx))
5916     goto clear_and_exit;
5917     }
5918     if (hash < prev_hash &&
5919     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920     goto clear_and_exit;
5921     dx_db = &dx_dir->dx_block[blk];
5922     if (dx_db->flags & DX_FLAG_REFERENCED) {
5923     dx_db->flags |= DX_FLAG_DUP_REF;
5924     } else {
5925     dx_db->flags |= DX_FLAG_REFERENCED;
5926     dx_db->parent = db->blockcnt;
5927     }
5928     if (hash < min_hash)
5929     min_hash = hash;
5930     if (hash > max_hash)
5931     max_hash = hash;
5932     dx_db->node_min_hash = hash;
5933     if ((i+1) < count)
5934     dx_db->node_max_hash =
5935     ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936     else {
5937     dx_db->node_max_hash = 0xfffffffe;
5938     dx_db->flags |= DX_FLAG_LAST;
5939     }
5940     if (i == 0)
5941     dx_db->flags |= DX_FLAG_FIRST;
5942     }
5943     dx_db = &dx_dir->dx_block[db->blockcnt];
5944     dx_db->min_hash = min_hash;
5945     dx_db->max_hash = max_hash;
5946     return;
5947    
5948     clear_and_exit:
5949     clear_htree(cd->ctx, cd->pctx.ino);
5950     dx_dir->numblocks = 0;
5951     }
5952     #endif /* ENABLE_HTREE */
5953    
5954     /*
5955     * Given a busted directory, try to salvage it somehow.
5956     *
5957     */
5958     static void salvage_directory(ext2_filsys fs,
5959     struct ext2_dir_entry *dirent,
5960     struct ext2_dir_entry *prev,
5961     unsigned int *offset)
5962     {
5963     char *cp = (char *) dirent;
5964     int left = fs->blocksize - *offset - dirent->rec_len;
5965     int name_len = dirent->name_len & 0xFF;
5966    
5967     /*
5968     * Special case of directory entry of size 8: copy what's left
5969     * of the directory block up to cover up the invalid hole.
5970     */
5971     if ((left >= 12) && (dirent->rec_len == 8)) {
5972     memmove(cp, cp+8, left);
5973     memset(cp + left, 0, 8);
5974     return;
5975     }
5976     /*
5977     * If the directory entry overruns the end of the directory
5978     * block, and the name is small enough to fit, then adjust the
5979     * record length.
5980     */
5981     if ((left < 0) &&
5982     (name_len + 8 <= dirent->rec_len + left) &&
5983     dirent->inode <= fs->super->s_inodes_count &&
5984     strnlen(dirent->name, name_len) == name_len) {
5985     dirent->rec_len += left;
5986     return;
5987     }
5988     /*
5989     * If the directory entry is a multiple of four, so it is
5990     * valid, let the previous directory entry absorb the invalid
5991     * one.
5992     */
5993     if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994     prev->rec_len += dirent->rec_len;
5995     *offset += dirent->rec_len;
5996     return;
5997     }
5998     /*
5999     * Default salvage method --- kill all of the directory
6000     * entries for the rest of the block. We will either try to
6001     * absorb it into the previous directory entry, or create a
6002     * new empty directory entry the rest of the directory block.
6003     */
6004     if (prev) {
6005     prev->rec_len += fs->blocksize - *offset;
6006     *offset = fs->blocksize;
6007     } else {
6008     dirent->rec_len = fs->blocksize - *offset;
6009     dirent->name_len = 0;
6010     dirent->inode = 0;
6011     }
6012     }
6013    
6014     static int check_dir_block(ext2_filsys fs,
6015     struct ext2_db_entry *db,
6016     void *priv_data)
6017     {
6018     struct dir_info *subdir, *dir;
6019     struct dx_dir_info *dx_dir;
6020     #ifdef ENABLE_HTREE
6021     struct dx_dirblock_info *dx_db = 0;
6022     #endif /* ENABLE_HTREE */
6023     struct ext2_dir_entry *dirent, *prev;
6024     ext2_dirhash_t hash;
6025     unsigned int offset = 0;
6026     int dir_modified = 0;
6027     int dot_state;
6028     blk_t block_nr = db->blk;
6029     ext2_ino_t ino = db->ino;
6030     __u16 links;
6031     struct check_dir_struct *cd;
6032     char *buf;
6033     e2fsck_t ctx;
6034     int problem;
6035     struct ext2_dx_root_info *root;
6036     struct ext2_dx_countlimit *limit;
6037     static dict_t de_dict;
6038     struct problem_context pctx;
6039     int dups_found = 0;
6040    
6041     cd = (struct check_dir_struct *) priv_data;
6042     buf = cd->buf;
6043     ctx = cd->ctx;
6044    
6045     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046     return DIRENT_ABORT;
6047    
6048     if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049     return DIRENT_ABORT;
6050    
6051     /*
6052     * Make sure the inode is still in use (could have been
6053     * deleted in the duplicate/bad blocks pass.
6054     */
6055     if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056     return 0;
6057    
6058     cd->pctx.ino = ino;
6059     cd->pctx.blk = block_nr;
6060     cd->pctx.blkcount = db->blockcnt;
6061     cd->pctx.ino2 = 0;
6062     cd->pctx.dirent = 0;
6063     cd->pctx.num = 0;
6064    
6065     if (db->blk == 0) {
6066     if (allocate_dir_block(ctx, db, &cd->pctx))
6067     return 0;
6068     block_nr = db->blk;
6069     }
6070    
6071     if (db->blockcnt)
6072     dot_state = 2;
6073     else
6074     dot_state = 0;
6075    
6076     if (ctx->dirs_to_hash &&
6077     ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078     dups_found++;
6079    
6080     cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081     if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082     cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083     if (cd->pctx.errcode) {
6084     if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085     ctx->flags |= E2F_FLAG_ABORT;
6086     return DIRENT_ABORT;
6087     }
6088     memset(buf, 0, fs->blocksize);
6089     }
6090     #ifdef ENABLE_HTREE
6091     dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092     if (dx_dir && dx_dir->numblocks) {
6093     if (db->blockcnt >= dx_dir->numblocks) {
6094     printf("XXX should never happen!!!\n");
6095     abort();
6096     }
6097     dx_db = &dx_dir->dx_block[db->blockcnt];
6098     dx_db->type = DX_DIRBLOCK_LEAF;
6099     dx_db->phys = block_nr;
6100     dx_db->min_hash = ~0;
6101     dx_db->max_hash = 0;
6102    
6103     dirent = (struct ext2_dir_entry *) buf;
6104     limit = (struct ext2_dx_countlimit *) (buf+8);
6105     if (db->blockcnt == 0) {
6106     root = (struct ext2_dx_root_info *) (buf + 24);
6107     dx_db->type = DX_DIRBLOCK_ROOT;
6108     dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109     if ((root->reserved_zero ||
6110     root->info_length < 8 ||
6111     root->indirect_levels > 1) &&
6112     fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113     clear_htree(ctx, ino);
6114     dx_dir->numblocks = 0;
6115     dx_db = 0;
6116     }
6117     dx_dir->hashversion = root->hash_version;
6118     dx_dir->depth = root->indirect_levels + 1;
6119     } else if ((dirent->inode == 0) &&
6120     (dirent->rec_len == fs->blocksize) &&
6121     (dirent->name_len == 0) &&
6122     (ext2fs_le16_to_cpu(limit->limit) ==
6123     ((fs->blocksize-8) /
6124     sizeof(struct ext2_dx_entry))))
6125     dx_db->type = DX_DIRBLOCK_NODE;
6126     }
6127     #endif /* ENABLE_HTREE */
6128    
6129     dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130     prev = 0;
6131     do {
6132     problem = 0;
6133     dirent = (struct ext2_dir_entry *) (buf + offset);
6134     cd->pctx.dirent = dirent;
6135     cd->pctx.num = offset;
6136     if (((offset + dirent->rec_len) > fs->blocksize) ||
6137     (dirent->rec_len < 12) ||
6138     ((dirent->rec_len % 4) != 0) ||
6139     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140     if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141     salvage_directory(fs, dirent, prev, &offset);
6142     dir_modified++;
6143     continue;
6144     } else
6145     goto abort_free_dict;
6146     }
6147     if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148     if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149     dirent->name_len = EXT2_NAME_LEN;
6150     dir_modified++;
6151     }
6152     }
6153    
6154     if (dot_state == 0) {
6155     if (check_dot(ctx, dirent, ino, &cd->pctx))
6156     dir_modified++;
6157     } else if (dot_state == 1) {
6158     dir = e2fsck_get_dir_info(ctx, ino);
6159     if (!dir) {
6160     fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161     goto abort_free_dict;
6162     }
6163     if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164     dir_modified++;
6165     } else if (dirent->inode == ino) {
6166     problem = PR_2_LINK_DOT;
6167     if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168     dirent->inode = 0;
6169     dir_modified++;
6170     goto next;
6171     }
6172     }
6173     if (!dirent->inode)
6174     goto next;
6175    
6176     /*
6177     * Make sure the inode listed is a legal one.
6178     */
6179     if (((dirent->inode != EXT2_ROOT_INO) &&
6180     (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181     (dirent->inode > fs->super->s_inodes_count)) {
6182     problem = PR_2_BAD_INO;
6183     } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184     dirent->inode))) {
6185     /*
6186     * If the inode is unused, offer to clear it.
6187     */
6188     problem = PR_2_UNUSED_INODE;
6189     } else if ((dot_state > 1) &&
6190     ((dirent->name_len & 0xFF) == 1) &&
6191     (dirent->name[0] == '.')) {
6192     /*
6193     * If there's a '.' entry in anything other
6194     * than the first directory entry, it's a
6195     * duplicate entry that should be removed.
6196     */
6197     problem = PR_2_DUP_DOT;
6198     } else if ((dot_state > 1) &&
6199     ((dirent->name_len & 0xFF) == 2) &&
6200     (dirent->name[0] == '.') &&
6201     (dirent->name[1] == '.')) {
6202     /*
6203     * If there's a '..' entry in anything other
6204     * than the second directory entry, it's a
6205     * duplicate entry that should be removed.
6206     */
6207     problem = PR_2_DUP_DOT_DOT;
6208     } else if ((dot_state > 1) &&
6209     (dirent->inode == EXT2_ROOT_INO)) {
6210     /*
6211     * Don't allow links to the root directory.
6212     * We check this specially to make sure we
6213     * catch this error case even if the root
6214     * directory hasn't been created yet.
6215     */
6216     problem = PR_2_LINK_ROOT;
6217     } else if ((dot_state > 1) &&
6218     (dirent->name_len & 0xFF) == 0) {
6219     /*
6220     * Don't allow zero-length directory names.
6221     */
6222     problem = PR_2_NULL_NAME;
6223     }
6224    
6225     if (problem) {
6226     if (fix_problem(ctx, problem, &cd->pctx)) {
6227     dirent->inode = 0;
6228     dir_modified++;
6229     goto next;
6230     } else {
6231     ext2fs_unmark_valid(fs);
6232     if (problem == PR_2_BAD_INO)
6233     goto next;
6234     }
6235     }
6236    
6237     /*
6238     * If the inode was marked as having bad fields in
6239     * pass1, process it and offer to fix/clear it.
6240     * (We wait until now so that we can display the
6241     * pathname to the user.)
6242     */
6243     if (ctx->inode_bad_map &&
6244     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245     dirent->inode)) {
6246     if (e2fsck_process_bad_inode(ctx, ino,
6247     dirent->inode,
6248     buf + fs->blocksize)) {
6249     dirent->inode = 0;
6250     dir_modified++;
6251     goto next;
6252     }
6253     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254     return DIRENT_ABORT;
6255     }
6256    
6257     if (check_name(ctx, dirent, &cd->pctx))
6258     dir_modified++;
6259    
6260     if (check_filetype(ctx, dirent, &cd->pctx))
6261     dir_modified++;
6262    
6263     #ifdef ENABLE_HTREE
6264     if (dx_db) {
6265     ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266     (dirent->name_len & 0xFF),
6267     fs->super->s_hash_seed, &hash, 0);
6268     if (hash < dx_db->min_hash)
6269     dx_db->min_hash = hash;
6270     if (hash > dx_db->max_hash)
6271     dx_db->max_hash = hash;
6272     }
6273     #endif
6274    
6275     /*
6276     * If this is a directory, then mark its parent in its
6277     * dir_info structure. If the parent field is already
6278     * filled in, then this directory has more than one
6279     * hard link. We assume the first link is correct,
6280     * and ask the user if he/she wants to clear this one.
6281     */
6282     if ((dot_state > 1) &&
6283     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284     dirent->inode))) {
6285     subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286     if (!subdir) {
6287     cd->pctx.ino = dirent->inode;
6288     fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289     goto abort_free_dict;
6290     }
6291     if (subdir->parent) {
6292     cd->pctx.ino2 = subdir->parent;
6293     if (fix_problem(ctx, PR_2_LINK_DIR,
6294     &cd->pctx)) {
6295     dirent->inode = 0;
6296     dir_modified++;
6297     goto next;
6298     }
6299     cd->pctx.ino2 = 0;
6300     } else
6301     subdir->parent = ino;
6302     }
6303    
6304     if (dups_found) {
6305     ;
6306     } else if (dict_lookup(&de_dict, dirent)) {
6307     clear_problem_context(&pctx);
6308     pctx.ino = ino;
6309     pctx.dirent = dirent;
6310     fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311     if (!ctx->dirs_to_hash)
6312     ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313     if (ctx->dirs_to_hash)
6314     ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315     dups_found++;
6316     } else
6317     dict_alloc_insert(&de_dict, dirent, dirent);
6318    
6319     ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320     &links);
6321     if (links > 1)
6322     ctx->fs_links_count++;
6323     ctx->fs_total_count++;
6324     next:
6325     prev = dirent;
6326     offset += dirent->rec_len;
6327     dot_state++;
6328     } while (offset < fs->blocksize);
6329     #ifdef ENABLE_HTREE
6330     if (dx_db) {
6331     cd->pctx.dir = cd->pctx.ino;
6332     if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333     (dx_db->type == DX_DIRBLOCK_NODE))
6334     parse_int_node(fs, db, cd, dx_dir, buf);
6335     }
6336     #endif /* ENABLE_HTREE */
6337     if (offset != fs->blocksize) {
6338     cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339     if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340     dirent->rec_len = cd->pctx.num;
6341     dir_modified++;
6342     }
6343     }
6344     if (dir_modified) {
6345     cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346     if (cd->pctx.errcode) {
6347     if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348     &cd->pctx))
6349     goto abort_free_dict;
6350     }
6351     ext2fs_mark_changed(fs);
6352     }
6353     dict_free_nodes(&de_dict);
6354     return 0;
6355     abort_free_dict:
6356     dict_free_nodes(&de_dict);
6357     ctx->flags |= E2F_FLAG_ABORT;
6358     return DIRENT_ABORT;
6359     }
6360    
6361     /*
6362     * This function is called to deallocate a block, and is an interator
6363     * functioned called by deallocate inode via ext2fs_iterate_block().
6364     */
6365     static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366     e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367     blk_t ref_block FSCK_ATTR((unused)),
6368     int ref_offset FSCK_ATTR((unused)),
6369     void *priv_data)
6370     {
6371     e2fsck_t ctx = (e2fsck_t) priv_data;
6372    
6373     if (HOLE_BLKADDR(*block_nr))
6374     return 0;
6375     if ((*block_nr < fs->super->s_first_data_block) ||
6376     (*block_nr >= fs->super->s_blocks_count))
6377     return 0;
6378     ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379     ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380     return 0;
6381     }
6382    
6383     /*
6384     * This fuction deallocates an inode
6385     */
6386     static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6387     {
6388     ext2_filsys fs = ctx->fs;
6389     struct ext2_inode inode;
6390     struct problem_context pctx;
6391     __u32 count;
6392    
6393     ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394     e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395     inode.i_links_count = 0;
6396     inode.i_dtime = time(0);
6397     e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398     clear_problem_context(&pctx);
6399     pctx.ino = ino;
6400    
6401     /*
6402     * Fix up the bitmaps...
6403     */
6404     e2fsck_read_bitmaps(ctx);
6405     ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406     ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407     if (ctx->inode_bad_map)
6408     ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409     ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6410    
6411     if (inode.i_file_acl &&
6412     (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413     pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414     block_buf, -1, &count);
6415     if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416     pctx.errcode = 0;
6417     count = 1;
6418     }
6419     if (pctx.errcode) {
6420     pctx.blk = inode.i_file_acl;
6421     fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422     ctx->flags |= E2F_FLAG_ABORT;
6423     return;
6424     }
6425     if (count == 0) {
6426     ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427     inode.i_file_acl);
6428     ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6429     }
6430     inode.i_file_acl = 0;
6431     }
6432    
6433     if (!ext2fs_inode_has_valid_blocks(&inode))
6434     return;
6435    
6436     if (LINUX_S_ISREG(inode.i_mode) &&
6437     (inode.i_size_high || inode.i_size & 0x80000000UL))
6438     ctx->large_files--;
6439    
6440     pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441     deallocate_inode_block, ctx);
6442     if (pctx.errcode) {
6443     fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444     ctx->flags |= E2F_FLAG_ABORT;
6445     return;
6446     }
6447     }
6448    
6449     /*
6450     * This fuction clears the htree flag on an inode
6451     */
6452     static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6453     {
6454     struct ext2_inode inode;
6455    
6456     e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457     inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458     e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459     if (ctx->dirs_to_hash)
6460     ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6461     }
6462    
6463    
6464     static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465     ext2_ino_t ino, char *buf)
6466     {
6467     ext2_filsys fs = ctx->fs;
6468     struct ext2_inode inode;
6469     int inode_modified = 0;
6470     int not_fixed = 0;
6471     unsigned char *frag, *fsize;
6472     struct problem_context pctx;
6473     int problem = 0;
6474    
6475     e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6476    
6477     clear_problem_context(&pctx);
6478     pctx.ino = ino;
6479     pctx.dir = dir;
6480     pctx.inode = &inode;
6481    
6482     if (inode.i_file_acl &&
6483     !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484     fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485     inode.i_file_acl = 0;
6486     #if BB_BIG_ENDIAN
6487     /*
6488     * This is a special kludge to deal with long symlinks
6489     * on big endian systems. i_blocks had already been
6490     * decremented earlier in pass 1, but since i_file_acl
6491     * hadn't yet been cleared, ext2fs_read_inode()
6492     * assumed that the file was short symlink and would
6493     * not have byte swapped i_block[0]. Hence, we have
6494     * to byte-swap it here.
6495     */
6496     if (LINUX_S_ISLNK(inode.i_mode) &&
6497     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498     (inode.i_blocks == fs->blocksize >> 9))
6499     inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500     #endif
6501     inode_modified++;
6502     } else
6503     not_fixed++;
6504    
6505     if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506     !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507     !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508     !(LINUX_S_ISSOCK(inode.i_mode)))
6509     problem = PR_2_BAD_MODE;
6510     else if (LINUX_S_ISCHR(inode.i_mode)
6511     && !e2fsck_pass1_check_device_inode(fs, &inode))
6512     problem = PR_2_BAD_CHAR_DEV;
6513     else if (LINUX_S_ISBLK(inode.i_mode)
6514     && !e2fsck_pass1_check_device_inode(fs, &inode))
6515     problem = PR_2_BAD_BLOCK_DEV;
6516     else if (LINUX_S_ISFIFO(inode.i_mode)
6517     && !e2fsck_pass1_check_device_inode(fs, &inode))
6518     problem = PR_2_BAD_FIFO;
6519     else if (LINUX_S_ISSOCK(inode.i_mode)
6520     && !e2fsck_pass1_check_device_inode(fs, &inode))
6521     problem = PR_2_BAD_SOCKET;
6522     else if (LINUX_S_ISLNK(inode.i_mode)
6523     && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524     problem = PR_2_INVALID_SYMLINK;
6525     }
6526    
6527     if (problem) {
6528     if (fix_problem(ctx, problem, &pctx)) {
6529     deallocate_inode(ctx, ino, 0);
6530     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531     return 0;
6532     return 1;
6533     } else
6534     not_fixed++;
6535     problem = 0;
6536     }
6537    
6538     if (inode.i_faddr) {
6539     if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540     inode.i_faddr = 0;
6541     inode_modified++;
6542     } else
6543     not_fixed++;
6544     }
6545    
6546     switch (fs->super->s_creator_os) {
6547     case EXT2_OS_LINUX:
6548     frag = &inode.osd2.linux2.l_i_frag;
6549     fsize = &inode.osd2.linux2.l_i_fsize;
6550     break;
6551     case EXT2_OS_HURD:
6552     frag = &inode.osd2.hurd2.h_i_frag;
6553     fsize = &inode.osd2.hurd2.h_i_fsize;
6554     break;
6555     case EXT2_OS_MASIX:
6556     frag = &inode.osd2.masix2.m_i_frag;
6557     fsize = &inode.osd2.masix2.m_i_fsize;
6558     break;
6559     default:
6560     frag = fsize = 0;
6561     }
6562     if (frag && *frag) {
6563     pctx.num = *frag;
6564     if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565     *frag = 0;
6566     inode_modified++;
6567     } else
6568     not_fixed++;
6569     pctx.num = 0;
6570     }
6571     if (fsize && *fsize) {
6572     pctx.num = *fsize;
6573     if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574     *fsize = 0;
6575     inode_modified++;
6576     } else
6577     not_fixed++;
6578     pctx.num = 0;
6579     }
6580    
6581     if (inode.i_file_acl &&
6582     ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583     (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584     if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585     inode.i_file_acl = 0;
6586     inode_modified++;
6587     } else
6588     not_fixed++;
6589     }
6590     if (inode.i_dir_acl &&
6591     LINUX_S_ISDIR(inode.i_mode)) {
6592     if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593     inode.i_dir_acl = 0;
6594     inode_modified++;
6595     } else
6596     not_fixed++;
6597     }
6598    
6599     if (inode_modified)
6600     e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601     if (!not_fixed)
6602     ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603     return 0;
6604     }
6605    
6606    
6607     /*
6608     * allocate_dir_block --- this function allocates a new directory
6609     * block for a particular inode; this is done if a directory has
6610     * a "hole" in it, or if a directory has a illegal block number
6611     * that was zeroed out and now needs to be replaced.
6612     */
6613     static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614     struct problem_context *pctx)
6615     {
6616     ext2_filsys fs = ctx->fs;
6617     blk_t blk;
6618     char *block;
6619     struct ext2_inode inode;
6620    
6621     if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622     return 1;
6623    
6624     /*
6625     * Read the inode and block bitmaps in; we'll be messing with
6626     * them.
6627     */
6628     e2fsck_read_bitmaps(ctx);
6629    
6630     /*
6631     * First, find a free block
6632     */
6633     pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634     if (pctx->errcode) {
6635     pctx->str = "ext2fs_new_block";
6636     fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637     return 1;
6638     }
6639     ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640     ext2fs_mark_block_bitmap(fs->block_map, blk);
6641     ext2fs_mark_bb_dirty(fs);
6642    
6643     /*
6644     * Now let's create the actual data block for the inode
6645     */
6646     if (db->blockcnt)
6647     pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648     else
6649     pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650     EXT2_ROOT_INO, &block);
6651    
6652     if (pctx->errcode) {
6653     pctx->str = "ext2fs_new_dir_block";
6654     fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655     return 1;
6656     }
6657    
6658     pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659     ext2fs_free_mem(&block);
6660     if (pctx->errcode) {
6661     pctx->str = "ext2fs_write_dir_block";
6662     fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663     return 1;
6664     }
6665    
6666     /*
6667     * Update the inode block count
6668     */
6669     e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670     inode.i_blocks += fs->blocksize / 512;
6671     if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672     inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673     e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6674    
6675     /*
6676     * Finally, update the block pointers for the inode
6677     */
6678     db->blk = blk;
6679     pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680     0, update_dir_block, db);
6681     if (pctx->errcode) {
6682     pctx->str = "ext2fs_block_iterate";
6683     fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684     return 1;
6685     }
6686    
6687     return 0;
6688     }
6689    
6690     /*
6691     * This is a helper function for allocate_dir_block().
6692     */
6693     static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694     blk_t *block_nr,
6695     e2_blkcnt_t blockcnt,
6696     blk_t ref_block FSCK_ATTR((unused)),
6697     int ref_offset FSCK_ATTR((unused)),
6698     void *priv_data)
6699     {
6700     struct ext2_db_entry *db;
6701    
6702     db = (struct ext2_db_entry *) priv_data;
6703     if (db->blockcnt == (int) blockcnt) {
6704     *block_nr = db->blk;
6705     return BLOCK_CHANGED;
6706     }
6707     return 0;
6708     }
6709    
6710     /*
6711     * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6712     *
6713     * Pass #3 assures that all directories are connected to the
6714     * filesystem tree, using the following algorithm:
6715     *
6716     * First, the root directory is checked to make sure it exists; if
6717     * not, e2fsck will offer to create a new one. It is then marked as
6718     * "done".
6719     *
6720     * Then, pass3 interates over all directory inodes; for each directory
6721     * it attempts to trace up the filesystem tree, using dirinfo.parent
6722     * until it reaches a directory which has been marked "done". If it
6723     * cannot do so, then the directory must be disconnected, and e2fsck
6724     * will offer to reconnect it to /lost+found. While it is chasing
6725     * parent pointers up the filesystem tree, if pass3 sees a directory
6726     * twice, then it has detected a filesystem loop, and it will again
6727     * offer to reconnect the directory to /lost+found in to break the
6728     * filesystem loop.
6729     *
6730     * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731     * reconnect inodes to /lost+found; this subroutine is also used by
6732     * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6733     * is responsible for creating /lost+found if it does not exist.
6734     *
6735     * Pass 3 frees the following data structures:
6736     * - The dirinfo directory information cache.
6737     */
6738    
6739     static void check_root(e2fsck_t ctx);
6740     static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741     struct problem_context *pctx);
6742     static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6743    
6744     static ext2fs_inode_bitmap inode_loop_detect;
6745     static ext2fs_inode_bitmap inode_done_map;
6746    
6747     static void e2fsck_pass3(e2fsck_t ctx)
6748     {
6749     ext2_filsys fs = ctx->fs;
6750     int i;
6751     struct problem_context pctx;
6752     struct dir_info *dir;
6753     unsigned long maxdirs, count;
6754    
6755     clear_problem_context(&pctx);
6756    
6757     /* Pass 3 */
6758    
6759     if (!(ctx->options & E2F_OPT_PREEN))
6760     fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6761    
6762     /*
6763     * Allocate some bitmaps to do loop detection.
6764     */
6765     pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766     &inode_done_map);
6767     if (pctx.errcode) {
6768     pctx.num = 2;
6769     fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770     ctx->flags |= E2F_FLAG_ABORT;
6771     goto abort_exit;
6772     }
6773     check_root(ctx);
6774     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775     goto abort_exit;
6776    
6777     ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6778    
6779     maxdirs = e2fsck_get_num_dirinfo(ctx);
6780     count = 1;
6781    
6782     if (ctx->progress)
6783     if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784     goto abort_exit;
6785    
6786     for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788     goto abort_exit;
6789     if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790     goto abort_exit;
6791     if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792     if (check_directory(ctx, dir, &pctx))
6793     goto abort_exit;
6794     }
6795    
6796     /*
6797     * Force the creation of /lost+found if not present
6798     */
6799     if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800     e2fsck_get_lost_and_found(ctx, 1);
6801    
6802     /*
6803     * If there are any directories that need to be indexed or
6804     * optimized, do it here.
6805     */
6806     e2fsck_rehash_directories(ctx);
6807    
6808     abort_exit:
6809     e2fsck_free_dir_info(ctx);
6810     ext2fs_free_inode_bitmap(inode_loop_detect);
6811     inode_loop_detect = 0;
6812     ext2fs_free_inode_bitmap(inode_done_map);
6813     inode_done_map = 0;
6814     }
6815    
6816     /*
6817     * This makes sure the root inode is present; if not, we ask if the
6818     * user wants us to create it. Not creating it is a fatal error.
6819     */
6820     static void check_root(e2fsck_t ctx)
6821     {
6822     ext2_filsys fs = ctx->fs;
6823     blk_t blk;
6824     struct ext2_inode inode;
6825     char * block;
6826     struct problem_context pctx;
6827    
6828     clear_problem_context(&pctx);
6829    
6830     if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6831     /*
6832     * If the root inode is not a directory, die here. The
6833     * user must have answered 'no' in pass1 when we
6834     * offered to clear it.
6835     */
6836     if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837     EXT2_ROOT_INO))) {
6838     fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839     ctx->flags |= E2F_FLAG_ABORT;
6840     }
6841     return;
6842     }
6843    
6844     if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845     fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846     ctx->flags |= E2F_FLAG_ABORT;
6847     return;
6848     }
6849    
6850     e2fsck_read_bitmaps(ctx);
6851    
6852     /*
6853     * First, find a free block
6854     */
6855     pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856     if (pctx.errcode) {
6857     pctx.str = "ext2fs_new_block";
6858     fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859     ctx->flags |= E2F_FLAG_ABORT;
6860     return;
6861     }
6862     ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863     ext2fs_mark_block_bitmap(fs->block_map, blk);
6864     ext2fs_mark_bb_dirty(fs);
6865    
6866     /*
6867     * Now let's create the actual data block for the inode
6868     */
6869     pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870     &block);
6871     if (pctx.errcode) {
6872     pctx.str = "ext2fs_new_dir_block";
6873     fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874     ctx->flags |= E2F_FLAG_ABORT;
6875     return;
6876     }
6877    
6878     pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879     if (pctx.errcode) {
6880     pctx.str = "ext2fs_write_dir_block";
6881     fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882     ctx->flags |= E2F_FLAG_ABORT;
6883     return;
6884     }
6885     ext2fs_free_mem(&block);
6886    
6887     /*
6888     * Set up the inode structure
6889     */
6890     memset(&inode, 0, sizeof(inode));
6891     inode.i_mode = 040755;
6892     inode.i_size = fs->blocksize;
6893     inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
6894     inode.i_links_count = 2;
6895     inode.i_blocks = fs->blocksize / 512;
6896     inode.i_block[0] = blk;
6897    
6898     /*
6899     * Write out the inode.
6900     */
6901     pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902     if (pctx.errcode) {
6903     pctx.str = "ext2fs_write_inode";
6904     fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905     ctx->flags |= E2F_FLAG_ABORT;
6906     return;
6907     }
6908    
6909     /*
6910     * Miscellaneous bookkeeping...
6911     */
6912     e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913     ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914     ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6915    
6916     ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917     ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918     ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919     ext2fs_mark_ib_dirty(fs);
6920     }
6921    
6922     /*
6923     * This subroutine is responsible for making sure that a particular
6924     * directory is connected to the root; if it isn't we trace it up as
6925     * far as we can go, and then offer to connect the resulting parent to
6926     * the lost+found. We have to do loop detection; if we ever discover
6927     * a loop, we treat that as a disconnected directory and offer to
6928     * reparent it to lost+found.
6929     *
6930     * However, loop detection is expensive, because for very large
6931     * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932     * is non-trivial. Loops in filesystems are also a rare error case,
6933     * and we shouldn't optimize for error cases. So we try two passes of
6934     * the algorithm. The first time, we ignore loop detection and merely
6935     * increment a counter; if the counter exceeds some extreme threshold,
6936     * then we try again with the loop detection bitmap enabled.
6937     */
6938     static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939     struct problem_context *pctx)
6940     {
6941     ext2_filsys fs = ctx->fs;
6942     struct dir_info *p = dir;
6943     int loop_pass = 0, parent_count = 0;
6944    
6945     if (!p)
6946     return 0;
6947    
6948     while (1) {
6949     /*
6950     * Mark this inode as being "done"; by the time we
6951     * return from this function, the inode we either be
6952     * verified as being connected to the directory tree,
6953     * or we will have offered to reconnect this to
6954     * lost+found.
6955     *
6956     * If it was marked done already, then we've reached a
6957     * parent we've already checked.
6958     */
6959     if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960     break;
6961    
6962     /*
6963     * If this directory doesn't have a parent, or we've
6964     * seen the parent once already, then offer to
6965     * reparent it to lost+found
6966     */
6967     if (!p->parent ||
6968     (loop_pass &&
6969     (ext2fs_test_inode_bitmap(inode_loop_detect,
6970     p->parent)))) {
6971     pctx->ino = p->ino;
6972     if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973     if (e2fsck_reconnect_file(ctx, pctx->ino))
6974     ext2fs_unmark_valid(fs);
6975     else {
6976     p = e2fsck_get_dir_info(ctx, pctx->ino);
6977     p->parent = ctx->lost_and_found;
6978     fix_dotdot(ctx, p, ctx->lost_and_found);
6979     }
6980     }
6981     break;
6982     }
6983     p = e2fsck_get_dir_info(ctx, p->parent);
6984     if (!p) {
6985     fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986     return 0;
6987     }
6988     if (loop_pass) {
6989     ext2fs_mark_inode_bitmap(inode_loop_detect,
6990     p->ino);
6991     } else if (parent_count++ > 2048) {
6992     /*
6993     * If we've run into a path depth that's
6994     * greater than 2048, try again with the inode
6995     * loop bitmap turned on and start from the
6996     * top.
6997     */
6998     loop_pass = 1;
6999     if (inode_loop_detect)
7000     ext2fs_clear_inode_bitmap(inode_loop_detect);
7001     else {
7002     pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003     if (pctx->errcode) {
7004     pctx->num = 1;
7005     fix_problem(ctx,
7006     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007     ctx->flags |= E2F_FLAG_ABORT;
7008     return -1;
7009     }
7010     }
7011     p = dir;
7012     }
7013     }
7014    
7015     /*
7016     * Make sure that .. and the parent directory are the same;
7017     * offer to fix it if not.
7018     */
7019     if (dir->parent != dir->dotdot) {
7020     pctx->ino = dir->ino;
7021     pctx->ino2 = dir->dotdot;
7022     pctx->dir = dir->parent;
7023     if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024     fix_dotdot(ctx, dir, dir->parent);
7025     }
7026     return 0;
7027     }
7028    
7029     /*
7030     * This routine gets the lost_and_found inode, making it a directory
7031     * if necessary
7032     */
7033     ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7034     {
7035     ext2_filsys fs = ctx->fs;
7036     ext2_ino_t ino;
7037     blk_t blk;
7038     errcode_t retval;
7039     struct ext2_inode inode;
7040     char * block;
7041     static const char name[] = "lost+found";
7042     struct problem_context pctx;
7043     struct dir_info *dirinfo;
7044    
7045     if (ctx->lost_and_found)
7046     return ctx->lost_and_found;
7047    
7048     clear_problem_context(&pctx);
7049    
7050     retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051     sizeof(name)-1, 0, &ino);
7052     if (retval && !fix)
7053     return 0;
7054     if (!retval) {
7055     if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056     ctx->lost_and_found = ino;
7057     return ino;
7058     }
7059    
7060     /* Lost+found isn't a directory! */
7061     if (!fix)
7062     return 0;
7063     pctx.ino = ino;
7064     if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065     return 0;
7066    
7067     /* OK, unlink the old /lost+found file. */
7068     pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069     if (pctx.errcode) {
7070     pctx.str = "ext2fs_unlink";
7071     fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072     return 0;
7073     }
7074     dirinfo = e2fsck_get_dir_info(ctx, ino);
7075     if (dirinfo)
7076     dirinfo->parent = 0;
7077     e2fsck_adjust_inode_count(ctx, ino, -1);
7078     } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079     pctx.errcode = retval;
7080     fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7081     }
7082     if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083     return 0;
7084    
7085     /*
7086     * Read the inode and block bitmaps in; we'll be messing with
7087     * them.
7088     */
7089     e2fsck_read_bitmaps(ctx);
7090    
7091     /*
7092     * First, find a free block
7093     */
7094     retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095     if (retval) {
7096     pctx.errcode = retval;
7097     fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098     return 0;
7099     }
7100     ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101     ext2fs_block_alloc_stats(fs, blk, +1);
7102    
7103     /*
7104     * Next find a free inode.
7105     */
7106     retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107     ctx->inode_used_map, &ino);
7108     if (retval) {
7109     pctx.errcode = retval;
7110     fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111     return 0;
7112     }
7113     ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114     ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115     ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7116    
7117     /*
7118     * Now let's create the actual data block for the inode
7119     */
7120     retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121     if (retval) {
7122     pctx.errcode = retval;
7123     fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124     return 0;
7125     }
7126    
7127     retval = ext2fs_write_dir_block(fs, blk, block);
7128     ext2fs_free_mem(&block);
7129     if (retval) {
7130     pctx.errcode = retval;
7131     fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132     return 0;
7133     }
7134    
7135     /*
7136     * Set up the inode structure
7137     */
7138     memset(&inode, 0, sizeof(inode));
7139     inode.i_mode = 040700;
7140     inode.i_size = fs->blocksize;
7141     inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
7142     inode.i_links_count = 2;
7143     inode.i_blocks = fs->blocksize / 512;
7144     inode.i_block[0] = blk;
7145    
7146     /*
7147     * Next, write out the inode.
7148     */
7149     pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150     if (pctx.errcode) {
7151     pctx.str = "ext2fs_write_inode";
7152     fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153     return 0;
7154     }
7155     /*
7156     * Finally, create the directory link
7157     */
7158     pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159     if (pctx.errcode) {
7160     pctx.str = "ext2fs_link";
7161     fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162     return 0;
7163     }
7164    
7165     /*
7166     * Miscellaneous bookkeeping that needs to be kept straight.
7167     */
7168     e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169     e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170     ext2fs_icount_store(ctx->inode_count, ino, 2);
7171     ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172     ctx->lost_and_found = ino;
7173     return ino;
7174     }
7175    
7176     /*
7177     * This routine will connect a file to lost+found
7178     */
7179     int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7180     {
7181     ext2_filsys fs = ctx->fs;
7182     errcode_t retval;
7183     char name[80];
7184     struct problem_context pctx;
7185     struct ext2_inode inode;
7186     int file_type = 0;
7187    
7188     clear_problem_context(&pctx);
7189     pctx.ino = ino;
7190    
7191     if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192     if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193     ctx->bad_lost_and_found++;
7194     }
7195     if (ctx->bad_lost_and_found) {
7196     fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197     return 1;
7198     }
7199    
7200     sprintf(name, "#%u", ino);
7201     if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202     file_type = ext2_file_type(inode.i_mode);
7203     retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204     if (retval == EXT2_ET_DIR_NO_SPACE) {
7205     if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206     return 1;
7207     retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208     1, 0);
7209     if (retval) {
7210     pctx.errcode = retval;
7211     fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212     return 1;
7213     }
7214     retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215     ino, file_type);
7216     }
7217     if (retval) {
7218     pctx.errcode = retval;
7219     fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220     return 1;
7221     }
7222     e2fsck_adjust_inode_count(ctx, ino, 1);
7223    
7224     return 0;
7225     }
7226    
7227     /*
7228     * Utility routine to adjust the inode counts on an inode.
7229     */
7230     errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7231     {
7232     ext2_filsys fs = ctx->fs;
7233     errcode_t retval;
7234     struct ext2_inode inode;
7235    
7236     if (!ino)
7237     return 0;
7238    
7239     retval = ext2fs_read_inode(fs, ino, &inode);
7240     if (retval)
7241     return retval;
7242    
7243     if (adj == 1) {
7244     ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245     if (inode.i_links_count == (__u16) ~0)
7246     return 0;
7247     ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248     inode.i_links_count++;
7249     } else if (adj == -1) {
7250     ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251     if (inode.i_links_count == 0)
7252     return 0;
7253     ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254     inode.i_links_count--;
7255     }
7256    
7257     retval = ext2fs_write_inode(fs, ino, &inode);
7258     if (retval)
7259     return retval;
7260    
7261     return 0;
7262     }
7263    
7264     /*
7265     * Fix parent --- this routine fixes up the parent of a directory.
7266     */
7267     struct fix_dotdot_struct {
7268     ext2_filsys fs;
7269     ext2_ino_t parent;
7270     int done;
7271     e2fsck_t ctx;
7272     };
7273    
7274     static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275     int offset FSCK_ATTR((unused)),
7276     int blocksize FSCK_ATTR((unused)),
7277     char *buf FSCK_ATTR((unused)),
7278     void *priv_data)
7279     {
7280     struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281     errcode_t retval;
7282     struct problem_context pctx;
7283    
7284     if ((dirent->name_len & 0xFF) != 2)
7285     return 0;
7286     if (strncmp(dirent->name, "..", 2))
7287     return 0;
7288    
7289     clear_problem_context(&pctx);
7290    
7291     retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292     if (retval) {
7293     pctx.errcode = retval;
7294     fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7295     }
7296     retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297     if (retval) {
7298     pctx.errcode = retval;
7299     fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7300     }
7301     dirent->inode = fp->parent;
7302    
7303     fp->done++;
7304     return DIRENT_ABORT | DIRENT_CHANGED;
7305     }
7306    
7307     static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7308     {
7309     ext2_filsys fs = ctx->fs;
7310     errcode_t retval;
7311     struct fix_dotdot_struct fp;
7312     struct problem_context pctx;
7313    
7314     fp.fs = fs;
7315     fp.parent = parent;
7316     fp.done = 0;
7317     fp.ctx = ctx;
7318    
7319     retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320     0, fix_dotdot_proc, &fp);
7321     if (retval || !fp.done) {
7322     clear_problem_context(&pctx);
7323     pctx.ino = dir->ino;
7324     pctx.errcode = retval;
7325     fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326     PR_3_FIX_PARENT_NOFIND, &pctx);
7327     ext2fs_unmark_valid(fs);
7328     }
7329     dir->dotdot = parent;
7330     }
7331    
7332     /*
7333     * These routines are responsible for expanding a /lost+found if it is
7334     * too small.
7335     */
7336    
7337     struct expand_dir_struct {
7338     int num;
7339     int guaranteed_size;
7340     int newblocks;
7341     int last_block;
7342     errcode_t err;
7343     e2fsck_t ctx;
7344     };
7345    
7346     static int expand_dir_proc(ext2_filsys fs,
7347     blk_t *blocknr,
7348     e2_blkcnt_t blockcnt,
7349     blk_t ref_block FSCK_ATTR((unused)),
7350     int ref_offset FSCK_ATTR((unused)),
7351     void *priv_data)
7352     {
7353     struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354     blk_t new_blk;
7355     static blk_t last_blk = 0;
7356     char *block;
7357     errcode_t retval;
7358     e2fsck_t ctx;
7359    
7360     ctx = es->ctx;
7361    
7362     if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363     return BLOCK_ABORT;
7364    
7365     if (blockcnt > 0)
7366     es->last_block = blockcnt;
7367     if (*blocknr) {
7368     last_blk = *blocknr;
7369     return 0;
7370     }
7371     retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372     &new_blk);
7373     if (retval) {
7374     es->err = retval;
7375     return BLOCK_ABORT;
7376     }
7377     if (blockcnt > 0) {
7378     retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379     if (retval) {
7380     es->err = retval;
7381     return BLOCK_ABORT;
7382     }
7383     es->num--;
7384     retval = ext2fs_write_dir_block(fs, new_blk, block);
7385     } else {
7386     retval = ext2fs_get_mem(fs->blocksize, &block);
7387     if (retval) {
7388     es->err = retval;
7389     return BLOCK_ABORT;
7390     }
7391     memset(block, 0, fs->blocksize);
7392     retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7393     }
7394     if (retval) {
7395     es->err = retval;
7396     return BLOCK_ABORT;
7397     }
7398     ext2fs_free_mem(&block);
7399     *blocknr = new_blk;
7400     ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401     ext2fs_block_alloc_stats(fs, new_blk, +1);
7402     es->newblocks++;
7403    
7404     if (es->num == 0)
7405     return (BLOCK_CHANGED | BLOCK_ABORT);
7406     else
7407     return BLOCK_CHANGED;
7408     }
7409    
7410     errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411     int num, int guaranteed_size)
7412     {
7413     ext2_filsys fs = ctx->fs;
7414     errcode_t retval;
7415     struct expand_dir_struct es;
7416     struct ext2_inode inode;
7417    
7418     if (!(fs->flags & EXT2_FLAG_RW))
7419     return EXT2_ET_RO_FILSYS;
7420    
7421     /*
7422     * Read the inode and block bitmaps in; we'll be messing with
7423     * them.
7424     */
7425     e2fsck_read_bitmaps(ctx);
7426    
7427     retval = ext2fs_check_directory(fs, dir);
7428     if (retval)
7429     return retval;
7430    
7431     es.num = num;
7432     es.guaranteed_size = guaranteed_size;
7433     es.last_block = 0;
7434     es.err = 0;
7435     es.newblocks = 0;
7436     es.ctx = ctx;
7437    
7438     retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439     0, expand_dir_proc, &es);
7440    
7441     if (es.err)
7442     return es.err;
7443    
7444     /*
7445     * Update the size and block count fields in the inode.
7446     */
7447     retval = ext2fs_read_inode(fs, dir, &inode);
7448     if (retval)
7449     return retval;
7450    
7451     inode.i_size = (es.last_block + 1) * fs->blocksize;
7452     inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7453    
7454     e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7455    
7456     return 0;
7457     }
7458    
7459     /*
7460     * pass4.c -- pass #4 of e2fsck: Check reference counts
7461     *
7462     * Pass 4 frees the following data structures:
7463     * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7464     */
7465    
7466     /*
7467     * This routine is called when an inode is not connected to the
7468     * directory tree.
7469     *
7470     * This subroutine returns 1 then the caller shouldn't bother with the
7471     * rest of the pass 4 tests.
7472     */
7473     static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7474     {
7475     ext2_filsys fs = ctx->fs;
7476     struct ext2_inode inode;
7477     struct problem_context pctx;
7478    
7479     e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480     clear_problem_context(&pctx);
7481     pctx.ino = i;
7482     pctx.inode = &inode;
7483    
7484     /*
7485     * Offer to delete any zero-length files that does not have
7486     * blocks. If there is an EA block, it might have useful
7487     * information, so we won't prompt to delete it, but let it be
7488     * reconnected to lost+found.
7489     */
7490     if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491     LINUX_S_ISDIR(inode.i_mode))) {
7492     if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493     ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494     inode.i_links_count = 0;
7495     inode.i_dtime = time(0);
7496     e2fsck_write_inode(ctx, i, &inode,
7497     "disconnect_inode");
7498     /*
7499     * Fix up the bitmaps...
7500     */
7501     e2fsck_read_bitmaps(ctx);
7502     ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503     ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504     ext2fs_inode_alloc_stats2(fs, i, -1,
7505     LINUX_S_ISDIR(inode.i_mode));
7506     return 0;
7507     }
7508     }
7509    
7510     /*
7511     * Prompt to reconnect.
7512     */
7513     if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514     if (e2fsck_reconnect_file(ctx, i))
7515     ext2fs_unmark_valid(fs);
7516     } else {
7517     /*
7518     * If we don't attach the inode, then skip the
7519     * i_links_test since there's no point in trying to
7520     * force i_links_count to zero.
7521     */
7522     ext2fs_unmark_valid(fs);
7523     return 1;
7524     }
7525     return 0;
7526     }
7527    
7528    
7529     static void e2fsck_pass4(e2fsck_t ctx)
7530     {
7531     ext2_filsys fs = ctx->fs;
7532     ext2_ino_t i;
7533     struct ext2_inode inode;
7534     struct problem_context pctx;
7535     __u16 link_count, link_counted;
7536     char *buf = 0;
7537     int group, maxgroup;
7538    
7539     /* Pass 4 */
7540    
7541     clear_problem_context(&pctx);
7542    
7543     if (!(ctx->options & E2F_OPT_PREEN))
7544     fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7545    
7546     group = 0;
7547     maxgroup = fs->group_desc_count;
7548     if (ctx->progress)
7549     if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550     return;
7551    
7552     for (i=1; i <= fs->super->s_inodes_count; i++) {
7553     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554     return;
7555     if ((i % fs->super->s_inodes_per_group) == 0) {
7556     group++;
7557     if (ctx->progress)
7558     if ((ctx->progress)(ctx, 4, group, maxgroup))
7559     return;
7560     }
7561     if (i == EXT2_BAD_INO ||
7562     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563     continue;
7564     if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565     (ctx->inode_imagic_map &&
7566     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567     continue;
7568     ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569     ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570     if (link_counted == 0) {
7571     if (!buf)
7572     buf = e2fsck_allocate_memory(ctx,
7573     fs->blocksize, "bad_inode buffer");
7574     if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575     continue;
7576     if (disconnect_inode(ctx, i))
7577     continue;
7578     ext2fs_icount_fetch(ctx->inode_link_info, i,
7579     &link_count);
7580     ext2fs_icount_fetch(ctx->inode_count, i,
7581     &link_counted);
7582     }
7583     if (link_counted != link_count) {
7584     e2fsck_read_inode(ctx, i, &inode, "pass4");
7585     pctx.ino = i;
7586     pctx.inode = &inode;
7587     if (link_count != inode.i_links_count) {
7588     pctx.num = link_count;
7589     fix_problem(ctx,
7590     PR_4_INCONSISTENT_COUNT, &pctx);
7591     }
7592     pctx.num = link_counted;
7593     if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594     inode.i_links_count = link_counted;
7595     e2fsck_write_inode(ctx, i, &inode, "pass4");
7596     }
7597     }
7598     }
7599     ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600     ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601     ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602     ctx->inode_imagic_map = 0;
7603     ext2fs_free_mem(&buf);
7604     }
7605    
7606     /*
7607     * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7608     */
7609    
7610     #define NO_BLK ((blk_t) -1)
7611    
7612     static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613     struct problem_context *pctx)
7614     {
7615     switch (problem) {
7616     case PR_5_BLOCK_UNUSED:
7617     if (pctx->blk == pctx->blk2)
7618     pctx->blk2 = 0;
7619     else
7620     problem = PR_5_BLOCK_RANGE_UNUSED;
7621     break;
7622     case PR_5_BLOCK_USED:
7623     if (pctx->blk == pctx->blk2)
7624     pctx->blk2 = 0;
7625     else
7626     problem = PR_5_BLOCK_RANGE_USED;
7627     break;
7628     case PR_5_INODE_UNUSED:
7629     if (pctx->ino == pctx->ino2)
7630     pctx->ino2 = 0;
7631     else
7632     problem = PR_5_INODE_RANGE_UNUSED;
7633     break;
7634     case PR_5_INODE_USED:
7635     if (pctx->ino == pctx->ino2)
7636     pctx->ino2 = 0;
7637     else
7638     problem = PR_5_INODE_RANGE_USED;
7639     break;
7640     }
7641     fix_problem(ctx, problem, pctx);
7642     pctx->blk = pctx->blk2 = NO_BLK;
7643     pctx->ino = pctx->ino2 = 0;
7644     }
7645    
7646     static void check_block_bitmaps(e2fsck_t ctx)
7647     {
7648     ext2_filsys fs = ctx->fs;
7649     blk_t i;
7650     int *free_array;
7651     int group = 0;
7652     unsigned int blocks = 0;
7653     unsigned int free_blocks = 0;
7654     int group_free = 0;
7655     int actual, bitmap;
7656     struct problem_context pctx;
7657     int problem, save_problem, fixit, had_problem;
7658     errcode_t retval;
7659    
7660     clear_problem_context(&pctx);
7661     free_array = (int *) e2fsck_allocate_memory(ctx,
7662     fs->group_desc_count * sizeof(int), "free block count array");
7663    
7664     if ((fs->super->s_first_data_block <
7665     ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666     (fs->super->s_blocks_count-1 >
7667     ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668     pctx.num = 1;
7669     pctx.blk = fs->super->s_first_data_block;
7670     pctx.blk2 = fs->super->s_blocks_count -1;
7671     pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672     pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673     fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7674    
7675     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676     return;
7677     }
7678    
7679     if ((fs->super->s_first_data_block <
7680     ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681     (fs->super->s_blocks_count-1 >
7682     ext2fs_get_block_bitmap_end(fs->block_map))) {
7683     pctx.num = 2;
7684     pctx.blk = fs->super->s_first_data_block;
7685     pctx.blk2 = fs->super->s_blocks_count -1;
7686     pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687     pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688     fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7689    
7690     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691     return;
7692     }
7693    
7694     redo_counts:
7695     had_problem = 0;
7696     save_problem = 0;
7697     pctx.blk = pctx.blk2 = NO_BLK;
7698     for (i = fs->super->s_first_data_block;
7699     i < fs->super->s_blocks_count;
7700     i++) {
7701     actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702     bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7703    
7704     if (actual == bitmap)
7705     goto do_counts;
7706    
7707     if (!actual && bitmap) {
7708     /*
7709     * Block not used, but marked in use in the bitmap.
7710     */
7711     problem = PR_5_BLOCK_UNUSED;
7712     } else {
7713     /*
7714     * Block used, but not marked in use in the bitmap.
7715     */
7716     problem = PR_5_BLOCK_USED;
7717     }
7718     if (pctx.blk == NO_BLK) {
7719     pctx.blk = pctx.blk2 = i;
7720     save_problem = problem;
7721     } else {
7722     if ((problem == save_problem) &&
7723     (pctx.blk2 == i-1))
7724     pctx.blk2++;
7725     else {
7726     print_bitmap_problem(ctx, save_problem, &pctx);
7727     pctx.blk = pctx.blk2 = i;
7728     save_problem = problem;
7729     }
7730     }
7731     ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732     had_problem++;
7733    
7734     do_counts:
7735     if (!bitmap) {
7736     group_free++;
7737     free_blocks++;
7738     }
7739     blocks ++;
7740     if ((blocks == fs->super->s_blocks_per_group) ||
7741     (i == fs->super->s_blocks_count-1)) {
7742     free_array[group] = group_free;
7743     group ++;
7744     blocks = 0;
7745     group_free = 0;
7746     if (ctx->progress)
7747     if ((ctx->progress)(ctx, 5, group,
7748     fs->group_desc_count*2))
7749     return;
7750     }
7751     }
7752     if (pctx.blk != NO_BLK)
7753     print_bitmap_problem(ctx, save_problem, &pctx);
7754     if (had_problem)
7755     fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756     else
7757     fixit = -1;
7758     ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7759    
7760     if (fixit == 1) {
7761     ext2fs_free_block_bitmap(fs->block_map);
7762     retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763     &fs->block_map);
7764     if (retval) {
7765     clear_problem_context(&pctx);
7766     fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767     ctx->flags |= E2F_FLAG_ABORT;
7768     return;
7769     }
7770     ext2fs_set_bitmap_padding(fs->block_map);
7771     ext2fs_mark_bb_dirty(fs);
7772    
7773     /* Redo the counts */
7774     blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775     memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776     goto redo_counts;
7777     } else if (fixit == 0)
7778     ext2fs_unmark_valid(fs);
7779    
7780     for (i = 0; i < fs->group_desc_count; i++) {
7781     if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782     pctx.group = i;
7783     pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784     pctx.blk2 = free_array[i];
7785    
7786     if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787     &pctx)) {
7788     fs->group_desc[i].bg_free_blocks_count =
7789     free_array[i];
7790     ext2fs_mark_super_dirty(fs);
7791     } else
7792     ext2fs_unmark_valid(fs);
7793     }
7794     }
7795     if (free_blocks != fs->super->s_free_blocks_count) {
7796     pctx.group = 0;
7797     pctx.blk = fs->super->s_free_blocks_count;
7798     pctx.blk2 = free_blocks;
7799    
7800     if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801     fs->super->s_free_blocks_count = free_blocks;
7802     ext2fs_mark_super_dirty(fs);
7803     } else
7804     ext2fs_unmark_valid(fs);
7805     }
7806     ext2fs_free_mem(&free_array);
7807     }
7808    
7809     static void check_inode_bitmaps(e2fsck_t ctx)
7810     {
7811     ext2_filsys fs = ctx->fs;
7812     ext2_ino_t i;
7813     unsigned int free_inodes = 0;
7814     int group_free = 0;
7815     int dirs_count = 0;
7816     int group = 0;
7817     unsigned int inodes = 0;
7818     int *free_array;
7819     int *dir_array;
7820     int actual, bitmap;
7821     errcode_t retval;
7822     struct problem_context pctx;
7823     int problem, save_problem, fixit, had_problem;
7824    
7825     clear_problem_context(&pctx);
7826     free_array = (int *) e2fsck_allocate_memory(ctx,
7827     fs->group_desc_count * sizeof(int), "free inode count array");
7828    
7829     dir_array = (int *) e2fsck_allocate_memory(ctx,
7830     fs->group_desc_count * sizeof(int), "directory count array");
7831    
7832     if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833     (fs->super->s_inodes_count >
7834     ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835     pctx.num = 3;
7836     pctx.blk = 1;
7837     pctx.blk2 = fs->super->s_inodes_count;
7838     pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839     pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840     fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841    
7842     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843     return;
7844     }
7845     if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846     (fs->super->s_inodes_count >
7847     ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848     pctx.num = 4;
7849     pctx.blk = 1;
7850     pctx.blk2 = fs->super->s_inodes_count;
7851     pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852     pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853     fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7854    
7855     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856     return;
7857     }
7858    
7859     redo_counts:
7860     had_problem = 0;
7861     save_problem = 0;
7862     pctx.ino = pctx.ino2 = 0;
7863     for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864     actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865     bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7866    
7867     if (actual == bitmap)
7868     goto do_counts;
7869    
7870     if (!actual && bitmap) {
7871     /*
7872     * Inode wasn't used, but marked in bitmap
7873     */
7874     problem = PR_5_INODE_UNUSED;
7875     } else /* if (actual && !bitmap) */ {
7876     /*
7877     * Inode used, but not in bitmap
7878     */
7879     problem = PR_5_INODE_USED;
7880     }
7881     if (pctx.ino == 0) {
7882     pctx.ino = pctx.ino2 = i;
7883     save_problem = problem;
7884     } else {
7885     if ((problem == save_problem) &&
7886     (pctx.ino2 == i-1))
7887     pctx.ino2++;
7888     else {
7889     print_bitmap_problem(ctx, save_problem, &pctx);
7890     pctx.ino = pctx.ino2 = i;
7891     save_problem = problem;
7892     }
7893     }
7894     ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895     had_problem++;
7896    
7897     do_counts:
7898     if (!bitmap) {
7899     group_free++;
7900     free_inodes++;
7901     } else {
7902     if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903     dirs_count++;
7904     }
7905     inodes++;
7906     if ((inodes == fs->super->s_inodes_per_group) ||
7907     (i == fs->super->s_inodes_count)) {
7908     free_array[group] = group_free;
7909     dir_array[group] = dirs_count;
7910     group ++;
7911     inodes = 0;
7912     group_free = 0;
7913     dirs_count = 0;
7914     if (ctx->progress)
7915     if ((ctx->progress)(ctx, 5,
7916     group + fs->group_desc_count,
7917     fs->group_desc_count*2))
7918     return;
7919     }
7920     }
7921     if (pctx.ino)
7922     print_bitmap_problem(ctx, save_problem, &pctx);
7923    
7924     if (had_problem)
7925     fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926     else
7927     fixit = -1;
7928     ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7929    
7930     if (fixit == 1) {
7931     ext2fs_free_inode_bitmap(fs->inode_map);
7932     retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933     &fs->inode_map);
7934     if (retval) {
7935     clear_problem_context(&pctx);
7936     fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937     ctx->flags |= E2F_FLAG_ABORT;
7938     return;
7939     }
7940     ext2fs_set_bitmap_padding(fs->inode_map);
7941     ext2fs_mark_ib_dirty(fs);
7942    
7943     /* redo counts */
7944     inodes = 0; free_inodes = 0; group_free = 0;
7945     dirs_count = 0; group = 0;
7946     memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947     memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948     goto redo_counts;
7949     } else if (fixit == 0)
7950     ext2fs_unmark_valid(fs);
7951    
7952     for (i = 0; i < fs->group_desc_count; i++) {
7953     if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954     pctx.group = i;
7955     pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956     pctx.ino2 = free_array[i];
7957     if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958     &pctx)) {
7959     fs->group_desc[i].bg_free_inodes_count =
7960     free_array[i];
7961     ext2fs_mark_super_dirty(fs);
7962     } else
7963     ext2fs_unmark_valid(fs);
7964     }
7965     if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966     pctx.group = i;
7967     pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968     pctx.ino2 = dir_array[i];
7969    
7970     if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971     &pctx)) {
7972     fs->group_desc[i].bg_used_dirs_count =
7973     dir_array[i];
7974     ext2fs_mark_super_dirty(fs);
7975     } else
7976     ext2fs_unmark_valid(fs);
7977     }
7978     }
7979     if (free_inodes != fs->super->s_free_inodes_count) {
7980     pctx.group = -1;
7981     pctx.ino = fs->super->s_free_inodes_count;
7982     pctx.ino2 = free_inodes;
7983    
7984     if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985     fs->super->s_free_inodes_count = free_inodes;
7986     ext2fs_mark_super_dirty(fs);
7987     } else
7988     ext2fs_unmark_valid(fs);
7989     }
7990     ext2fs_free_mem(&free_array);
7991     ext2fs_free_mem(&dir_array);
7992     }
7993    
7994     static void check_inode_end(e2fsck_t ctx)
7995     {
7996     ext2_filsys fs = ctx->fs;
7997     ext2_ino_t end, save_inodes_count, i;
7998     struct problem_context pctx;
7999    
8000     clear_problem_context(&pctx);
8001    
8002     end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003     pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004     &save_inodes_count);
8005     if (pctx.errcode) {
8006     pctx.num = 1;
8007     fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009     return;
8010     }
8011     if (save_inodes_count == end)
8012     return;
8013    
8014     for (i = save_inodes_count + 1; i <= end; i++) {
8015     if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016     if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017     for (i = save_inodes_count + 1; i <= end; i++)
8018     ext2fs_mark_inode_bitmap(fs->inode_map,
8019     i);
8020     ext2fs_mark_ib_dirty(fs);
8021     } else
8022     ext2fs_unmark_valid(fs);
8023     break;
8024     }
8025     }
8026    
8027     pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028     save_inodes_count, 0);
8029     if (pctx.errcode) {
8030     pctx.num = 2;
8031     fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033     return;
8034     }
8035     }
8036    
8037     static void check_block_end(e2fsck_t ctx)
8038     {
8039     ext2_filsys fs = ctx->fs;
8040     blk_t end, save_blocks_count, i;
8041     struct problem_context pctx;
8042    
8043     clear_problem_context(&pctx);
8044    
8045     end = fs->block_map->start +
8046     (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047     pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048     &save_blocks_count);
8049     if (pctx.errcode) {
8050     pctx.num = 3;
8051     fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053     return;
8054     }
8055     if (save_blocks_count == end)
8056     return;
8057    
8058     for (i = save_blocks_count + 1; i <= end; i++) {
8059     if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060     if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061     for (i = save_blocks_count + 1; i <= end; i++)
8062     ext2fs_mark_block_bitmap(fs->block_map,
8063     i);
8064     ext2fs_mark_bb_dirty(fs);
8065     } else
8066     ext2fs_unmark_valid(fs);
8067     break;
8068     }
8069     }
8070    
8071     pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072     save_blocks_count, 0);
8073     if (pctx.errcode) {
8074     pctx.num = 4;
8075     fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076     ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077     return;
8078     }
8079     }
8080    
8081     static void e2fsck_pass5(e2fsck_t ctx)
8082     {
8083     struct problem_context pctx;
8084    
8085     /* Pass 5 */
8086    
8087     clear_problem_context(&pctx);
8088    
8089     if (!(ctx->options & E2F_OPT_PREEN))
8090     fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8091    
8092     if (ctx->progress)
8093     if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094     return;
8095    
8096     e2fsck_read_bitmaps(ctx);
8097    
8098     check_block_bitmaps(ctx);
8099     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100     return;
8101     check_inode_bitmaps(ctx);
8102     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103     return;
8104     check_inode_end(ctx);
8105     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106     return;
8107     check_block_end(ctx);
8108     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109     return;
8110    
8111     ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112     ctx->inode_used_map = 0;
8113     ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114     ctx->inode_dir_map = 0;
8115     ext2fs_free_block_bitmap(ctx->block_found_map);
8116     ctx->block_found_map = 0;
8117     }
8118    
8119     /*
8120     * problem.c --- report filesystem problems to the user
8121     */
8122    
8123     #define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8124     #define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8125     #define PR_NO_DEFAULT 0x000004 /* Default to no */
8126     #define PR_MSG_ONLY 0x000008 /* Print message only */
8127    
8128     /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8129    
8130     #define PR_FATAL 0x001000 /* Fatal error */
8131     #define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8132     /* ask another */
8133     #define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8134     #define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8135     #define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8136     #define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8137     #define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8138    
8139    
8140     #define PROMPT_NONE 0
8141     #define PROMPT_FIX 1
8142     #define PROMPT_CLEAR 2
8143     #define PROMPT_RELOCATE 3
8144     #define PROMPT_ALLOCATE 4
8145     #define PROMPT_EXPAND 5
8146     #define PROMPT_CONNECT 6
8147     #define PROMPT_CREATE 7
8148     #define PROMPT_SALVAGE 8
8149     #define PROMPT_TRUNCATE 9
8150     #define PROMPT_CLEAR_INODE 10
8151     #define PROMPT_ABORT 11
8152     #define PROMPT_SPLIT 12
8153     #define PROMPT_CONTINUE 13
8154     #define PROMPT_CLONE 14
8155     #define PROMPT_DELETE 15
8156     #define PROMPT_SUPPRESS 16
8157     #define PROMPT_UNLINK 17
8158     #define PROMPT_CLEAR_HTREE 18
8159     #define PROMPT_RECREATE 19
8160     #define PROMPT_NULL 20
8161    
8162     struct e2fsck_problem {
8163     problem_t e2p_code;
8164     const char * e2p_description;
8165     char prompt;
8166     int flags;
8167     problem_t second_code;
8168     };
8169    
8170     struct latch_descr {
8171     int latch_code;
8172     problem_t question;
8173     problem_t end_message;
8174     int flags;
8175     };
8176    
8177     /*
8178     * These are the prompts which are used to ask the user if they want
8179     * to fix a problem.
8180     */
8181 niro 816 static const char *const prompt[] = {
8182 niro 532 N_("(no prompt)"), /* 0 */
8183     N_("Fix"), /* 1 */
8184     N_("Clear"), /* 2 */
8185     N_("Relocate"), /* 3 */
8186     N_("Allocate"), /* 4 */
8187     N_("Expand"), /* 5 */
8188     N_("Connect to /lost+found"), /* 6 */
8189     N_("Create"), /* 7 */
8190     N_("Salvage"), /* 8 */
8191     N_("Truncate"), /* 9 */
8192     N_("Clear inode"), /* 10 */
8193     N_("Abort"), /* 11 */
8194     N_("Split"), /* 12 */
8195     N_("Continue"), /* 13 */
8196     N_("Clone multiply-claimed blocks"), /* 14 */
8197     N_("Delete file"), /* 15 */
8198     N_("Suppress messages"),/* 16 */
8199     N_("Unlink"), /* 17 */
8200     N_("Clear HTree index"),/* 18 */
8201     N_("Recreate"), /* 19 */
8202     "", /* 20 */
8203     };
8204    
8205     /*
8206     * These messages are printed when we are preen mode and we will be
8207     * automatically fixing the problem.
8208     */
8209 niro 816 static const char *const preen_msg[] = {
8210 niro 532 N_("(NONE)"), /* 0 */
8211     N_("FIXED"), /* 1 */
8212     N_("CLEARED"), /* 2 */
8213     N_("RELOCATED"), /* 3 */
8214     N_("ALLOCATED"), /* 4 */
8215     N_("EXPANDED"), /* 5 */
8216     N_("RECONNECTED"), /* 6 */
8217     N_("CREATED"), /* 7 */
8218     N_("SALVAGED"), /* 8 */
8219     N_("TRUNCATED"), /* 9 */
8220     N_("INODE CLEARED"), /* 10 */
8221     N_("ABORTED"), /* 11 */
8222     N_("SPLIT"), /* 12 */
8223     N_("CONTINUING"), /* 13 */
8224     N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225     N_("FILE DELETED"), /* 15 */
8226     N_("SUPPRESSED"), /* 16 */
8227     N_("UNLINKED"), /* 17 */
8228     N_("HTREE INDEX CLEARED"),/* 18 */
8229     N_("WILL RECREATE"), /* 19 */
8230     "", /* 20 */
8231     };
8232    
8233     static const struct e2fsck_problem problem_table[] = {
8234    
8235     /* Pre-Pass 1 errors */
8236    
8237     /* Block bitmap not in group */
8238     { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8239     PROMPT_RELOCATE, PR_LATCH_RELOC },
8240    
8241     /* Inode bitmap not in group */
8242     { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8243     PROMPT_RELOCATE, PR_LATCH_RELOC },
8244    
8245     /* Inode table not in group */
8246     { PR_0_ITABLE_NOT_GROUP,
8247     N_("@i table for @g %g is not in @g. (@b %b)\n"
8248     "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249     PROMPT_RELOCATE, PR_LATCH_RELOC },
8250    
8251     /* Superblock corrupt */
8252     { PR_0_SB_CORRUPT,
8253     N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254     "@f. If the @v is valid and it really contains an ext2\n"
8255     "@f (and not swap or ufs or something else), then the @S\n"
8256     "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257     " e2fsck -b %S <@v>\n\n"),
8258     PROMPT_NONE, PR_FATAL },
8259    
8260     /* Filesystem size is wrong */
8261     { PR_0_FS_SIZE_WRONG,
8262     N_("The @f size (according to the @S) is %b @bs\n"
8263     "The physical size of the @v is %c @bs\n"
8264     "Either the @S or the partition table is likely to be corrupt!\n"),
8265     PROMPT_ABORT, 0 },
8266    
8267     /* Fragments not supported */
8268     { PR_0_NO_FRAGMENTS,
8269     N_("@S @b_size = %b, fragsize = %c.\n"
8270     "This version of e2fsck does not support fragment sizes different\n"
8271     "from the @b size.\n"),
8272     PROMPT_NONE, PR_FATAL },
8273    
8274     /* Bad blocks_per_group */
8275     { PR_0_BLOCKS_PER_GROUP,
8276     N_("@S @bs_per_group = %b, should have been %c\n"),
8277     PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8278    
8279     /* Bad first_data_block */
8280     { PR_0_FIRST_DATA_BLOCK,
8281     N_("@S first_data_@b = %b, should have been %c\n"),
8282     PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8283    
8284     /* Adding UUID to filesystem */
8285     { PR_0_ADD_UUID,
8286     N_("@f did not have a UUID; generating one.\n\n"),
8287     PROMPT_NONE, 0 },
8288    
8289     /* Relocate hint */
8290     { PR_0_RELOCATE_HINT,
8291     N_("Note: if several inode or block bitmap blocks or part\n"
8292     "of the inode table require relocation, you may wish to try\n"
8293     "running e2fsck with the '-b %S' option first. The problem\n"
8294     "may lie only with the primary block group descriptors, and\n"
8295     "the backup block group descriptors may be OK.\n\n"),
8296     PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8297    
8298     /* Miscellaneous superblock corruption */
8299     { PR_0_MISC_CORRUPT_SUPER,
8300     N_("Corruption found in @S. (%s = %N).\n"),
8301     PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8302    
8303     /* Error determing physical device size of filesystem */
8304     { PR_0_GETSIZE_ERROR,
8305     N_("Error determining size of the physical @v: %m\n"),
8306     PROMPT_NONE, PR_FATAL },
8307    
8308     /* Inode count in superblock is incorrect */
8309     { PR_0_INODE_COUNT_WRONG,
8310     N_("@i count in @S is %i, @s %j.\n"),
8311     PROMPT_FIX, 0 },
8312    
8313     { PR_0_HURD_CLEAR_FILETYPE,
8314     N_("The Hurd does not support the filetype feature.\n"),
8315     PROMPT_CLEAR, 0 },
8316    
8317     /* Journal inode is invalid */
8318     { PR_0_JOURNAL_BAD_INODE,
8319     N_("@S has an @n ext3 @j (@i %i).\n"),
8320     PROMPT_CLEAR, PR_PREEN_OK },
8321    
8322     /* The external journal has (unsupported) multiple filesystems */
8323     { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324     N_("External @j has multiple @f users (unsupported).\n"),
8325     PROMPT_NONE, PR_FATAL },
8326    
8327     /* Can't find external journal */
8328     { PR_0_CANT_FIND_JOURNAL,
8329     N_("Can't find external @j\n"),
8330     PROMPT_NONE, PR_FATAL },
8331    
8332     /* External journal has bad superblock */
8333     { PR_0_EXT_JOURNAL_BAD_SUPER,
8334     N_("External @j has bad @S\n"),
8335     PROMPT_NONE, PR_FATAL },
8336    
8337     /* Superblock has a bad journal UUID */
8338     { PR_0_JOURNAL_BAD_UUID,
8339     N_("External @j does not support this @f\n"),
8340     PROMPT_NONE, PR_FATAL },
8341    
8342     /* Journal has an unknown superblock type */
8343     { PR_0_JOURNAL_UNSUPP_SUPER,
8344     N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345     "It is likely that your copy of e2fsck is old and/or doesn't "
8346     "support this @j format.\n"
8347     "It is also possible the @j @S is corrupt.\n"),
8348     PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8349    
8350     /* Journal superblock is corrupt */
8351     { PR_0_JOURNAL_BAD_SUPER,
8352     N_("Ext3 @j @S is corrupt.\n"),
8353     PROMPT_FIX, PR_PREEN_OK },
8354    
8355     /* Superblock flag should be cleared */
8356     { PR_0_JOURNAL_HAS_JOURNAL,
8357     N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358     PROMPT_CLEAR, PR_PREEN_OK },
8359    
8360     /* Superblock flag is incorrect */
8361     { PR_0_JOURNAL_RECOVER_SET,
8362     N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363     PROMPT_CLEAR, PR_PREEN_OK },
8364    
8365     /* Journal has data, but recovery flag is clear */
8366     { PR_0_JOURNAL_RECOVERY_CLEAR,
8367     N_("ext3 recovery flag is clear, but @j has data.\n"),
8368     PROMPT_NONE, 0 },
8369    
8370     /* Ask if we should clear the journal */
8371     { PR_0_JOURNAL_RESET_JOURNAL,
8372     N_("Clear @j"),
8373     PROMPT_NULL, PR_PREEN_NOMSG },
8374    
8375     /* Ask if we should run the journal anyway */
8376     { PR_0_JOURNAL_RUN,
8377     N_("Run @j anyway"),
8378     PROMPT_NULL, 0 },
8379    
8380     /* Run the journal by default */
8381     { PR_0_JOURNAL_RUN_DEFAULT,
8382     N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383     PROMPT_NONE, 0 },
8384    
8385     /* Clearing orphan inode */
8386     { PR_0_ORPHAN_CLEAR_INODE,
8387     N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388     PROMPT_NONE, 0 },
8389    
8390     /* Illegal block found in orphaned inode */
8391     { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392     N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393     PROMPT_NONE, 0 },
8394    
8395     /* Already cleared block found in orphaned inode */
8396     { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397     N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398     PROMPT_NONE, 0 },
8399    
8400     /* Illegal orphan inode in superblock */
8401     { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402     N_("@I @o @i %i in @S.\n"),
8403     PROMPT_NONE, 0 },
8404    
8405     /* Illegal inode in orphaned inode list */
8406     { PR_0_ORPHAN_ILLEGAL_INODE,
8407     N_("@I @i %i in @o @i list.\n"),
8408     PROMPT_NONE, 0 },
8409    
8410     /* Filesystem revision is 0, but feature flags are set */
8411     { PR_0_FS_REV_LEVEL,
8412     N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8413     PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8414    
8415     /* Journal superblock has an unknown read-only feature flag set */
8416     { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417     N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418     PROMPT_ABORT, 0 },
8419    
8420     /* Journal superblock has an unknown incompatible feature flag set */
8421     { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422     N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423     PROMPT_ABORT, 0 },
8424    
8425     /* Journal has unsupported version number */
8426     { PR_0_JOURNAL_UNSUPP_VERSION,
8427     N_("@j version not supported by this e2fsck.\n"),
8428     PROMPT_ABORT, 0 },
8429    
8430     /* Moving journal to hidden file */
8431     { PR_0_MOVE_JOURNAL,
8432     N_("Moving @j from /%s to hidden @i.\n\n"),
8433     PROMPT_NONE, 0 },
8434    
8435     /* Error moving journal to hidden file */
8436     { PR_0_ERR_MOVE_JOURNAL,
8437     N_("Error moving @j: %m\n\n"),
8438     PROMPT_NONE, 0 },
8439    
8440     /* Clearing V2 journal superblock */
8441     { PR_0_CLEAR_V2_JOURNAL,
8442     N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443     "Clearing fields beyond the V1 @j @S...\n\n"),
8444     PROMPT_NONE, 0 },
8445    
8446     /* Backup journal inode blocks */
8447     { PR_0_BACKUP_JNL,
8448     N_("Backing up @j @i @b information.\n\n"),
8449     PROMPT_NONE, 0 },
8450    
8451     /* Reserved blocks w/o resize_inode */
8452     { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453     N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454     "is %N; @s zero. "),
8455     PROMPT_FIX, 0 },
8456    
8457     /* Resize_inode not enabled, but resize inode is non-zero */
8458     { PR_0_CLEAR_RESIZE_INODE,
8459     N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8460     PROMPT_CLEAR, 0 },
8461    
8462     /* Resize inode invalid */
8463     { PR_0_RESIZE_INODE_INVALID,
8464     N_("Resize @i not valid. "),
8465     PROMPT_RECREATE, 0 },
8466    
8467     /* Pass 1 errors */
8468    
8469     /* Pass 1: Checking inodes, blocks, and sizes */
8470     { PR_1_PASS_HEADER,
8471     N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472     PROMPT_NONE, 0 },
8473    
8474     /* Root directory is not an inode */
8475     { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8476     PROMPT_CLEAR, 0 },
8477    
8478     /* Root directory has dtime set */
8479     { PR_1_ROOT_DTIME,
8480     N_("@r has dtime set (probably due to old mke2fs). "),
8481     PROMPT_FIX, PR_PREEN_OK },
8482    
8483     /* Reserved inode has bad mode */
8484     { PR_1_RESERVED_BAD_MODE,
8485     N_("Reserved @i %i (%Q) has @n mode. "),
8486     PROMPT_CLEAR, PR_PREEN_OK },
8487    
8488     /* Deleted inode has zero dtime */
8489     { PR_1_ZERO_DTIME,
8490     N_("@D @i %i has zero dtime. "),
8491     PROMPT_FIX, PR_PREEN_OK },
8492    
8493     /* Inode in use, but dtime set */
8494     { PR_1_SET_DTIME,
8495     N_("@i %i is in use, but has dtime set. "),
8496     PROMPT_FIX, PR_PREEN_OK },
8497    
8498     /* Zero-length directory */
8499     { PR_1_ZERO_LENGTH_DIR,
8500     N_("@i %i is a @z @d. "),
8501     PROMPT_CLEAR, PR_PREEN_OK },
8502    
8503     /* Block bitmap conflicts with some other fs block */
8504     { PR_1_BB_CONFLICT,
8505     N_("@g %g's @b @B at %b @C.\n"),
8506     PROMPT_RELOCATE, 0 },
8507    
8508     /* Inode bitmap conflicts with some other fs block */
8509     { PR_1_IB_CONFLICT,
8510     N_("@g %g's @i @B at %b @C.\n"),
8511     PROMPT_RELOCATE, 0 },
8512    
8513     /* Inode table conflicts with some other fs block */
8514     { PR_1_ITABLE_CONFLICT,
8515     N_("@g %g's @i table at %b @C.\n"),
8516     PROMPT_RELOCATE, 0 },
8517    
8518     /* Block bitmap is on a bad block */
8519     { PR_1_BB_BAD_BLOCK,
8520     N_("@g %g's @b @B (%b) is bad. "),
8521     PROMPT_RELOCATE, 0 },
8522    
8523     /* Inode bitmap is on a bad block */
8524     { PR_1_IB_BAD_BLOCK,
8525     N_("@g %g's @i @B (%b) is bad. "),
8526     PROMPT_RELOCATE, 0 },
8527    
8528     /* Inode has incorrect i_size */
8529     { PR_1_BAD_I_SIZE,
8530     N_("@i %i, i_size is %Is, @s %N. "),
8531     PROMPT_FIX, PR_PREEN_OK },
8532    
8533     /* Inode has incorrect i_blocks */
8534     { PR_1_BAD_I_BLOCKS,
8535     N_("@i %i, i_@bs is %Ib, @s %N. "),
8536     PROMPT_FIX, PR_PREEN_OK },
8537    
8538     /* Illegal blocknumber in inode */
8539     { PR_1_ILLEGAL_BLOCK_NUM,
8540     N_("@I @b #%B (%b) in @i %i. "),
8541     PROMPT_CLEAR, PR_LATCH_BLOCK },
8542    
8543     /* Block number overlaps fs metadata */
8544     { PR_1_BLOCK_OVERLAPS_METADATA,
8545     N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8546     PROMPT_CLEAR, PR_LATCH_BLOCK },
8547    
8548     /* Inode has illegal blocks (latch question) */
8549     { PR_1_INODE_BLOCK_LATCH,
8550     N_("@i %i has illegal @b(s). "),
8551     PROMPT_CLEAR, 0 },
8552    
8553     /* Too many bad blocks in inode */
8554     { PR_1_TOO_MANY_BAD_BLOCKS,
8555     N_("Too many illegal @bs in @i %i.\n"),
8556     PROMPT_CLEAR_INODE, PR_NO_OK },
8557    
8558     /* Illegal block number in bad block inode */
8559     { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560     N_("@I @b #%B (%b) in bad @b @i. "),
8561     PROMPT_CLEAR, PR_LATCH_BBLOCK },
8562    
8563     /* Bad block inode has illegal blocks (latch question) */
8564     { PR_1_INODE_BBLOCK_LATCH,
8565     N_("Bad @b @i has illegal @b(s). "),
8566     PROMPT_CLEAR, 0 },
8567    
8568     /* Duplicate or bad blocks in use! */
8569     { PR_1_DUP_BLOCKS_PREENSTOP,
8570     N_("Duplicate or bad @b in use!\n"),
8571     PROMPT_NONE, 0 },
8572    
8573     /* Bad block used as bad block indirect block */
8574     { PR_1_BBINODE_BAD_METABLOCK,
8575     N_("Bad @b %b used as bad @b @i indirect @b. "),
8576     PROMPT_CLEAR, PR_LATCH_BBLOCK },
8577    
8578     /* Inconsistency can't be fixed prompt */
8579     { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580     N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8581     "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582     "in the @f.\n"),
8583     PROMPT_CONTINUE, PR_PREEN_NOMSG },
8584    
8585     /* Bad primary block */
8586     { PR_1_BAD_PRIMARY_BLOCK,
8587     N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588     PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8589    
8590     /* Bad primary block prompt */
8591     { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592     N_("You can remove this @b from the bad @b list and hope\n"
8593     "that the @b is really OK. But there are no guarantees.\n\n"),
8594     PROMPT_CLEAR, PR_PREEN_NOMSG },
8595    
8596     /* Bad primary superblock */
8597     { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598     N_("The primary @S (%b) is on the bad @b list.\n"),
8599     PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8600    
8601     /* Bad primary block group descriptors */
8602     { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603     N_("Block %b in the primary @g descriptors "
8604     "is on the bad @b list\n"),
8605     PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8606    
8607     /* Bad superblock in group */
8608     { PR_1_BAD_SUPERBLOCK,
8609     N_("Warning: Group %g's @S (%b) is bad.\n"),
8610     PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8611    
8612     /* Bad block group descriptors in group */
8613     { PR_1_BAD_GROUP_DESCRIPTORS,
8614     N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615     "@b (%b).\n"),
8616     PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8617    
8618     /* Block claimed for no reason */
8619     { PR_1_PROGERR_CLAIMED_BLOCK,
8620     N_("Programming error? @b #%b claimed for no reason in "
8621     "process_bad_@b.\n"),
8622     PROMPT_NONE, PR_PREEN_OK },
8623    
8624     /* Error allocating blocks for relocating metadata */
8625     { PR_1_RELOC_BLOCK_ALLOCATE,
8626     N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627     PROMPT_NONE, PR_PREEN_OK },
8628    
8629     /* Error allocating block buffer during relocation process */
8630     { PR_1_RELOC_MEMORY_ALLOCATE,
8631     N_("@A @b buffer for relocating %s\n"),
8632     PROMPT_NONE, PR_PREEN_OK },
8633    
8634     /* Relocating metadata group information from X to Y */
8635     { PR_1_RELOC_FROM_TO,
8636     N_("Relocating @g %g's %s from %b to %c...\n"),
8637     PROMPT_NONE, PR_PREEN_OK },
8638    
8639     /* Relocating metatdata group information to X */
8640     { PR_1_RELOC_TO,
8641     N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642     PROMPT_NONE, PR_PREEN_OK },
8643    
8644     /* Block read error during relocation process */
8645     { PR_1_RELOC_READ_ERR,
8646     N_("Warning: could not read @b %b of %s: %m\n"),
8647     PROMPT_NONE, PR_PREEN_OK },
8648    
8649     /* Block write error during relocation process */
8650     { PR_1_RELOC_WRITE_ERR,
8651     N_("Warning: could not write @b %b for %s: %m\n"),
8652     PROMPT_NONE, PR_PREEN_OK },
8653    
8654     /* Error allocating inode bitmap */
8655     { PR_1_ALLOCATE_IBITMAP_ERROR,
8656     N_("@A @i @B (%N): %m\n"),
8657     PROMPT_NONE, PR_FATAL },
8658    
8659     /* Error allocating block bitmap */
8660     { PR_1_ALLOCATE_BBITMAP_ERROR,
8661     N_("@A @b @B (%N): %m\n"),
8662     PROMPT_NONE, PR_FATAL },
8663    
8664     /* Error allocating icount structure */
8665     { PR_1_ALLOCATE_ICOUNT,
8666     N_("@A icount link information: %m\n"),
8667     PROMPT_NONE, PR_FATAL },
8668    
8669     /* Error allocating dbcount */
8670     { PR_1_ALLOCATE_DBCOUNT,
8671     N_("@A @d @b array: %m\n"),
8672     PROMPT_NONE, PR_FATAL },
8673    
8674     /* Error while scanning inodes */
8675     { PR_1_ISCAN_ERROR,
8676     N_("Error while scanning @is (%i): %m\n"),
8677     PROMPT_NONE, PR_FATAL },
8678    
8679     /* Error while iterating over blocks */
8680     { PR_1_BLOCK_ITERATE,
8681     N_("Error while iterating over @bs in @i %i: %m\n"),
8682     PROMPT_NONE, PR_FATAL },
8683    
8684     /* Error while storing inode count information */
8685     { PR_1_ICOUNT_STORE,
8686     N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687     PROMPT_NONE, PR_FATAL },
8688    
8689     /* Error while storing directory block information */
8690     { PR_1_ADD_DBLOCK,
8691     N_("Error storing @d @b information "
8692     "(@i=%i, @b=%b, num=%N): %m\n"),
8693     PROMPT_NONE, PR_FATAL },
8694    
8695     /* Error while reading inode (for clearing) */
8696     { PR_1_READ_INODE,
8697     N_("Error reading @i %i: %m\n"),
8698     PROMPT_NONE, PR_FATAL },
8699    
8700     /* Suppress messages prompt */
8701     { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8702    
8703     /* Imagic flag set on an inode when filesystem doesn't support it */
8704     { PR_1_SET_IMAGIC,
8705     N_("@i %i has imagic flag set. "),
8706     PROMPT_CLEAR, 0 },
8707    
8708     /* Immutable flag set on a device or socket inode */
8709     { PR_1_SET_IMMUTABLE,
8710     N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711     "or append-only flag set. "),
8712     PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8713    
8714     /* Compression flag set on an inode when filesystem doesn't support it */
8715     { PR_1_COMPR_SET,
8716     N_("@i %i has @cion flag set on @f without @cion support. "),
8717     PROMPT_CLEAR, 0 },
8718    
8719     /* Non-zero size for device, fifo or socket inode */
8720     { PR_1_SET_NONZSIZE,
8721     N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8722     PROMPT_FIX, PR_PREEN_OK },
8723    
8724     /* Filesystem revision is 0, but feature flags are set */
8725     { PR_1_FS_REV_LEVEL,
8726     N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8727     PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8728    
8729     /* Journal inode is not in use, but contains data */
8730     { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731     N_("@j @i is not in use, but contains data. "),
8732     PROMPT_CLEAR, PR_PREEN_OK },
8733    
8734     /* Journal has bad mode */
8735     { PR_1_JOURNAL_BAD_MODE,
8736     N_("@j is not regular file. "),
8737     PROMPT_FIX, PR_PREEN_OK },
8738    
8739     /* Deal with inodes that were part of orphan linked list */
8740     { PR_1_LOW_DTIME,
8741     N_("@i %i was part of the @o @i list. "),
8742     PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8743    
8744     /* Deal with inodes that were part of corrupted orphan linked
8745     list (latch question) */
8746     { PR_1_ORPHAN_LIST_REFUGEES,
8747     N_("@is that were part of a corrupted orphan linked list found. "),
8748     PROMPT_FIX, 0 },
8749    
8750     /* Error allocating refcount structure */
8751     { PR_1_ALLOCATE_REFCOUNT,
8752     N_("@A refcount structure (%N): %m\n"),
8753     PROMPT_NONE, PR_FATAL },
8754    
8755     /* Error reading extended attribute block */
8756     { PR_1_READ_EA_BLOCK,
8757     N_("Error reading @a @b %b for @i %i. "),
8758     PROMPT_CLEAR, 0 },
8759    
8760     /* Invalid extended attribute block */
8761     { PR_1_BAD_EA_BLOCK,
8762     N_("@i %i has a bad @a @b %b. "),
8763     PROMPT_CLEAR, 0 },
8764    
8765     /* Error reading Extended Attribute block while fixing refcount */
8766     { PR_1_EXTATTR_READ_ABORT,
8767     N_("Error reading @a @b %b (%m). "),
8768     PROMPT_ABORT, 0 },
8769    
8770     /* Extended attribute reference count incorrect */
8771     { PR_1_EXTATTR_REFCOUNT,
8772     N_("@a @b %b has reference count %B, @s %N. "),
8773     PROMPT_FIX, 0 },
8774    
8775     /* Error writing Extended Attribute block while fixing refcount */
8776     { PR_1_EXTATTR_WRITE,
8777     N_("Error writing @a @b %b (%m). "),
8778     PROMPT_ABORT, 0 },
8779    
8780     /* Multiple EA blocks not supported */
8781     { PR_1_EA_MULTI_BLOCK,
8782     N_("@a @b %b has h_@bs > 1. "),
8783     PROMPT_CLEAR, 0},
8784    
8785     /* Error allocating EA region allocation structure */
8786     { PR_1_EA_ALLOC_REGION,
8787     N_("@A @a @b %b. "),
8788     PROMPT_ABORT, 0},
8789    
8790     /* Error EA allocation collision */
8791     { PR_1_EA_ALLOC_COLLISION,
8792     N_("@a @b %b is corrupt (allocation collision). "),
8793     PROMPT_CLEAR, 0},
8794    
8795     /* Bad extended attribute name */
8796     { PR_1_EA_BAD_NAME,
8797     N_("@a @b %b is corrupt (@n name). "),
8798     PROMPT_CLEAR, 0},
8799    
8800     /* Bad extended attribute value */
8801     { PR_1_EA_BAD_VALUE,
8802     N_("@a @b %b is corrupt (@n value). "),
8803     PROMPT_CLEAR, 0},
8804    
8805     /* Inode too big (latch question) */
8806     { PR_1_INODE_TOOBIG,
8807     N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8808    
8809     /* Directory too big */
8810     { PR_1_TOOBIG_DIR,
8811     N_("@b #%B (%b) causes @d to be too big. "),
8812     PROMPT_CLEAR, PR_LATCH_TOOBIG },
8813    
8814     /* Regular file too big */
8815     { PR_1_TOOBIG_REG,
8816     N_("@b #%B (%b) causes file to be too big. "),
8817     PROMPT_CLEAR, PR_LATCH_TOOBIG },
8818    
8819     /* Symlink too big */
8820     { PR_1_TOOBIG_SYMLINK,
8821     N_("@b #%B (%b) causes symlink to be too big. "),
8822     PROMPT_CLEAR, PR_LATCH_TOOBIG },
8823    
8824     /* INDEX_FL flag set on a non-HTREE filesystem */
8825     { PR_1_HTREE_SET,
8826     N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8828    
8829     /* INDEX_FL flag set on a non-directory */
8830     { PR_1_HTREE_NODIR,
8831     N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8833    
8834     /* Invalid root node in HTREE directory */
8835     { PR_1_HTREE_BADROOT,
8836     N_("@h %i has an @n root node.\n"),
8837     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8838    
8839     /* Unsupported hash version in HTREE directory */
8840     { PR_1_HTREE_HASHV,
8841     N_("@h %i has an unsupported hash version (%N)\n"),
8842     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8843    
8844     /* Incompatible flag in HTREE root node */
8845     { PR_1_HTREE_INCOMPAT,
8846     N_("@h %i uses an incompatible htree root node flag.\n"),
8847     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8848    
8849     /* HTREE too deep */
8850     { PR_1_HTREE_DEPTH,
8851     N_("@h %i has a tree depth (%N) which is too big\n"),
8852     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853    
8854     /* Bad block has indirect block that conflicts with filesystem block */
8855     { PR_1_BB_FS_BLOCK,
8856     N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857     "@f metadata. "),
8858     PROMPT_CLEAR, PR_LATCH_BBLOCK },
8859    
8860     /* Resize inode failed */
8861     { PR_1_RESIZE_INODE_CREATE,
8862     N_("Resize @i (re)creation failed: %m."),
8863     PROMPT_ABORT, 0 },
8864    
8865     /* invalid inode->i_extra_isize */
8866     { PR_1_EXTRA_ISIZE,
8867     N_("@i %i has a extra size (%IS) which is @n\n"),
8868     PROMPT_FIX, PR_PREEN_OK },
8869    
8870     /* invalid ea entry->e_name_len */
8871     { PR_1_ATTR_NAME_LEN,
8872     N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873     PROMPT_CLEAR, PR_PREEN_OK },
8874    
8875     /* invalid ea entry->e_value_size */
8876     { PR_1_ATTR_VALUE_SIZE,
8877     N_("@a in @i %i has a value size (%N) which is @n\n"),
8878     PROMPT_CLEAR, PR_PREEN_OK },
8879    
8880     /* invalid ea entry->e_value_offs */
8881     { PR_1_ATTR_VALUE_OFFSET,
8882     N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883     PROMPT_CLEAR, PR_PREEN_OK },
8884    
8885     /* invalid ea entry->e_value_block */
8886     { PR_1_ATTR_VALUE_BLOCK,
8887     N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888     PROMPT_CLEAR, PR_PREEN_OK },
8889    
8890     /* invalid ea entry->e_hash */
8891     { PR_1_ATTR_HASH,
8892     N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893     PROMPT_CLEAR, PR_PREEN_OK },
8894    
8895     /* Pass 1b errors */
8896    
8897     /* Pass 1B: Rescan for duplicate/bad blocks */
8898     { PR_1B_PASS_HEADER,
8899     N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900     "Pass 1B: Rescanning for @m @bs\n"),
8901     PROMPT_NONE, 0 },
8902    
8903     /* Duplicate/bad block(s) header */
8904     { PR_1B_DUP_BLOCK_HEADER,
8905     N_("@m @b(s) in @i %i:"),
8906     PROMPT_NONE, 0 },
8907    
8908     /* Duplicate/bad block(s) in inode */
8909     { PR_1B_DUP_BLOCK,
8910     " %b",
8911     PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8912    
8913     /* Duplicate/bad block(s) end */
8914     { PR_1B_DUP_BLOCK_END,
8915     "\n",
8916     PROMPT_NONE, PR_PREEN_NOHDR },
8917    
8918     /* Error while scanning inodes */
8919     { PR_1B_ISCAN_ERROR,
8920     N_("Error while scanning inodes (%i): %m\n"),
8921     PROMPT_NONE, PR_FATAL },
8922    
8923     /* Error allocating inode bitmap */
8924     { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925     N_("@A @i @B (@i_dup_map): %m\n"),
8926     PROMPT_NONE, PR_FATAL },
8927    
8928     /* Error while iterating over blocks */
8929     { PR_1B_BLOCK_ITERATE,
8930     N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931     PROMPT_NONE, 0 },
8932    
8933     /* Error adjusting EA refcount */
8934     { PR_1B_ADJ_EA_REFCOUNT,
8935     N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936     PROMPT_NONE, 0 },
8937    
8938    
8939     /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940     { PR_1C_PASS_HEADER,
8941     N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942     PROMPT_NONE, 0 },
8943    
8944    
8945     /* Pass 1D: Reconciling multiply-claimed blocks */
8946     { PR_1D_PASS_HEADER,
8947     N_("Pass 1D: Reconciling @m @bs\n"),
8948     PROMPT_NONE, 0 },
8949    
8950     /* File has duplicate blocks */
8951     { PR_1D_DUP_FILE,
8952     N_("File %Q (@i #%i, mod time %IM)\n"
8953     " has %B @m @b(s), shared with %N file(s):\n"),
8954     PROMPT_NONE, 0 },
8955    
8956     /* List of files sharing duplicate blocks */
8957     { PR_1D_DUP_FILE_LIST,
8958     N_("\t%Q (@i #%i, mod time %IM)\n"),
8959     PROMPT_NONE, 0 },
8960    
8961     /* File sharing blocks with filesystem metadata */
8962     { PR_1D_SHARE_METADATA,
8963     N_("\t<@f metadata>\n"),
8964     PROMPT_NONE, 0 },
8965    
8966     /* Report of how many duplicate/bad inodes */
8967     { PR_1D_NUM_DUP_INODES,
8968     N_("(There are %N @is containing @m @bs.)\n\n"),
8969     PROMPT_NONE, 0 },
8970    
8971     /* Duplicated blocks already reassigned or cloned. */
8972     { PR_1D_DUP_BLOCKS_DEALT,
8973     N_("@m @bs already reassigned or cloned.\n\n"),
8974     PROMPT_NONE, 0 },
8975    
8976     /* Clone duplicate/bad blocks? */
8977     { PR_1D_CLONE_QUESTION,
8978     "", PROMPT_CLONE, PR_NO_OK },
8979    
8980     /* Delete file? */
8981     { PR_1D_DELETE_QUESTION,
8982     "", PROMPT_DELETE, 0 },
8983    
8984     /* Couldn't clone file (error) */
8985     { PR_1D_CLONE_ERROR,
8986     N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8987    
8988     /* Pass 2 errors */
8989    
8990     /* Pass 2: Checking directory structure */
8991     { PR_2_PASS_HEADER,
8992     N_("Pass 2: Checking @d structure\n"),
8993     PROMPT_NONE, 0 },
8994    
8995     /* Bad inode number for '.' */
8996     { PR_2_BAD_INODE_DOT,
8997     N_("@n @i number for '.' in @d @i %i.\n"),
8998     PROMPT_FIX, 0 },
8999    
9000     /* Directory entry has bad inode number */
9001     { PR_2_BAD_INO,
9002     N_("@E has @n @i #: %Di.\n"),
9003     PROMPT_CLEAR, 0 },
9004    
9005     /* Directory entry has deleted or unused inode */
9006     { PR_2_UNUSED_INODE,
9007     N_("@E has @D/unused @i %Di. "),
9008     PROMPT_CLEAR, PR_PREEN_OK },
9009    
9010     /* Directry entry is link to '.' */
9011     { PR_2_LINK_DOT,
9012     N_("@E @L to '.' "),
9013     PROMPT_CLEAR, 0 },
9014    
9015     /* Directory entry points to inode now located in a bad block */
9016     { PR_2_BB_INODE,
9017     N_("@E points to @i (%Di) located in a bad @b.\n"),
9018     PROMPT_CLEAR, 0 },
9019    
9020     /* Directory entry contains a link to a directory */
9021     { PR_2_LINK_DIR,
9022     N_("@E @L to @d %P (%Di).\n"),
9023     PROMPT_CLEAR, 0 },
9024    
9025     /* Directory entry contains a link to the root directry */
9026     { PR_2_LINK_ROOT,
9027     N_("@E @L to the @r.\n"),
9028     PROMPT_CLEAR, 0 },
9029    
9030     /* Directory entry has illegal characters in its name */
9031     { PR_2_BAD_NAME,
9032     N_("@E has illegal characters in its name.\n"),
9033     PROMPT_FIX, 0 },
9034    
9035     /* Missing '.' in directory inode */
9036     { PR_2_MISSING_DOT,
9037     N_("Missing '.' in @d @i %i.\n"),
9038     PROMPT_FIX, 0 },
9039    
9040     /* Missing '..' in directory inode */
9041     { PR_2_MISSING_DOT_DOT,
9042     N_("Missing '..' in @d @i %i.\n"),
9043     PROMPT_FIX, 0 },
9044    
9045     /* First entry in directory inode doesn't contain '.' */
9046     { PR_2_1ST_NOT_DOT,
9047     N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048     PROMPT_FIX, 0 },
9049    
9050     /* Second entry in directory inode doesn't contain '..' */
9051     { PR_2_2ND_NOT_DOT_DOT,
9052     N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053     PROMPT_FIX, 0 },
9054    
9055     /* i_faddr should be zero */
9056     { PR_2_FADDR_ZERO,
9057     N_("i_faddr @F %IF, @s zero.\n"),
9058     PROMPT_CLEAR, 0 },
9059    
9060     /* i_file_acl should be zero */
9061     { PR_2_FILE_ACL_ZERO,
9062     N_("i_file_acl @F %If, @s zero.\n"),
9063     PROMPT_CLEAR, 0 },
9064    
9065     /* i_dir_acl should be zero */
9066     { PR_2_DIR_ACL_ZERO,
9067     N_("i_dir_acl @F %Id, @s zero.\n"),
9068     PROMPT_CLEAR, 0 },
9069    
9070     /* i_frag should be zero */
9071     { PR_2_FRAG_ZERO,
9072     N_("i_frag @F %N, @s zero.\n"),
9073     PROMPT_CLEAR, 0 },
9074    
9075     /* i_fsize should be zero */
9076     { PR_2_FSIZE_ZERO,
9077     N_("i_fsize @F %N, @s zero.\n"),
9078     PROMPT_CLEAR, 0 },
9079    
9080     /* inode has bad mode */
9081     { PR_2_BAD_MODE,
9082     N_("@i %i (%Q) has @n mode (%Im).\n"),
9083     PROMPT_CLEAR, 0 },
9084    
9085     /* directory corrupted */
9086     { PR_2_DIR_CORRUPTED,
9087     N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088     PROMPT_SALVAGE, 0 },
9089    
9090     /* filename too long */
9091     { PR_2_FILENAME_LONG,
9092     N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093     PROMPT_TRUNCATE, 0 },
9094    
9095     /* Directory inode has a missing block (hole) */
9096     { PR_2_DIRECTORY_HOLE,
9097     N_("@d @i %i has an unallocated @b #%B. "),
9098     PROMPT_ALLOCATE, 0 },
9099    
9100     /* '.' is not NULL terminated */
9101     { PR_2_DOT_NULL_TERM,
9102     N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103     PROMPT_FIX, 0 },
9104    
9105     /* '..' is not NULL terminated */
9106     { PR_2_DOT_DOT_NULL_TERM,
9107     N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108     PROMPT_FIX, 0 },
9109    
9110     /* Illegal character device inode */
9111     { PR_2_BAD_CHAR_DEV,
9112     N_("@i %i (%Q) is an @I character @v.\n"),
9113     PROMPT_CLEAR, 0 },
9114    
9115     /* Illegal block device inode */
9116     { PR_2_BAD_BLOCK_DEV,
9117     N_("@i %i (%Q) is an @I @b @v.\n"),
9118     PROMPT_CLEAR, 0 },
9119    
9120     /* Duplicate '.' entry */
9121     { PR_2_DUP_DOT,
9122     N_("@E is duplicate '.' @e.\n"),
9123     PROMPT_FIX, 0 },
9124    
9125     /* Duplicate '..' entry */
9126     { PR_2_DUP_DOT_DOT,
9127     N_("@E is duplicate '..' @e.\n"),
9128     PROMPT_FIX, 0 },
9129    
9130     /* Internal error: couldn't find dir_info */
9131     { PR_2_NO_DIRINFO,
9132     N_("Internal error: cannot find dir_info for %i.\n"),
9133     PROMPT_NONE, PR_FATAL },
9134    
9135     /* Final rec_len is wrong */
9136     { PR_2_FINAL_RECLEN,
9137     N_("@E has rec_len of %Dr, @s %N.\n"),
9138     PROMPT_FIX, 0 },
9139    
9140     /* Error allocating icount structure */
9141     { PR_2_ALLOCATE_ICOUNT,
9142     N_("@A icount structure: %m\n"),
9143     PROMPT_NONE, PR_FATAL },
9144    
9145     /* Error iterating over directory blocks */
9146     { PR_2_DBLIST_ITERATE,
9147     N_("Error iterating over @d @bs: %m\n"),
9148     PROMPT_NONE, PR_FATAL },
9149    
9150     /* Error reading directory block */
9151     { PR_2_READ_DIRBLOCK,
9152     N_("Error reading @d @b %b (@i %i): %m\n"),
9153     PROMPT_CONTINUE, 0 },
9154    
9155     /* Error writing directory block */
9156     { PR_2_WRITE_DIRBLOCK,
9157     N_("Error writing @d @b %b (@i %i): %m\n"),
9158     PROMPT_CONTINUE, 0 },
9159    
9160     /* Error allocating new directory block */
9161     { PR_2_ALLOC_DIRBOCK,
9162     N_("@A new @d @b for @i %i (%s): %m\n"),
9163     PROMPT_NONE, 0 },
9164    
9165     /* Error deallocating inode */
9166     { PR_2_DEALLOC_INODE,
9167     N_("Error deallocating @i %i: %m\n"),
9168     PROMPT_NONE, PR_FATAL },
9169    
9170     /* Directory entry for '.' is big. Split? */
9171     { PR_2_SPLIT_DOT,
9172     N_("@d @e for '.' is big. "),
9173     PROMPT_SPLIT, PR_NO_OK },
9174    
9175     /* Illegal FIFO inode */
9176     { PR_2_BAD_FIFO,
9177     N_("@i %i (%Q) is an @I FIFO.\n"),
9178     PROMPT_CLEAR, 0 },
9179    
9180     /* Illegal socket inode */
9181     { PR_2_BAD_SOCKET,
9182     N_("@i %i (%Q) is an @I socket.\n"),
9183     PROMPT_CLEAR, 0 },
9184    
9185     /* Directory filetype not set */
9186     { PR_2_SET_FILETYPE,
9187     N_("Setting filetype for @E to %N.\n"),
9188     PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9189    
9190     /* Directory filetype incorrect */
9191     { PR_2_BAD_FILETYPE,
9192     N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193     PROMPT_FIX, 0 },
9194    
9195     /* Directory filetype set on filesystem */
9196     { PR_2_CLEAR_FILETYPE,
9197     N_("@E has filetype set.\n"),
9198     PROMPT_CLEAR, PR_PREEN_OK },
9199    
9200     /* Directory filename is null */
9201     { PR_2_NULL_NAME,
9202     N_("@E has a @z name.\n"),
9203     PROMPT_CLEAR, 0 },
9204    
9205     /* Invalid symlink */
9206     { PR_2_INVALID_SYMLINK,
9207     N_("Symlink %Q (@i #%i) is @n.\n"),
9208     PROMPT_CLEAR, 0 },
9209    
9210     /* i_file_acl (extended attribute block) is bad */
9211     { PR_2_FILE_ACL_BAD,
9212     N_("@a @b @F @n (%If).\n"),
9213     PROMPT_CLEAR, 0 },
9214    
9215     /* Filesystem contains large files, but has no such flag in sb */
9216     { PR_2_FEATURE_LARGE_FILES,
9217     N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218     PROMPT_FIX, 0 },
9219    
9220     /* Node in HTREE directory not referenced */
9221     { PR_2_HTREE_NOTREF,
9222     N_("@p @h %d: node (%B) not referenced\n"),
9223     PROMPT_NONE, 0 },
9224    
9225     /* Node in HTREE directory referenced twice */
9226     { PR_2_HTREE_DUPREF,
9227     N_("@p @h %d: node (%B) referenced twice\n"),
9228     PROMPT_NONE, 0 },
9229    
9230     /* Node in HTREE directory has bad min hash */
9231     { PR_2_HTREE_MIN_HASH,
9232     N_("@p @h %d: node (%B) has bad min hash\n"),
9233     PROMPT_NONE, 0 },
9234    
9235     /* Node in HTREE directory has bad max hash */
9236     { PR_2_HTREE_MAX_HASH,
9237     N_("@p @h %d: node (%B) has bad max hash\n"),
9238     PROMPT_NONE, 0 },
9239    
9240     /* Clear invalid HTREE directory */
9241     { PR_2_HTREE_CLEAR,
9242     N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9243    
9244     /* Bad block in htree interior node */
9245     { PR_2_HTREE_BADBLK,
9246     N_("@p @h %d (%q): bad @b number %b.\n"),
9247     PROMPT_CLEAR_HTREE, 0 },
9248    
9249     /* Error adjusting EA refcount */
9250     { PR_2_ADJ_EA_REFCOUNT,
9251     N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252     PROMPT_NONE, PR_FATAL },
9253    
9254     /* Invalid HTREE root node */
9255     { PR_2_HTREE_BAD_ROOT,
9256     N_("@p @h %d: root node is @n\n"),
9257     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9258    
9259     /* Invalid HTREE limit */
9260     { PR_2_HTREE_BAD_LIMIT,
9261     N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9263    
9264     /* Invalid HTREE count */
9265     { PR_2_HTREE_BAD_COUNT,
9266     N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9268    
9269     /* HTREE interior node has out-of-order hashes in table */
9270     { PR_2_HTREE_HASH_ORDER,
9271     N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272     PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9273    
9274     /* Node in HTREE directory has invalid depth */
9275     { PR_2_HTREE_BAD_DEPTH,
9276     N_("@p @h %d: node (%B) has @n depth\n"),
9277     PROMPT_NONE, 0 },
9278    
9279     /* Duplicate directory entry found */
9280     { PR_2_DUPLICATE_DIRENT,
9281     N_("Duplicate @E found. "),
9282     PROMPT_CLEAR, 0 },
9283    
9284     /* Non-unique filename found */
9285     { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286     N_("@E has a non-unique filename.\nRename to %s"),
9287     PROMPT_NULL, 0 },
9288    
9289     /* Duplicate directory entry found */
9290     { PR_2_REPORT_DUP_DIRENT,
9291     N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292     PROMPT_NONE, 0 },
9293    
9294     /* Pass 3 errors */
9295    
9296     /* Pass 3: Checking directory connectivity */
9297     { PR_3_PASS_HEADER,
9298     N_("Pass 3: Checking @d connectivity\n"),
9299     PROMPT_NONE, 0 },
9300    
9301     /* Root inode not allocated */
9302     { PR_3_NO_ROOT_INODE,
9303     N_("@r not allocated. "),
9304     PROMPT_ALLOCATE, 0 },
9305    
9306     /* No room in lost+found */
9307     { PR_3_EXPAND_LF_DIR,
9308     N_("No room in @l @d. "),
9309     PROMPT_EXPAND, 0 },
9310    
9311     /* Unconnected directory inode */
9312     { PR_3_UNCONNECTED_DIR,
9313     N_("Unconnected @d @i %i (%p)\n"),
9314     PROMPT_CONNECT, 0 },
9315    
9316     /* /lost+found not found */
9317     { PR_3_NO_LF_DIR,
9318     N_("/@l not found. "),
9319     PROMPT_CREATE, PR_PREEN_OK },
9320    
9321     /* .. entry is incorrect */
9322     { PR_3_BAD_DOT_DOT,
9323     N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324     PROMPT_FIX, 0 },
9325    
9326     /* Bad or non-existent /lost+found. Cannot reconnect */
9327     { PR_3_NO_LPF,
9328     N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9329     PROMPT_NONE, 0 },
9330    
9331     /* Could not expand /lost+found */
9332     { PR_3_CANT_EXPAND_LPF,
9333     N_("Could not expand /@l: %m\n"),
9334     PROMPT_NONE, 0 },
9335    
9336     /* Could not reconnect inode */
9337     { PR_3_CANT_RECONNECT,
9338     N_("Could not reconnect %i: %m\n"),
9339     PROMPT_NONE, 0 },
9340    
9341     /* Error while trying to find /lost+found */
9342     { PR_3_ERR_FIND_LPF,
9343     N_("Error while trying to find /@l: %m\n"),
9344     PROMPT_NONE, 0 },
9345    
9346     /* Error in ext2fs_new_block while creating /lost+found */
9347     { PR_3_ERR_LPF_NEW_BLOCK,
9348     N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349     PROMPT_NONE, 0 },
9350    
9351     /* Error in ext2fs_new_inode while creating /lost+found */
9352     { PR_3_ERR_LPF_NEW_INODE,
9353     N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354     PROMPT_NONE, 0 },
9355    
9356     /* Error in ext2fs_new_dir_block while creating /lost+found */
9357     { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358     N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359     PROMPT_NONE, 0 },
9360    
9361     /* Error while writing directory block for /lost+found */
9362     { PR_3_ERR_LPF_WRITE_BLOCK,
9363     N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364     PROMPT_NONE, 0 },
9365    
9366     /* Error while adjusting inode count */
9367     { PR_3_ADJUST_INODE,
9368     N_("Error while adjusting @i count on @i %i\n"),
9369     PROMPT_NONE, 0 },
9370    
9371     /* Couldn't fix parent directory -- error */
9372     { PR_3_FIX_PARENT_ERR,
9373     N_("Couldn't fix parent of @i %i: %m\n\n"),
9374     PROMPT_NONE, 0 },
9375    
9376     /* Couldn't fix parent directory -- couldn't find it */
9377     { PR_3_FIX_PARENT_NOFIND,
9378     N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379     PROMPT_NONE, 0 },
9380    
9381     /* Error allocating inode bitmap */
9382     { PR_3_ALLOCATE_IBITMAP_ERROR,
9383     N_("@A @i @B (%N): %m\n"),
9384     PROMPT_NONE, PR_FATAL },
9385    
9386     /* Error creating root directory */
9387     { PR_3_CREATE_ROOT_ERROR,
9388     N_("Error creating root @d (%s): %m\n"),
9389     PROMPT_NONE, PR_FATAL },
9390    
9391     /* Error creating lost and found directory */
9392     { PR_3_CREATE_LPF_ERROR,
9393     N_("Error creating /@l @d (%s): %m\n"),
9394     PROMPT_NONE, PR_FATAL },
9395    
9396     /* Root inode is not directory; aborting */
9397     { PR_3_ROOT_NOT_DIR_ABORT,
9398     N_("@r is not a @d; aborting.\n"),
9399     PROMPT_NONE, PR_FATAL },
9400    
9401     /* Cannot proceed without a root inode. */
9402     { PR_3_NO_ROOT_INODE_ABORT,
9403     N_("Cannot proceed without a @r.\n"),
9404     PROMPT_NONE, PR_FATAL },
9405    
9406     /* Internal error: couldn't find dir_info */
9407     { PR_3_NO_DIRINFO,
9408     N_("Internal error: cannot find dir_info for %i.\n"),
9409     PROMPT_NONE, PR_FATAL },
9410    
9411     /* Lost+found not a directory */
9412     { PR_3_LPF_NOTDIR,
9413     N_("/@l is not a @d (ino=%i)\n"),
9414     PROMPT_UNLINK, 0 },
9415    
9416     /* Pass 3A Directory Optimization */
9417    
9418     /* Pass 3A: Optimizing directories */
9419     { PR_3A_PASS_HEADER,
9420     N_("Pass 3A: Optimizing directories\n"),
9421     PROMPT_NONE, PR_PREEN_NOMSG },
9422    
9423     /* Error iterating over directories */
9424     { PR_3A_OPTIMIZE_ITER,
9425     N_("Failed to create dirs_to_hash iterator: %m"),
9426     PROMPT_NONE, 0 },
9427    
9428     /* Error rehash directory */
9429     { PR_3A_OPTIMIZE_DIR_ERR,
9430     N_("Failed to optimize directory %q (%d): %m"),
9431     PROMPT_NONE, 0 },
9432    
9433     /* Rehashing dir header */
9434     { PR_3A_OPTIMIZE_DIR_HEADER,
9435     N_("Optimizing directories: "),
9436     PROMPT_NONE, PR_MSG_ONLY },
9437    
9438     /* Rehashing directory %d */
9439     { PR_3A_OPTIMIZE_DIR,
9440     " %d",
9441     PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9442    
9443     /* Rehashing dir end */
9444     { PR_3A_OPTIMIZE_DIR_END,
9445     "\n",
9446     PROMPT_NONE, PR_PREEN_NOHDR },
9447    
9448     /* Pass 4 errors */
9449    
9450     /* Pass 4: Checking reference counts */
9451     { PR_4_PASS_HEADER,
9452     N_("Pass 4: Checking reference counts\n"),
9453     PROMPT_NONE, 0 },
9454    
9455     /* Unattached zero-length inode */
9456     { PR_4_ZERO_LEN_INODE,
9457     N_("@u @z @i %i. "),
9458     PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9459    
9460     /* Unattached inode */
9461     { PR_4_UNATTACHED_INODE,
9462     N_("@u @i %i\n"),
9463     PROMPT_CONNECT, 0 },
9464    
9465     /* Inode ref count wrong */
9466     { PR_4_BAD_REF_COUNT,
9467     N_("@i %i ref count is %Il, @s %N. "),
9468     PROMPT_FIX, PR_PREEN_OK },
9469    
9470     { PR_4_INCONSISTENT_COUNT,
9471     N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472     "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473     "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9474     "They @s the same!\n"),
9475     PROMPT_NONE, 0 },
9476    
9477     /* Pass 5 errors */
9478    
9479     /* Pass 5: Checking group summary information */
9480     { PR_5_PASS_HEADER,
9481     N_("Pass 5: Checking @g summary information\n"),
9482     PROMPT_NONE, 0 },
9483    
9484     /* Padding at end of inode bitmap is not set. */
9485     { PR_5_INODE_BMAP_PADDING,
9486     N_("Padding at end of @i @B is not set. "),
9487     PROMPT_FIX, PR_PREEN_OK },
9488    
9489     /* Padding at end of block bitmap is not set. */
9490     { PR_5_BLOCK_BMAP_PADDING,
9491     N_("Padding at end of @b @B is not set. "),
9492     PROMPT_FIX, PR_PREEN_OK },
9493    
9494     /* Block bitmap differences header */
9495     { PR_5_BLOCK_BITMAP_HEADER,
9496     N_("@b @B differences: "),
9497     PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9498    
9499     /* Block not used, but marked in bitmap */
9500     { PR_5_BLOCK_UNUSED,
9501     " -%b",
9502     PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9503    
9504     /* Block used, but not marked used in bitmap */
9505     { PR_5_BLOCK_USED,
9506     " +%b",
9507     PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9508    
9509     /* Block bitmap differences end */
9510     { PR_5_BLOCK_BITMAP_END,
9511     "\n",
9512     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9513    
9514     /* Inode bitmap differences header */
9515     { PR_5_INODE_BITMAP_HEADER,
9516     N_("@i @B differences: "),
9517     PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9518    
9519     /* Inode not used, but marked in bitmap */
9520     { PR_5_INODE_UNUSED,
9521     " -%i",
9522     PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9523    
9524     /* Inode used, but not marked used in bitmap */
9525     { PR_5_INODE_USED,
9526     " +%i",
9527     PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528    
9529     /* Inode bitmap differences end */
9530     { PR_5_INODE_BITMAP_END,
9531     "\n",
9532     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9533    
9534     /* Free inodes count for group wrong */
9535     { PR_5_FREE_INODE_COUNT_GROUP,
9536     N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538    
9539     /* Directories count for group wrong */
9540     { PR_5_FREE_DIR_COUNT_GROUP,
9541     N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9543    
9544     /* Free inodes count wrong */
9545     { PR_5_FREE_INODE_COUNT,
9546     N_("Free @is count wrong (%i, counted=%j).\n"),
9547     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9548    
9549     /* Free blocks count for group wrong */
9550     { PR_5_FREE_BLOCK_COUNT_GROUP,
9551     N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9553    
9554     /* Free blocks count wrong */
9555     { PR_5_FREE_BLOCK_COUNT,
9556     N_("Free @bs count wrong (%b, counted=%c).\n"),
9557     PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558    
9559     /* Programming error: bitmap endpoints don't match */
9560     { PR_5_BMAP_ENDPOINTS,
9561     N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562     "match calculated @B endpoints (%i, %j)\n"),
9563     PROMPT_NONE, PR_FATAL },
9564    
9565     /* Internal error: fudging end of bitmap */
9566     { PR_5_FUDGE_BITMAP_ERROR,
9567     N_("Internal error: fudging end of bitmap (%N)\n"),
9568     PROMPT_NONE, PR_FATAL },
9569    
9570     /* Error copying in replacement inode bitmap */
9571     { PR_5_COPY_IBITMAP_ERROR,
9572     N_("Error copying in replacement @i @B: %m\n"),
9573     PROMPT_NONE, PR_FATAL },
9574    
9575     /* Error copying in replacement block bitmap */
9576     { PR_5_COPY_BBITMAP_ERROR,
9577     N_("Error copying in replacement @b @B: %m\n"),
9578     PROMPT_NONE, PR_FATAL },
9579    
9580     /* Block range not used, but marked in bitmap */
9581     { PR_5_BLOCK_RANGE_UNUSED,
9582     " -(%b--%c)",
9583     PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9584    
9585     /* Block range used, but not marked used in bitmap */
9586     { PR_5_BLOCK_RANGE_USED,
9587     " +(%b--%c)",
9588     PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9589    
9590     /* Inode range not used, but marked in bitmap */
9591     { PR_5_INODE_RANGE_UNUSED,
9592     " -(%i--%j)",
9593     PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9594    
9595     /* Inode range used, but not marked used in bitmap */
9596     { PR_5_INODE_RANGE_USED,
9597     " +(%i--%j)",
9598     PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9599    
9600     { 0 }
9601     };
9602    
9603     /*
9604     * This is the latch flags register. It allows several problems to be
9605     * "latched" together. This means that the user has to answer but one
9606     * question for the set of problems, and all of the associated
9607     * problems will be either fixed or not fixed.
9608     */
9609     static struct latch_descr pr_latch_info[] = {
9610     { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611     { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612     { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613     { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614     { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615     { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616     { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617     { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618     { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619     { -1, 0, 0 },
9620     };
9621    
9622     static const struct e2fsck_problem *find_problem(problem_t code)
9623     {
9624     int i;
9625    
9626     for (i=0; problem_table[i].e2p_code; i++) {
9627     if (problem_table[i].e2p_code == code)
9628     return &problem_table[i];
9629     }
9630     return 0;
9631     }
9632    
9633     static struct latch_descr *find_latch(int code)
9634     {
9635     int i;
9636    
9637     for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638     if (pr_latch_info[i].latch_code == code)
9639     return &pr_latch_info[i];
9640     }
9641     return 0;
9642     }
9643    
9644     int end_problem_latch(e2fsck_t ctx, int mask)
9645     {
9646     struct latch_descr *ldesc;
9647     struct problem_context pctx;
9648     int answer = -1;
9649    
9650     ldesc = find_latch(mask);
9651     if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652     clear_problem_context(&pctx);
9653     answer = fix_problem(ctx, ldesc->end_message, &pctx);
9654     }
9655     ldesc->flags &= ~(PRL_VARIABLE);
9656     return answer;
9657     }
9658    
9659     int set_latch_flags(int mask, int setflags, int clearflags)
9660     {
9661     struct latch_descr *ldesc;
9662    
9663     ldesc = find_latch(mask);
9664     if (!ldesc)
9665     return -1;
9666     ldesc->flags |= setflags;
9667     ldesc->flags &= ~clearflags;
9668     return 0;
9669     }
9670    
9671     void clear_problem_context(struct problem_context *ctx)
9672     {
9673     memset(ctx, 0, sizeof(struct problem_context));
9674     ctx->blkcount = -1;
9675     ctx->group = -1;
9676     }
9677    
9678     int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9679     {
9680     ext2_filsys fs = ctx->fs;
9681     const struct e2fsck_problem *ptr;
9682     struct latch_descr *ldesc = 0;
9683     const char *message;
9684     int def_yn, answer, ans;
9685     int print_answer = 0;
9686     int suppress = 0;
9687    
9688     ptr = find_problem(code);
9689     if (!ptr) {
9690     printf(_("Unhandled error code (0x%x)!\n"), code);
9691     return 0;
9692     }
9693     def_yn = 1;
9694     if ((ptr->flags & PR_NO_DEFAULT) ||
9695     ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696     (ctx->options & E2F_OPT_NO))
9697     def_yn= 0;
9698    
9699     /*
9700     * Do special latch processing. This is where we ask the
9701     * latch question, if it exists
9702     */
9703     if (ptr->flags & PR_LATCH_MASK) {
9704     ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705     if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706     ans = fix_problem(ctx, ldesc->question, pctx);
9707     if (ans == 1)
9708     ldesc->flags |= PRL_YES;
9709     if (ans == 0)
9710     ldesc->flags |= PRL_NO;
9711     ldesc->flags |= PRL_LATCHED;
9712     }
9713     if (ldesc->flags & PRL_SUPPRESS)
9714     suppress++;
9715     }
9716     if ((ptr->flags & PR_PREEN_NOMSG) &&
9717     (ctx->options & E2F_OPT_PREEN))
9718     suppress++;
9719     if ((ptr->flags & PR_NO_NOMSG) &&
9720     (ctx->options & E2F_OPT_NO))
9721     suppress++;
9722     if (!suppress) {
9723     message = ptr->e2p_description;
9724     if ((ctx->options & E2F_OPT_PREEN) &&
9725     !(ptr->flags & PR_PREEN_NOHDR)) {
9726     printf("%s: ", ctx->device_name ?
9727     ctx->device_name : ctx->filesystem_name);
9728     }
9729     if (*message)
9730     print_e2fsck_message(ctx, _(message), pctx, 1);
9731     }
9732     if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733     preenhalt(ctx);
9734    
9735     if (ptr->flags & PR_FATAL)
9736     bb_error_msg_and_die(0);
9737    
9738     if (ptr->prompt == PROMPT_NONE) {
9739     if (ptr->flags & PR_NOCOLLATE)
9740     answer = -1;
9741     else
9742     answer = def_yn;
9743     } else {
9744     if (ctx->options & E2F_OPT_PREEN) {
9745     answer = def_yn;
9746     if (!(ptr->flags & PR_PREEN_NOMSG))
9747     print_answer = 1;
9748     } else if ((ptr->flags & PR_LATCH_MASK) &&
9749     (ldesc->flags & (PRL_YES | PRL_NO))) {
9750     if (!suppress)
9751     print_answer = 1;
9752     if (ldesc->flags & PRL_YES)
9753     answer = 1;
9754     else
9755     answer = 0;
9756     } else
9757     answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758     if (!answer && !(ptr->flags & PR_NO_OK))
9759     ext2fs_unmark_valid(fs);
9760    
9761     if (print_answer)
9762     printf("%s.\n", answer ?
9763     _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9764    
9765     }
9766    
9767     if ((ptr->prompt == PROMPT_ABORT) && answer)
9768     bb_error_msg_and_die(0);
9769    
9770     if (ptr->flags & PR_AFTER_CODE)
9771     answer = fix_problem(ctx, ptr->second_code, pctx);
9772    
9773     return answer;
9774     }
9775    
9776     /*
9777     * linux/fs/recovery.c
9778     *
9779     * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9780     */
9781    
9782     /*
9783     * Maintain information about the progress of the recovery job, so that
9784     * the different passes can carry information between them.
9785     */
9786     struct recovery_info
9787     {
9788     tid_t start_transaction;
9789     tid_t end_transaction;
9790    
9791     int nr_replays;
9792     int nr_revokes;
9793     int nr_revoke_hits;
9794     };
9795    
9796     enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9797     static int do_one_pass(journal_t *journal,
9798     struct recovery_info *info, enum passtype pass);
9799     static int scan_revoke_records(journal_t *, struct buffer_head *,
9800     tid_t, struct recovery_info *);
9801    
9802     /*
9803     * Read a block from the journal
9804     */
9805    
9806     static int jread(struct buffer_head **bhp, journal_t *journal,
9807     unsigned int offset)
9808     {
9809     int err;
9810     unsigned long blocknr;
9811     struct buffer_head *bh;
9812    
9813     *bhp = NULL;
9814    
9815     err = journal_bmap(journal, offset, &blocknr);
9816    
9817     if (err) {
9818     printf("JBD: bad block at offset %u\n", offset);
9819     return err;
9820     }
9821    
9822     bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9823     if (!bh)
9824     return -ENOMEM;
9825    
9826     if (!buffer_uptodate(bh)) {
9827     /* If this is a brand new buffer, start readahead.
9828     Otherwise, we assume we are already reading it. */
9829     if (!buffer_req(bh))
9830     do_readahead(journal, offset);
9831     wait_on_buffer(bh);
9832     }
9833    
9834     if (!buffer_uptodate(bh)) {
9835     printf("JBD: Failed to read block at offset %u\n", offset);
9836     brelse(bh);
9837     return -EIO;
9838     }
9839    
9840     *bhp = bh;
9841     return 0;
9842     }
9843    
9844    
9845     /*
9846     * Count the number of in-use tags in a journal descriptor block.
9847     */
9848    
9849     static int count_tags(struct buffer_head *bh, int size)
9850     {
9851     char * tagp;
9852     journal_block_tag_t * tag;
9853     int nr = 0;
9854    
9855     tagp = &bh->b_data[sizeof(journal_header_t)];
9856    
9857     while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9858     tag = (journal_block_tag_t *) tagp;
9859    
9860     nr++;
9861     tagp += sizeof(journal_block_tag_t);
9862     if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9863     tagp += 16;
9864    
9865     if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9866     break;
9867     }
9868    
9869     return nr;
9870     }
9871    
9872    
9873     /* Make sure we wrap around the log correctly! */
9874     #define wrap(journal, var) \
9875     do { \
9876     if (var >= (journal)->j_last) \
9877     var -= ((journal)->j_last - (journal)->j_first); \
9878     } while (0)
9879    
9880     /**
9881     * int journal_recover(journal_t *journal) - recovers a on-disk journal
9882     * @journal: the journal to recover
9883     *
9884     * The primary function for recovering the log contents when mounting a
9885     * journaled device.
9886     *
9887     * Recovery is done in three passes. In the first pass, we look for the
9888     * end of the log. In the second, we assemble the list of revoke
9889     * blocks. In the third and final pass, we replay any un-revoked blocks
9890     * in the log.
9891     */
9892     int journal_recover(journal_t *journal)
9893     {
9894     int err;
9895     journal_superblock_t * sb;
9896    
9897     struct recovery_info info;
9898    
9899     memset(&info, 0, sizeof(info));
9900     sb = journal->j_superblock;
9901    
9902     /*
9903     * The journal superblock's s_start field (the current log head)
9904     * is always zero if, and only if, the journal was cleanly
9905     * unmounted.
9906     */
9907    
9908     if (!sb->s_start) {
9909     journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9910     return 0;
9911     }
9912    
9913     err = do_one_pass(journal, &info, PASS_SCAN);
9914     if (!err)
9915     err = do_one_pass(journal, &info, PASS_REVOKE);
9916     if (!err)
9917     err = do_one_pass(journal, &info, PASS_REPLAY);
9918    
9919     /* Restart the log at the next transaction ID, thus invalidating
9920     * any existing commit records in the log. */
9921     journal->j_transaction_sequence = ++info.end_transaction;
9922    
9923     journal_clear_revoke(journal);
9924     sync_blockdev(journal->j_fs_dev);
9925     return err;
9926     }
9927    
9928     static int do_one_pass(journal_t *journal,
9929     struct recovery_info *info, enum passtype pass)
9930     {
9931     unsigned int first_commit_ID, next_commit_ID;
9932     unsigned long next_log_block;
9933     int err, success = 0;
9934     journal_superblock_t * sb;
9935     journal_header_t * tmp;
9936     struct buffer_head * bh;
9937     unsigned int sequence;
9938     int blocktype;
9939    
9940     /* Precompute the maximum metadata descriptors in a descriptor block */
9941     int MAX_BLOCKS_PER_DESC;
9942     MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9943     / sizeof(journal_block_tag_t));
9944    
9945     /*
9946     * First thing is to establish what we expect to find in the log
9947     * (in terms of transaction IDs), and where (in terms of log
9948     * block offsets): query the superblock.
9949     */
9950    
9951     sb = journal->j_superblock;
9952     next_commit_ID = ntohl(sb->s_sequence);
9953     next_log_block = ntohl(sb->s_start);
9954    
9955     first_commit_ID = next_commit_ID;
9956     if (pass == PASS_SCAN)
9957     info->start_transaction = first_commit_ID;
9958    
9959     /*
9960     * Now we walk through the log, transaction by transaction,
9961     * making sure that each transaction has a commit block in the
9962     * expected place. Each complete transaction gets replayed back
9963     * into the main filesystem.
9964     */
9965    
9966     while (1) {
9967     int flags;
9968     char * tagp;
9969     journal_block_tag_t * tag;
9970     struct buffer_head * obh;
9971     struct buffer_head * nbh;
9972    
9973     /* If we already know where to stop the log traversal,
9974     * check right now that we haven't gone past the end of
9975     * the log. */
9976    
9977     if (pass != PASS_SCAN)
9978     if (tid_geq(next_commit_ID, info->end_transaction))
9979     break;
9980    
9981     /* Skip over each chunk of the transaction looking
9982     * either the next descriptor block or the final commit
9983     * record. */
9984    
9985     err = jread(&bh, journal, next_log_block);
9986     if (err)
9987     goto failed;
9988    
9989     next_log_block++;
9990     wrap(journal, next_log_block);
9991    
9992     /* What kind of buffer is it?
9993     *
9994     * If it is a descriptor block, check that it has the
9995     * expected sequence number. Otherwise, we're all done
9996     * here. */
9997    
9998     tmp = (journal_header_t *)bh->b_data;
9999    
10000     if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10001     brelse(bh);
10002     break;
10003     }
10004    
10005     blocktype = ntohl(tmp->h_blocktype);
10006     sequence = ntohl(tmp->h_sequence);
10007    
10008     if (sequence != next_commit_ID) {
10009     brelse(bh);
10010     break;
10011     }
10012    
10013     /* OK, we have a valid descriptor block which matches
10014     * all of the sequence number checks. What are we going
10015     * to do with it? That depends on the pass... */
10016    
10017 niro 816 switch (blocktype) {
10018 niro 532 case JFS_DESCRIPTOR_BLOCK:
10019     /* If it is a valid descriptor block, replay it
10020     * in pass REPLAY; otherwise, just skip over the
10021     * blocks it describes. */
10022     if (pass != PASS_REPLAY) {
10023     next_log_block +=
10024     count_tags(bh, journal->j_blocksize);
10025     wrap(journal, next_log_block);
10026     brelse(bh);
10027     continue;
10028     }
10029    
10030     /* A descriptor block: we can now write all of
10031     * the data blocks. Yay, useful work is finally
10032     * getting done here! */
10033    
10034     tagp = &bh->b_data[sizeof(journal_header_t)];
10035     while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10036     <= journal->j_blocksize) {
10037     unsigned long io_block;
10038    
10039     tag = (journal_block_tag_t *) tagp;
10040     flags = ntohl(tag->t_flags);
10041    
10042     io_block = next_log_block++;
10043     wrap(journal, next_log_block);
10044     err = jread(&obh, journal, io_block);
10045     if (err) {
10046     /* Recover what we can, but
10047     * report failure at the end. */
10048     success = err;
10049     printf("JBD: IO error %d recovering "
10050     "block %ld in log\n",
10051     err, io_block);
10052     } else {
10053     unsigned long blocknr;
10054    
10055     blocknr = ntohl(tag->t_blocknr);
10056    
10057     /* If the block has been
10058     * revoked, then we're all done
10059     * here. */
10060     if (journal_test_revoke
10061     (journal, blocknr,
10062     next_commit_ID)) {
10063     brelse(obh);
10064     ++info->nr_revoke_hits;
10065     goto skip_write;
10066     }
10067    
10068     /* Find a buffer for the new
10069     * data being restored */
10070     nbh = getblk(journal->j_fs_dev,
10071     blocknr,
10072     journal->j_blocksize);
10073     if (nbh == NULL) {
10074     printf("JBD: Out of memory "
10075     "during recovery.\n");
10076     err = -ENOMEM;
10077     brelse(bh);
10078     brelse(obh);
10079     goto failed;
10080     }
10081    
10082     lock_buffer(nbh);
10083     memcpy(nbh->b_data, obh->b_data,
10084     journal->j_blocksize);
10085     if (flags & JFS_FLAG_ESCAPE) {
10086     *((unsigned int *)bh->b_data) =
10087     htonl(JFS_MAGIC_NUMBER);
10088     }
10089    
10090     mark_buffer_uptodate(nbh, 1);
10091     mark_buffer_dirty(nbh);
10092     ++info->nr_replays;
10093     /* ll_rw_block(WRITE, 1, &nbh); */
10094     unlock_buffer(nbh);
10095     brelse(obh);
10096     brelse(nbh);
10097     }
10098    
10099     skip_write:
10100     tagp += sizeof(journal_block_tag_t);
10101     if (!(flags & JFS_FLAG_SAME_UUID))
10102     tagp += 16;
10103    
10104     if (flags & JFS_FLAG_LAST_TAG)
10105     break;
10106     }
10107    
10108     brelse(bh);
10109     continue;
10110    
10111     case JFS_COMMIT_BLOCK:
10112     /* Found an expected commit block: not much to
10113     * do other than move on to the next sequence
10114     * number. */
10115     brelse(bh);
10116     next_commit_ID++;
10117     continue;
10118    
10119     case JFS_REVOKE_BLOCK:
10120     /* If we aren't in the REVOKE pass, then we can
10121     * just skip over this block. */
10122     if (pass != PASS_REVOKE) {
10123     brelse(bh);
10124     continue;
10125     }
10126    
10127     err = scan_revoke_records(journal, bh,
10128     next_commit_ID, info);
10129     brelse(bh);
10130     if (err)
10131     goto failed;
10132     continue;
10133    
10134     default:
10135     goto done;
10136     }
10137     }
10138    
10139     done:
10140     /*
10141     * We broke out of the log scan loop: either we came to the
10142     * known end of the log or we found an unexpected block in the
10143     * log. If the latter happened, then we know that the "current"
10144     * transaction marks the end of the valid log.
10145     */
10146    
10147     if (pass == PASS_SCAN)
10148     info->end_transaction = next_commit_ID;
10149     else {
10150     /* It's really bad news if different passes end up at
10151     * different places (but possible due to IO errors). */
10152     if (info->end_transaction != next_commit_ID) {
10153     printf("JBD: recovery pass %d ended at "
10154     "transaction %u, expected %u\n",
10155     pass, next_commit_ID, info->end_transaction);
10156     if (!success)
10157     success = -EIO;
10158     }
10159     }
10160    
10161     return success;
10162    
10163     failed:
10164     return err;
10165     }
10166    
10167    
10168     /* Scan a revoke record, marking all blocks mentioned as revoked. */
10169    
10170     static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10171     tid_t sequence, struct recovery_info *info)
10172     {
10173     journal_revoke_header_t *header;
10174     int offset, max;
10175    
10176     header = (journal_revoke_header_t *) bh->b_data;
10177     offset = sizeof(journal_revoke_header_t);
10178     max = ntohl(header->r_count);
10179    
10180     while (offset < max) {
10181     unsigned long blocknr;
10182     int err;
10183    
10184     blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10185     offset += 4;
10186     err = journal_set_revoke(journal, blocknr, sequence);
10187     if (err)
10188     return err;
10189     ++info->nr_revokes;
10190     }
10191     return 0;
10192     }
10193    
10194    
10195     /*
10196     * rehash.c --- rebuild hash tree directories
10197     *
10198     * This algorithm is designed for simplicity of implementation and to
10199     * pack the directory as much as possible. It however requires twice
10200     * as much memory as the size of the directory. The maximum size
10201     * directory supported using a 4k blocksize is roughly a gigabyte, and
10202     * so there may very well be problems with machines that don't have
10203     * virtual memory, and obscenely large directories.
10204     *
10205     * An alternate algorithm which is much more disk intensive could be
10206     * written, and probably will need to be written in the future. The
10207     * design goals of such an algorithm are: (a) use (roughly) constant
10208     * amounts of memory, no matter how large the directory, (b) the
10209     * directory must be safe at all times, even if e2fsck is interrupted
10210     * in the middle, (c) we must use minimal amounts of extra disk
10211     * blocks. This pretty much requires an incremental approach, where
10212     * we are reading from one part of the directory, and inserting into
10213     * the front half. So the algorithm will have to keep track of a
10214     * moving block boundary between the new tree and the old tree, and
10215     * files will need to be moved from the old directory and inserted
10216     * into the new tree. If the new directory requires space which isn't
10217     * yet available, blocks from the beginning part of the old directory
10218     * may need to be moved to the end of the directory to make room for
10219     * the new tree:
10220     *
10221     * --------------------------------------------------------
10222     * | new tree | | old tree |
10223     * --------------------------------------------------------
10224     * ^ ptr ^ptr
10225     * tail new head old
10226     *
10227     * This is going to be a pain in the tuckus to implement, and will
10228     * require a lot more disk accesses. So I'm going to skip it for now;
10229     * it's only really going to be an issue for really, really big
10230     * filesystems (when we reach the level of tens of millions of files
10231     * in a single directory). It will probably be easier to simply
10232     * require that e2fsck use VM first.
10233     */
10234    
10235     struct fill_dir_struct {
10236     char *buf;
10237     struct ext2_inode *inode;
10238     int err;
10239     e2fsck_t ctx;
10240     struct hash_entry *harray;
10241     int max_array, num_array;
10242     int dir_size;
10243     int compress;
10244     ino_t parent;
10245     };
10246    
10247     struct hash_entry {
10248     ext2_dirhash_t hash;
10249     ext2_dirhash_t minor_hash;
10250     struct ext2_dir_entry *dir;
10251     };
10252    
10253     struct out_dir {
10254     int num;
10255     int max;
10256     char *buf;
10257     ext2_dirhash_t *hashes;
10258     };
10259    
10260     static int fill_dir_block(ext2_filsys fs,
10261     blk_t *block_nr,
10262     e2_blkcnt_t blockcnt,
10263     blk_t ref_block FSCK_ATTR((unused)),
10264     int ref_offset FSCK_ATTR((unused)),
10265     void *priv_data)
10266     {
10267     struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10268     struct hash_entry *new_array, *ent;
10269     struct ext2_dir_entry *dirent;
10270     char *dir;
10271     unsigned int offset, dir_offset;
10272    
10273     if (blockcnt < 0)
10274     return 0;
10275    
10276     offset = blockcnt * fs->blocksize;
10277     if (offset + fs->blocksize > fd->inode->i_size) {
10278     fd->err = EXT2_ET_DIR_CORRUPTED;
10279     return BLOCK_ABORT;
10280     }
10281     dir = (fd->buf+offset);
10282     if (HOLE_BLKADDR(*block_nr)) {
10283     memset(dir, 0, fs->blocksize);
10284     dirent = (struct ext2_dir_entry *) dir;
10285     dirent->rec_len = fs->blocksize;
10286     } else {
10287     fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10288     if (fd->err)
10289     return BLOCK_ABORT;
10290     }
10291     /* While the directory block is "hot", index it. */
10292     dir_offset = 0;
10293     while (dir_offset < fs->blocksize) {
10294     dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10295     if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10296     (dirent->rec_len < 8) ||
10297     ((dirent->rec_len % 4) != 0) ||
10298     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10299     fd->err = EXT2_ET_DIR_CORRUPTED;
10300     return BLOCK_ABORT;
10301     }
10302     dir_offset += dirent->rec_len;
10303     if (dirent->inode == 0)
10304     continue;
10305     if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10306     (dirent->name[0] == '.'))
10307     continue;
10308     if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10309     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10310     fd->parent = dirent->inode;
10311     continue;
10312     }
10313     if (fd->num_array >= fd->max_array) {
10314     new_array = realloc(fd->harray,
10315     sizeof(struct hash_entry) * (fd->max_array+500));
10316     if (!new_array) {
10317     fd->err = ENOMEM;
10318     return BLOCK_ABORT;
10319     }
10320     fd->harray = new_array;
10321     fd->max_array += 500;
10322     }
10323     ent = fd->harray + fd->num_array++;
10324     ent->dir = dirent;
10325     fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10326     if (fd->compress)
10327     ent->hash = ent->minor_hash = 0;
10328     else {
10329     fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10330     dirent->name,
10331     dirent->name_len & 0xFF,
10332     fs->super->s_hash_seed,
10333     &ent->hash, &ent->minor_hash);
10334     if (fd->err)
10335     return BLOCK_ABORT;
10336     }
10337     }
10338    
10339     return 0;
10340     }
10341    
10342     /* Used for sorting the hash entry */
10343     static int name_cmp(const void *a, const void *b)
10344     {
10345     const struct hash_entry *he_a = (const struct hash_entry *) a;
10346     const struct hash_entry *he_b = (const struct hash_entry *) b;
10347     int ret;
10348     int min_len;
10349    
10350     min_len = he_a->dir->name_len;
10351     if (min_len > he_b->dir->name_len)
10352     min_len = he_b->dir->name_len;
10353    
10354     ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10355     if (ret == 0) {
10356     if (he_a->dir->name_len > he_b->dir->name_len)
10357     ret = 1;
10358     else if (he_a->dir->name_len < he_b->dir->name_len)
10359     ret = -1;
10360     else
10361     ret = he_b->dir->inode - he_a->dir->inode;
10362     }
10363     return ret;
10364     }
10365    
10366     /* Used for sorting the hash entry */
10367     static int hash_cmp(const void *a, const void *b)
10368     {
10369     const struct hash_entry *he_a = (const struct hash_entry *) a;
10370     const struct hash_entry *he_b = (const struct hash_entry *) b;
10371     int ret;
10372    
10373     if (he_a->hash > he_b->hash)
10374     ret = 1;
10375     else if (he_a->hash < he_b->hash)
10376     ret = -1;
10377     else {
10378     if (he_a->minor_hash > he_b->minor_hash)
10379     ret = 1;
10380     else if (he_a->minor_hash < he_b->minor_hash)
10381     ret = -1;
10382     else
10383     ret = name_cmp(a, b);
10384     }
10385     return ret;
10386     }
10387    
10388     static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10389     int blocks)
10390     {
10391     void *new_mem;
10392    
10393     if (outdir->max) {
10394     new_mem = realloc(outdir->buf, blocks * fs->blocksize);
10395     if (!new_mem)
10396     return ENOMEM;
10397     outdir->buf = new_mem;
10398     new_mem = realloc(outdir->hashes,
10399     blocks * sizeof(ext2_dirhash_t));
10400     if (!new_mem)
10401     return ENOMEM;
10402     outdir->hashes = new_mem;
10403     } else {
10404     outdir->buf = malloc(blocks * fs->blocksize);
10405     outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
10406     outdir->num = 0;
10407     }
10408     outdir->max = blocks;
10409     return 0;
10410     }
10411    
10412     static void free_out_dir(struct out_dir *outdir)
10413     {
10414     free(outdir->buf);
10415     free(outdir->hashes);
10416     outdir->max = 0;
10417     outdir->num =0;
10418     }
10419    
10420     static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10421     char ** ret)
10422     {
10423     errcode_t retval;
10424    
10425     if (outdir->num >= outdir->max) {
10426     retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10427     if (retval)
10428     return retval;
10429     }
10430     *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10431     memset(*ret, 0, fs->blocksize);
10432     return 0;
10433     }
10434    
10435     /*
10436     * This function is used to make a unique filename. We do this by
10437     * appending ~0, and then incrementing the number. However, we cannot
10438     * expand the length of the filename beyond the padding available in
10439     * the directory entry.
10440     */
10441     static void mutate_name(char *str, __u16 *len)
10442     {
10443     int i;
10444     __u16 l = *len & 0xFF, h = *len & 0xff00;
10445    
10446     /*
10447     * First check to see if it looks the name has been mutated
10448     * already
10449     */
10450     for (i = l-1; i > 0; i--) {
10451     if (!isdigit(str[i]))
10452     break;
10453     }
10454     if ((i == l-1) || (str[i] != '~')) {
10455     if (((l-1) & 3) < 2)
10456     l += 2;
10457     else
10458     l = (l+3) & ~3;
10459     str[l-2] = '~';
10460     str[l-1] = '0';
10461     *len = l | h;
10462     return;
10463     }
10464     for (i = l-1; i >= 0; i--) {
10465     if (isdigit(str[i])) {
10466     if (str[i] == '9')
10467     str[i] = '0';
10468     else {
10469     str[i]++;
10470     return;
10471     }
10472     continue;
10473     }
10474     if (i == 1) {
10475     if (str[0] == 'z')
10476     str[0] = 'A';
10477     else if (str[0] == 'Z') {
10478     str[0] = '~';
10479     str[1] = '0';
10480     } else
10481     str[0]++;
10482     } else if (i > 0) {
10483     str[i] = '1';
10484     str[i-1] = '~';
10485     } else {
10486     if (str[0] == '~')
10487     str[0] = 'a';
10488     else
10489     str[0]++;
10490     }
10491     break;
10492     }
10493     }
10494    
10495     static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10496     ext2_ino_t ino,
10497     struct fill_dir_struct *fd)
10498     {
10499     struct problem_context pctx;
10500     struct hash_entry *ent, *prev;
10501     int i, j;
10502     int fixed = 0;
10503     char new_name[256];
10504     __u16 new_len;
10505    
10506     clear_problem_context(&pctx);
10507     pctx.ino = ino;
10508    
10509     for (i=1; i < fd->num_array; i++) {
10510     ent = fd->harray + i;
10511     prev = ent - 1;
10512     if (!ent->dir->inode ||
10513     ((ent->dir->name_len & 0xFF) !=
10514     (prev->dir->name_len & 0xFF)) ||
10515     (strncmp(ent->dir->name, prev->dir->name,
10516     ent->dir->name_len & 0xFF)))
10517     continue;
10518     pctx.dirent = ent->dir;
10519     if ((ent->dir->inode == prev->dir->inode) &&
10520     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10521     e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10522     ent->dir->inode = 0;
10523     fixed++;
10524     continue;
10525     }
10526     memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10527     new_len = ent->dir->name_len;
10528     mutate_name(new_name, &new_len);
10529     for (j=0; j < fd->num_array; j++) {
10530     if ((i==j) ||
10531     ((ent->dir->name_len & 0xFF) !=
10532     (fd->harray[j].dir->name_len & 0xFF)) ||
10533     (strncmp(new_name, fd->harray[j].dir->name,
10534     new_len & 0xFF)))
10535     continue;
10536     mutate_name(new_name, &new_len);
10537    
10538     j = -1;
10539     }
10540     new_name[new_len & 0xFF] = 0;
10541     pctx.str = new_name;
10542     if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10543     memcpy(ent->dir->name, new_name, new_len & 0xFF);
10544     ent->dir->name_len = new_len;
10545     ext2fs_dirhash(fs->super->s_def_hash_version,
10546     ent->dir->name,
10547     ent->dir->name_len & 0xFF,
10548     fs->super->s_hash_seed,
10549     &ent->hash, &ent->minor_hash);
10550     fixed++;
10551     }
10552     }
10553     return fixed;
10554     }
10555    
10556    
10557     static errcode_t copy_dir_entries(ext2_filsys fs,
10558     struct fill_dir_struct *fd,
10559     struct out_dir *outdir)
10560     {
10561     errcode_t retval;
10562     char *block_start;
10563     struct hash_entry *ent;
10564     struct ext2_dir_entry *dirent;
10565     int i, rec_len, left;
10566     ext2_dirhash_t prev_hash;
10567     int offset;
10568    
10569     outdir->max = 0;
10570     retval = alloc_size_dir(fs, outdir,
10571     (fd->dir_size / fs->blocksize) + 2);
10572     if (retval)
10573     return retval;
10574     outdir->num = fd->compress ? 0 : 1;
10575     offset = 0;
10576     outdir->hashes[0] = 0;
10577     prev_hash = 1;
10578     if ((retval = get_next_block(fs, outdir, &block_start)))
10579     return retval;
10580     dirent = (struct ext2_dir_entry *) block_start;
10581     left = fs->blocksize;
10582     for (i=0; i < fd->num_array; i++) {
10583     ent = fd->harray + i;
10584     if (ent->dir->inode == 0)
10585     continue;
10586     rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10587     if (rec_len > left) {
10588     if (left)
10589     dirent->rec_len += left;
10590     if ((retval = get_next_block(fs, outdir,
10591     &block_start)))
10592     return retval;
10593     offset = 0;
10594     }
10595     left = fs->blocksize - offset;
10596     dirent = (struct ext2_dir_entry *) (block_start + offset);
10597     if (offset == 0) {
10598     if (ent->hash == prev_hash)
10599     outdir->hashes[outdir->num-1] = ent->hash | 1;
10600     else
10601     outdir->hashes[outdir->num-1] = ent->hash;
10602     }
10603     dirent->inode = ent->dir->inode;
10604     dirent->name_len = ent->dir->name_len;
10605     dirent->rec_len = rec_len;
10606     memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10607     offset += rec_len;
10608     left -= rec_len;
10609     if (left < 12) {
10610     dirent->rec_len += left;
10611     offset += left;
10612     left = 0;
10613     }
10614     prev_hash = ent->hash;
10615     }
10616     if (left)
10617     dirent->rec_len += left;
10618    
10619     return 0;
10620     }
10621    
10622    
10623     static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10624     ext2_ino_t ino, ext2_ino_t parent)
10625     {
10626     struct ext2_dir_entry *dir;
10627     struct ext2_dx_root_info *root;
10628     struct ext2_dx_countlimit *limits;
10629     int filetype = 0;
10630    
10631     if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10632     filetype = EXT2_FT_DIR << 8;
10633    
10634     memset(buf, 0, fs->blocksize);
10635     dir = (struct ext2_dir_entry *) buf;
10636     dir->inode = ino;
10637     dir->name[0] = '.';
10638     dir->name_len = 1 | filetype;
10639     dir->rec_len = 12;
10640     dir = (struct ext2_dir_entry *) (buf + 12);
10641     dir->inode = parent;
10642     dir->name[0] = '.';
10643     dir->name[1] = '.';
10644     dir->name_len = 2 | filetype;
10645     dir->rec_len = fs->blocksize - 12;
10646    
10647     root = (struct ext2_dx_root_info *) (buf+24);
10648     root->reserved_zero = 0;
10649     root->hash_version = fs->super->s_def_hash_version;
10650     root->info_length = 8;
10651     root->indirect_levels = 0;
10652     root->unused_flags = 0;
10653    
10654     limits = (struct ext2_dx_countlimit *) (buf+32);
10655     limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10656     limits->count = 0;
10657    
10658     return root;
10659     }
10660    
10661    
10662     static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10663     {
10664     struct ext2_dir_entry *dir;
10665     struct ext2_dx_countlimit *limits;
10666    
10667     memset(buf, 0, fs->blocksize);
10668     dir = (struct ext2_dir_entry *) buf;
10669     dir->inode = 0;
10670     dir->rec_len = fs->blocksize;
10671    
10672     limits = (struct ext2_dx_countlimit *) (buf+8);
10673     limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10674     limits->count = 0;
10675    
10676     return (struct ext2_dx_entry *) limits;
10677     }
10678    
10679     /*
10680     * This function takes the leaf nodes which have been written in
10681     * outdir, and populates the root node and any necessary interior nodes.
10682     */
10683     static errcode_t calculate_tree(ext2_filsys fs,
10684     struct out_dir *outdir,
10685     ext2_ino_t ino,
10686     ext2_ino_t parent)
10687     {
10688     struct ext2_dx_root_info *root_info;
10689     struct ext2_dx_entry *root, *dx_ent = 0;
10690     struct ext2_dx_countlimit *root_limit, *limit;
10691     errcode_t retval;
10692     char * block_start;
10693     int i, c1, c2, nblks;
10694     int limit_offset, root_offset;
10695    
10696     root_info = set_root_node(fs, outdir->buf, ino, parent);
10697     root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10698     root_info->info_length;
10699     root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10700     c1 = root_limit->limit;
10701     nblks = outdir->num;
10702    
10703     /* Write out the pointer blocks */
10704     if (nblks-1 <= c1) {
10705     /* Just write out the root block, and we're done */
10706     root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10707     for (i=1; i < nblks; i++) {
10708     root->block = ext2fs_cpu_to_le32(i);
10709     if (i != 1)
10710     root->hash =
10711     ext2fs_cpu_to_le32(outdir->hashes[i]);
10712     root++;
10713     c1--;
10714     }
10715     } else {
10716     c2 = 0;
10717     limit = 0;
10718     root_info->indirect_levels = 1;
10719     for (i=1; i < nblks; i++) {
10720     if (c1 == 0)
10721     return ENOSPC;
10722     if (c2 == 0) {
10723     if (limit)
10724     limit->limit = limit->count =
10725     ext2fs_cpu_to_le16(limit->limit);
10726     root = (struct ext2_dx_entry *)
10727     (outdir->buf + root_offset);
10728     root->block = ext2fs_cpu_to_le32(outdir->num);
10729     if (i != 1)
10730     root->hash =
10731     ext2fs_cpu_to_le32(outdir->hashes[i]);
10732     if ((retval = get_next_block(fs, outdir,
10733     &block_start)))
10734     return retval;
10735     dx_ent = set_int_node(fs, block_start);
10736     limit = (struct ext2_dx_countlimit *) dx_ent;
10737     c2 = limit->limit;
10738     root_offset += sizeof(struct ext2_dx_entry);
10739     c1--;
10740     }
10741     dx_ent->block = ext2fs_cpu_to_le32(i);
10742     if (c2 != limit->limit)
10743     dx_ent->hash =
10744     ext2fs_cpu_to_le32(outdir->hashes[i]);
10745     dx_ent++;
10746     c2--;
10747     }
10748     limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10749     limit->limit = ext2fs_cpu_to_le16(limit->limit);
10750     }
10751     root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10752     root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10753     root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10754    
10755     return 0;
10756     }
10757    
10758     struct write_dir_struct {
10759     struct out_dir *outdir;
10760     errcode_t err;
10761     e2fsck_t ctx;
10762     int cleared;
10763     };
10764    
10765     /*
10766     * Helper function which writes out a directory block.
10767     */
10768     static int write_dir_block(ext2_filsys fs,
10769     blk_t *block_nr,
10770     e2_blkcnt_t blockcnt,
10771     blk_t ref_block FSCK_ATTR((unused)),
10772     int ref_offset FSCK_ATTR((unused)),
10773     void *priv_data)
10774     {
10775     struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10776     blk_t blk;
10777     char *dir;
10778    
10779     if (*block_nr == 0)
10780     return 0;
10781     if (blockcnt >= wd->outdir->num) {
10782     e2fsck_read_bitmaps(wd->ctx);
10783     blk = *block_nr;
10784     ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10785     ext2fs_block_alloc_stats(fs, blk, -1);
10786     *block_nr = 0;
10787     wd->cleared++;
10788     return BLOCK_CHANGED;
10789     }
10790     if (blockcnt < 0)
10791     return 0;
10792    
10793     dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10794     wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10795     if (wd->err)
10796     return BLOCK_ABORT;
10797     return 0;
10798     }
10799    
10800     static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10801     struct out_dir *outdir,
10802     ext2_ino_t ino, int compress)
10803     {
10804     struct write_dir_struct wd;
10805     errcode_t retval;
10806     struct ext2_inode inode;
10807    
10808     retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10809     if (retval)
10810     return retval;
10811    
10812     wd.outdir = outdir;
10813     wd.err = 0;
10814     wd.ctx = ctx;
10815     wd.cleared = 0;
10816    
10817     retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10818     write_dir_block, &wd);
10819     if (retval)
10820     return retval;
10821     if (wd.err)
10822     return wd.err;
10823    
10824     e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10825     if (compress)
10826     inode.i_flags &= ~EXT2_INDEX_FL;
10827     else
10828     inode.i_flags |= EXT2_INDEX_FL;
10829     inode.i_size = outdir->num * fs->blocksize;
10830     inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10831     e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10832    
10833     return 0;
10834     }
10835    
10836     static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10837     {
10838     ext2_filsys fs = ctx->fs;
10839     errcode_t retval;
10840     struct ext2_inode inode;
10841     char *dir_buf = 0;
10842     struct fill_dir_struct fd;
10843     struct out_dir outdir;
10844    
10845     outdir.max = outdir.num = 0;
10846     outdir.buf = 0;
10847     outdir.hashes = 0;
10848     e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10849    
10850     retval = ENOMEM;
10851     fd.harray = 0;
10852     dir_buf = malloc(inode.i_size);
10853     if (!dir_buf)
10854     goto errout;
10855    
10856     fd.max_array = inode.i_size / 32;
10857     fd.num_array = 0;
10858     fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
10859     if (!fd.harray)
10860     goto errout;
10861    
10862     fd.ctx = ctx;
10863     fd.buf = dir_buf;
10864     fd.inode = &inode;
10865     fd.err = 0;
10866     fd.dir_size = 0;
10867     fd.compress = 0;
10868     if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10869     (inode.i_size / fs->blocksize) < 2)
10870     fd.compress = 1;
10871     fd.parent = 0;
10872    
10873     /* Read in the entire directory into memory */
10874     retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10875     fill_dir_block, &fd);
10876     if (fd.err) {
10877     retval = fd.err;
10878     goto errout;
10879     }
10880    
10881     /* Sort the list */
10882     resort:
10883     if (fd.compress)
10884     qsort(fd.harray+2, fd.num_array-2,
10885     sizeof(struct hash_entry), name_cmp);
10886     else
10887     qsort(fd.harray, fd.num_array,
10888     sizeof(struct hash_entry), hash_cmp);
10889    
10890     /*
10891     * Look for duplicates
10892     */
10893     if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10894     goto resort;
10895    
10896     if (ctx->options & E2F_OPT_NO) {
10897     retval = 0;
10898     goto errout;
10899     }
10900    
10901     /*
10902     * Copy the directory entries. In a htree directory these
10903     * will become the leaf nodes.
10904     */
10905     retval = copy_dir_entries(fs, &fd, &outdir);
10906     if (retval)
10907     goto errout;
10908    
10909     free(dir_buf); dir_buf = 0;
10910    
10911     if (!fd.compress) {
10912     /* Calculate the interior nodes */
10913     retval = calculate_tree(fs, &outdir, ino, fd.parent);
10914     if (retval)
10915     goto errout;
10916     }
10917    
10918     retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10919    
10920     errout:
10921     free(dir_buf);
10922     free(fd.harray);
10923    
10924     free_out_dir(&outdir);
10925     return retval;
10926     }
10927    
10928     void e2fsck_rehash_directories(e2fsck_t ctx)
10929     {
10930     struct problem_context pctx;
10931     struct dir_info *dir;
10932     ext2_u32_iterate iter;
10933     ext2_ino_t ino;
10934     errcode_t retval;
10935     int i, cur, max, all_dirs, dir_index, first = 1;
10936    
10937     all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10938    
10939     if (!ctx->dirs_to_hash && !all_dirs)
10940     return;
10941    
10942     e2fsck_get_lost_and_found(ctx, 0);
10943    
10944     clear_problem_context(&pctx);
10945    
10946     dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10947     cur = 0;
10948     if (all_dirs) {
10949     i = 0;
10950     max = e2fsck_get_num_dirinfo(ctx);
10951     } else {
10952     retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10953     &iter);
10954     if (retval) {
10955     pctx.errcode = retval;
10956     fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10957     return;
10958     }
10959     max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10960     }
10961     while (1) {
10962     if (all_dirs) {
10963     if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10964     break;
10965     ino = dir->ino;
10966     } else {
10967     if (!ext2fs_u32_list_iterate(iter, &ino))
10968     break;
10969     }
10970     if (ino == ctx->lost_and_found)
10971     continue;
10972     pctx.dir = ino;
10973     if (first) {
10974     fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10975     first = 0;
10976     }
10977     pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10978     if (pctx.errcode) {
10979     end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10980     fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10981     }
10982     if (ctx->progress && !ctx->progress_fd)
10983     e2fsck_simple_progress(ctx, "Rebuilding directory",
10984     100.0 * (float) (++cur) / (float) max, ino);
10985     }
10986     end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10987     if (!all_dirs)
10988     ext2fs_u32_list_iterate_end(iter);
10989    
10990     ext2fs_u32_list_free(ctx->dirs_to_hash);
10991     ctx->dirs_to_hash = 0;
10992     }
10993    
10994     /*
10995     * linux/fs/revoke.c
10996     *
10997     * Journal revoke routines for the generic filesystem journaling code;
10998     * part of the ext2fs journaling system.
10999     *
11000     * Revoke is the mechanism used to prevent old log records for deleted
11001     * metadata from being replayed on top of newer data using the same
11002     * blocks. The revoke mechanism is used in two separate places:
11003     *
11004     * + Commit: during commit we write the entire list of the current
11005     * transaction's revoked blocks to the journal
11006     *
11007     * + Recovery: during recovery we record the transaction ID of all
11008     * revoked blocks. If there are multiple revoke records in the log
11009     * for a single block, only the last one counts, and if there is a log
11010     * entry for a block beyond the last revoke, then that log entry still
11011     * gets replayed.
11012     *
11013     * We can get interactions between revokes and new log data within a
11014     * single transaction:
11015     *
11016     * Block is revoked and then journaled:
11017     * The desired end result is the journaling of the new block, so we
11018     * cancel the revoke before the transaction commits.
11019     *
11020     * Block is journaled and then revoked:
11021     * The revoke must take precedence over the write of the block, so we
11022     * need either to cancel the journal entry or to write the revoke
11023     * later in the log than the log block. In this case, we choose the
11024     * latter: journaling a block cancels any revoke record for that block
11025     * in the current transaction, so any revoke for that block in the
11026     * transaction must have happened after the block was journaled and so
11027     * the revoke must take precedence.
11028     *
11029     * Block is revoked and then written as data:
11030     * The data write is allowed to succeed, but the revoke is _not_
11031     * cancelled. We still need to prevent old log records from
11032     * overwriting the new data. We don't even need to clear the revoke
11033     * bit here.
11034     *
11035     * Revoke information on buffers is a tri-state value:
11036     *
11037     * RevokeValid clear: no cached revoke status, need to look it up
11038     * RevokeValid set, Revoked clear:
11039     * buffer has not been revoked, and cancel_revoke
11040     * need do nothing.
11041     * RevokeValid set, Revoked set:
11042     * buffer has been revoked.
11043     */
11044    
11045     static kmem_cache_t *revoke_record_cache;
11046     static kmem_cache_t *revoke_table_cache;
11047    
11048     /* Each revoke record represents one single revoked block. During
11049     journal replay, this involves recording the transaction ID of the
11050     last transaction to revoke this block. */
11051    
11052     struct jbd_revoke_record_s
11053     {
11054     struct list_head hash;
11055     tid_t sequence; /* Used for recovery only */
11056     unsigned long blocknr;
11057     };
11058    
11059    
11060     /* The revoke table is just a simple hash table of revoke records. */
11061     struct jbd_revoke_table_s
11062     {
11063     /* It is conceivable that we might want a larger hash table
11064     * for recovery. Must be a power of two. */
11065     int hash_size;
11066     int hash_shift;
11067     struct list_head *hash_table;
11068     };
11069    
11070    
11071     /* Utility functions to maintain the revoke table */
11072    
11073     /* Borrowed from buffer.c: this is a tried and tested block hash function */
11074     static int hash(journal_t *journal, unsigned long block)
11075     {
11076     struct jbd_revoke_table_s *table = journal->j_revoke;
11077     int hash_shift = table->hash_shift;
11078    
11079     return ((block << (hash_shift - 6)) ^
11080     (block >> 13) ^
11081     (block << (hash_shift - 12))) & (table->hash_size - 1);
11082     }
11083    
11084     static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11085     tid_t seq)
11086     {
11087     struct list_head *hash_list;
11088     struct jbd_revoke_record_s *record;
11089    
11090     record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11091     if (!record)
11092     goto oom;
11093    
11094     record->sequence = seq;
11095     record->blocknr = blocknr;
11096     hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11097     list_add(&record->hash, hash_list);
11098     return 0;
11099    
11100     oom:
11101     return -ENOMEM;
11102     }
11103    
11104     /* Find a revoke record in the journal's hash table. */
11105    
11106     static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11107     unsigned long blocknr)
11108     {
11109     struct list_head *hash_list;
11110     struct jbd_revoke_record_s *record;
11111    
11112     hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11113    
11114     record = (struct jbd_revoke_record_s *) hash_list->next;
11115     while (&(record->hash) != hash_list) {
11116     if (record->blocknr == blocknr)
11117     return record;
11118     record = (struct jbd_revoke_record_s *) record->hash.next;
11119     }
11120     return NULL;
11121     }
11122    
11123     int journal_init_revoke_caches(void)
11124     {
11125     revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11126     if (revoke_record_cache == 0)
11127     return -ENOMEM;
11128    
11129     revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11130     if (revoke_table_cache == 0) {
11131     do_cache_destroy(revoke_record_cache);
11132     revoke_record_cache = NULL;
11133     return -ENOMEM;
11134     }
11135     return 0;
11136     }
11137    
11138     void journal_destroy_revoke_caches(void)
11139     {
11140     do_cache_destroy(revoke_record_cache);
11141     revoke_record_cache = 0;
11142     do_cache_destroy(revoke_table_cache);
11143     revoke_table_cache = 0;
11144     }
11145    
11146     /* Initialise the revoke table for a given journal to a given size. */
11147    
11148     int journal_init_revoke(journal_t *journal, int hash_size)
11149     {
11150     int shift, tmp;
11151    
11152     journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11153     if (!journal->j_revoke)
11154     return -ENOMEM;
11155    
11156     /* Check that the hash_size is a power of two */
11157     journal->j_revoke->hash_size = hash_size;
11158    
11159     shift = 0;
11160     tmp = hash_size;
11161 niro 816 while ((tmp >>= 1UL) != 0UL)
11162 niro 532 shift++;
11163     journal->j_revoke->hash_shift = shift;
11164    
11165     journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
11166     if (!journal->j_revoke->hash_table) {
11167     free(journal->j_revoke);
11168     journal->j_revoke = NULL;
11169     return -ENOMEM;
11170     }
11171    
11172     for (tmp = 0; tmp < hash_size; tmp++)
11173     INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11174    
11175     return 0;
11176     }
11177    
11178     /* Destoy a journal's revoke table. The table must already be empty! */
11179    
11180     void journal_destroy_revoke(journal_t *journal)
11181     {
11182     struct jbd_revoke_table_s *table;
11183     struct list_head *hash_list;
11184     int i;
11185    
11186     table = journal->j_revoke;
11187     if (!table)
11188     return;
11189    
11190     for (i=0; i<table->hash_size; i++) {
11191     hash_list = &table->hash_table[i];
11192     }
11193    
11194     free(table->hash_table);
11195     free(table);
11196     journal->j_revoke = NULL;
11197     }
11198    
11199     /*
11200     * Revoke support for recovery.
11201     *
11202     * Recovery needs to be able to:
11203     *
11204     * record all revoke records, including the tid of the latest instance
11205     * of each revoke in the journal
11206     *
11207     * check whether a given block in a given transaction should be replayed
11208     * (ie. has not been revoked by a revoke record in that or a subsequent
11209     * transaction)
11210     *
11211     * empty the revoke table after recovery.
11212     */
11213    
11214     /*
11215     * First, setting revoke records. We create a new revoke record for
11216     * every block ever revoked in the log as we scan it for recovery, and
11217     * we update the existing records if we find multiple revokes for a
11218     * single block.
11219     */
11220    
11221     int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11222     tid_t sequence)
11223     {
11224     struct jbd_revoke_record_s *record;
11225    
11226     record = find_revoke_record(journal, blocknr);
11227     if (record) {
11228     /* If we have multiple occurences, only record the
11229     * latest sequence number in the hashed record */
11230     if (tid_gt(sequence, record->sequence))
11231     record->sequence = sequence;
11232     return 0;
11233     }
11234     return insert_revoke_hash(journal, blocknr, sequence);
11235     }
11236    
11237     /*
11238     * Test revoke records. For a given block referenced in the log, has
11239     * that block been revoked? A revoke record with a given transaction
11240     * sequence number revokes all blocks in that transaction and earlier
11241     * ones, but later transactions still need replayed.
11242     */
11243    
11244     int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11245     tid_t sequence)
11246     {
11247     struct jbd_revoke_record_s *record;
11248    
11249     record = find_revoke_record(journal, blocknr);
11250     if (!record)
11251     return 0;
11252     if (tid_gt(sequence, record->sequence))
11253     return 0;
11254     return 1;
11255     }
11256    
11257     /*
11258     * Finally, once recovery is over, we need to clear the revoke table so
11259     * that it can be reused by the running filesystem.
11260     */
11261    
11262     void journal_clear_revoke(journal_t *journal)
11263     {
11264     int i;
11265     struct list_head *hash_list;
11266     struct jbd_revoke_record_s *record;
11267     struct jbd_revoke_table_s *revoke_var;
11268    
11269     revoke_var = journal->j_revoke;
11270    
11271     for (i = 0; i < revoke_var->hash_size; i++) {
11272     hash_list = &revoke_var->hash_table[i];
11273     while (!list_empty(hash_list)) {
11274     record = (struct jbd_revoke_record_s*) hash_list->next;
11275     list_del(&record->hash);
11276     free(record);
11277     }
11278     }
11279     }
11280    
11281     /*
11282     * e2fsck.c - superblock checks
11283     */
11284    
11285     #define MIN_CHECK 1
11286     #define MAX_CHECK 2
11287    
11288     static void check_super_value(e2fsck_t ctx, const char *descr,
11289     unsigned long value, int flags,
11290     unsigned long min_val, unsigned long max_val)
11291     {
11292     struct problem_context pctx;
11293    
11294     if (((flags & MIN_CHECK) && (value < min_val)) ||
11295     ((flags & MAX_CHECK) && (value > max_val))) {
11296     clear_problem_context(&pctx);
11297     pctx.num = value;
11298     pctx.str = descr;
11299     fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11300     ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11301     }
11302     }
11303    
11304     /*
11305     * This routine may get stubbed out in special compilations of the
11306     * e2fsck code..
11307     */
11308     #ifndef EXT2_SPECIAL_DEVICE_SIZE
11309     static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11310     {
11311     return (ext2fs_get_device_size(ctx->filesystem_name,
11312     EXT2_BLOCK_SIZE(ctx->fs->super),
11313     &ctx->num_blocks));
11314     }
11315     #endif
11316    
11317     /*
11318     * helper function to release an inode
11319     */
11320     struct process_block_struct {
11321     e2fsck_t ctx;
11322     char *buf;
11323     struct problem_context *pctx;
11324     int truncating;
11325     int truncate_offset;
11326     e2_blkcnt_t truncate_block;
11327     int truncated_blocks;
11328     int abort;
11329     errcode_t errcode;
11330     };
11331    
11332     static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11333     e2_blkcnt_t blockcnt,
11334     blk_t ref_blk FSCK_ATTR((unused)),
11335     int ref_offset FSCK_ATTR((unused)),
11336     void *priv_data)
11337     {
11338     struct process_block_struct *pb;
11339     e2fsck_t ctx;
11340     struct problem_context *pctx;
11341     blk_t blk = *block_nr;
11342     int retval = 0;
11343    
11344     pb = (struct process_block_struct *) priv_data;
11345     ctx = pb->ctx;
11346     pctx = pb->pctx;
11347    
11348     pctx->blk = blk;
11349     pctx->blkcount = blockcnt;
11350    
11351     if (HOLE_BLKADDR(blk))
11352     return 0;
11353    
11354     if ((blk < fs->super->s_first_data_block) ||
11355     (blk >= fs->super->s_blocks_count)) {
11356     fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11357     return_abort:
11358     pb->abort = 1;
11359     return BLOCK_ABORT;
11360     }
11361    
11362     if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11363     fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11364     goto return_abort;
11365     }
11366    
11367     /*
11368     * If we are deleting an orphan, then we leave the fields alone.
11369     * If we are truncating an orphan, then update the inode fields
11370     * and clean up any partial block data.
11371     */
11372     if (pb->truncating) {
11373     /*
11374     * We only remove indirect blocks if they are
11375     * completely empty.
11376     */
11377     if (blockcnt < 0) {
11378     int i, limit;
11379     blk_t *bp;
11380    
11381     pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11382     pb->buf);
11383     if (pb->errcode)
11384     goto return_abort;
11385    
11386     limit = fs->blocksize >> 2;
11387     for (i = 0, bp = (blk_t *) pb->buf;
11388     i < limit; i++, bp++)
11389     if (*bp)
11390     return 0;
11391     }
11392     /*
11393     * We don't remove direct blocks until we've reached
11394     * the truncation block.
11395     */
11396     if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11397     return 0;
11398     /*
11399     * If part of the last block needs truncating, we do
11400     * it here.
11401     */
11402     if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11403     pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11404     pb->buf);
11405     if (pb->errcode)
11406     goto return_abort;
11407     memset(pb->buf + pb->truncate_offset, 0,
11408     fs->blocksize - pb->truncate_offset);
11409     pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11410     pb->buf);
11411     if (pb->errcode)
11412     goto return_abort;
11413     }
11414     pb->truncated_blocks++;
11415     *block_nr = 0;
11416     retval |= BLOCK_CHANGED;
11417     }
11418    
11419     ext2fs_block_alloc_stats(fs, blk, -1);
11420     return retval;
11421     }
11422    
11423     /*
11424     * This function releases an inode. Returns 1 if an inconsistency was
11425     * found. If the inode has a link count, then it is being truncated and
11426     * not deleted.
11427     */
11428     static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11429     struct ext2_inode *inode, char *block_buf,
11430     struct problem_context *pctx)
11431     {
11432     struct process_block_struct pb;
11433     ext2_filsys fs = ctx->fs;
11434     errcode_t retval;
11435     __u32 count;
11436    
11437     if (!ext2fs_inode_has_valid_blocks(inode))
11438     return 0;
11439    
11440     pb.buf = block_buf + 3 * ctx->fs->blocksize;
11441     pb.ctx = ctx;
11442     pb.abort = 0;
11443     pb.errcode = 0;
11444     pb.pctx = pctx;
11445     if (inode->i_links_count) {
11446     pb.truncating = 1;
11447     pb.truncate_block = (e2_blkcnt_t)
11448     ((((long long)inode->i_size_high << 32) +
11449     inode->i_size + fs->blocksize - 1) /
11450     fs->blocksize);
11451     pb.truncate_offset = inode->i_size % fs->blocksize;
11452     } else {
11453     pb.truncating = 0;
11454     pb.truncate_block = 0;
11455     pb.truncate_offset = 0;
11456     }
11457     pb.truncated_blocks = 0;
11458     retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11459     block_buf, release_inode_block, &pb);
11460     if (retval) {
11461     bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11462     ino);
11463     return 1;
11464     }
11465     if (pb.abort)
11466     return 1;
11467    
11468     /* Refresh the inode since ext2fs_block_iterate may have changed it */
11469     e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11470    
11471     if (pb.truncated_blocks)
11472     inode->i_blocks -= pb.truncated_blocks *
11473     (fs->blocksize / 512);
11474    
11475     if (inode->i_file_acl) {
11476     retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11477     block_buf, -1, &count);
11478     if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11479     retval = 0;
11480     count = 1;
11481     }
11482     if (retval) {
11483     bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11484     ino);
11485     return 1;
11486     }
11487     if (count == 0)
11488     ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11489     inode->i_file_acl = 0;
11490     }
11491     return 0;
11492     }
11493    
11494     /*
11495     * This function releases all of the orphan inodes. It returns 1 if
11496     * it hit some error, and 0 on success.
11497     */
11498     static int release_orphan_inodes(e2fsck_t ctx)
11499     {
11500     ext2_filsys fs = ctx->fs;
11501     ext2_ino_t ino, next_ino;
11502     struct ext2_inode inode;
11503     struct problem_context pctx;
11504     char *block_buf;
11505    
11506     if ((ino = fs->super->s_last_orphan) == 0)
11507     return 0;
11508    
11509     /*
11510     * Win or lose, we won't be using the head of the orphan inode
11511     * list again.
11512     */
11513     fs->super->s_last_orphan = 0;
11514     ext2fs_mark_super_dirty(fs);
11515    
11516     /*
11517     * If the filesystem contains errors, don't run the orphan
11518     * list, since the orphan list can't be trusted; and we're
11519     * going to be running a full e2fsck run anyway...
11520     */
11521     if (fs->super->s_state & EXT2_ERROR_FS)
11522     return 0;
11523    
11524     if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11525     (ino > fs->super->s_inodes_count)) {
11526     clear_problem_context(&pctx);
11527     pctx.ino = ino;
11528     fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11529     return 1;
11530     }
11531    
11532     block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11533     "block iterate buffer");
11534     e2fsck_read_bitmaps(ctx);
11535    
11536     while (ino) {
11537     e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11538     clear_problem_context(&pctx);
11539     pctx.ino = ino;
11540     pctx.inode = &inode;
11541     pctx.str = inode.i_links_count ? _("Truncating") :
11542     _("Clearing");
11543    
11544     fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11545    
11546     next_ino = inode.i_dtime;
11547     if (next_ino &&
11548     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11549     (next_ino > fs->super->s_inodes_count))) {
11550     pctx.ino = next_ino;
11551     fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11552     goto return_abort;
11553     }
11554    
11555     if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11556     goto return_abort;
11557    
11558     if (!inode.i_links_count) {
11559     ext2fs_inode_alloc_stats2(fs, ino, -1,
11560     LINUX_S_ISDIR(inode.i_mode));
11561     inode.i_dtime = time(0);
11562     } else {
11563     inode.i_dtime = 0;
11564     }
11565     e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11566     ino = next_ino;
11567     }
11568     ext2fs_free_mem(&block_buf);
11569     return 0;
11570     return_abort:
11571     ext2fs_free_mem(&block_buf);
11572     return 1;
11573     }
11574    
11575     /*
11576     * Check the resize inode to make sure it is sane. We check both for
11577     * the case where on-line resizing is not enabled (in which case the
11578     * resize inode should be cleared) as well as the case where on-line
11579     * resizing is enabled.
11580     */
11581     static void check_resize_inode(e2fsck_t ctx)
11582     {
11583     ext2_filsys fs = ctx->fs;
11584     struct ext2_inode inode;
11585     struct problem_context pctx;
11586     int i, j, gdt_off, ind_off;
11587     blk_t blk, pblk, expect;
11588     __u32 *dind_buf = 0, *ind_buf;
11589     errcode_t retval;
11590    
11591     clear_problem_context(&pctx);
11592    
11593     /*
11594     * If the resize inode feature isn't set, then
11595     * s_reserved_gdt_blocks must be zero.
11596     */
11597     if (!(fs->super->s_feature_compat &
11598     EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11599     if (fs->super->s_reserved_gdt_blocks) {
11600     pctx.num = fs->super->s_reserved_gdt_blocks;
11601     if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11602     &pctx)) {
11603     fs->super->s_reserved_gdt_blocks = 0;
11604     ext2fs_mark_super_dirty(fs);
11605     }
11606     }
11607     }
11608    
11609     /* Read the resize inode */
11610     pctx.ino = EXT2_RESIZE_INO;
11611     retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11612     if (retval) {
11613     if (fs->super->s_feature_compat &
11614     EXT2_FEATURE_COMPAT_RESIZE_INODE)
11615     ctx->flags |= E2F_FLAG_RESIZE_INODE;
11616     return;
11617     }
11618    
11619     /*
11620     * If the resize inode feature isn't set, check to make sure
11621     * the resize inode is cleared; then we're done.
11622     */
11623     if (!(fs->super->s_feature_compat &
11624     EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11625     for (i=0; i < EXT2_N_BLOCKS; i++) {
11626     if (inode.i_block[i])
11627     break;
11628     }
11629     if ((i < EXT2_N_BLOCKS) &&
11630     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11631     memset(&inode, 0, sizeof(inode));
11632     e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11633     "clear_resize");
11634     }
11635     return;
11636     }
11637    
11638     /*
11639     * The resize inode feature is enabled; check to make sure the
11640     * only block in use is the double indirect block
11641     */
11642     blk = inode.i_block[EXT2_DIND_BLOCK];
11643     for (i=0; i < EXT2_N_BLOCKS; i++) {
11644     if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11645     break;
11646     }
11647     if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11648     !(inode.i_mode & LINUX_S_IFREG) ||
11649     (blk < fs->super->s_first_data_block ||
11650     blk >= fs->super->s_blocks_count)) {
11651     resize_inode_invalid:
11652     if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11653     memset(&inode, 0, sizeof(inode));
11654     e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11655     "clear_resize");
11656     ctx->flags |= E2F_FLAG_RESIZE_INODE;
11657     }
11658     if (!(ctx->options & E2F_OPT_READONLY)) {
11659     fs->super->s_state &= ~EXT2_VALID_FS;
11660     ext2fs_mark_super_dirty(fs);
11661     }
11662     goto cleanup;
11663     }
11664     dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11665     "resize dind buffer");
11666     ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11667    
11668     retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11669     if (retval)
11670     goto resize_inode_invalid;
11671    
11672     gdt_off = fs->desc_blocks;
11673     pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11674     for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11675     i++, gdt_off++, pblk++) {
11676     gdt_off %= fs->blocksize/4;
11677     if (dind_buf[gdt_off] != pblk)
11678     goto resize_inode_invalid;
11679     retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11680     if (retval)
11681     goto resize_inode_invalid;
11682     ind_off = 0;
11683     for (j = 1; j < fs->group_desc_count; j++) {
11684     if (!ext2fs_bg_has_super(fs, j))
11685     continue;
11686     expect = pblk + (j * fs->super->s_blocks_per_group);
11687     if (ind_buf[ind_off] != expect)
11688     goto resize_inode_invalid;
11689     ind_off++;
11690     }
11691     }
11692    
11693     cleanup:
11694     ext2fs_free_mem(&dind_buf);
11695    
11696     }
11697    
11698     static void check_super_block(e2fsck_t ctx)
11699     {
11700     ext2_filsys fs = ctx->fs;
11701     blk_t first_block, last_block;
11702     struct ext2_super_block *sb = fs->super;
11703     struct ext2_group_desc *gd;
11704     blk_t blocks_per_group = fs->super->s_blocks_per_group;
11705     blk_t bpg_max;
11706     int inodes_per_block;
11707     int ipg_max;
11708     int inode_size;
11709     dgrp_t i;
11710     blk_t should_be;
11711     struct problem_context pctx;
11712     __u32 free_blocks = 0, free_inodes = 0;
11713    
11714     inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11715     ipg_max = inodes_per_block * (blocks_per_group - 4);
11716     if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11717     ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11718     bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11719     if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11720     bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11721    
11722     ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11723     sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11724     ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11725     sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11726     ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11727     sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11728    
11729     clear_problem_context(&pctx);
11730    
11731     /*
11732     * Verify the super block constants...
11733     */
11734     check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11735     MIN_CHECK, 1, 0);
11736     check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11737     MIN_CHECK, 1, 0);
11738     check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11739     MAX_CHECK, 0, sb->s_blocks_count);
11740     check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11741     MIN_CHECK | MAX_CHECK, 0,
11742     EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11743     check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11744     MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11745     check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11746     MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11747     bpg_max);
11748     check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11749     MIN_CHECK | MAX_CHECK, 8, bpg_max);
11750     check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11751     MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11752     check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11753     MAX_CHECK, 0, sb->s_blocks_count / 2);
11754     check_super_value(ctx, "reserved_gdt_blocks",
11755     sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11756     fs->blocksize/4);
11757     inode_size = EXT2_INODE_SIZE(sb);
11758     check_super_value(ctx, "inode_size",
11759     inode_size, MIN_CHECK | MAX_CHECK,
11760     EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11761     if (inode_size & (inode_size - 1)) {
11762     pctx.num = inode_size;
11763     pctx.str = "inode_size";
11764     fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11765     ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11766     return;
11767     }
11768    
11769     if (!ctx->num_blocks) {
11770     pctx.errcode = e2fsck_get_device_size(ctx);
11771     if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11772     fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11773     ctx->flags |= E2F_FLAG_ABORT;
11774     return;
11775     }
11776     if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11777     (ctx->num_blocks < sb->s_blocks_count)) {
11778     pctx.blk = sb->s_blocks_count;
11779     pctx.blk2 = ctx->num_blocks;
11780     if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11781     ctx->flags |= E2F_FLAG_ABORT;
11782     return;
11783     }
11784     }
11785     }
11786    
11787     if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11788     pctx.blk = EXT2_BLOCK_SIZE(sb);
11789     pctx.blk2 = EXT2_FRAG_SIZE(sb);
11790     fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11791     ctx->flags |= E2F_FLAG_ABORT;
11792     return;
11793     }
11794    
11795     should_be = sb->s_frags_per_group >>
11796     (sb->s_log_block_size - sb->s_log_frag_size);
11797     if (sb->s_blocks_per_group != should_be) {
11798     pctx.blk = sb->s_blocks_per_group;
11799     pctx.blk2 = should_be;
11800     fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11801     ctx->flags |= E2F_FLAG_ABORT;
11802     return;
11803     }
11804    
11805     should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11806     if (sb->s_first_data_block != should_be) {
11807     pctx.blk = sb->s_first_data_block;
11808     pctx.blk2 = should_be;
11809     fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11810     ctx->flags |= E2F_FLAG_ABORT;
11811     return;
11812     }
11813    
11814     should_be = sb->s_inodes_per_group * fs->group_desc_count;
11815     if (sb->s_inodes_count != should_be) {
11816     pctx.ino = sb->s_inodes_count;
11817     pctx.ino2 = should_be;
11818     if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11819     sb->s_inodes_count = should_be;
11820     ext2fs_mark_super_dirty(fs);
11821     }
11822     }
11823    
11824     /*
11825     * Verify the group descriptors....
11826     */
11827     first_block = sb->s_first_data_block;
11828     last_block = first_block + blocks_per_group;
11829    
11830     for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11831     pctx.group = i;
11832    
11833     if (i == fs->group_desc_count - 1)
11834     last_block = sb->s_blocks_count;
11835     if ((gd->bg_block_bitmap < first_block) ||
11836     (gd->bg_block_bitmap >= last_block)) {
11837     pctx.blk = gd->bg_block_bitmap;
11838     if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11839     gd->bg_block_bitmap = 0;
11840     }
11841     if (gd->bg_block_bitmap == 0) {
11842     ctx->invalid_block_bitmap_flag[i]++;
11843     ctx->invalid_bitmaps++;
11844     }
11845     if ((gd->bg_inode_bitmap < first_block) ||
11846     (gd->bg_inode_bitmap >= last_block)) {
11847     pctx.blk = gd->bg_inode_bitmap;
11848     if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11849     gd->bg_inode_bitmap = 0;
11850     }
11851     if (gd->bg_inode_bitmap == 0) {
11852     ctx->invalid_inode_bitmap_flag[i]++;
11853     ctx->invalid_bitmaps++;
11854     }
11855     if ((gd->bg_inode_table < first_block) ||
11856     ((gd->bg_inode_table +
11857     fs->inode_blocks_per_group - 1) >= last_block)) {
11858     pctx.blk = gd->bg_inode_table;
11859     if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11860     gd->bg_inode_table = 0;
11861     }
11862     if (gd->bg_inode_table == 0) {
11863     ctx->invalid_inode_table_flag[i]++;
11864     ctx->invalid_bitmaps++;
11865     }
11866     free_blocks += gd->bg_free_blocks_count;
11867     free_inodes += gd->bg_free_inodes_count;
11868     first_block += sb->s_blocks_per_group;
11869     last_block += sb->s_blocks_per_group;
11870    
11871     if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11872     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11873     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11874     ext2fs_unmark_valid(fs);
11875    
11876     }
11877    
11878     /*
11879     * Update the global counts from the block group counts. This
11880     * is needed for an experimental patch which eliminates
11881     * locking the entire filesystem when allocating blocks or
11882     * inodes; if the filesystem is not unmounted cleanly, the
11883     * global counts may not be accurate.
11884     */
11885     if ((free_blocks != sb->s_free_blocks_count) ||
11886     (free_inodes != sb->s_free_inodes_count)) {
11887     if (ctx->options & E2F_OPT_READONLY)
11888     ext2fs_unmark_valid(fs);
11889     else {
11890     sb->s_free_blocks_count = free_blocks;
11891     sb->s_free_inodes_count = free_inodes;
11892     ext2fs_mark_super_dirty(fs);
11893     }
11894     }
11895    
11896     if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11897     (sb->s_free_inodes_count > sb->s_inodes_count))
11898     ext2fs_unmark_valid(fs);
11899    
11900    
11901     /*
11902     * If we have invalid bitmaps, set the error state of the
11903     * filesystem.
11904     */
11905     if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11906     sb->s_state &= ~EXT2_VALID_FS;
11907     ext2fs_mark_super_dirty(fs);
11908     }
11909    
11910     clear_problem_context(&pctx);
11911    
11912     /*
11913     * If the UUID field isn't assigned, assign it.
11914     */
11915     if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11916     if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11917     uuid_generate(sb->s_uuid);
11918     ext2fs_mark_super_dirty(fs);
11919     fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11920     }
11921     }
11922    
11923     /* FIXME - HURD support?
11924     * For the Hurd, check to see if the filetype option is set,
11925     * since it doesn't support it.
11926     */
11927     if (!(ctx->options & E2F_OPT_READONLY) &&
11928     fs->super->s_creator_os == EXT2_OS_HURD &&
11929     (fs->super->s_feature_incompat &
11930     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11931     if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11932     fs->super->s_feature_incompat &=
11933     ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11934     ext2fs_mark_super_dirty(fs);
11935    
11936     }
11937     }
11938    
11939     /*
11940     * If we have any of the compatibility flags set, we need to have a
11941     * revision 1 filesystem. Most kernels will not check the flags on
11942     * a rev 0 filesystem and we may have corruption issues because of
11943     * the incompatible changes to the filesystem.
11944     */
11945     if (!(ctx->options & E2F_OPT_READONLY) &&
11946     fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11947     (fs->super->s_feature_compat ||
11948     fs->super->s_feature_ro_compat ||
11949     fs->super->s_feature_incompat) &&
11950     fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11951     ext2fs_update_dynamic_rev(fs);
11952     ext2fs_mark_super_dirty(fs);
11953     }
11954    
11955     check_resize_inode(ctx);
11956    
11957     /*
11958     * Clean up any orphan inodes, if present.
11959     */
11960     if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11961     fs->super->s_state &= ~EXT2_VALID_FS;
11962     ext2fs_mark_super_dirty(fs);
11963     }
11964    
11965     /*
11966     * Move the ext3 journal file, if necessary.
11967     */
11968     e2fsck_move_ext3_journal(ctx);
11969     }
11970    
11971     /*
11972     * swapfs.c --- byte-swap an ext2 filesystem
11973     */
11974    
11975     #ifdef ENABLE_SWAPFS
11976    
11977     struct swap_block_struct {
11978     ext2_ino_t ino;
11979     int isdir;
11980     errcode_t errcode;
11981     char *dir_buf;
11982     struct ext2_inode *inode;
11983     };
11984    
11985     /*
11986     * This is a helper function for block_iterate. We mark all of the
11987     * indirect and direct blocks as changed, so that block_iterate will
11988     * write them out.
11989     */
11990     static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11991     void *priv_data)
11992     {
11993     errcode_t retval;
11994    
11995     struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11996    
11997     if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11998     retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11999     if (retval) {
12000     sb->errcode = retval;
12001     return BLOCK_ABORT;
12002     }
12003     retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
12004     if (retval) {
12005     sb->errcode = retval;
12006     return BLOCK_ABORT;
12007     }
12008     }
12009     if (blockcnt >= 0) {
12010     if (blockcnt < EXT2_NDIR_BLOCKS)
12011     return 0;
12012     return BLOCK_CHANGED;
12013     }
12014     if (blockcnt == BLOCK_COUNT_IND) {
12015     if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
12016     return 0;
12017     return BLOCK_CHANGED;
12018     }
12019     if (blockcnt == BLOCK_COUNT_DIND) {
12020     if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12021     return 0;
12022     return BLOCK_CHANGED;
12023     }
12024     if (blockcnt == BLOCK_COUNT_TIND) {
12025     if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12026     return 0;
12027     return BLOCK_CHANGED;
12028     }
12029     return BLOCK_CHANGED;
12030     }
12031    
12032     /*
12033     * This function is responsible for byte-swapping all of the indirect,
12034     * block pointers. It is also responsible for byte-swapping directories.
12035     */
12036     static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12037     struct ext2_inode *inode)
12038     {
12039     errcode_t retval;
12040     struct swap_block_struct sb;
12041    
12042     sb.ino = ino;
12043     sb.inode = inode;
12044     sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12045     sb.errcode = 0;
12046     sb.isdir = 0;
12047     if (LINUX_S_ISDIR(inode->i_mode))
12048     sb.isdir = 1;
12049    
12050     retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12051     swap_block, &sb);
12052     if (retval) {
12053     bb_error_msg(_("while calling ext2fs_block_iterate"));
12054     ctx->flags |= E2F_FLAG_ABORT;
12055     return;
12056     }
12057     if (sb.errcode) {
12058     bb_error_msg(_("while calling iterator function"));
12059     ctx->flags |= E2F_FLAG_ABORT;
12060     return;
12061     }
12062     }
12063    
12064     static void swap_inodes(e2fsck_t ctx)
12065     {
12066     ext2_filsys fs = ctx->fs;
12067     dgrp_t group;
12068     unsigned int i;
12069     ext2_ino_t ino = 1;
12070     char *buf, *block_buf;
12071     errcode_t retval;
12072     struct ext2_inode * inode;
12073    
12074     e2fsck_use_inode_shortcuts(ctx, 1);
12075    
12076     retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12077     &buf);
12078     if (retval) {
12079     bb_error_msg(_("while allocating inode buffer"));
12080     ctx->flags |= E2F_FLAG_ABORT;
12081     return;
12082     }
12083     block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12084     "block interate buffer");
12085     for (group = 0; group < fs->group_desc_count; group++) {
12086     retval = io_channel_read_blk(fs->io,
12087     fs->group_desc[group].bg_inode_table,
12088     fs->inode_blocks_per_group, buf);
12089     if (retval) {
12090     bb_error_msg(_("while reading inode table (group %d)"),
12091     group);
12092     ctx->flags |= E2F_FLAG_ABORT;
12093     return;
12094     }
12095     inode = (struct ext2_inode *) buf;
12096     for (i=0; i < fs->super->s_inodes_per_group;
12097     i++, ino++, inode++) {
12098     ctx->stashed_ino = ino;
12099     ctx->stashed_inode = inode;
12100    
12101     if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12102     ext2fs_swap_inode(fs, inode, inode, 0);
12103    
12104     /*
12105     * Skip deleted files.
12106     */
12107     if (inode->i_links_count == 0)
12108     continue;
12109    
12110     if (LINUX_S_ISDIR(inode->i_mode) ||
12111     ((inode->i_block[EXT2_IND_BLOCK] ||
12112     inode->i_block[EXT2_DIND_BLOCK] ||
12113     inode->i_block[EXT2_TIND_BLOCK]) &&
12114     ext2fs_inode_has_valid_blocks(inode)))
12115     swap_inode_blocks(ctx, ino, block_buf, inode);
12116    
12117     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12118     return;
12119    
12120     if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12121     ext2fs_swap_inode(fs, inode, inode, 1);
12122     }
12123     retval = io_channel_write_blk(fs->io,
12124     fs->group_desc[group].bg_inode_table,
12125     fs->inode_blocks_per_group, buf);
12126     if (retval) {
12127     bb_error_msg(_("while writing inode table (group %d)"),
12128     group);
12129     ctx->flags |= E2F_FLAG_ABORT;
12130     return;
12131     }
12132     }
12133     ext2fs_free_mem(&buf);
12134     ext2fs_free_mem(&block_buf);
12135     e2fsck_use_inode_shortcuts(ctx, 0);
12136     ext2fs_flush_icache(fs);
12137     }
12138    
12139     #if defined(__powerpc__) && BB_BIG_ENDIAN
12140     /*
12141     * On the PowerPC, the big-endian variant of the ext2 filesystem
12142     * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12143     * of each word. Thus a bitmap with only bit 0 set would be, as
12144     * a string of bytes, 00 00 00 01 00 ...
12145     * To cope with this, we byte-reverse each word of a bitmap if
12146     * we have a big-endian filesystem, that is, if we are *not*
12147     * byte-swapping other word-sized numbers.
12148     */
12149     #define EXT2_BIG_ENDIAN_BITMAPS
12150     #endif
12151    
12152     #ifdef EXT2_BIG_ENDIAN_BITMAPS
12153     static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12154     {
12155     __u32 *p = (__u32 *) bmap->bitmap;
12156     int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12157    
12158     for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12159     *p = ext2fs_swab32(*p);
12160     }
12161     #endif
12162    
12163    
12164     #ifdef ENABLE_SWAPFS
12165     static void swap_filesys(e2fsck_t ctx)
12166     {
12167     ext2_filsys fs = ctx->fs;
12168     if (!(ctx->options & E2F_OPT_PREEN))
12169     printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12170    
12171     /* Byte swap */
12172    
12173     if (fs->super->s_mnt_count) {
12174     fprintf(stderr, _("%s: the filesystem must be freshly "
12175     "checked using fsck\n"
12176     "and not mounted before trying to "
12177     "byte-swap it.\n"), ctx->device_name);
12178     ctx->flags |= E2F_FLAG_ABORT;
12179     return;
12180     }
12181     if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12182     fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12183     EXT2_FLAG_SWAP_BYTES_WRITE);
12184     fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12185     } else {
12186     fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12187     fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12188     }
12189     swap_inodes(ctx);
12190     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12191     return;
12192     if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12193     fs->flags |= EXT2_FLAG_SWAP_BYTES;
12194     fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12195     EXT2_FLAG_SWAP_BYTES_WRITE);
12196    
12197     #ifdef EXT2_BIG_ENDIAN_BITMAPS
12198     e2fsck_read_bitmaps(ctx);
12199     ext2fs_swap_bitmap(fs->inode_map);
12200     ext2fs_swap_bitmap(fs->block_map);
12201     fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12202     #endif
12203     fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12204     ext2fs_flush(fs);
12205     fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12206     }
12207     #endif /* ENABLE_SWAPFS */
12208    
12209     #endif
12210    
12211     /*
12212     * util.c --- miscellaneous utilities
12213     */
12214    
12215    
12216     void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12217     const char *description)
12218     {
12219     void *ret;
12220     char buf[256];
12221    
12222     ret = malloc(size);
12223     if (!ret) {
12224     sprintf(buf, "Can't allocate %s\n", description);
12225     bb_error_msg_and_die(buf);
12226     }
12227     memset(ret, 0, size);
12228     return ret;
12229     }
12230    
12231     static char *string_copy(const char *str, int len)
12232     {
12233     char *ret;
12234    
12235     if (!str)
12236     return NULL;
12237     if (!len)
12238     len = strlen(str);
12239     ret = malloc(len+1);
12240     if (ret) {
12241     strncpy(ret, str, len);
12242     ret[len] = 0;
12243     }
12244     return ret;
12245     }
12246    
12247     #ifndef HAVE_CONIO_H
12248     static int read_a_char(void)
12249     {
12250     char c;
12251     int r;
12252     int fail = 0;
12253    
12254 niro 816 while (1) {
12255 niro 532 if (e2fsck_global_ctx &&
12256     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12257     return 3;
12258     }
12259     r = read(0, &c, 1);
12260     if (r == 1)
12261     return c;
12262     if (fail++ > 100)
12263     break;
12264     }
12265     return EOF;
12266     }
12267     #endif
12268    
12269     static int ask_yn(const char * string, int def)
12270     {
12271     int c;
12272     const char *defstr;
12273     static const char short_yes[] = "yY";
12274     static const char short_no[] = "nN";
12275    
12276     #ifdef HAVE_TERMIOS_H
12277     struct termios termios, tmp;
12278    
12279     tcgetattr (0, &termios);
12280     tmp = termios;
12281     tmp.c_lflag &= ~(ICANON | ECHO);
12282     tmp.c_cc[VMIN] = 1;
12283     tmp.c_cc[VTIME] = 0;
12284 niro 816 tcsetattr_stdin_TCSANOW(&tmp);
12285 niro 532 #endif
12286    
12287     if (def == 1)
12288     defstr = "<y>";
12289     else if (def == 0)
12290     defstr = "<n>";
12291     else
12292     defstr = " (y/n)";
12293     printf("%s%s? ", string, defstr);
12294     while (1) {
12295     fflush (stdout);
12296     if ((c = read_a_char()) == EOF)
12297     break;
12298     if (c == 3) {
12299     #ifdef HAVE_TERMIOS_H
12300 niro 816 tcsetattr_stdin_TCSANOW(&termios);
12301 niro 532 #endif
12302     if (e2fsck_global_ctx &&
12303     e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12304     puts("\n");
12305     longjmp(e2fsck_global_ctx->abort_loc, 1);
12306     }
12307     puts(_("cancelled!\n"));
12308     return 0;
12309     }
12310     if (strchr(short_yes, (char) c)) {
12311     def = 1;
12312     break;
12313     }
12314     else if (strchr(short_no, (char) c)) {
12315     def = 0;
12316     break;
12317     }
12318     else if ((c == ' ' || c == '\n') && (def != -1))
12319     break;
12320     }
12321     if (def)
12322     puts("yes\n");
12323     else
12324     puts ("no\n");
12325     #ifdef HAVE_TERMIOS_H
12326 niro 816 tcsetattr_stdin_TCSANOW(&termios);
12327 niro 532 #endif
12328     return def;
12329     }
12330    
12331     int ask (e2fsck_t ctx, const char * string, int def)
12332     {
12333     if (ctx->options & E2F_OPT_NO) {
12334     printf(_("%s? no\n\n"), string);
12335     return 0;
12336     }
12337     if (ctx->options & E2F_OPT_YES) {
12338     printf(_("%s? yes\n\n"), string);
12339     return 1;
12340     }
12341     if (ctx->options & E2F_OPT_PREEN) {
12342     printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12343     return def;
12344     }
12345     return ask_yn(string, def);
12346     }
12347    
12348     void e2fsck_read_bitmaps(e2fsck_t ctx)
12349     {
12350     ext2_filsys fs = ctx->fs;
12351     errcode_t retval;
12352    
12353     if (ctx->invalid_bitmaps) {
12354     bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12355     ctx->device_name);
12356     bb_error_msg_and_die(0);
12357     }
12358    
12359     ehandler_operation(_("reading inode and block bitmaps"));
12360     retval = ext2fs_read_bitmaps(fs);
12361     ehandler_operation(0);
12362     if (retval) {
12363     bb_error_msg(_("while retrying to read bitmaps for %s"),
12364     ctx->device_name);
12365     bb_error_msg_and_die(0);
12366     }
12367     }
12368    
12369     static void e2fsck_write_bitmaps(e2fsck_t ctx)
12370     {
12371     ext2_filsys fs = ctx->fs;
12372     errcode_t retval;
12373    
12374     if (ext2fs_test_bb_dirty(fs)) {
12375     ehandler_operation(_("writing block bitmaps"));
12376     retval = ext2fs_write_block_bitmap(fs);
12377     ehandler_operation(0);
12378     if (retval) {
12379     bb_error_msg(_("while retrying to write block bitmaps for %s"),
12380     ctx->device_name);
12381     bb_error_msg_and_die(0);
12382     }
12383     }
12384    
12385     if (ext2fs_test_ib_dirty(fs)) {
12386     ehandler_operation(_("writing inode bitmaps"));
12387     retval = ext2fs_write_inode_bitmap(fs);
12388     ehandler_operation(0);
12389     if (retval) {
12390     bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12391     ctx->device_name);
12392     bb_error_msg_and_die(0);
12393     }
12394     }
12395     }
12396    
12397     void preenhalt(e2fsck_t ctx)
12398     {
12399     ext2_filsys fs = ctx->fs;
12400    
12401     if (!(ctx->options & E2F_OPT_PREEN))
12402     return;
12403     fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12404     "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12405     ctx->device_name);
12406     if (fs != NULL) {
12407     fs->super->s_state |= EXT2_ERROR_FS;
12408     ext2fs_mark_super_dirty(fs);
12409     ext2fs_close(fs);
12410     }
12411     exit(EXIT_UNCORRECTED);
12412     }
12413    
12414     void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12415     struct ext2_inode * inode, const char *proc)
12416     {
12417     int retval;
12418    
12419     retval = ext2fs_read_inode(ctx->fs, ino, inode);
12420     if (retval) {
12421     bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12422     bb_error_msg_and_die(0);
12423     }
12424     }
12425    
12426     extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12427     struct ext2_inode * inode, int bufsize,
12428     const char *proc)
12429     {
12430     int retval;
12431    
12432     retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12433     if (retval) {
12434     bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12435     bb_error_msg_and_die(0);
12436     }
12437     }
12438    
12439     extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12440     struct ext2_inode * inode, const char *proc)
12441     {
12442     int retval;
12443    
12444     retval = ext2fs_write_inode(ctx->fs, ino, inode);
12445     if (retval) {
12446     bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12447     bb_error_msg_and_die(0);
12448     }
12449     }
12450    
12451     blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12452     io_manager manager)
12453     {
12454     struct ext2_super_block *sb;
12455     io_channel io = NULL;
12456     void *buf = NULL;
12457     int blocksize;
12458     blk_t superblock, ret_sb = 8193;
12459    
12460     if (fs && fs->super) {
12461     ret_sb = (fs->super->s_blocks_per_group +
12462     fs->super->s_first_data_block);
12463     if (ctx) {
12464     ctx->superblock = ret_sb;
12465     ctx->blocksize = fs->blocksize;
12466     }
12467     return ret_sb;
12468     }
12469    
12470     if (ctx) {
12471     if (ctx->blocksize) {
12472     ret_sb = ctx->blocksize * 8;
12473     if (ctx->blocksize == 1024)
12474     ret_sb++;
12475     ctx->superblock = ret_sb;
12476     return ret_sb;
12477     }
12478     ctx->superblock = ret_sb;
12479     ctx->blocksize = 1024;
12480     }
12481    
12482     if (!name || !manager)
12483     goto cleanup;
12484    
12485     if (manager->open(name, 0, &io) != 0)
12486     goto cleanup;
12487    
12488     if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12489     goto cleanup;
12490     sb = (struct ext2_super_block *) buf;
12491    
12492     for (blocksize = EXT2_MIN_BLOCK_SIZE;
12493 niro 816 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12494 niro 532 superblock = blocksize*8;
12495     if (blocksize == 1024)
12496     superblock++;
12497     io_channel_set_blksize(io, blocksize);
12498     if (io_channel_read_blk(io, superblock,
12499     -SUPERBLOCK_SIZE, buf))
12500     continue;
12501     #if BB_BIG_ENDIAN
12502     if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12503     ext2fs_swap_super(sb);
12504     #endif
12505     if (sb->s_magic == EXT2_SUPER_MAGIC) {
12506     ret_sb = superblock;
12507     if (ctx) {
12508     ctx->superblock = superblock;
12509     ctx->blocksize = blocksize;
12510     }
12511     break;
12512     }
12513     }
12514    
12515     cleanup:
12516     if (io)
12517     io_channel_close(io);
12518     ext2fs_free_mem(&buf);
12519     return ret_sb;
12520     }
12521    
12522    
12523     /*
12524     * This function runs through the e2fsck passes and calls them all,
12525     * returning restart, abort, or cancel as necessary...
12526     */
12527     typedef void (*pass_t)(e2fsck_t ctx);
12528    
12529     static const pass_t e2fsck_passes[] = {
12530     e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12531     e2fsck_pass5, 0 };
12532    
12533     #define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12534    
12535     static int e2fsck_run(e2fsck_t ctx)
12536     {
12537     int i;
12538     pass_t e2fsck_pass;
12539    
12540     if (setjmp(ctx->abort_loc)) {
12541     ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12542     return (ctx->flags & E2F_FLAG_RUN_RETURN);
12543     }
12544     ctx->flags |= E2F_FLAG_SETJMP_OK;
12545    
12546     for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12547     if (ctx->flags & E2F_FLAG_RUN_RETURN)
12548     break;
12549     e2fsck_pass(ctx);
12550     if (ctx->progress)
12551     (void) (ctx->progress)(ctx, 0, 0, 0);
12552     }
12553     ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12554    
12555     if (ctx->flags & E2F_FLAG_RUN_RETURN)
12556     return (ctx->flags & E2F_FLAG_RUN_RETURN);
12557     return 0;
12558     }
12559    
12560    
12561     /*
12562     * unix.c - The unix-specific code for e2fsck
12563     */
12564    
12565    
12566     /* Command line options */
12567     static int swapfs;
12568     #ifdef ENABLE_SWAPFS
12569     static int normalize_swapfs;
12570     #endif
12571     static int cflag; /* check disk */
12572     static int show_version_only;
12573     static int verbose;
12574    
12575     #define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12576    
12577     static void show_stats(e2fsck_t ctx)
12578     {
12579     ext2_filsys fs = ctx->fs;
12580     int inodes, inodes_used, blocks, blocks_used;
12581     int dir_links;
12582     int num_files, num_links;
12583     int frag_percent;
12584    
12585     dir_links = 2 * ctx->fs_directory_count - 1;
12586     num_files = ctx->fs_total_count - dir_links;
12587     num_links = ctx->fs_links_count - dir_links;
12588     inodes = fs->super->s_inodes_count;
12589     inodes_used = (fs->super->s_inodes_count -
12590     fs->super->s_free_inodes_count);
12591     blocks = fs->super->s_blocks_count;
12592     blocks_used = (fs->super->s_blocks_count -
12593     fs->super->s_free_blocks_count);
12594    
12595     frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12596     frag_percent = (frag_percent + 5) / 10;
12597    
12598     if (!verbose) {
12599     printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12600     ctx->device_name, inodes_used, inodes,
12601     frag_percent / 10, frag_percent % 10,
12602     blocks_used, blocks);
12603     return;
12604     }
12605     printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12606     100 * inodes_used / inodes);
12607     printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12608     P_E2("", "s", ctx->fs_fragmented),
12609     frag_percent / 10, frag_percent % 10);
12610     printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12611     ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12612     printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12613     (int) ((long long) 100 * blocks_used / blocks));
12614     printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12615     printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12616     printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12617     printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12618     printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12619     printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12620     printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12621     printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12622     printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12623     printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12624     printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12625     }
12626    
12627     static void check_mount(e2fsck_t ctx)
12628     {
12629     errcode_t retval;
12630     int cont;
12631    
12632     retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12633     &ctx->mount_flags);
12634     if (retval) {
12635     bb_error_msg(_("while determining whether %s is mounted."),
12636     ctx->filesystem_name);
12637     return;
12638     }
12639    
12640     /*
12641     * If the filesystem isn't mounted, or it's the root filesystem
12642     * and it's mounted read-only, then everything's fine.
12643     */
12644     if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12645     ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12646     (ctx->mount_flags & EXT2_MF_READONLY)))
12647     return;
12648    
12649     if (ctx->options & E2F_OPT_READONLY) {
12650     printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12651     return;
12652     }
12653    
12654     printf(_("%s is mounted. "), ctx->filesystem_name);
12655     if (!ctx->interactive)
12656     bb_error_msg_and_die(_("Cannot continue, aborting."));
12657     printf(_("\n\n\007\007\007\007WARNING!!! "
12658     "Running e2fsck on a mounted filesystem may cause\n"
12659     "SEVERE filesystem damage.\007\007\007\n\n"));
12660     cont = ask_yn(_("Do you really want to continue"), -1);
12661     if (!cont) {
12662     printf(_("check aborted.\n"));
12663 niro 816 exit(0);
12664 niro 532 }
12665     }
12666    
12667     static int is_on_batt(void)
12668     {
12669     FILE *f;
12670     DIR *d;
12671     char tmp[80], tmp2[80], fname[80];
12672     unsigned int acflag;
12673     struct dirent* de;
12674    
12675 niro 816 f = fopen_for_read("/proc/apm");
12676 niro 532 if (f) {
12677     if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12678     acflag = 1;
12679     fclose(f);
12680     return (acflag != 1);
12681     }
12682     d = opendir("/proc/acpi/ac_adapter");
12683     if (d) {
12684     while ((de=readdir(d)) != NULL) {
12685     if (!strncmp(".", de->d_name, 1))
12686     continue;
12687     snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12688     de->d_name);
12689 niro 816 f = fopen_for_read(fname);
12690 niro 532 if (!f)
12691     continue;
12692     if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12693     tmp[0] = 0;
12694     fclose(f);
12695     if (strncmp(tmp, "off-line", 8) == 0) {
12696     closedir(d);
12697     return 1;
12698     }
12699     }
12700     closedir(d);
12701     }
12702     return 0;
12703     }
12704    
12705     /*
12706     * This routine checks to see if a filesystem can be skipped; if so,
12707     * it will exit with EXIT_OK. Under some conditions it will print a
12708     * message explaining why a check is being forced.
12709     */
12710     static void check_if_skip(e2fsck_t ctx)
12711     {
12712     ext2_filsys fs = ctx->fs;
12713     const char *reason = NULL;
12714     unsigned int reason_arg = 0;
12715     long next_check;
12716     int batt = is_on_batt();
12717     time_t now = time(0);
12718    
12719     if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12720     return;
12721    
12722     if ((fs->super->s_state & EXT2_ERROR_FS) ||
12723     !ext2fs_test_valid(fs))
12724     reason = _(" contains a file system with errors");
12725     else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12726     reason = _(" was not cleanly unmounted");
12727     else if ((fs->super->s_max_mnt_count > 0) &&
12728     (fs->super->s_mnt_count >=
12729     (unsigned) fs->super->s_max_mnt_count)) {
12730     reason = _(" has been mounted %u times without being checked");
12731     reason_arg = fs->super->s_mnt_count;
12732     if (batt && (fs->super->s_mnt_count <
12733     (unsigned) fs->super->s_max_mnt_count*2))
12734     reason = 0;
12735     } else if (fs->super->s_checkinterval &&
12736     ((now - fs->super->s_lastcheck) >=
12737     fs->super->s_checkinterval)) {
12738     reason = _(" has gone %u days without being checked");
12739     reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12740     if (batt && ((now - fs->super->s_lastcheck) <
12741     fs->super->s_checkinterval*2))
12742     reason = 0;
12743     }
12744     if (reason) {
12745     fputs(ctx->device_name, stdout);
12746     printf(reason, reason_arg);
12747     fputs(_(", check forced.\n"), stdout);
12748     return;
12749     }
12750     printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12751     fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12752     fs->super->s_inodes_count,
12753     fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12754     fs->super->s_blocks_count);
12755     next_check = 100000;
12756     if (fs->super->s_max_mnt_count > 0) {
12757     next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12758     if (next_check <= 0)
12759     next_check = 1;
12760     }
12761     if (fs->super->s_checkinterval &&
12762     ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12763     next_check = 1;
12764     if (next_check <= 5) {
12765     if (next_check == 1)
12766     fputs(_(" (check after next mount)"), stdout);
12767     else
12768     printf(_(" (check in %ld mounts)"), next_check);
12769     }
12770 niro 816 bb_putchar('\n');
12771 niro 532 ext2fs_close(fs);
12772     ctx->fs = NULL;
12773     e2fsck_free_context(ctx);
12774     exit(EXIT_OK);
12775     }
12776    
12777     /*
12778     * For completion notice
12779     */
12780     struct percent_tbl {
12781     int max_pass;
12782     int table[32];
12783     };
12784     static const struct percent_tbl e2fsck_tbl = {
12785     5, { 0, 70, 90, 92, 95, 100 }
12786     };
12787    
12788     static char bar[128], spaces[128];
12789    
12790     static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12791     int max)
12792     {
12793     float percent;
12794    
12795     if (pass <= 0)
12796     return 0.0;
12797     if (pass > tbl->max_pass || max == 0)
12798     return 100.0;
12799     percent = ((float) curr) / ((float) max);
12800     return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12801     + tbl->table[pass-1]);
12802     }
12803    
12804     void e2fsck_clear_progbar(e2fsck_t ctx)
12805     {
12806     if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12807     return;
12808    
12809     printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12810     ctx->stop_meta);
12811     fflush(stdout);
12812     ctx->flags &= ~E2F_FLAG_PROG_BAR;
12813     }
12814    
12815     int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12816     unsigned int dpynum)
12817     {
12818     static const char spinner[] = "\\|/-";
12819     int i;
12820     unsigned int tick;
12821     struct timeval tv;
12822     int dpywidth;
12823     int fixed_percent;
12824    
12825     if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12826     return 0;
12827    
12828     /*
12829     * Calculate the new progress position. If the
12830     * percentage hasn't changed, then we skip out right
12831     * away.
12832     */
12833     fixed_percent = (int) ((10 * percent) + 0.5);
12834     if (ctx->progress_last_percent == fixed_percent)
12835     return 0;
12836     ctx->progress_last_percent = fixed_percent;
12837    
12838     /*
12839     * If we've already updated the spinner once within
12840     * the last 1/8th of a second, no point doing it
12841     * again.
12842     */
12843     gettimeofday(&tv, NULL);
12844     tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12845     if ((tick == ctx->progress_last_time) &&
12846     (fixed_percent != 0) && (fixed_percent != 1000))
12847     return 0;
12848     ctx->progress_last_time = tick;
12849    
12850     /*
12851     * Advance the spinner, and note that the progress bar
12852     * will be on the screen
12853     */
12854     ctx->progress_pos = (ctx->progress_pos+1) & 3;
12855     ctx->flags |= E2F_FLAG_PROG_BAR;
12856    
12857     dpywidth = 66 - strlen(label);
12858     dpywidth = 8 * (dpywidth / 8);
12859     if (dpynum)
12860     dpywidth -= 8;
12861    
12862     i = ((percent * dpywidth) + 50) / 100;
12863     printf("%s%s: |%s%s", ctx->start_meta, label,
12864     bar + (sizeof(bar) - (i+1)),
12865     spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12866     if (fixed_percent == 1000)
12867 niro 816 bb_putchar('|');
12868 niro 532 else
12869 niro 816 bb_putchar(spinner[ctx->progress_pos & 3]);
12870 niro 532 printf(" %4.1f%% ", percent);
12871     if (dpynum)
12872     printf("%u\r", dpynum);
12873     else
12874     fputs(" \r", stdout);
12875     fputs(ctx->stop_meta, stdout);
12876    
12877     if (fixed_percent == 1000)
12878     e2fsck_clear_progbar(ctx);
12879     fflush(stdout);
12880    
12881     return 0;
12882     }
12883    
12884     static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12885     unsigned long cur, unsigned long max)
12886     {
12887     char buf[80];
12888     float percent;
12889    
12890     if (pass == 0)
12891     return 0;
12892    
12893     if (ctx->progress_fd) {
12894     sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12895     write(ctx->progress_fd, buf, strlen(buf));
12896     } else {
12897     percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12898     e2fsck_simple_progress(ctx, ctx->device_name,
12899     percent, 0);
12900     }
12901     return 0;
12902     }
12903    
12904     static void reserve_stdio_fds(void)
12905     {
12906     int fd;
12907    
12908     while (1) {
12909     fd = open(bb_dev_null, O_RDWR);
12910     if (fd > 2)
12911     break;
12912     if (fd < 0) {
12913     fprintf(stderr, _("ERROR: Cannot open "
12914     "/dev/null (%s)\n"),
12915     strerror(errno));
12916     break;
12917     }
12918     }
12919     close(fd);
12920     }
12921    
12922     static void signal_progress_on(int sig FSCK_ATTR((unused)))
12923     {
12924     e2fsck_t ctx = e2fsck_global_ctx;
12925    
12926     if (!ctx)
12927     return;
12928    
12929     ctx->progress = e2fsck_update_progress;
12930     ctx->progress_fd = 0;
12931     }
12932    
12933     static void signal_progress_off(int sig FSCK_ATTR((unused)))
12934     {
12935     e2fsck_t ctx = e2fsck_global_ctx;
12936    
12937     if (!ctx)
12938     return;
12939    
12940     e2fsck_clear_progbar(ctx);
12941     ctx->progress = 0;
12942     }
12943    
12944     static void signal_cancel(int sig FSCK_ATTR((unused)))
12945     {
12946     e2fsck_t ctx = e2fsck_global_ctx;
12947    
12948     if (!ctx)
12949     exit(FSCK_CANCELED);
12950    
12951     ctx->flags |= E2F_FLAG_CANCEL;
12952     }
12953    
12954     static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12955     {
12956     char *buf, *token, *next, *p, *arg;
12957     int ea_ver;
12958     int extended_usage = 0;
12959    
12960     buf = string_copy(opts, 0);
12961     for (token = buf; token && *token; token = next) {
12962     p = strchr(token, ',');
12963     next = 0;
12964     if (p) {
12965     *p = 0;
12966     next = p+1;
12967     }
12968     arg = strchr(token, '=');
12969     if (arg) {
12970     *arg = 0;
12971     arg++;
12972     }
12973     if (strcmp(token, "ea_ver") == 0) {
12974     if (!arg) {
12975     extended_usage++;
12976     continue;
12977     }
12978     ea_ver = strtoul(arg, &p, 0);
12979     if (*p ||
12980     ((ea_ver != 1) && (ea_ver != 2))) {
12981     fprintf(stderr,
12982     _("Invalid EA version.\n"));
12983     extended_usage++;
12984     continue;
12985     }
12986     ctx->ext_attr_ver = ea_ver;
12987     } else {
12988     fprintf(stderr, _("Unknown extended option: %s\n"),
12989     token);
12990     extended_usage++;
12991     }
12992     }
12993     if (extended_usage) {
12994     bb_error_msg_and_die(
12995     "Extended options are separated by commas, "
12996     "and may take an argument which\n"
12997     "is set off by an equals ('=') sign. "
12998     "Valid extended options are:\n"
12999     "\tea_ver=<ea_version (1 or 2)>\n\n");
13000     }
13001     }
13002    
13003    
13004 niro 816 static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
13005 niro 532 {
13006     int flush = 0;
13007     int c, fd;
13008     e2fsck_t ctx;
13009     errcode_t retval;
13010     struct sigaction sa;
13011     char *extended_opts = 0;
13012    
13013     retval = e2fsck_allocate_context(&ctx);
13014     if (retval)
13015     return retval;
13016    
13017     *ret_ctx = ctx;
13018    
13019     setvbuf(stdout, NULL, _IONBF, BUFSIZ);
13020     setvbuf(stderr, NULL, _IONBF, BUFSIZ);
13021     if (isatty(0) && isatty(1)) {
13022     ctx->interactive = 1;
13023     } else {
13024     ctx->start_meta[0] = '\001';
13025     ctx->stop_meta[0] = '\002';
13026     }
13027     memset(bar, '=', sizeof(bar)-1);
13028     memset(spaces, ' ', sizeof(spaces)-1);
13029     blkid_get_cache(&ctx->blkid, NULL);
13030    
13031     if (argc && *argv)
13032     ctx->program_name = *argv;
13033     else
13034     ctx->program_name = "e2fsck";
13035     while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13036     switch (c) {
13037     case 'C':
13038     ctx->progress = e2fsck_update_progress;
13039     ctx->progress_fd = atoi(optarg);
13040     if (!ctx->progress_fd)
13041     break;
13042     /* Validate the file descriptor to avoid disasters */
13043     fd = dup(ctx->progress_fd);
13044     if (fd < 0) {
13045     fprintf(stderr,
13046     _("Error validating file descriptor %d: %s\n"),
13047     ctx->progress_fd,
13048     error_message(errno));
13049     bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13050     } else
13051     close(fd);
13052     break;
13053     case 'D':
13054     ctx->options |= E2F_OPT_COMPRESS_DIRS;
13055     break;
13056     case 'E':
13057     extended_opts = optarg;
13058     break;
13059     case 'p':
13060     case 'a':
13061     if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13062     conflict_opt:
13063     bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
13064     }
13065     ctx->options |= E2F_OPT_PREEN;
13066     break;
13067     case 'n':
13068     if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13069     goto conflict_opt;
13070     ctx->options |= E2F_OPT_NO;
13071     break;
13072     case 'y':
13073     if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13074     goto conflict_opt;
13075     ctx->options |= E2F_OPT_YES;
13076     break;
13077     case 't':
13078     /* FIXME - This needs to go away in a future path - will change binary */
13079     fprintf(stderr, _("The -t option is not "
13080     "supported on this version of e2fsck.\n"));
13081     break;
13082     case 'c':
13083     if (cflag++)
13084     ctx->options |= E2F_OPT_WRITECHECK;
13085     ctx->options |= E2F_OPT_CHECKBLOCKS;
13086     break;
13087     case 'r':
13088     /* What we do by default, anyway! */
13089     break;
13090     case 'b':
13091     ctx->use_superblock = atoi(optarg);
13092     ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13093     break;
13094     case 'B':
13095     ctx->blocksize = atoi(optarg);
13096     break;
13097     case 'I':
13098     ctx->inode_buffer_blocks = atoi(optarg);
13099     break;
13100     case 'j':
13101     ctx->journal_name = string_copy(optarg, 0);
13102     break;
13103     case 'P':
13104     ctx->process_inode_size = atoi(optarg);
13105     break;
13106     case 'd':
13107     ctx->options |= E2F_OPT_DEBUG;
13108     break;
13109     case 'f':
13110     ctx->options |= E2F_OPT_FORCE;
13111     break;
13112     case 'F':
13113     flush = 1;
13114     break;
13115     case 'v':
13116     verbose = 1;
13117     break;
13118     case 'V':
13119     show_version_only = 1;
13120     break;
13121     case 'N':
13122     ctx->device_name = optarg;
13123     break;
13124     #ifdef ENABLE_SWAPFS
13125     case 's':
13126     normalize_swapfs = 1;
13127     case 'S':
13128     swapfs = 1;
13129     break;
13130     #else
13131     case 's':
13132     case 'S':
13133     fprintf(stderr, _("Byte-swapping filesystems "
13134     "not compiled in this version "
13135     "of e2fsck\n"));
13136     exit(1);
13137     #endif
13138     default:
13139     bb_show_usage();
13140     }
13141     if (show_version_only)
13142     return 0;
13143     if (optind != argc - 1)
13144     bb_show_usage();
13145     if ((ctx->options & E2F_OPT_NO) &&
13146     !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13147     ctx->options |= E2F_OPT_READONLY;
13148     ctx->io_options = strchr(argv[optind], '?');
13149     if (ctx->io_options)
13150     *ctx->io_options++ = 0;
13151     ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13152     if (!ctx->filesystem_name) {
13153     bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13154     bb_error_msg_and_die(0);
13155     }
13156     if (extended_opts)
13157     parse_extended_opts(ctx, extended_opts);
13158    
13159     if (flush) {
13160     fd = open(ctx->filesystem_name, O_RDONLY, 0);
13161     if (fd < 0) {
13162     bb_error_msg(_("while opening %s for flushing"),
13163     ctx->filesystem_name);
13164     bb_error_msg_and_die(0);
13165     }
13166     if ((retval = ext2fs_sync_device(fd, 1))) {
13167     bb_error_msg(_("while trying to flush %s"),
13168     ctx->filesystem_name);
13169     bb_error_msg_and_die(0);
13170     }
13171     close(fd);
13172     }
13173     #ifdef ENABLE_SWAPFS
13174     if (swapfs && cflag) {
13175     fprintf(stderr, _("Incompatible options not "
13176     "allowed when byte-swapping.\n"));
13177     exit(EXIT_USAGE);
13178     }
13179     #endif
13180     /*
13181     * Set up signal action
13182     */
13183     memset(&sa, 0, sizeof(struct sigaction));
13184     sa.sa_handler = signal_cancel;
13185     sigaction(SIGINT, &sa, 0);
13186     sigaction(SIGTERM, &sa, 0);
13187     #ifdef SA_RESTART
13188     sa.sa_flags = SA_RESTART;
13189     #endif
13190     e2fsck_global_ctx = ctx;
13191     sa.sa_handler = signal_progress_on;
13192     sigaction(SIGUSR1, &sa, 0);
13193     sa.sa_handler = signal_progress_off;
13194     sigaction(SIGUSR2, &sa, 0);
13195    
13196     /* Update our PATH to include /sbin if we need to run badblocks */
13197     if (cflag)
13198     e2fs_set_sbin_path();
13199     return 0;
13200     }
13201    
13202     static const char my_ver_string[] = E2FSPROGS_VERSION;
13203     static const char my_ver_date[] = E2FSPROGS_DATE;
13204    
13205 niro 816 int e2fsck_main (int argc, char **argv);
13206     int e2fsck_main (int argc, char **argv)
13207 niro 532 {
13208     errcode_t retval;
13209     int exit_value = EXIT_OK;
13210     ext2_filsys fs = 0;
13211     io_manager io_ptr;
13212     struct ext2_super_block *sb;
13213     const char *lib_ver_date;
13214     int my_ver, lib_ver;
13215     e2fsck_t ctx;
13216     struct problem_context pctx;
13217     int flags, run_result;
13218    
13219     clear_problem_context(&pctx);
13220    
13221     my_ver = ext2fs_parse_version_string(my_ver_string);
13222     lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13223     if (my_ver > lib_ver) {
13224     fprintf( stderr, _("Error: ext2fs library version "
13225     "out of date!\n"));
13226     show_version_only++;
13227     }
13228    
13229     retval = PRS(argc, argv, &ctx);
13230     if (retval) {
13231     bb_error_msg(_("while trying to initialize program"));
13232     exit(EXIT_ERROR);
13233     }
13234     reserve_stdio_fds();
13235    
13236     if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13237     fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13238     my_ver_date);
13239    
13240     if (show_version_only) {
13241     fprintf(stderr, _("\tUsing %s, %s\n"),
13242     error_message(EXT2_ET_BASE), lib_ver_date);
13243     exit(EXIT_OK);
13244     }
13245    
13246     check_mount(ctx);
13247    
13248     if (!(ctx->options & E2F_OPT_PREEN) &&
13249     !(ctx->options & E2F_OPT_NO) &&
13250     !(ctx->options & E2F_OPT_YES)) {
13251     if (!ctx->interactive)
13252     bb_error_msg_and_die(_("need terminal for interactive repairs"));
13253     }
13254     ctx->superblock = ctx->use_superblock;
13255     restart:
13256     #ifdef CONFIG_TESTIO_DEBUG
13257     io_ptr = test_io_manager;
13258     test_io_backing_manager = unix_io_manager;
13259     #else
13260     io_ptr = unix_io_manager;
13261     #endif
13262     flags = 0;
13263     if ((ctx->options & E2F_OPT_READONLY) == 0)
13264     flags |= EXT2_FLAG_RW;
13265    
13266     if (ctx->superblock && ctx->blocksize) {
13267     retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13268     flags, ctx->superblock, ctx->blocksize,
13269     io_ptr, &fs);
13270     } else if (ctx->superblock) {
13271     int blocksize;
13272     for (blocksize = EXT2_MIN_BLOCK_SIZE;
13273     blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13274     retval = ext2fs_open2(ctx->filesystem_name,
13275     ctx->io_options, flags,
13276     ctx->superblock, blocksize,
13277     io_ptr, &fs);
13278     if (!retval)
13279     break;
13280     }
13281     } else
13282     retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13283     flags, 0, 0, io_ptr, &fs);
13284     if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13285     !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13286     ((retval == EXT2_ET_BAD_MAGIC) ||
13287     ((retval == 0) && ext2fs_check_desc(fs)))) {
13288     if (!fs || (fs->group_desc_count > 1)) {
13289     printf(_("%s trying backup blocks...\n"),
13290     retval ? _("Couldn't find ext2 superblock,") :
13291     _("Group descriptors look bad..."));
13292     get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13293     if (fs)
13294     ext2fs_close(fs);
13295     goto restart;
13296     }
13297     }
13298     if (retval) {
13299     bb_error_msg(_("while trying to open %s"),
13300     ctx->filesystem_name);
13301     if (retval == EXT2_ET_REV_TOO_HIGH) {
13302     printf(_("The filesystem revision is apparently "
13303     "too high for this version of e2fsck.\n"
13304     "(Or the filesystem superblock "
13305     "is corrupt)\n\n"));
13306     fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13307     } else if (retval == EXT2_ET_SHORT_READ)
13308     printf(_("Could this be a zero-length partition?\n"));
13309     else if ((retval == EPERM) || (retval == EACCES))
13310     printf(_("You must have %s access to the "
13311     "filesystem or be root\n"),
13312     (ctx->options & E2F_OPT_READONLY) ?
13313     "r/o" : "r/w");
13314     else if (retval == ENXIO)
13315     printf(_("Possibly non-existent or swap device?\n"));
13316     #ifdef EROFS
13317     else if (retval == EROFS)
13318     printf(_("Disk write-protected; use the -n option "
13319     "to do a read-only\n"
13320     "check of the device.\n"));
13321     #endif
13322     else
13323     fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13324     bb_error_msg_and_die(0);
13325     }
13326     ctx->fs = fs;
13327     fs->priv_data = ctx;
13328     sb = fs->super;
13329     if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13330     bb_error_msg(_("while trying to open %s"),
13331     ctx->filesystem_name);
13332     get_newer:
13333     bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13334     }
13335    
13336     /*
13337     * Set the device name, which is used whenever we print error
13338     * or informational messages to the user.
13339     */
13340     if (ctx->device_name == 0 &&
13341     (sb->s_volume_name[0] != 0)) {
13342     ctx->device_name = string_copy(sb->s_volume_name,
13343     sizeof(sb->s_volume_name));
13344     }
13345     if (ctx->device_name == 0)
13346     ctx->device_name = ctx->filesystem_name;
13347    
13348     /*
13349     * Make sure the ext3 superblock fields are consistent.
13350     */
13351     retval = e2fsck_check_ext3_journal(ctx);
13352     if (retval) {
13353     bb_error_msg(_("while checking ext3 journal for %s"),
13354     ctx->device_name);
13355     bb_error_msg_and_die(0);
13356     }
13357    
13358     /*
13359     * Check to see if we need to do ext3-style recovery. If so,
13360     * do it, and then restart the fsck.
13361     */
13362     if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13363     if (ctx->options & E2F_OPT_READONLY) {
13364     printf(_("Warning: skipping journal recovery "
13365     "because doing a read-only filesystem "
13366     "check.\n"));
13367     io_channel_flush(ctx->fs->io);
13368     } else {
13369     if (ctx->flags & E2F_FLAG_RESTARTED) {
13370     /*
13371     * Whoops, we attempted to run the
13372     * journal twice. This should never
13373     * happen, unless the hardware or
13374     * device driver is being bogus.
13375     */
13376     bb_error_msg(_("cannot set superblock flags on %s"), ctx->device_name);
13377     bb_error_msg_and_die(0);
13378     }
13379     retval = e2fsck_run_ext3_journal(ctx);
13380     if (retval) {
13381     bb_error_msg(_("while recovering ext3 journal of %s"),
13382     ctx->device_name);
13383     bb_error_msg_and_die(0);
13384     }
13385     ext2fs_close(ctx->fs);
13386     ctx->fs = 0;
13387     ctx->flags |= E2F_FLAG_RESTARTED;
13388     goto restart;
13389     }
13390     }
13391    
13392     /*
13393     * Check for compatibility with the feature sets. We need to
13394     * be more stringent than ext2fs_open().
13395     */
13396     if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13397     (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13398     bb_error_msg("(%s)", ctx->device_name);
13399     goto get_newer;
13400     }
13401     if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13402     bb_error_msg("(%s)", ctx->device_name);
13403     goto get_newer;
13404     }
13405     #ifdef ENABLE_COMPRESSION
13406     /* FIXME - do we support this at all? */
13407     if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13408     bb_error_msg(_("Warning: compression support is experimental."));
13409     #endif
13410     #ifndef ENABLE_HTREE
13411     if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13412     bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13413     "but filesystem %s has HTREE directories."),
13414     ctx->device_name);
13415     goto get_newer;
13416     }
13417     #endif
13418    
13419     /*
13420     * If the user specified a specific superblock, presumably the
13421     * master superblock has been trashed. So we mark the
13422     * superblock as dirty, so it can be written out.
13423     */
13424     if (ctx->superblock &&
13425     !(ctx->options & E2F_OPT_READONLY))
13426     ext2fs_mark_super_dirty(fs);
13427    
13428     /*
13429     * We only update the master superblock because (a) paranoia;
13430     * we don't want to corrupt the backup superblocks, and (b) we
13431     * don't need to update the mount count and last checked
13432     * fields in the backup superblock (the kernel doesn't
13433     * update the backup superblocks anyway).
13434     */
13435     fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13436    
13437     ehandler_init(fs->io);
13438    
13439     if (ctx->superblock)
13440     set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13441     ext2fs_mark_valid(fs);
13442     check_super_block(ctx);
13443     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13444     bb_error_msg_and_die(0);
13445     check_if_skip(ctx);
13446     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13447     bb_error_msg_and_die(0);
13448     #ifdef ENABLE_SWAPFS
13449    
13450     #ifdef WORDS_BIGENDIAN
13451     #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13452     #else
13453     #define NATIVE_FLAG 0
13454     #endif
13455    
13456    
13457     if (normalize_swapfs) {
13458     if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13459     fprintf(stderr, _("%s: Filesystem byte order "
13460     "already normalized.\n"), ctx->device_name);
13461     bb_error_msg_and_die(0);
13462     }
13463     }
13464     if (swapfs) {
13465     swap_filesys(ctx);
13466     if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13467     bb_error_msg_and_die(0);
13468     }
13469     #endif
13470    
13471     /*
13472     * Mark the system as valid, 'til proven otherwise
13473     */
13474     ext2fs_mark_valid(fs);
13475    
13476     retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13477     if (retval) {
13478     bb_error_msg(_("while reading bad blocks inode"));
13479     preenhalt(ctx);
13480     printf(_("This doesn't bode well,"
13481     " but we'll try to go on...\n"));
13482     }
13483    
13484     run_result = e2fsck_run(ctx);
13485     e2fsck_clear_progbar(ctx);
13486     if (run_result == E2F_FLAG_RESTART) {
13487     printf(_("Restarting e2fsck from the beginning...\n"));
13488     retval = e2fsck_reset_context(ctx);
13489     if (retval) {
13490     bb_error_msg(_("while resetting context"));
13491     bb_error_msg_and_die(0);
13492     }
13493     ext2fs_close(fs);
13494     goto restart;
13495     }
13496     if (run_result & E2F_FLAG_CANCEL) {
13497     printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13498     ctx->device_name : ctx->filesystem_name);
13499     exit_value |= FSCK_CANCELED;
13500     }
13501     if (run_result & E2F_FLAG_ABORT)
13502     bb_error_msg_and_die(_("aborted"));
13503    
13504     /* Cleanup */
13505     if (ext2fs_test_changed(fs)) {
13506     exit_value |= EXIT_NONDESTRUCT;
13507     if (!(ctx->options & E2F_OPT_PREEN))
13508     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13509     ctx->device_name);
13510     if (ctx->mount_flags & EXT2_MF_ISROOT) {
13511     printf(_("%s: ***** REBOOT LINUX *****\n"),
13512     ctx->device_name);
13513     exit_value |= EXIT_DESTRUCT;
13514     }
13515     }
13516     if (!ext2fs_test_valid(fs)) {
13517     printf(_("\n%s: ********** WARNING: Filesystem still has "
13518     "errors **********\n\n"), ctx->device_name);
13519     exit_value |= EXIT_UNCORRECTED;
13520     exit_value &= ~EXIT_NONDESTRUCT;
13521     }
13522     if (exit_value & FSCK_CANCELED)
13523     exit_value &= ~EXIT_NONDESTRUCT;
13524     else {
13525     show_stats(ctx);
13526     if (!(ctx->options & E2F_OPT_READONLY)) {
13527     if (ext2fs_test_valid(fs)) {
13528     if (!(sb->s_state & EXT2_VALID_FS))
13529     exit_value |= EXIT_NONDESTRUCT;
13530     sb->s_state = EXT2_VALID_FS;
13531     } else
13532     sb->s_state &= ~EXT2_VALID_FS;
13533     sb->s_mnt_count = 0;
13534     sb->s_lastcheck = time(NULL);
13535     ext2fs_mark_super_dirty(fs);
13536     }
13537     }
13538    
13539     e2fsck_write_bitmaps(ctx);
13540    
13541     ext2fs_close(fs);
13542     ctx->fs = NULL;
13543     free(ctx->filesystem_name);
13544     free(ctx->journal_name);
13545     e2fsck_free_context(ctx);
13546    
13547     return exit_value;
13548     }