blob: f58fe9286784827297244186d905f5ae3adf0368 [file] [log] [blame]
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001/* 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
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000032#include "e2fsck.h" /*Put all of our defines here to clean things up*/
33
34#define _(x) x
35#define N_(x) x
36
37/*
38 * Procedure declarations
39 */
40
41static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
42
43/* pass1.c */
44static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
45
46/* pass2.c */
47static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
48 ext2_ino_t ino, char *buf);
49
50/* pass3.c */
51static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
52static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
53 int num, int gauranteed_size);
54static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
55static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
56 int adj);
57
58/* rehash.c */
59static void e2fsck_rehash_directories(e2fsck_t ctx);
60
61/* util.c */
62static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
63 const char *description);
64static int ask(e2fsck_t ctx, const char * string, int def);
65static void e2fsck_read_bitmaps(e2fsck_t ctx);
66static void preenhalt(e2fsck_t ctx);
67static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
68 struct ext2_inode * inode, const char * proc);
69static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
70 struct ext2_inode * inode, const char * proc);
71static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
72 const char *name, io_manager manager);
73
74/* unix.c */
75static void e2fsck_clear_progbar(e2fsck_t ctx);
76static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
77 float percent, unsigned int dpynum);
78
79
80/*
81 * problem.h --- e2fsck problem error codes
82 */
83
84typedef __u32 problem_t;
85
86struct problem_context {
87 errcode_t errcode;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010088 ext2_ino_t ino, ino2, dir;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000089 struct ext2_inode *inode;
90 struct ext2_dir_entry *dirent;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010091 blk_t blk, blk2;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000092 e2_blkcnt_t blkcount;
93 int group;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010094 __u64 num;
95 const char *str;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000096};
97
98
99/*
100 * Function declarations
101 */
102static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
103static int end_problem_latch(e2fsck_t ctx, int mask);
104static int set_latch_flags(int mask, int setflags, int clearflags);
105static void clear_problem_context(struct problem_context *ctx);
106
107/*
108 * Dictionary Abstract Data Type
109 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
110 *
111 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
112 * kazlib_1_20
113 */
114
115#ifndef DICT_H
116#define DICT_H
117
118/*
119 * Blurb for inclusion into C++ translation units
120 */
121
122typedef unsigned long dictcount_t;
123#define DICTCOUNT_T_MAX ULONG_MAX
124
125/*
126 * The dictionary is implemented as a red-black tree
127 */
128
129typedef enum { dnode_red, dnode_black } dnode_color_t;
130
131typedef struct dnode_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100132 struct dnode_t *dict_left;
133 struct dnode_t *dict_right;
134 struct dnode_t *dict_parent;
135 dnode_color_t dict_color;
136 const void *dict_key;
137 void *dict_data;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000138} dnode_t;
139
140typedef int (*dict_comp_t)(const void *, const void *);
141typedef void (*dnode_free_t)(dnode_t *);
142
143typedef struct dict_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100144 dnode_t dict_nilnode;
145 dictcount_t dict_nodecount;
146 dictcount_t dict_maxcount;
147 dict_comp_t dict_compare;
148 dnode_free_t dict_freenode;
149 int dict_dupes;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000150} dict_t;
151
152typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
153
154typedef struct dict_load_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100155 dict_t *dict_dictptr;
156 dnode_t dict_nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000157} dict_load_t;
158
159#define dict_count(D) ((D)->dict_nodecount)
160#define dnode_get(N) ((N)->dict_data)
161#define dnode_getkey(N) ((N)->dict_key)
162
163#endif
164
165/*
166 * Compatibility header file for e2fsck which should be included
167 * instead of linux/jfs.h
168 *
169 * Copyright (C) 2000 Stephen C. Tweedie
170 */
171
172/*
173 * Pull in the definition of the e2fsck context structure
174 */
175
176struct buffer_head {
177 char b_data[8192];
178 e2fsck_t b_ctx;
179 io_channel b_io;
180 int b_size;
181 blk_t b_blocknr;
182 int b_dirty;
183 int b_uptodate;
184 int b_err;
185};
186
187
188#define K_DEV_FS 1
189#define K_DEV_JOURNAL 2
190
Denis Vlasenkobb045062008-09-27 14:06:06 +0000191#define lock_buffer(bh) do {} while (0)
192#define unlock_buffer(bh) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000193#define buffer_req(bh) 1
Denis Vlasenkobb045062008-09-27 14:06:06 +0000194#define do_readahead(journal, start) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000195
196static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
197
198typedef struct {
199 int object_length;
200} kmem_cache_t;
201
202#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
203
204/*
205 * We use the standard libext2fs portability tricks for inline
206 * functions.
207 */
208
209static kmem_cache_t * do_cache_create(int len)
210{
211 kmem_cache_t *new_cache;
212
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100213 new_cache = xmalloc(sizeof(*new_cache));
214 new_cache->object_length = len;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000215 return new_cache;
216}
217
218static void do_cache_destroy(kmem_cache_t *cache)
219{
220 free(cache);
221}
222
223
224/*
225 * Dictionary Abstract Data Type
226 */
227
228
229/*
230 * These macros provide short convenient names for structure members,
231 * which are embellished with dict_ prefixes so that they are
232 * properly confined to the documented namespace. It's legal for a
233 * program which uses dict to define, for instance, a macro called ``parent''.
234 * Such a macro would interfere with the dnode_t struct definition.
235 * In general, highly portable and reusable C modules which expose their
236 * structures need to confine structure member names to well-defined spaces.
237 * The resulting identifiers aren't necessarily convenient to use, nor
238 * readable, in the implementation, however!
239 */
240
241#define left dict_left
242#define right dict_right
243#define parent dict_parent
244#define color dict_color
245#define key dict_key
246#define data dict_data
247
248#define nilnode dict_nilnode
249#define maxcount dict_maxcount
250#define compare dict_compare
251#define dupes dict_dupes
252
253#define dict_root(D) ((D)->nilnode.left)
254#define dict_nil(D) (&(D)->nilnode)
255
256static void dnode_free(dnode_t *node);
257
258/*
259 * Perform a ``left rotation'' adjustment on the tree. The given node P and
260 * its right child C are rearranged so that the P instead becomes the left
261 * child of C. The left subtree of C is inherited as the new right subtree
262 * for P. The ordering of the keys within the tree is thus preserved.
263 */
264
265static void rotate_left(dnode_t *upper)
266{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100267 dnode_t *lower, *lowleft, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000268
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100269 lower = upper->right;
270 upper->right = lowleft = lower->left;
271 lowleft->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000272
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100273 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000274
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100275 /* don't need to check for root node here because root->parent is
276 the sentinel nil node, and root->parent->left points back to root */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000277
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100278 if (upper == upparent->left) {
279 upparent->left = lower;
280 } else {
281 assert (upper == upparent->right);
282 upparent->right = lower;
283 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000284
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100285 lower->left = upper;
286 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000287}
288
289/*
290 * This operation is the ``mirror'' image of rotate_left. It is
291 * the same procedure, but with left and right interchanged.
292 */
293
294static void rotate_right(dnode_t *upper)
295{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100296 dnode_t *lower, *lowright, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000297
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100298 lower = upper->left;
299 upper->left = lowright = lower->right;
300 lowright->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000301
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100302 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000303
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100304 if (upper == upparent->right) {
305 upparent->right = lower;
306 } else {
307 assert (upper == upparent->left);
308 upparent->left = lower;
309 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000310
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100311 lower->right = upper;
312 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000313}
314
315/*
316 * Do a postorder traversal of the tree rooted at the specified
317 * node and free everything under it. Used by dict_free().
318 */
319
320static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
321{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100322 if (node == nil)
323 return;
324 free_nodes(dict, node->left, nil);
325 free_nodes(dict, node->right, nil);
326 dict->dict_freenode(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000327}
328
329/*
330 * Verify that the tree contains the given node. This is done by
331 * traversing all of the nodes and comparing their pointers to the
332 * given pointer. Returns 1 if the node is found, otherwise
333 * returns zero. It is intended for debugging purposes.
334 */
335
336static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
337{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100338 if (root != nil) {
339 return root == node
340 || verify_dict_has_node(nil, root->left, node)
341 || verify_dict_has_node(nil, root->right, node);
342 }
343 return 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000344}
345
346
347/*
348 * Select a different set of node allocator routines.
349 */
350
351static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
352{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100353 assert(dict_count(dict) == 0);
354 dict->dict_freenode = fr;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000355}
356
357/*
358 * Free all the nodes in the dictionary by using the dictionary's
359 * installed free routine. The dictionary is emptied.
360 */
361
362static void dict_free_nodes(dict_t *dict)
363{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100364 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
365 free_nodes(dict, root, nil);
366 dict->dict_nodecount = 0;
367 dict->nilnode.left = &dict->nilnode;
368 dict->nilnode.right = &dict->nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000369}
370
371/*
372 * Initialize a user-supplied dictionary object.
373 */
374
375static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
376{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100377 dict->compare = comp;
378 dict->dict_freenode = dnode_free;
379 dict->dict_nodecount = 0;
380 dict->maxcount = maxcount;
381 dict->nilnode.left = &dict->nilnode;
382 dict->nilnode.right = &dict->nilnode;
383 dict->nilnode.parent = &dict->nilnode;
384 dict->nilnode.color = dnode_black;
385 dict->dupes = 0;
386 return dict;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000387}
388
389/*
390 * Locate a node in the dictionary having the given key.
391 * If the node is not found, a null a pointer is returned (rather than
392 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
393 * located node is returned.
394 */
395
396static dnode_t *dict_lookup(dict_t *dict, const void *key)
397{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100398 dnode_t *root = dict_root(dict);
399 dnode_t *nil = dict_nil(dict);
400 dnode_t *saved;
401 int result;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000402
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100403 /* simple binary search adapted for trees that contain duplicate keys */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000404
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100405 while (root != nil) {
406 result = dict->compare(key, root->key);
407 if (result < 0)
408 root = root->left;
409 else if (result > 0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000410 root = root->right;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100411 else {
412 if (!dict->dupes) { /* no duplicates, return match */
413 return root;
414 } else { /* could be dupes, find leftmost one */
415 do {
416 saved = root;
417 root = root->left;
418 while (root != nil && dict->compare(key, root->key))
419 root = root->right;
420 } while (root != nil);
421 return saved;
422 }
423 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000424 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000425
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100426 return NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000427}
428
429/*
430 * Insert a node into the dictionary. The node should have been
431 * initialized with a data field. All other fields are ignored.
432 * The behavior is undefined if the user attempts to insert into
433 * a dictionary that is already full (for which the dict_isfull()
434 * function returns true).
435 */
436
437static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
438{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100439 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
440 dnode_t *parent = nil, *uncle, *grandpa;
441 int result = -1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000442
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100443 node->key = key;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000444
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100445 /* basic binary tree insert */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000446
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100447 while (where != nil) {
448 parent = where;
449 result = dict->compare(key, where->key);
450 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
451 assert(dict->dupes || result != 0);
452 if (result < 0)
453 where = where->left;
454 else
455 where = where->right;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000456 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000457
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100458 assert(where == nil);
459
460 if (result < 0)
461 parent->left = node;
462 else
463 parent->right = node;
464
465 node->parent = parent;
466 node->left = nil;
467 node->right = nil;
468
469 dict->dict_nodecount++;
470
471 /* red black adjustments */
472
473 node->color = dnode_red;
474
475 while (parent->color == dnode_red) {
476 grandpa = parent->parent;
477 if (parent == grandpa->left) {
478 uncle = grandpa->right;
479 if (uncle->color == dnode_red) { /* red parent, red uncle */
480 parent->color = dnode_black;
481 uncle->color = dnode_black;
482 grandpa->color = dnode_red;
483 node = grandpa;
484 parent = grandpa->parent;
485 } else { /* red parent, black uncle */
486 if (node == parent->right) {
487 rotate_left(parent);
488 parent = node;
489 assert (grandpa == parent->parent);
490 /* rotation between parent and child preserves grandpa */
491 }
492 parent->color = dnode_black;
493 grandpa->color = dnode_red;
494 rotate_right(grandpa);
495 break;
496 }
497 } else { /* symmetric cases: parent == parent->parent->right */
498 uncle = grandpa->left;
499 if (uncle->color == dnode_red) {
500 parent->color = dnode_black;
501 uncle->color = dnode_black;
502 grandpa->color = dnode_red;
503 node = grandpa;
504 parent = grandpa->parent;
505 } else {
506 if (node == parent->left) {
507 rotate_right(parent);
508 parent = node;
509 assert (grandpa == parent->parent);
510 }
511 parent->color = dnode_black;
512 grandpa->color = dnode_red;
513 rotate_left(grandpa);
514 break;
515 }
516 }
517 }
518
519 dict_root(dict)->color = dnode_black;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000520}
521
522/*
523 * Allocate a node using the dictionary's allocator routine, give it
524 * the data item.
525 */
526
527static dnode_t *dnode_init(dnode_t *dnode, void *data)
528{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100529 dnode->data = data;
530 dnode->parent = NULL;
531 dnode->left = NULL;
532 dnode->right = NULL;
533 return dnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000534}
535
536static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
537{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100538 dnode_t *node = xmalloc(sizeof(dnode_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000539
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000540 dnode_init(node, data);
541 dict_insert(dict, node, key);
542 return 1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000543}
544
545/*
546 * Return the node with the lowest (leftmost) key. If the dictionary is empty
547 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
548 */
549
550static dnode_t *dict_first(dict_t *dict)
551{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100552 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000553
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100554 if (root != nil)
555 while ((left = root->left) != nil)
556 root = left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000557
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100558 return (root == nil) ? NULL : root;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000559}
560
561/*
562 * Return the given node's successor node---the node which has the
563 * next key in the the left to right ordering. If the node has
564 * no successor, a null pointer is returned rather than a pointer to
565 * the nil node.
566 */
567
568static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
569{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100570 dnode_t *nil = dict_nil(dict), *parent, *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000571
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100572 if (curr->right != nil) {
573 curr = curr->right;
574 while ((left = curr->left) != nil)
575 curr = left;
576 return curr;
577 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000578
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000579 parent = curr->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000580
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100581 while (parent != nil && curr == parent->right) {
582 curr = parent;
583 parent = curr->parent;
584 }
585
586 return (parent == nil) ? NULL : parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000587}
588
589
590static void dnode_free(dnode_t *node)
591{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100592 free(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000593}
594
595
596#undef left
597#undef right
598#undef parent
599#undef color
600#undef key
601#undef data
602
603#undef nilnode
604#undef maxcount
605#undef compare
606#undef dupes
607
608
609/*
610 * dirinfo.c --- maintains the directory information table for e2fsck.
611 */
612
613/*
614 * This subroutine is called during pass1 to create a directory info
615 * entry. During pass1, the passed-in parent is 0; it will get filled
616 * in during pass2.
617 */
618static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
619{
620 struct dir_info *dir;
621 int i, j;
622 ext2_ino_t num_dirs;
623 errcode_t retval;
624 unsigned long old_size;
625
626 if (!ctx->dir_info) {
627 ctx->dir_info_count = 0;
628 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
629 if (retval)
630 num_dirs = 1024; /* Guess */
631 ctx->dir_info_size = num_dirs + 10;
632 ctx->dir_info = (struct dir_info *)
633 e2fsck_allocate_memory(ctx, ctx->dir_info_size
634 * sizeof (struct dir_info),
635 "directory map");
636 }
637
638 if (ctx->dir_info_count >= ctx->dir_info_size) {
639 old_size = ctx->dir_info_size * sizeof(struct dir_info);
640 ctx->dir_info_size += 10;
641 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
642 sizeof(struct dir_info),
643 &ctx->dir_info);
644 if (retval) {
645 ctx->dir_info_size -= 10;
646 return;
647 }
648 }
649
650 /*
651 * Normally, add_dir_info is called with each inode in
652 * sequential order; but once in a while (like when pass 3
653 * needs to recreate the root directory or lost+found
654 * directory) it is called out of order. In those cases, we
655 * need to move the dir_info entries down to make room, since
656 * the dir_info array needs to be sorted by inode number for
657 * get_dir_info()'s sake.
658 */
659 if (ctx->dir_info_count &&
660 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
661 for (i = ctx->dir_info_count-1; i > 0; i--)
662 if (ctx->dir_info[i-1].ino < ino)
663 break;
664 dir = &ctx->dir_info[i];
665 if (dir->ino != ino)
666 for (j = ctx->dir_info_count++; j > i; j--)
667 ctx->dir_info[j] = ctx->dir_info[j-1];
668 } else
669 dir = &ctx->dir_info[ctx->dir_info_count++];
670
671 dir->ino = ino;
672 dir->dotdot = parent;
673 dir->parent = parent;
674}
675
676/*
677 * get_dir_info() --- given an inode number, try to find the directory
678 * information entry for it.
679 */
680static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
681{
682 int low, high, mid;
683
684 low = 0;
685 high = ctx->dir_info_count-1;
686 if (!ctx->dir_info)
687 return 0;
688 if (ino == ctx->dir_info[low].ino)
689 return &ctx->dir_info[low];
690 if (ino == ctx->dir_info[high].ino)
691 return &ctx->dir_info[high];
692
693 while (low < high) {
694 mid = (low+high)/2;
695 if (mid == low || mid == high)
696 break;
697 if (ino == ctx->dir_info[mid].ino)
698 return &ctx->dir_info[mid];
699 if (ino < ctx->dir_info[mid].ino)
700 high = mid;
701 else
702 low = mid;
703 }
704 return 0;
705}
706
707/*
708 * Free the dir_info structure when it isn't needed any more.
709 */
710static void e2fsck_free_dir_info(e2fsck_t ctx)
711{
712 ext2fs_free_mem(&ctx->dir_info);
713 ctx->dir_info_size = 0;
714 ctx->dir_info_count = 0;
715}
716
717/*
718 * Return the count of number of directories in the dir_info structure
719 */
720static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
721{
722 return ctx->dir_info_count;
723}
724
725/*
726 * A simple interator function
727 */
728static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
729{
730 if (*control >= ctx->dir_info_count)
731 return 0;
732
733 return ctx->dir_info + (*control)++;
734}
735
736/*
737 * dirinfo.c --- maintains the directory information table for e2fsck.
738 *
739 */
740
741#ifdef ENABLE_HTREE
742
743/*
744 * This subroutine is called during pass1 to create a directory info
745 * entry. During pass1, the passed-in parent is 0; it will get filled
746 * in during pass2.
747 */
748static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
749{
750 struct dx_dir_info *dir;
751 int i, j;
752 errcode_t retval;
753 unsigned long old_size;
754
755 if (!ctx->dx_dir_info) {
756 ctx->dx_dir_info_count = 0;
757 ctx->dx_dir_info_size = 100; /* Guess */
758 ctx->dx_dir_info = (struct dx_dir_info *)
759 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
760 * sizeof (struct dx_dir_info),
761 "directory map");
762 }
763
764 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
765 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
766 ctx->dx_dir_info_size += 10;
767 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
768 sizeof(struct dx_dir_info),
769 &ctx->dx_dir_info);
770 if (retval) {
771 ctx->dx_dir_info_size -= 10;
772 return;
773 }
774 }
775
776 /*
777 * Normally, add_dx_dir_info is called with each inode in
778 * sequential order; but once in a while (like when pass 3
779 * needs to recreate the root directory or lost+found
780 * directory) it is called out of order. In those cases, we
781 * need to move the dx_dir_info entries down to make room, since
782 * the dx_dir_info array needs to be sorted by inode number for
783 * get_dx_dir_info()'s sake.
784 */
785 if (ctx->dx_dir_info_count &&
786 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
787 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
788 if (ctx->dx_dir_info[i-1].ino < ino)
789 break;
790 dir = &ctx->dx_dir_info[i];
791 if (dir->ino != ino)
792 for (j = ctx->dx_dir_info_count++; j > i; j--)
793 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
794 } else
795 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
796
797 dir->ino = ino;
798 dir->numblocks = num_blocks;
799 dir->hashversion = 0;
800 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
801 * sizeof (struct dx_dirblock_info),
802 "dx_block info array");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000803}
804
805/*
806 * get_dx_dir_info() --- given an inode number, try to find the directory
807 * information entry for it.
808 */
809static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
810{
811 int low, high, mid;
812
813 low = 0;
814 high = ctx->dx_dir_info_count-1;
815 if (!ctx->dx_dir_info)
816 return 0;
817 if (ino == ctx->dx_dir_info[low].ino)
818 return &ctx->dx_dir_info[low];
819 if (ino == ctx->dx_dir_info[high].ino)
820 return &ctx->dx_dir_info[high];
821
822 while (low < high) {
823 mid = (low+high)/2;
824 if (mid == low || mid == high)
825 break;
826 if (ino == ctx->dx_dir_info[mid].ino)
827 return &ctx->dx_dir_info[mid];
828 if (ino < ctx->dx_dir_info[mid].ino)
829 high = mid;
830 else
831 low = mid;
832 }
833 return 0;
834}
835
836/*
837 * Free the dx_dir_info structure when it isn't needed any more.
838 */
839static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
840{
841 int i;
842 struct dx_dir_info *dir;
843
844 if (ctx->dx_dir_info) {
845 dir = ctx->dx_dir_info;
846 for (i=0; i < ctx->dx_dir_info_count; i++) {
847 ext2fs_free_mem(&dir->dx_block);
848 }
849 ext2fs_free_mem(&ctx->dx_dir_info);
850 }
851 ctx->dx_dir_info_size = 0;
852 ctx->dx_dir_info_count = 0;
853}
854
855/*
856 * A simple interator function
857 */
858static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
859{
860 if (*control >= ctx->dx_dir_info_count)
861 return 0;
862
863 return ctx->dx_dir_info + (*control)++;
864}
865
866#endif /* ENABLE_HTREE */
867/*
868 * e2fsck.c - a consistency checker for the new extended file system.
869 *
870 */
871
872/*
873 * This function allocates an e2fsck context
874 */
875static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
876{
877 e2fsck_t context;
878 errcode_t retval;
879
880 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
881 if (retval)
882 return retval;
883
884 memset(context, 0, sizeof(struct e2fsck_struct));
885
886 context->process_inode_size = 256;
887 context->ext_attr_ver = 2;
888
889 *ret = context;
890 return 0;
891}
892
893struct ea_refcount_el {
894 blk_t ea_blk;
895 int ea_count;
896};
897
898struct ea_refcount {
899 blk_t count;
900 blk_t size;
901 blk_t cursor;
902 struct ea_refcount_el *list;
903};
904
905static void ea_refcount_free(ext2_refcount_t refcount)
906{
907 if (!refcount)
908 return;
909
910 ext2fs_free_mem(&refcount->list);
911 ext2fs_free_mem(&refcount);
912}
913
914/*
915 * This function resets an e2fsck context; it is called when e2fsck
916 * needs to be restarted.
917 */
918static errcode_t e2fsck_reset_context(e2fsck_t ctx)
919{
920 ctx->flags = 0;
921 ctx->lost_and_found = 0;
922 ctx->bad_lost_and_found = 0;
923 ext2fs_free_inode_bitmap(ctx->inode_used_map);
924 ctx->inode_used_map = 0;
925 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
926 ctx->inode_dir_map = 0;
927 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
928 ctx->inode_reg_map = 0;
929 ext2fs_free_block_bitmap(ctx->block_found_map);
930 ctx->block_found_map = 0;
931 ext2fs_free_icount(ctx->inode_link_info);
932 ctx->inode_link_info = 0;
933 if (ctx->journal_io) {
934 if (ctx->fs && ctx->fs->io != ctx->journal_io)
935 io_channel_close(ctx->journal_io);
936 ctx->journal_io = 0;
937 }
938 if (ctx->fs) {
939 ext2fs_free_dblist(ctx->fs->dblist);
940 ctx->fs->dblist = 0;
941 }
942 e2fsck_free_dir_info(ctx);
943#ifdef ENABLE_HTREE
944 e2fsck_free_dx_dir_info(ctx);
945#endif
946 ea_refcount_free(ctx->refcount);
947 ctx->refcount = 0;
948 ea_refcount_free(ctx->refcount_extra);
949 ctx->refcount_extra = 0;
950 ext2fs_free_block_bitmap(ctx->block_dup_map);
951 ctx->block_dup_map = 0;
952 ext2fs_free_block_bitmap(ctx->block_ea_map);
953 ctx->block_ea_map = 0;
954 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
955 ctx->inode_bad_map = 0;
956 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
957 ctx->inode_imagic_map = 0;
958 ext2fs_u32_list_free(ctx->dirs_to_hash);
959 ctx->dirs_to_hash = 0;
960
961 /*
962 * Clear the array of invalid meta-data flags
963 */
964 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
965 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
966 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
967
968 /* Clear statistic counters */
969 ctx->fs_directory_count = 0;
970 ctx->fs_regular_count = 0;
971 ctx->fs_blockdev_count = 0;
972 ctx->fs_chardev_count = 0;
973 ctx->fs_links_count = 0;
974 ctx->fs_symlinks_count = 0;
975 ctx->fs_fast_symlinks_count = 0;
976 ctx->fs_fifo_count = 0;
977 ctx->fs_total_count = 0;
978 ctx->fs_sockets_count = 0;
979 ctx->fs_ind_count = 0;
980 ctx->fs_dind_count = 0;
981 ctx->fs_tind_count = 0;
982 ctx->fs_fragmented = 0;
983 ctx->large_files = 0;
984
985 /* Reset the superblock to the user's requested value */
986 ctx->superblock = ctx->use_superblock;
987
988 return 0;
989}
990
991static void e2fsck_free_context(e2fsck_t ctx)
992{
993 if (!ctx)
994 return;
995
996 e2fsck_reset_context(ctx);
997 if (ctx->blkid)
998 blkid_put_cache(ctx->blkid);
999
1000 ext2fs_free_mem(&ctx);
1001}
1002
1003/*
1004 * ea_refcount.c
1005 */
1006
1007/*
1008 * The strategy we use for keeping track of EA refcounts is as
1009 * follows. We keep a sorted array of first EA blocks and its
1010 * reference counts. Once the refcount has dropped to zero, it is
1011 * removed from the array to save memory space. Once the EA block is
1012 * checked, its bit is set in the block_ea_map bitmap.
1013 */
1014
1015
1016static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1017{
1018 ext2_refcount_t refcount;
1019 errcode_t retval;
1020 size_t bytes;
1021
1022 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1023 if (retval)
1024 return retval;
1025 memset(refcount, 0, sizeof(struct ea_refcount));
1026
1027 if (!size)
1028 size = 500;
1029 refcount->size = size;
1030 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1031#ifdef DEBUG
1032 printf("Refcount allocated %d entries, %d bytes.\n",
1033 refcount->size, bytes);
1034#endif
1035 retval = ext2fs_get_mem(bytes, &refcount->list);
1036 if (retval)
1037 goto errout;
1038 memset(refcount->list, 0, bytes);
1039
1040 refcount->count = 0;
1041 refcount->cursor = 0;
1042
1043 *ret = refcount;
1044 return 0;
1045
1046errout:
1047 ea_refcount_free(refcount);
1048 return retval;
1049}
1050
1051/*
1052 * collapse_refcount() --- go through the refcount array, and get rid
1053 * of any count == zero entries
1054 */
1055static void refcount_collapse(ext2_refcount_t refcount)
1056{
1057 unsigned int i, j;
1058 struct ea_refcount_el *list;
1059
1060 list = refcount->list;
1061 for (i = 0, j = 0; i < refcount->count; i++) {
1062 if (list[i].ea_count) {
1063 if (i != j)
1064 list[j] = list[i];
1065 j++;
1066 }
1067 }
1068#if defined(DEBUG) || defined(TEST_PROGRAM)
1069 printf("Refcount_collapse: size was %d, now %d\n",
1070 refcount->count, j);
1071#endif
1072 refcount->count = j;
1073}
1074
1075
1076/*
1077 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1078 * specified position.
1079 */
1080static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1081 blk_t blk, int pos)
1082{
1083 struct ea_refcount_el *el;
1084 errcode_t retval;
1085 blk_t new_size = 0;
1086 int num;
1087
1088 if (refcount->count >= refcount->size) {
1089 new_size = refcount->size + 100;
1090#ifdef DEBUG
1091 printf("Reallocating refcount %d entries...\n", new_size);
1092#endif
1093 retval = ext2fs_resize_mem((size_t) refcount->size *
1094 sizeof(struct ea_refcount_el),
1095 (size_t) new_size *
1096 sizeof(struct ea_refcount_el),
1097 &refcount->list);
1098 if (retval)
1099 return 0;
1100 refcount->size = new_size;
1101 }
1102 num = (int) refcount->count - pos;
1103 if (num < 0)
1104 return 0; /* should never happen */
1105 if (num) {
1106 memmove(&refcount->list[pos+1], &refcount->list[pos],
1107 sizeof(struct ea_refcount_el) * num);
1108 }
1109 refcount->count++;
1110 el = &refcount->list[pos];
1111 el->ea_count = 0;
1112 el->ea_blk = blk;
1113 return el;
1114}
1115
1116
1117/*
1118 * get_refcount_el() --- given an block number, try to find refcount
1119 * information in the sorted list. If the create flag is set,
1120 * and we can't find an entry, create one in the sorted list.
1121 */
1122static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1123 blk_t blk, int create)
1124{
1125 float range;
1126 int low, high, mid;
1127 blk_t lowval, highval;
1128
1129 if (!refcount || !refcount->list)
1130 return 0;
1131retry:
1132 low = 0;
1133 high = (int) refcount->count-1;
1134 if (create && ((refcount->count == 0) ||
1135 (blk > refcount->list[high].ea_blk))) {
1136 if (refcount->count >= refcount->size)
1137 refcount_collapse(refcount);
1138
1139 return insert_refcount_el(refcount, blk,
1140 (unsigned) refcount->count);
1141 }
1142 if (refcount->count == 0)
1143 return 0;
1144
1145 if (refcount->cursor >= refcount->count)
1146 refcount->cursor = 0;
1147 if (blk == refcount->list[refcount->cursor].ea_blk)
1148 return &refcount->list[refcount->cursor++];
1149#ifdef DEBUG
1150 printf("Non-cursor get_refcount_el: %u\n", blk);
1151#endif
1152 while (low <= high) {
1153 if (low == high)
1154 mid = low;
1155 else {
1156 /* Interpolate for efficiency */
1157 lowval = refcount->list[low].ea_blk;
1158 highval = refcount->list[high].ea_blk;
1159
1160 if (blk < lowval)
1161 range = 0;
1162 else if (blk > highval)
1163 range = 1;
1164 else
1165 range = ((float) (blk - lowval)) /
1166 (highval - lowval);
1167 mid = low + ((int) (range * (high-low)));
1168 }
1169
1170 if (blk == refcount->list[mid].ea_blk) {
1171 refcount->cursor = mid+1;
1172 return &refcount->list[mid];
1173 }
1174 if (blk < refcount->list[mid].ea_blk)
1175 high = mid-1;
1176 else
1177 low = mid+1;
1178 }
1179 /*
1180 * If we need to create a new entry, it should be right at
1181 * low (where high will be left at low-1).
1182 */
1183 if (create) {
1184 if (refcount->count >= refcount->size) {
1185 refcount_collapse(refcount);
1186 if (refcount->count < refcount->size)
1187 goto retry;
1188 }
1189 return insert_refcount_el(refcount, blk, low);
1190 }
1191 return 0;
1192}
1193
1194static errcode_t
1195ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1196{
1197 struct ea_refcount_el *el;
1198
1199 el = get_refcount_el(refcount, blk, 1);
1200 if (!el)
1201 return EXT2_ET_NO_MEMORY;
1202 el->ea_count++;
1203
1204 if (ret)
1205 *ret = el->ea_count;
1206 return 0;
1207}
1208
1209static errcode_t
1210ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1211{
1212 struct ea_refcount_el *el;
1213
1214 el = get_refcount_el(refcount, blk, 0);
1215 if (!el || el->ea_count == 0)
1216 return EXT2_ET_INVALID_ARGUMENT;
1217
1218 el->ea_count--;
1219
1220 if (ret)
1221 *ret = el->ea_count;
1222 return 0;
1223}
1224
1225static errcode_t
1226ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1227{
1228 struct ea_refcount_el *el;
1229
1230 /*
1231 * Get the refcount element
1232 */
1233 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1234 if (!el)
1235 return count ? EXT2_ET_NO_MEMORY : 0;
1236 el->ea_count = count;
1237 return 0;
1238}
1239
1240static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1241{
1242 refcount->cursor = 0;
1243}
1244
1245
1246static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1247{
1248 struct ea_refcount_el *list;
1249
1250 while (1) {
1251 if (refcount->cursor >= refcount->count)
1252 return 0;
1253 list = refcount->list;
1254 if (list[refcount->cursor].ea_count) {
1255 if (ret)
1256 *ret = list[refcount->cursor].ea_count;
1257 return list[refcount->cursor++].ea_blk;
1258 }
1259 refcount->cursor++;
1260 }
1261}
1262
1263
1264/*
1265 * ehandler.c --- handle bad block errors which come up during the
1266 * course of an e2fsck session.
1267 */
1268
1269
1270static const char *operation;
1271
1272static errcode_t
1273e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1274 void *data, size_t size FSCK_ATTR((unused)),
1275 int actual FSCK_ATTR((unused)), errcode_t error)
1276{
1277 int i;
1278 char *p;
1279 ext2_filsys fs = (ext2_filsys) channel->app_data;
1280 e2fsck_t ctx;
1281
1282 ctx = (e2fsck_t) fs->priv_data;
1283
1284 /*
1285 * If more than one block was read, try reading each block
1286 * separately. We could use the actual bytes read to figure
1287 * out where to start, but we don't bother.
1288 */
1289 if (count > 1) {
1290 p = (char *) data;
1291 for (i=0; i < count; i++, p += channel->block_size, block++) {
1292 error = io_channel_read_blk(channel, block,
1293 1, p);
1294 if (error)
1295 return error;
1296 }
1297 return 0;
1298 }
1299 if (operation)
1300 printf(_("Error reading block %lu (%s) while %s. "), block,
1301 error_message(error), operation);
1302 else
1303 printf(_("Error reading block %lu (%s). "), block,
1304 error_message(error));
1305 preenhalt(ctx);
1306 if (ask(ctx, _("Ignore error"), 1)) {
1307 if (ask(ctx, _("Force rewrite"), 1))
1308 io_channel_write_blk(channel, block, 1, data);
1309 return 0;
1310 }
1311
1312 return error;
1313}
1314
1315static errcode_t
1316e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1317 const void *data, size_t size FSCK_ATTR((unused)),
1318 int actual FSCK_ATTR((unused)), errcode_t error)
1319{
1320 int i;
1321 const char *p;
1322 ext2_filsys fs = (ext2_filsys) channel->app_data;
1323 e2fsck_t ctx;
1324
1325 ctx = (e2fsck_t) fs->priv_data;
1326
1327 /*
1328 * If more than one block was written, try writing each block
1329 * separately. We could use the actual bytes read to figure
1330 * out where to start, but we don't bother.
1331 */
1332 if (count > 1) {
1333 p = (const char *) data;
1334 for (i=0; i < count; i++, p += channel->block_size, block++) {
1335 error = io_channel_write_blk(channel, block,
1336 1, p);
1337 if (error)
1338 return error;
1339 }
1340 return 0;
1341 }
1342
1343 if (operation)
1344 printf(_("Error writing block %lu (%s) while %s. "), block,
1345 error_message(error), operation);
1346 else
1347 printf(_("Error writing block %lu (%s). "), block,
1348 error_message(error));
1349 preenhalt(ctx);
1350 if (ask(ctx, _("Ignore error"), 1))
1351 return 0;
1352
1353 return error;
1354}
1355
1356static const char *ehandler_operation(const char *op)
1357{
1358 const char *ret = operation;
1359
1360 operation = op;
1361 return ret;
1362}
1363
1364static void ehandler_init(io_channel channel)
1365{
1366 channel->read_error = e2fsck_handle_read_error;
1367 channel->write_error = e2fsck_handle_write_error;
1368}
1369
1370/*
1371 * journal.c --- code for handling the "ext3" journal
1372 *
1373 * Copyright (C) 2000 Andreas Dilger
1374 * Copyright (C) 2000 Theodore Ts'o
1375 *
1376 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1377 * Copyright (C) 1999 Red Hat Software
1378 *
1379 * This file may be redistributed under the terms of the
1380 * GNU General Public License version 2 or at your discretion
1381 * any later version.
1382 */
1383
1384/*
1385 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1386 * This creates a larger static binary, and a smaller binary using
1387 * shared libraries. It's also probably slightly less CPU-efficient,
1388 * which is why it's not on by default. But, it's a good way of
1389 * testing the functions in inode_io.c and fileio.c.
1390 */
1391#undef USE_INODE_IO
1392
1393/* Kernel compatibility functions for handling the journal. These allow us
1394 * to use the recovery.c file virtually unchanged from the kernel, so we
1395 * don't have to do much to keep kernel and user recovery in sync.
1396 */
1397static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1398{
1399#ifdef USE_INODE_IO
1400 *phys = block;
1401 return 0;
1402#else
1403 struct inode *inode = journal->j_inode;
1404 errcode_t retval;
1405 blk_t pblk;
1406
1407 if (!inode) {
1408 *phys = block;
1409 return 0;
1410 }
1411
1412 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1413 &inode->i_ext2, NULL, 0, block, &pblk);
1414 *phys = pblk;
1415 return retval;
1416#endif
1417}
1418
1419static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1420{
1421 struct buffer_head *bh;
1422
1423 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1424 if (!bh)
1425 return NULL;
1426
1427 bh->b_ctx = kdev->k_ctx;
1428 if (kdev->k_dev == K_DEV_FS)
1429 bh->b_io = kdev->k_ctx->fs->io;
1430 else
1431 bh->b_io = kdev->k_ctx->journal_io;
1432 bh->b_size = blocksize;
1433 bh->b_blocknr = blocknr;
1434
1435 return bh;
1436}
1437
1438static void sync_blockdev(kdev_t kdev)
1439{
1440 io_channel io;
1441
1442 if (kdev->k_dev == K_DEV_FS)
1443 io = kdev->k_ctx->fs->io;
1444 else
1445 io = kdev->k_ctx->journal_io;
1446
1447 io_channel_flush(io);
1448}
1449
1450static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1451{
1452 int retval;
1453 struct buffer_head *bh;
1454
1455 for (; nr > 0; --nr) {
1456 bh = *bhp++;
1457 if (rw == READ && !bh->b_uptodate) {
1458 retval = io_channel_read_blk(bh->b_io,
1459 bh->b_blocknr,
1460 1, bh->b_data);
1461 if (retval) {
1462 bb_error_msg("while reading block %lu",
1463 (unsigned long) bh->b_blocknr);
1464 bh->b_err = retval;
1465 continue;
1466 }
1467 bh->b_uptodate = 1;
1468 } else if (rw == WRITE && bh->b_dirty) {
1469 retval = io_channel_write_blk(bh->b_io,
1470 bh->b_blocknr,
1471 1, bh->b_data);
1472 if (retval) {
1473 bb_error_msg("while writing block %lu",
1474 (unsigned long) bh->b_blocknr);
1475 bh->b_err = retval;
1476 continue;
1477 }
1478 bh->b_dirty = 0;
1479 bh->b_uptodate = 1;
1480 }
1481 }
1482}
1483
1484static void mark_buffer_dirty(struct buffer_head *bh)
1485{
1486 bh->b_dirty = 1;
1487}
1488
1489static inline void mark_buffer_clean(struct buffer_head * bh)
1490{
1491 bh->b_dirty = 0;
1492}
1493
1494static void brelse(struct buffer_head *bh)
1495{
1496 if (bh->b_dirty)
1497 ll_rw_block(WRITE, 1, &bh);
1498 ext2fs_free_mem(&bh);
1499}
1500
1501static int buffer_uptodate(struct buffer_head *bh)
1502{
1503 return bh->b_uptodate;
1504}
1505
1506static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1507{
1508 bh->b_uptodate = val;
1509}
1510
1511static void wait_on_buffer(struct buffer_head *bh)
1512{
1513 if (!bh->b_uptodate)
1514 ll_rw_block(READ, 1, &bh);
1515}
1516
1517
1518static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1519{
1520 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1521
1522 /* if we had an error doing journal recovery, we need a full fsck */
1523 if (error)
1524 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1525 ext2fs_mark_super_dirty(ctx->fs);
1526}
1527
1528static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1529{
1530 struct ext2_super_block *sb = ctx->fs->super;
1531 struct ext2_super_block jsuper;
1532 struct problem_context pctx;
1533 struct buffer_head *bh;
1534 struct inode *j_inode = NULL;
1535 struct kdev_s *dev_fs = NULL, *dev_journal;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01001536 const char *journal_name = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001537 journal_t *journal = NULL;
1538 errcode_t retval = 0;
1539 io_manager io_ptr = 0;
1540 unsigned long start = 0;
1541 blk_t blk;
1542 int ext_journal = 0;
1543 int tried_backup_jnl = 0;
1544 int i;
1545
1546 clear_problem_context(&pctx);
1547
1548 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1549 if (!journal) {
1550 return EXT2_ET_NO_MEMORY;
1551 }
1552
1553 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1554 if (!dev_fs) {
1555 retval = EXT2_ET_NO_MEMORY;
1556 goto errout;
1557 }
1558 dev_journal = dev_fs+1;
1559
1560 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1561 dev_fs->k_dev = K_DEV_FS;
1562 dev_journal->k_dev = K_DEV_JOURNAL;
1563
1564 journal->j_dev = dev_journal;
1565 journal->j_fs_dev = dev_fs;
1566 journal->j_inode = NULL;
1567 journal->j_blocksize = ctx->fs->blocksize;
1568
1569 if (uuid_is_null(sb->s_journal_uuid)) {
1570 if (!sb->s_journal_inum)
1571 return EXT2_ET_BAD_INODE_NUM;
1572 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1573 "journal inode");
1574 if (!j_inode) {
1575 retval = EXT2_ET_NO_MEMORY;
1576 goto errout;
1577 }
1578
1579 j_inode->i_ctx = ctx;
1580 j_inode->i_ino = sb->s_journal_inum;
1581
1582 if ((retval = ext2fs_read_inode(ctx->fs,
1583 sb->s_journal_inum,
1584 &j_inode->i_ext2))) {
1585 try_backup_journal:
1586 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1587 tried_backup_jnl)
1588 goto errout;
1589 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1590 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1591 EXT2_N_BLOCKS*4);
1592 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1593 j_inode->i_ext2.i_links_count = 1;
1594 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1595 tried_backup_jnl++;
1596 }
1597 if (!j_inode->i_ext2.i_links_count ||
1598 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1599 retval = EXT2_ET_NO_JOURNAL;
1600 goto try_backup_journal;
1601 }
1602 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1603 JFS_MIN_JOURNAL_BLOCKS) {
1604 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1605 goto try_backup_journal;
1606 }
1607 for (i=0; i < EXT2_N_BLOCKS; i++) {
1608 blk = j_inode->i_ext2.i_block[i];
1609 if (!blk) {
1610 if (i < EXT2_NDIR_BLOCKS) {
1611 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1612 goto try_backup_journal;
1613 }
1614 continue;
1615 }
1616 if (blk < sb->s_first_data_block ||
1617 blk >= sb->s_blocks_count) {
1618 retval = EXT2_ET_BAD_BLOCK_NUM;
1619 goto try_backup_journal;
1620 }
1621 }
1622 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1623
1624#ifdef USE_INODE_IO
1625 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1626 &j_inode->i_ext2,
1627 &journal_name);
1628 if (retval)
1629 goto errout;
1630
1631 io_ptr = inode_io_manager;
1632#else
1633 journal->j_inode = j_inode;
1634 ctx->journal_io = ctx->fs->io;
1635 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1636 goto errout;
1637#endif
1638 } else {
1639 ext_journal = 1;
1640 if (!ctx->journal_name) {
1641 char uuid[37];
1642
1643 uuid_unparse(sb->s_journal_uuid, uuid);
1644 ctx->journal_name = blkid_get_devname(ctx->blkid,
1645 "UUID", uuid);
1646 if (!ctx->journal_name)
1647 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1648 }
1649 journal_name = ctx->journal_name;
1650
1651 if (!journal_name) {
1652 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1653 return EXT2_ET_LOAD_EXT_JOURNAL;
1654 }
1655
1656 io_ptr = unix_io_manager;
1657 }
1658
1659#ifndef USE_INODE_IO
1660 if (ext_journal)
1661#endif
1662 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1663 &ctx->journal_io);
1664 if (retval)
1665 goto errout;
1666
1667 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1668
1669 if (ext_journal) {
1670 if (ctx->fs->blocksize == 1024)
1671 start = 1;
1672 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1673 if (!bh) {
1674 retval = EXT2_ET_NO_MEMORY;
1675 goto errout;
1676 }
1677 ll_rw_block(READ, 1, &bh);
1678 if ((retval = bh->b_err) != 0)
1679 goto errout;
1680 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1681 sizeof(jsuper));
1682 brelse(bh);
1683#if BB_BIG_ENDIAN
1684 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1685 ext2fs_swap_super(&jsuper);
1686#endif
1687 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1688 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1689 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1690 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1691 goto errout;
1692 }
1693 /* Make sure the journal UUID is correct */
1694 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1695 sizeof(jsuper.s_uuid))) {
1696 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1697 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1698 goto errout;
1699 }
1700
1701 journal->j_maxlen = jsuper.s_blocks_count;
1702 start++;
1703 }
1704
1705 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1706 retval = EXT2_ET_NO_MEMORY;
1707 goto errout;
1708 }
1709
1710 journal->j_sb_buffer = bh;
1711 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1712
1713#ifdef USE_INODE_IO
1714 ext2fs_free_mem(&j_inode);
1715#endif
1716
1717 *ret_journal = journal;
1718 return 0;
1719
1720errout:
1721 ext2fs_free_mem(&dev_fs);
1722 ext2fs_free_mem(&j_inode);
1723 ext2fs_free_mem(&journal);
1724 return retval;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001725}
1726
1727static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1728 struct problem_context *pctx)
1729{
1730 struct ext2_super_block *sb = ctx->fs->super;
1731 int recover = ctx->fs->super->s_feature_incompat &
1732 EXT3_FEATURE_INCOMPAT_RECOVER;
1733 int has_journal = ctx->fs->super->s_feature_compat &
1734 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1735
1736 if (has_journal || sb->s_journal_inum) {
1737 /* The journal inode is bogus, remove and force full fsck */
1738 pctx->ino = sb->s_journal_inum;
1739 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1740 if (has_journal && sb->s_journal_inum)
1741 printf("*** ext3 journal has been deleted - "
1742 "filesystem is now ext2 only ***\n\n");
1743 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1744 sb->s_journal_inum = 0;
1745 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1746 e2fsck_clear_recover(ctx, 1);
1747 return 0;
1748 }
1749 return EXT2_ET_BAD_INODE_NUM;
1750 } else if (recover) {
1751 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1752 e2fsck_clear_recover(ctx, 1);
1753 return 0;
1754 }
1755 return EXT2_ET_UNSUPP_FEATURE;
1756 }
1757 return 0;
1758}
1759
1760#define V1_SB_SIZE 0x0024
1761static void clear_v2_journal_fields(journal_t *journal)
1762{
1763 e2fsck_t ctx = journal->j_dev->k_ctx;
1764 struct problem_context pctx;
1765
1766 clear_problem_context(&pctx);
1767
1768 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1769 return;
1770
1771 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1772 ctx->fs->blocksize-V1_SB_SIZE);
1773 mark_buffer_dirty(journal->j_sb_buffer);
1774}
1775
1776
1777static errcode_t e2fsck_journal_load(journal_t *journal)
1778{
1779 e2fsck_t ctx = journal->j_dev->k_ctx;
1780 journal_superblock_t *jsb;
1781 struct buffer_head *jbh = journal->j_sb_buffer;
1782 struct problem_context pctx;
1783
1784 clear_problem_context(&pctx);
1785
1786 ll_rw_block(READ, 1, &jbh);
1787 if (jbh->b_err) {
1788 bb_error_msg(_("reading journal superblock"));
1789 return jbh->b_err;
1790 }
1791
1792 jsb = journal->j_superblock;
1793 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1794 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1795 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1796
1797 switch (ntohl(jsb->s_header.h_blocktype)) {
1798 case JFS_SUPERBLOCK_V1:
1799 journal->j_format_version = 1;
1800 if (jsb->s_feature_compat ||
1801 jsb->s_feature_incompat ||
1802 jsb->s_feature_ro_compat ||
1803 jsb->s_nr_users)
1804 clear_v2_journal_fields(journal);
1805 break;
1806
1807 case JFS_SUPERBLOCK_V2:
1808 journal->j_format_version = 2;
1809 if (ntohl(jsb->s_nr_users) > 1 &&
1810 uuid_is_null(ctx->fs->super->s_journal_uuid))
1811 clear_v2_journal_fields(journal);
1812 if (ntohl(jsb->s_nr_users) > 1) {
1813 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1814 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1815 }
1816 break;
1817
1818 /*
1819 * These should never appear in a journal super block, so if
1820 * they do, the journal is badly corrupted.
1821 */
1822 case JFS_DESCRIPTOR_BLOCK:
1823 case JFS_COMMIT_BLOCK:
1824 case JFS_REVOKE_BLOCK:
1825 return EXT2_ET_CORRUPT_SUPERBLOCK;
1826
1827 /* If we don't understand the superblock major type, but there
1828 * is a magic number, then it is likely to be a new format we
1829 * just don't understand, so leave it alone. */
1830 default:
1831 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1832 }
1833
1834 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1835 return EXT2_ET_UNSUPP_FEATURE;
1836
1837 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1838 return EXT2_ET_RO_UNSUPP_FEATURE;
1839
1840 /* We have now checked whether we know enough about the journal
1841 * format to be able to proceed safely, so any other checks that
1842 * fail we should attempt to recover from. */
1843 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1844 bb_error_msg(_("%s: no valid journal superblock found"),
1845 ctx->device_name);
1846 return EXT2_ET_CORRUPT_SUPERBLOCK;
1847 }
1848
1849 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1850 journal->j_maxlen = ntohl(jsb->s_maxlen);
1851 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1852 bb_error_msg(_("%s: journal too short"),
1853 ctx->device_name);
1854 return EXT2_ET_CORRUPT_SUPERBLOCK;
1855 }
1856
1857 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1858 journal->j_transaction_sequence = journal->j_tail_sequence;
1859 journal->j_tail = ntohl(jsb->s_start);
1860 journal->j_first = ntohl(jsb->s_first);
1861 journal->j_last = ntohl(jsb->s_maxlen);
1862
1863 return 0;
1864}
1865
1866static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1867 journal_t *journal)
1868{
1869 char *p;
1870 union {
1871 uuid_t uuid;
1872 __u32 val[4];
1873 } u;
1874 __u32 new_seq = 0;
1875 int i;
1876
1877 /* Leave a valid existing V1 superblock signature alone.
Denys Vlasenkob22bbff2009-07-04 16:50:43 +02001878 * Anything unrecognizable we overwrite with a new V2
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001879 * signature. */
1880
1881 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1882 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1883 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1884 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1885 }
1886
1887 /* Zero out everything else beyond the superblock header */
1888
1889 p = ((char *) jsb) + sizeof(journal_header_t);
1890 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1891
1892 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1893 jsb->s_maxlen = htonl(journal->j_maxlen);
1894 jsb->s_first = htonl(1);
1895
1896 /* Initialize the journal sequence number so that there is "no"
1897 * chance we will find old "valid" transactions in the journal.
1898 * This avoids the need to zero the whole journal (slow to do,
1899 * and risky when we are just recovering the filesystem).
1900 */
1901 uuid_generate(u.uuid);
1902 for (i = 0; i < 4; i ++)
1903 new_seq ^= u.val[i];
1904 jsb->s_sequence = htonl(new_seq);
1905
1906 mark_buffer_dirty(journal->j_sb_buffer);
1907 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1908}
1909
1910static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1911 journal_t *journal,
1912 struct problem_context *pctx)
1913{
1914 struct ext2_super_block *sb = ctx->fs->super;
1915 int recover = ctx->fs->super->s_feature_incompat &
1916 EXT3_FEATURE_INCOMPAT_RECOVER;
1917
1918 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1919 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1920 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1921 journal);
1922 journal->j_transaction_sequence = 1;
1923 e2fsck_clear_recover(ctx, recover);
1924 return 0;
1925 }
1926 return EXT2_ET_CORRUPT_SUPERBLOCK;
1927 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1928 return EXT2_ET_CORRUPT_SUPERBLOCK;
1929
1930 return 0;
1931}
1932
1933static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1934 int reset, int drop)
1935{
1936 journal_superblock_t *jsb;
1937
1938 if (drop)
1939 mark_buffer_clean(journal->j_sb_buffer);
1940 else if (!(ctx->options & E2F_OPT_READONLY)) {
1941 jsb = journal->j_superblock;
1942 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1943 if (reset)
1944 jsb->s_start = 0; /* this marks the journal as empty */
1945 mark_buffer_dirty(journal->j_sb_buffer);
1946 }
1947 brelse(journal->j_sb_buffer);
1948
1949 if (ctx->journal_io) {
1950 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1951 io_channel_close(ctx->journal_io);
1952 ctx->journal_io = 0;
1953 }
1954
1955#ifndef USE_INODE_IO
1956 ext2fs_free_mem(&journal->j_inode);
1957#endif
1958 ext2fs_free_mem(&journal->j_fs_dev);
1959 ext2fs_free_mem(&journal);
1960}
1961
1962/*
1963 * This function makes sure that the superblock fields regarding the
1964 * journal are consistent.
1965 */
1966static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1967{
1968 struct ext2_super_block *sb = ctx->fs->super;
1969 journal_t *journal;
1970 int recover = ctx->fs->super->s_feature_incompat &
1971 EXT3_FEATURE_INCOMPAT_RECOVER;
1972 struct problem_context pctx;
1973 problem_t problem;
1974 int reset = 0, force_fsck = 0;
1975 int retval;
1976
1977 /* If we don't have any journal features, don't do anything more */
1978 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1979 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1980 uuid_is_null(sb->s_journal_uuid))
1981 return 0;
1982
1983 clear_problem_context(&pctx);
1984 pctx.num = sb->s_journal_inum;
1985
1986 retval = e2fsck_get_journal(ctx, &journal);
1987 if (retval) {
1988 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1989 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1990 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1991 (retval == EXT2_ET_NO_JOURNAL))
1992 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1993 return retval;
1994 }
1995
1996 retval = e2fsck_journal_load(journal);
1997 if (retval) {
1998 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
1999 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2000 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2001 &pctx))) ||
2002 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2003 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2004 &pctx))) ||
2005 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2006 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2007 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2008 &pctx);
2009 e2fsck_journal_release(ctx, journal, 0, 1);
2010 return retval;
2011 }
2012
2013 /*
2014 * We want to make the flags consistent here. We will not leave with
2015 * needs_recovery set but has_journal clear. We can't get in a loop
2016 * with -y, -n, or -p, only if a user isn't making up their mind.
2017 */
2018no_has_journal:
2019 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2020 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2021 pctx.str = "inode";
2022 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2023 if (recover &&
2024 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2025 goto no_has_journal;
2026 /*
2027 * Need a full fsck if we are releasing a
2028 * journal stored on a reserved inode.
2029 */
2030 force_fsck = recover ||
2031 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2032 /* Clear all of the journal fields */
2033 sb->s_journal_inum = 0;
2034 sb->s_journal_dev = 0;
2035 memset(sb->s_journal_uuid, 0,
2036 sizeof(sb->s_journal_uuid));
2037 e2fsck_clear_recover(ctx, force_fsck);
2038 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2039 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2040 ext2fs_mark_super_dirty(ctx->fs);
2041 }
2042 }
2043
2044 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2045 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2046 journal->j_superblock->s_start != 0) {
2047 /* Print status information */
2048 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2049 if (ctx->superblock)
2050 problem = PR_0_JOURNAL_RUN_DEFAULT;
2051 else
2052 problem = PR_0_JOURNAL_RUN;
2053 if (fix_problem(ctx, problem, &pctx)) {
2054 ctx->options |= E2F_OPT_FORCE;
2055 sb->s_feature_incompat |=
2056 EXT3_FEATURE_INCOMPAT_RECOVER;
2057 ext2fs_mark_super_dirty(ctx->fs);
2058 } else if (fix_problem(ctx,
2059 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2060 reset = 1;
2061 sb->s_state &= ~EXT2_VALID_FS;
2062 ext2fs_mark_super_dirty(ctx->fs);
2063 }
2064 /*
2065 * If the user answers no to the above question, we
2066 * ignore the fact that journal apparently has data;
2067 * accidentally replaying over valid data would be far
2068 * worse than skipping a questionable recovery.
2069 *
2070 * XXX should we abort with a fatal error here? What
2071 * will the ext3 kernel code do if a filesystem with
2072 * !NEEDS_RECOVERY but with a non-zero
2073 * journal->j_superblock->s_start is mounted?
2074 */
2075 }
2076
2077 e2fsck_journal_release(ctx, journal, reset, 0);
2078 return retval;
2079}
2080
2081static errcode_t recover_ext3_journal(e2fsck_t ctx)
2082{
2083 journal_t *journal;
2084 int retval;
2085
2086 journal_init_revoke_caches();
2087 retval = e2fsck_get_journal(ctx, &journal);
2088 if (retval)
2089 return retval;
2090
2091 retval = e2fsck_journal_load(journal);
2092 if (retval)
2093 goto errout;
2094
2095 retval = journal_init_revoke(journal, 1024);
2096 if (retval)
2097 goto errout;
2098
2099 retval = -journal_recover(journal);
2100 if (retval)
2101 goto errout;
2102
2103 if (journal->j_superblock->s_errno) {
2104 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2105 ext2fs_mark_super_dirty(ctx->fs);
2106 journal->j_superblock->s_errno = 0;
2107 mark_buffer_dirty(journal->j_sb_buffer);
2108 }
2109
2110errout:
2111 journal_destroy_revoke(journal);
2112 journal_destroy_revoke_caches();
2113 e2fsck_journal_release(ctx, journal, 1, 0);
2114 return retval;
2115}
2116
2117static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2118{
2119 io_manager io_ptr = ctx->fs->io->manager;
2120 int blocksize = ctx->fs->blocksize;
2121 errcode_t retval, recover_retval;
2122
2123 printf(_("%s: recovering journal\n"), ctx->device_name);
2124 if (ctx->options & E2F_OPT_READONLY) {
2125 printf(_("%s: won't do journal recovery while read-only\n"),
2126 ctx->device_name);
2127 return EXT2_ET_FILE_RO;
2128 }
2129
2130 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2131 ext2fs_flush(ctx->fs); /* Force out any modifications */
2132
2133 recover_retval = recover_ext3_journal(ctx);
2134
2135 /*
2136 * Reload the filesystem context to get up-to-date data from disk
2137 * because journal recovery will change the filesystem under us.
2138 */
2139 ext2fs_close(ctx->fs);
2140 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2141 ctx->superblock, blocksize, io_ptr,
2142 &ctx->fs);
2143
2144 if (retval) {
2145 bb_error_msg(_("while trying to re-open %s"),
2146 ctx->device_name);
2147 bb_error_msg_and_die(0);
2148 }
2149 ctx->fs->priv_data = ctx;
2150
2151 /* Set the superblock flags */
2152 e2fsck_clear_recover(ctx, recover_retval);
2153 return recover_retval;
2154}
2155
2156/*
2157 * This function will move the journal inode from a visible file in
2158 * the filesystem directory hierarchy to the reserved inode if necessary.
2159 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002160static const char *const journal_names[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002161 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2162
2163static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2164{
2165 struct ext2_super_block *sb = ctx->fs->super;
2166 struct problem_context pctx;
2167 struct ext2_inode inode;
2168 ext2_filsys fs = ctx->fs;
2169 ext2_ino_t ino;
2170 errcode_t retval;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002171 const char *const * cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002172 int group, mount_flags;
2173
2174 clear_problem_context(&pctx);
2175
2176 /*
2177 * If the filesystem is opened read-only, or there is no
2178 * journal, then do nothing.
2179 */
2180 if ((ctx->options & E2F_OPT_READONLY) ||
2181 (sb->s_journal_inum == 0) ||
2182 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2183 return;
2184
2185 /*
2186 * Read in the journal inode
2187 */
2188 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2189 return;
2190
2191 /*
2192 * If it's necessary to backup the journal inode, do so.
2193 */
2194 if ((sb->s_jnl_backup_type == 0) ||
2195 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2196 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2197 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2198 memcpy(sb->s_jnl_blocks, inode.i_block,
2199 EXT2_N_BLOCKS*4);
2200 sb->s_jnl_blocks[16] = inode.i_size;
2201 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2202 ext2fs_mark_super_dirty(fs);
2203 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2204 }
2205 }
2206
2207 /*
2208 * If the journal is already the hidden inode, then do nothing
2209 */
2210 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2211 return;
2212
2213 /*
2214 * The journal inode had better have only one link and not be readable.
2215 */
2216 if (inode.i_links_count != 1)
2217 return;
2218
2219 /*
2220 * If the filesystem is mounted, or we can't tell whether
2221 * or not it's mounted, do nothing.
2222 */
2223 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2224 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2225 return;
2226
2227 /*
2228 * If we can't find the name of the journal inode, then do
2229 * nothing.
2230 */
2231 for (cpp = journal_names; *cpp; cpp++) {
2232 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2233 strlen(*cpp), 0, &ino);
2234 if ((retval == 0) && (ino == sb->s_journal_inum))
2235 break;
2236 }
2237 if (*cpp == 0)
2238 return;
2239
2240 /* We need the inode bitmap to be loaded */
2241 retval = ext2fs_read_bitmaps(fs);
2242 if (retval)
2243 return;
2244
2245 pctx.str = *cpp;
2246 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2247 return;
2248
2249 /*
2250 * OK, we've done all the checks, let's actually move the
2251 * journal inode. Errors at this point mean we need to force
2252 * an ext2 filesystem check.
2253 */
2254 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2255 goto err_out;
2256 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2257 goto err_out;
2258 sb->s_journal_inum = EXT2_JOURNAL_INO;
2259 ext2fs_mark_super_dirty(fs);
2260 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2261 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00002262 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002263 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2264 goto err_out;
2265
2266 group = ext2fs_group_of_ino(fs, ino);
2267 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2268 ext2fs_mark_ib_dirty(fs);
2269 fs->group_desc[group].bg_free_inodes_count++;
2270 fs->super->s_free_inodes_count++;
2271 return;
2272
2273err_out:
2274 pctx.errcode = retval;
2275 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2276 fs->super->s_state &= ~EXT2_VALID_FS;
2277 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002278}
2279
2280/*
2281 * message.c --- print e2fsck messages (with compression)
2282 *
2283 * print_e2fsck_message() prints a message to the user, using
2284 * compression techniques and expansions of abbreviations.
2285 *
2286 * The following % expansions are supported:
2287 *
2288 * %b <blk> block number
2289 * %B <blkcount> integer
2290 * %c <blk2> block number
2291 * %Di <dirent>->ino inode number
2292 * %Dn <dirent>->name string
2293 * %Dr <dirent>->rec_len
2294 * %Dl <dirent>->name_len
2295 * %Dt <dirent>->filetype
2296 * %d <dir> inode number
2297 * %g <group> integer
2298 * %i <ino> inode number
2299 * %Is <inode> -> i_size
2300 * %IS <inode> -> i_extra_isize
2301 * %Ib <inode> -> i_blocks
2302 * %Il <inode> -> i_links_count
2303 * %Im <inode> -> i_mode
2304 * %IM <inode> -> i_mtime
2305 * %IF <inode> -> i_faddr
2306 * %If <inode> -> i_file_acl
2307 * %Id <inode> -> i_dir_acl
2308 * %Iu <inode> -> i_uid
2309 * %Ig <inode> -> i_gid
2310 * %j <ino2> inode number
2311 * %m <com_err error message>
2312 * %N <num>
2313 * %p ext2fs_get_pathname of directory <ino>
2314 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2315 * the containing directory. (If dirent is NULL
2316 * then return the pathname of directory <ino2>)
2317 * %q ext2fs_get_pathname of directory <dir>
2318 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2319 * the containing directory.
2320 * %s <str> miscellaneous string
2321 * %S backup superblock
2322 * %X <num> hexadecimal format
2323 *
2324 * The following '@' expansions are supported:
2325 *
2326 * @a extended attribute
2327 * @A error allocating
2328 * @b block
2329 * @B bitmap
2330 * @c compress
2331 * @C conflicts with some other fs block
2332 * @D deleted
2333 * @d directory
2334 * @e entry
2335 * @E Entry '%Dn' in %p (%i)
2336 * @f filesystem
2337 * @F for @i %i (%Q) is
2338 * @g group
2339 * @h HTREE directory inode
2340 * @i inode
2341 * @I illegal
2342 * @j journal
2343 * @l lost+found
2344 * @L is a link
2345 * @m multiply-claimed
2346 * @n invalid
2347 * @o orphaned
2348 * @p problem in
2349 * @r root inode
2350 * @s should be
2351 * @S superblock
2352 * @u unattached
2353 * @v device
2354 * @z zero-length
2355 */
2356
2357
2358/*
2359 * This structure defines the abbreviations used by the text strings
2360 * below. The first character in the string is the index letter. An
2361 * abbreviation of the form '@<i>' is expanded by looking up the index
2362 * letter <i> in the table below.
2363 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002364static const char *const abbrevs[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002365 N_("aextended attribute"),
2366 N_("Aerror allocating"),
2367 N_("bblock"),
2368 N_("Bbitmap"),
2369 N_("ccompress"),
2370 N_("Cconflicts with some other fs @b"),
2371 N_("iinode"),
2372 N_("Iillegal"),
2373 N_("jjournal"),
2374 N_("Ddeleted"),
2375 N_("ddirectory"),
2376 N_("eentry"),
2377 N_("E@e '%Dn' in %p (%i)"),
2378 N_("ffilesystem"),
2379 N_("Ffor @i %i (%Q) is"),
2380 N_("ggroup"),
2381 N_("hHTREE @d @i"),
2382 N_("llost+found"),
2383 N_("Lis a link"),
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002384 N_("mmultiply-claimed"),
2385 N_("ninvalid"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002386 N_("oorphaned"),
2387 N_("pproblem in"),
2388 N_("rroot @i"),
2389 N_("sshould be"),
2390 N_("Ssuper@b"),
2391 N_("uunattached"),
2392 N_("vdevice"),
2393 N_("zzero-length"),
2394 "@@",
2395 0
2396 };
2397
2398/*
2399 * Give more user friendly names to the "special" inodes.
2400 */
2401#define num_special_inodes 11
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002402static const char *const special_inode_name[] =
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002403{
2404 N_("<The NULL inode>"), /* 0 */
2405 N_("<The bad blocks inode>"), /* 1 */
2406 "/", /* 2 */
2407 N_("<The ACL index inode>"), /* 3 */
2408 N_("<The ACL data inode>"), /* 4 */
2409 N_("<The boot loader inode>"), /* 5 */
2410 N_("<The undelete directory inode>"), /* 6 */
2411 N_("<The group descriptor inode>"), /* 7 */
2412 N_("<The journal inode>"), /* 8 */
2413 N_("<Reserved inode 9>"), /* 9 */
2414 N_("<Reserved inode 10>"), /* 10 */
2415};
2416
2417/*
2418 * This function does "safe" printing. It will convert non-printable
2419 * ASCII characters using '^' and M- notation.
2420 */
2421static void safe_print(const char *cp, int len)
2422{
2423 unsigned char ch;
2424
2425 if (len < 0)
2426 len = strlen(cp);
2427
2428 while (len--) {
2429 ch = *cp++;
2430 if (ch > 128) {
2431 fputs("M-", stdout);
2432 ch -= 128;
2433 }
2434 if ((ch < 32) || (ch == 0x7f)) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002435 bb_putchar('^');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002436 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2437 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00002438 bb_putchar(ch);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002439 }
2440}
2441
2442
2443/*
2444 * This function prints a pathname, using the ext2fs_get_pathname
2445 * function
2446 */
2447static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2448{
2449 errcode_t retval;
2450 char *path;
2451
2452 if (!dir && (ino < num_special_inodes)) {
2453 fputs(_(special_inode_name[ino]), stdout);
2454 return;
2455 }
2456
2457 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2458 if (retval)
2459 fputs("???", stdout);
2460 else {
2461 safe_print(path, -1);
2462 ext2fs_free_mem(&path);
2463 }
2464}
2465
2466static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2467 struct problem_context *pctx, int first);
2468/*
2469 * This function handles the '@' expansion. We allow recursive
2470 * expansion; an @ expression can contain further '@' and '%'
2471 * expressions.
2472 */
2473static void expand_at_expression(e2fsck_t ctx, char ch,
2474 struct problem_context *pctx,
2475 int *first)
2476{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002477 const char *const *cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002478 const char *str;
2479
2480 /* Search for the abbreviation */
2481 for (cpp = abbrevs; *cpp; cpp++) {
2482 if (ch == *cpp[0])
2483 break;
2484 }
2485 if (*cpp) {
2486 str = _(*cpp) + 1;
2487 if (*first && islower(*str)) {
2488 *first = 0;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002489 bb_putchar(toupper(*str++));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002490 }
2491 print_e2fsck_message(ctx, str, pctx, *first);
2492 } else
2493 printf("@%c", ch);
2494}
2495
2496/*
2497 * This function expands '%IX' expressions
2498 */
2499static void expand_inode_expression(char ch,
2500 struct problem_context *ctx)
2501{
2502 struct ext2_inode *inode;
2503 struct ext2_inode_large *large_inode;
2504 char * time_str;
2505 time_t t;
2506 int do_gmt = -1;
2507
2508 if (!ctx || !ctx->inode)
2509 goto no_inode;
2510
2511 inode = ctx->inode;
2512 large_inode = (struct ext2_inode_large *) inode;
2513
2514 switch (ch) {
2515 case 's':
2516 if (LINUX_S_ISDIR(inode->i_mode))
2517 printf("%u", inode->i_size);
2518 else {
2519 printf("%"PRIu64, (inode->i_size |
2520 ((uint64_t) inode->i_size_high << 32)));
2521 }
2522 break;
2523 case 'S':
2524 printf("%u", large_inode->i_extra_isize);
2525 break;
2526 case 'b':
2527 printf("%u", inode->i_blocks);
2528 break;
2529 case 'l':
2530 printf("%d", inode->i_links_count);
2531 break;
2532 case 'm':
2533 printf("0%o", inode->i_mode);
2534 break;
2535 case 'M':
2536 /* The diet libc doesn't respect the TZ environemnt variable */
2537 if (do_gmt == -1) {
2538 time_str = getenv("TZ");
2539 if (!time_str)
2540 time_str = "";
2541 do_gmt = !strcmp(time_str, "GMT");
2542 }
2543 t = inode->i_mtime;
2544 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2545 printf("%.24s", time_str);
2546 break;
2547 case 'F':
2548 printf("%u", inode->i_faddr);
2549 break;
2550 case 'f':
2551 printf("%u", inode->i_file_acl);
2552 break;
2553 case 'd':
2554 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2555 inode->i_dir_acl : 0));
2556 break;
2557 case 'u':
2558 printf("%d", (inode->i_uid |
2559 (inode->osd2.linux2.l_i_uid_high << 16)));
2560 break;
2561 case 'g':
2562 printf("%d", (inode->i_gid |
2563 (inode->osd2.linux2.l_i_gid_high << 16)));
2564 break;
2565 default:
2566 no_inode:
2567 printf("%%I%c", ch);
2568 break;
2569 }
2570}
2571
2572/*
2573 * This function expands '%dX' expressions
2574 */
2575static void expand_dirent_expression(char ch,
2576 struct problem_context *ctx)
2577{
2578 struct ext2_dir_entry *dirent;
2579 int len;
2580
2581 if (!ctx || !ctx->dirent)
2582 goto no_dirent;
2583
2584 dirent = ctx->dirent;
2585
2586 switch (ch) {
2587 case 'i':
2588 printf("%u", dirent->inode);
2589 break;
2590 case 'n':
2591 len = dirent->name_len & 0xFF;
2592 if (len > EXT2_NAME_LEN)
2593 len = EXT2_NAME_LEN;
2594 if (len > dirent->rec_len)
2595 len = dirent->rec_len;
2596 safe_print(dirent->name, len);
2597 break;
2598 case 'r':
2599 printf("%u", dirent->rec_len);
2600 break;
2601 case 'l':
2602 printf("%u", dirent->name_len & 0xFF);
2603 break;
2604 case 't':
2605 printf("%u", dirent->name_len >> 8);
2606 break;
2607 default:
2608 no_dirent:
2609 printf("%%D%c", ch);
2610 break;
2611 }
2612}
2613
2614static void expand_percent_expression(ext2_filsys fs, char ch,
2615 struct problem_context *ctx)
2616{
2617 if (!ctx)
2618 goto no_context;
2619
2620 switch (ch) {
2621 case '%':
Denis Vlasenko4daad902007-09-27 10:20:47 +00002622 bb_putchar('%');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002623 break;
2624 case 'b':
2625 printf("%u", ctx->blk);
2626 break;
2627 case 'B':
2628 printf("%"PRIi64, ctx->blkcount);
2629 break;
2630 case 'c':
2631 printf("%u", ctx->blk2);
2632 break;
2633 case 'd':
2634 printf("%u", ctx->dir);
2635 break;
2636 case 'g':
2637 printf("%d", ctx->group);
2638 break;
2639 case 'i':
2640 printf("%u", ctx->ino);
2641 break;
2642 case 'j':
2643 printf("%u", ctx->ino2);
2644 break;
2645 case 'm':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002646 fputs(error_message(ctx->errcode), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002647 break;
2648 case 'N':
2649 printf("%"PRIi64, ctx->num);
2650 break;
2651 case 'p':
2652 print_pathname(fs, ctx->ino, 0);
2653 break;
2654 case 'P':
2655 print_pathname(fs, ctx->ino2,
2656 ctx->dirent ? ctx->dirent->inode : 0);
2657 break;
2658 case 'q':
2659 print_pathname(fs, ctx->dir, 0);
2660 break;
2661 case 'Q':
2662 print_pathname(fs, ctx->dir, ctx->ino);
2663 break;
2664 case 'S':
2665 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2666 break;
2667 case 's':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002668 fputs((ctx->str ? ctx->str : "NULL"), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002669 break;
2670 case 'X':
2671 printf("0x%"PRIi64, ctx->num);
2672 break;
2673 default:
2674 no_context:
2675 printf("%%%c", ch);
2676 break;
2677 }
2678}
2679
2680
2681static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2682 struct problem_context *pctx, int first)
2683{
2684 ext2_filsys fs = ctx->fs;
2685 const char * cp;
2686 int i;
2687
2688 e2fsck_clear_progbar(ctx);
2689 for (cp = msg; *cp; cp++) {
2690 if (cp[0] == '@') {
2691 cp++;
2692 expand_at_expression(ctx, *cp, pctx, &first);
2693 } else if (cp[0] == '%' && cp[1] == 'I') {
2694 cp += 2;
2695 expand_inode_expression(*cp, pctx);
2696 } else if (cp[0] == '%' && cp[1] == 'D') {
2697 cp += 2;
2698 expand_dirent_expression(*cp, pctx);
2699 } else if ((cp[0] == '%')) {
2700 cp++;
2701 expand_percent_expression(fs, *cp, pctx);
2702 } else {
2703 for (i=0; cp[i]; i++)
2704 if ((cp[i] == '@') || cp[i] == '%')
2705 break;
2706 printf("%.*s", i, cp);
2707 cp += i-1;
2708 }
2709 first = 0;
2710 }
2711}
2712
2713
2714/*
2715 * region.c --- code which manages allocations within a region.
2716 */
2717
2718struct region_el {
2719 region_addr_t start;
2720 region_addr_t end;
2721 struct region_el *next;
2722};
2723
2724struct region_struct {
2725 region_addr_t min;
2726 region_addr_t max;
2727 struct region_el *allocated;
2728};
2729
2730static region_t region_create(region_addr_t min, region_addr_t max)
2731{
2732 region_t region;
2733
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002734 region = xzalloc(sizeof(struct region_struct));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002735 region->min = min;
2736 region->max = max;
2737 return region;
2738}
2739
2740static void region_free(region_t region)
2741{
2742 struct region_el *r, *next;
2743
2744 for (r = region->allocated; r; r = next) {
2745 next = r->next;
2746 free(r);
2747 }
2748 memset(region, 0, sizeof(struct region_struct));
2749 free(region);
2750}
2751
2752static int region_allocate(region_t region, region_addr_t start, int n)
2753{
2754 struct region_el *r, *new_region, *prev, *next;
2755 region_addr_t end;
2756
2757 end = start+n;
2758 if ((start < region->min) || (end > region->max))
2759 return -1;
2760 if (n == 0)
2761 return 1;
2762
2763 /*
2764 * Search through the linked list. If we find that it
2765 * conflicts witih something that's already allocated, return
2766 * 1; if we can find an existing region which we can grow, do
2767 * so. Otherwise, stop when we find the appropriate place
2768 * insert a new region element into the linked list.
2769 */
2770 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2771 if (((start >= r->start) && (start < r->end)) ||
2772 ((end > r->start) && (end <= r->end)) ||
2773 ((start <= r->start) && (end >= r->end)))
2774 return 1;
2775 if (end == r->start) {
2776 r->start = start;
2777 return 0;
2778 }
2779 if (start == r->end) {
2780 if ((next = r->next)) {
2781 if (end > next->start)
2782 return 1;
2783 if (end == next->start) {
2784 r->end = next->end;
2785 r->next = next->next;
2786 free(next);
2787 return 0;
2788 }
2789 }
2790 r->end = end;
2791 return 0;
2792 }
2793 if (start < r->start)
2794 break;
2795 }
2796 /*
2797 * Insert a new region element structure into the linked list
2798 */
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002799 new_region = xmalloc(sizeof(struct region_el));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002800 new_region->start = start;
2801 new_region->end = start + n;
2802 new_region->next = r;
2803 if (prev)
2804 prev->next = new_region;
2805 else
2806 region->allocated = new_region;
2807 return 0;
2808}
2809
2810/*
2811 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2812 *
2813 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2814 * and applies the following tests to each inode:
2815 *
2816 * - The mode field of the inode must be legal.
2817 * - The size and block count fields of the inode are correct.
2818 * - A data block must not be used by another inode
2819 *
2820 * Pass 1 also gathers the collects the following information:
2821 *
2822 * - A bitmap of which inodes are in use. (inode_used_map)
2823 * - A bitmap of which inodes are directories. (inode_dir_map)
2824 * - A bitmap of which inodes are regular files. (inode_reg_map)
2825 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2826 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2827 * - A bitmap of which blocks are in use. (block_found_map)
2828 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2829 * - The data blocks of the directory inodes. (dir_map)
2830 *
2831 * Pass 1 is designed to stash away enough information so that the
2832 * other passes should not need to read in the inode information
2833 * during the normal course of a filesystem check. (Althogh if an
2834 * inconsistency is detected, other passes may need to read in an
2835 * inode to fix it.)
2836 *
2837 * Note that pass 1B will be invoked if there are any duplicate blocks
2838 * found.
2839 */
2840
2841
2842static int process_block(ext2_filsys fs, blk_t *blocknr,
2843 e2_blkcnt_t blockcnt, blk_t ref_blk,
2844 int ref_offset, void *priv_data);
2845static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2846 e2_blkcnt_t blockcnt, blk_t ref_blk,
2847 int ref_offset, void *priv_data);
2848static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2849 char *block_buf);
2850static void mark_table_blocks(e2fsck_t ctx);
2851static void alloc_imagic_map(e2fsck_t ctx);
2852static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2853static void handle_fs_bad_blocks(e2fsck_t ctx);
2854static void process_inodes(e2fsck_t ctx, char *block_buf);
2855static int process_inode_cmp(const void *a, const void *b);
2856static errcode_t scan_callback(ext2_filsys fs,
2857 dgrp_t group, void * priv_data);
2858static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2859 char *block_buf, int adjust_sign);
2860/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2861
2862static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2863 struct ext2_inode * inode, int bufsize,
2864 const char *proc);
2865
2866struct process_block_struct_1 {
2867 ext2_ino_t ino;
2868 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2869 fragmented:1, compressed:1, bbcheck:1;
2870 blk_t num_blocks;
2871 blk_t max_blocks;
2872 e2_blkcnt_t last_block;
2873 int num_illegal_blocks;
2874 blk_t previous_block;
2875 struct ext2_inode *inode;
2876 struct problem_context *pctx;
2877 ext2fs_block_bitmap fs_meta_blocks;
2878 e2fsck_t ctx;
2879};
2880
2881struct process_inode_block {
2882 ext2_ino_t ino;
2883 struct ext2_inode inode;
2884};
2885
2886struct scan_callback_struct {
2887 e2fsck_t ctx;
2888 char *block_buf;
2889};
2890
2891/*
2892 * For the inodes to process list.
2893 */
2894static struct process_inode_block *inodes_to_process;
2895static int process_inode_count;
2896
2897static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2898 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2899
2900/*
2901 * Free all memory allocated by pass1 in preparation for restarting
2902 * things.
2903 */
2904static void unwind_pass1(void)
2905{
2906 ext2fs_free_mem(&inodes_to_process);
2907}
2908
2909/*
2910 * Check to make sure a device inode is real. Returns 1 if the device
2911 * checks out, 0 if not.
2912 *
2913 * Note: this routine is now also used to check FIFO's and Sockets,
2914 * since they have the same requirement; the i_block fields should be
2915 * zero.
2916 */
2917static int
2918e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2919{
2920 int i;
2921
2922 /*
2923 * If i_blocks is non-zero, or the index flag is set, then
2924 * this is a bogus device/fifo/socket
2925 */
2926 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2927 (inode->i_flags & EXT2_INDEX_FL))
2928 return 0;
2929
2930 /*
2931 * We should be able to do the test below all the time, but
2932 * because the kernel doesn't forcibly clear the device
2933 * inode's additional i_block fields, there are some rare
2934 * occasions when a legitimate device inode will have non-zero
2935 * additional i_block fields. So for now, we only complain
2936 * when the immutable flag is set, which should never happen
2937 * for devices. (And that's when the problem is caused, since
2938 * you can't set or clear immutable flags for devices.) Once
2939 * the kernel has been fixed we can change this...
2940 */
2941 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2942 for (i=4; i < EXT2_N_BLOCKS; i++)
2943 if (inode->i_block[i])
2944 return 0;
2945 }
2946 return 1;
2947}
2948
2949/*
2950 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2951 * checks out, 0 if not.
2952 */
2953static int
2954e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2955{
2956 unsigned int len;
2957 int i;
2958 blk_t blocks;
2959
2960 if ((inode->i_size_high || inode->i_size == 0) ||
2961 (inode->i_flags & EXT2_INDEX_FL))
2962 return 0;
2963
2964 blocks = ext2fs_inode_data_blocks(fs, inode);
2965 if (blocks) {
2966 if ((inode->i_size >= fs->blocksize) ||
2967 (blocks != fs->blocksize >> 9) ||
2968 (inode->i_block[0] < fs->super->s_first_data_block) ||
2969 (inode->i_block[0] >= fs->super->s_blocks_count))
2970 return 0;
2971
2972 for (i = 1; i < EXT2_N_BLOCKS; i++)
2973 if (inode->i_block[i])
2974 return 0;
2975
2976 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2977 return 0;
2978
2979 len = strnlen(buf, fs->blocksize);
2980 if (len == fs->blocksize)
2981 return 0;
2982 } else {
2983 if (inode->i_size >= sizeof(inode->i_block))
2984 return 0;
2985
2986 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2987 if (len == sizeof(inode->i_block))
2988 return 0;
2989 }
2990 if (len != inode->i_size)
2991 return 0;
2992 return 1;
2993}
2994
2995/*
2996 * If the immutable (or append-only) flag is set on the inode, offer
2997 * to clear it.
2998 */
2999#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3000static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3001{
3002 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3003 return;
3004
3005 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3006 return;
3007
3008 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3009 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3010}
3011
3012/*
3013 * If device, fifo or socket, check size is zero -- if not offer to
3014 * clear it
3015 */
3016static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3017{
3018 struct ext2_inode *inode = pctx->inode;
3019
3020 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3021 return;
3022
3023 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3024 return;
3025
3026 inode->i_size = 0;
3027 inode->i_size_high = 0;
3028 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3029}
3030
3031static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3032{
3033 struct ext2_super_block *sb = ctx->fs->super;
3034 struct ext2_inode_large *inode;
3035 struct ext2_ext_attr_entry *entry;
3036 char *start, *end;
3037 int storage_size, remain, offs;
3038 int problem = 0;
3039
3040 inode = (struct ext2_inode_large *) pctx->inode;
3041 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3042 inode->i_extra_isize;
3043 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3044 inode->i_extra_isize + sizeof(__u32);
3045 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3046 entry = (struct ext2_ext_attr_entry *) start;
3047
3048 /* scan all entry's headers first */
3049
3050 /* take finish entry 0UL into account */
3051 remain = storage_size - sizeof(__u32);
3052 offs = end - start;
3053
3054 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3055
3056 /* header eats this space */
3057 remain -= sizeof(struct ext2_ext_attr_entry);
3058
3059 /* is attribute name valid? */
3060 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3061 pctx->num = entry->e_name_len;
3062 problem = PR_1_ATTR_NAME_LEN;
3063 goto fix;
3064 }
3065
3066 /* attribute len eats this space */
3067 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3068
3069 /* check value size */
3070 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3071 pctx->num = entry->e_value_size;
3072 problem = PR_1_ATTR_VALUE_SIZE;
3073 goto fix;
3074 }
3075
3076 /* check value placement */
3077 if (entry->e_value_offs +
3078 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3079 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3080 pctx->num = entry->e_value_offs;
3081 problem = PR_1_ATTR_VALUE_OFFSET;
3082 goto fix;
3083 }
3084
3085 /* e_value_block must be 0 in inode's ea */
3086 if (entry->e_value_block != 0) {
3087 pctx->num = entry->e_value_block;
3088 problem = PR_1_ATTR_VALUE_BLOCK;
3089 goto fix;
3090 }
3091
3092 /* e_hash must be 0 in inode's ea */
3093 if (entry->e_hash != 0) {
3094 pctx->num = entry->e_hash;
3095 problem = PR_1_ATTR_HASH;
3096 goto fix;
3097 }
3098
3099 remain -= entry->e_value_size;
3100 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3101
3102 entry = EXT2_EXT_ATTR_NEXT(entry);
3103 }
3104fix:
3105 /*
3106 * it seems like a corruption. it's very unlikely we could repair
3107 * EA(s) in automatic fashion -bzzz
3108 */
3109 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3110 return;
3111
3112 /* simple remove all possible EA(s) */
3113 *((__u32 *)start) = 0UL;
3114 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3115 EXT2_INODE_SIZE(sb), "pass1");
3116}
3117
3118static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3119{
3120 struct ext2_super_block *sb = ctx->fs->super;
3121 struct ext2_inode_large *inode;
3122 __u32 *eamagic;
3123 int min, max;
3124
3125 inode = (struct ext2_inode_large *) pctx->inode;
3126 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3127 /* this isn't large inode. so, nothing to check */
3128 return;
3129 }
3130
3131 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3132 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3133 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3134 /*
3135 * For now we will allow i_extra_isize to be 0, but really
3136 * implementations should never allow i_extra_isize to be 0
3137 */
3138 if (inode->i_extra_isize &&
3139 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3140 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3141 return;
3142 inode->i_extra_isize = min;
3143 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3144 EXT2_INODE_SIZE(sb), "pass1");
3145 return;
3146 }
3147
3148 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3149 inode->i_extra_isize);
3150 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3151 /* it seems inode has an extended attribute(s) in body */
3152 check_ea_in_inode(ctx, pctx);
3153 }
3154}
3155
3156static void e2fsck_pass1(e2fsck_t ctx)
3157{
3158 int i;
3159 __u64 max_sizes;
3160 ext2_filsys fs = ctx->fs;
3161 ext2_ino_t ino;
3162 struct ext2_inode *inode;
3163 ext2_inode_scan scan;
3164 char *block_buf;
3165 unsigned char frag, fsize;
3166 struct problem_context pctx;
3167 struct scan_callback_struct scan_struct;
3168 struct ext2_super_block *sb = ctx->fs->super;
3169 int imagic_fs;
3170 int busted_fs_time = 0;
3171 int inode_size;
3172
3173 clear_problem_context(&pctx);
3174
3175 if (!(ctx->options & E2F_OPT_PREEN))
3176 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3177
3178 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3179 !(ctx->options & E2F_OPT_NO)) {
3180 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3181 ctx->dirs_to_hash = 0;
3182 }
3183
3184 /* Pass 1 */
3185
3186#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3187
3188 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3189 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3190 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3191 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3192 max_sizes = (max_sizes * (1UL << i)) - 1;
3193 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3194 }
3195#undef EXT2_BPP
3196
3197 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3198
3199 /*
3200 * Allocate bitmaps structures
3201 */
3202 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3203 &ctx->inode_used_map);
3204 if (pctx.errcode) {
3205 pctx.num = 1;
3206 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3207 ctx->flags |= E2F_FLAG_ABORT;
3208 return;
3209 }
3210 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3211 _("directory inode map"), &ctx->inode_dir_map);
3212 if (pctx.errcode) {
3213 pctx.num = 2;
3214 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3215 ctx->flags |= E2F_FLAG_ABORT;
3216 return;
3217 }
3218 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3219 _("regular file inode map"), &ctx->inode_reg_map);
3220 if (pctx.errcode) {
3221 pctx.num = 6;
3222 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3223 ctx->flags |= E2F_FLAG_ABORT;
3224 return;
3225 }
3226 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3227 &ctx->block_found_map);
3228 if (pctx.errcode) {
3229 pctx.num = 1;
3230 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3231 ctx->flags |= E2F_FLAG_ABORT;
3232 return;
3233 }
3234 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3235 &ctx->inode_link_info);
3236 if (pctx.errcode) {
3237 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3238 ctx->flags |= E2F_FLAG_ABORT;
3239 return;
3240 }
3241 inode_size = EXT2_INODE_SIZE(fs->super);
3242 inode = (struct ext2_inode *)
3243 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3244
3245 inodes_to_process = (struct process_inode_block *)
3246 e2fsck_allocate_memory(ctx,
3247 (ctx->process_inode_size *
3248 sizeof(struct process_inode_block)),
3249 "array of inodes to process");
3250 process_inode_count = 0;
3251
3252 pctx.errcode = ext2fs_init_dblist(fs, 0);
3253 if (pctx.errcode) {
3254 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3255 ctx->flags |= E2F_FLAG_ABORT;
3256 return;
3257 }
3258
3259 /*
3260 * If the last orphan field is set, clear it, since the pass1
3261 * processing will automatically find and clear the orphans.
3262 * In the future, we may want to try using the last_orphan
3263 * linked list ourselves, but for now, we clear it so that the
3264 * ext3 mount code won't get confused.
3265 */
3266 if (!(ctx->options & E2F_OPT_READONLY)) {
3267 if (fs->super->s_last_orphan) {
3268 fs->super->s_last_orphan = 0;
3269 ext2fs_mark_super_dirty(fs);
3270 }
3271 }
3272
3273 mark_table_blocks(ctx);
3274 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3275 "block interate buffer");
3276 e2fsck_use_inode_shortcuts(ctx, 1);
3277 ehandler_operation(_("doing inode scan"));
3278 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3279 &scan);
3280 if (pctx.errcode) {
3281 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3282 ctx->flags |= E2F_FLAG_ABORT;
3283 return;
3284 }
3285 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3286 ctx->stashed_inode = inode;
3287 scan_struct.ctx = ctx;
3288 scan_struct.block_buf = block_buf;
3289 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3290 if (ctx->progress)
3291 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3292 return;
3293 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3294 (fs->super->s_mtime < fs->super->s_inodes_count))
3295 busted_fs_time = 1;
3296
3297 while (1) {
3298 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3299 inode, inode_size);
3300 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3301 return;
3302 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3303 continue;
3304 }
3305 if (pctx.errcode) {
3306 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3307 ctx->flags |= E2F_FLAG_ABORT;
3308 return;
3309 }
3310 if (!ino)
3311 break;
3312 pctx.ino = ino;
3313 pctx.inode = inode;
3314 ctx->stashed_ino = ino;
3315 if (inode->i_links_count) {
3316 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3317 ino, inode->i_links_count);
3318 if (pctx.errcode) {
3319 pctx.num = inode->i_links_count;
3320 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3321 ctx->flags |= E2F_FLAG_ABORT;
3322 return;
3323 }
3324 }
3325 if (ino == EXT2_BAD_INO) {
3326 struct process_block_struct_1 pb;
3327
3328 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3329 &pb.fs_meta_blocks);
3330 if (pctx.errcode) {
3331 pctx.num = 4;
3332 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3333 ctx->flags |= E2F_FLAG_ABORT;
3334 return;
3335 }
3336 pb.ino = EXT2_BAD_INO;
3337 pb.num_blocks = pb.last_block = 0;
3338 pb.num_illegal_blocks = 0;
3339 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3340 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3341 pb.inode = inode;
3342 pb.pctx = &pctx;
3343 pb.ctx = ctx;
3344 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3345 block_buf, process_bad_block, &pb);
3346 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3347 if (pctx.errcode) {
3348 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3349 ctx->flags |= E2F_FLAG_ABORT;
3350 return;
3351 }
3352 if (pb.bbcheck)
3353 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3354 ctx->flags |= E2F_FLAG_ABORT;
3355 return;
3356 }
3357 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3358 clear_problem_context(&pctx);
3359 continue;
3360 } else if (ino == EXT2_ROOT_INO) {
3361 /*
3362 * Make sure the root inode is a directory; if
3363 * not, offer to clear it. It will be
3364 * regnerated in pass #3.
3365 */
3366 if (!LINUX_S_ISDIR(inode->i_mode)) {
3367 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003368 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003369 inode->i_links_count = 0;
3370 ext2fs_icount_store(ctx->inode_link_info,
3371 ino, 0);
3372 e2fsck_write_inode(ctx, ino, inode,
3373 "pass1");
3374 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003375 }
3376 /*
3377 * If dtime is set, offer to clear it. mke2fs
3378 * version 0.2b created filesystems with the
3379 * dtime field set for the root and lost+found
3380 * directories. We won't worry about
3381 * /lost+found, since that can be regenerated
3382 * easily. But we will fix the root directory
3383 * as a special case.
3384 */
3385 if (inode->i_dtime && inode->i_links_count) {
3386 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3387 inode->i_dtime = 0;
3388 e2fsck_write_inode(ctx, ino, inode,
3389 "pass1");
3390 }
3391 }
3392 } else if (ino == EXT2_JOURNAL_INO) {
3393 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3394 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3395 if (!LINUX_S_ISREG(inode->i_mode) &&
3396 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3397 &pctx)) {
3398 inode->i_mode = LINUX_S_IFREG;
3399 e2fsck_write_inode(ctx, ino, inode,
3400 "pass1");
3401 }
3402 check_blocks(ctx, &pctx, block_buf);
3403 continue;
3404 }
3405 if ((inode->i_links_count || inode->i_blocks ||
3406 inode->i_blocks || inode->i_block[0]) &&
3407 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3408 &pctx)) {
3409 memset(inode, 0, inode_size);
3410 ext2fs_icount_store(ctx->inode_link_info,
3411 ino, 0);
3412 e2fsck_write_inode_full(ctx, ino, inode,
3413 inode_size, "pass1");
3414 }
3415 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3416 int problem = 0;
3417
3418 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3419 if (ino == EXT2_BOOT_LOADER_INO) {
3420 if (LINUX_S_ISDIR(inode->i_mode))
3421 problem = PR_1_RESERVED_BAD_MODE;
3422 } else if (ino == EXT2_RESIZE_INO) {
3423 if (inode->i_mode &&
3424 !LINUX_S_ISREG(inode->i_mode))
3425 problem = PR_1_RESERVED_BAD_MODE;
3426 } else {
3427 if (inode->i_mode != 0)
3428 problem = PR_1_RESERVED_BAD_MODE;
3429 }
3430 if (problem) {
3431 if (fix_problem(ctx, problem, &pctx)) {
3432 inode->i_mode = 0;
3433 e2fsck_write_inode(ctx, ino, inode,
3434 "pass1");
3435 }
3436 }
3437 check_blocks(ctx, &pctx, block_buf);
3438 continue;
3439 }
3440 /*
3441 * Check for inodes who might have been part of the
3442 * orphaned list linked list. They should have gotten
3443 * dealt with by now, unless the list had somehow been
3444 * corrupted.
3445 *
3446 * FIXME: In the future, inodes which are still in use
3447 * (and which are therefore) pending truncation should
3448 * be handled specially. Right now we just clear the
3449 * dtime field, and the normal e2fsck handling of
3450 * inodes where i_size and the inode blocks are
3451 * inconsistent is to fix i_size, instead of releasing
3452 * the extra blocks. This won't catch the inodes that
3453 * was at the end of the orphan list, but it's better
3454 * than nothing. The right answer is that there
3455 * shouldn't be any bugs in the orphan list handling. :-)
3456 */
3457 if (inode->i_dtime && !busted_fs_time &&
3458 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3459 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3460 inode->i_dtime = inode->i_links_count ?
Denis Vlasenko04158e02009-02-02 10:48:06 +00003461 0 : time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003462 e2fsck_write_inode(ctx, ino, inode,
3463 "pass1");
3464 }
3465 }
3466
3467 /*
3468 * This code assumes that deleted inodes have
3469 * i_links_count set to 0.
3470 */
3471 if (!inode->i_links_count) {
3472 if (!inode->i_dtime && inode->i_mode) {
3473 if (fix_problem(ctx,
3474 PR_1_ZERO_DTIME, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003475 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003476 e2fsck_write_inode(ctx, ino, inode,
3477 "pass1");
3478 }
3479 }
3480 continue;
3481 }
3482 /*
3483 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3484 * deleted files. Oops.
3485 *
3486 * Since all new ext2 implementations get this right,
3487 * we now assume that the case of non-zero
3488 * i_links_count and non-zero dtime means that we
3489 * should keep the file, not delete it.
3490 *
3491 */
3492 if (inode->i_dtime) {
3493 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3494 inode->i_dtime = 0;
3495 e2fsck_write_inode(ctx, ino, inode, "pass1");
3496 }
3497 }
3498
3499 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3500 switch (fs->super->s_creator_os) {
3501 case EXT2_OS_LINUX:
3502 frag = inode->osd2.linux2.l_i_frag;
3503 fsize = inode->osd2.linux2.l_i_fsize;
3504 break;
3505 case EXT2_OS_HURD:
3506 frag = inode->osd2.hurd2.h_i_frag;
3507 fsize = inode->osd2.hurd2.h_i_fsize;
3508 break;
3509 case EXT2_OS_MASIX:
3510 frag = inode->osd2.masix2.m_i_frag;
3511 fsize = inode->osd2.masix2.m_i_fsize;
3512 break;
3513 default:
3514 frag = fsize = 0;
3515 }
3516
3517 if (inode->i_faddr || frag || fsize ||
3518 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3519 mark_inode_bad(ctx, ino);
3520 if (inode->i_flags & EXT2_IMAGIC_FL) {
3521 if (imagic_fs) {
3522 if (!ctx->inode_imagic_map)
3523 alloc_imagic_map(ctx);
3524 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3525 ino);
3526 } else {
3527 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3528 inode->i_flags &= ~EXT2_IMAGIC_FL;
3529 e2fsck_write_inode(ctx, ino,
3530 inode, "pass1");
3531 }
3532 }
3533 }
3534
3535 check_inode_extra_space(ctx, &pctx);
3536
3537 if (LINUX_S_ISDIR(inode->i_mode)) {
3538 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3539 e2fsck_add_dir_info(ctx, ino, 0);
3540 ctx->fs_directory_count++;
3541 } else if (LINUX_S_ISREG (inode->i_mode)) {
3542 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3543 ctx->fs_regular_count++;
3544 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3545 e2fsck_pass1_check_device_inode(fs, inode)) {
3546 check_immutable(ctx, &pctx);
3547 check_size(ctx, &pctx);
3548 ctx->fs_chardev_count++;
3549 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3550 e2fsck_pass1_check_device_inode(fs, inode)) {
3551 check_immutable(ctx, &pctx);
3552 check_size(ctx, &pctx);
3553 ctx->fs_blockdev_count++;
3554 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3555 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3556 check_immutable(ctx, &pctx);
3557 ctx->fs_symlinks_count++;
3558 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3559 ctx->fs_fast_symlinks_count++;
3560 check_blocks(ctx, &pctx, block_buf);
3561 continue;
3562 }
3563 }
3564 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3565 e2fsck_pass1_check_device_inode(fs, inode)) {
3566 check_immutable(ctx, &pctx);
3567 check_size(ctx, &pctx);
3568 ctx->fs_fifo_count++;
3569 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3570 e2fsck_pass1_check_device_inode(fs, inode)) {
3571 check_immutable(ctx, &pctx);
3572 check_size(ctx, &pctx);
3573 ctx->fs_sockets_count++;
3574 } else
3575 mark_inode_bad(ctx, ino);
3576 if (inode->i_block[EXT2_IND_BLOCK])
3577 ctx->fs_ind_count++;
3578 if (inode->i_block[EXT2_DIND_BLOCK])
3579 ctx->fs_dind_count++;
3580 if (inode->i_block[EXT2_TIND_BLOCK])
3581 ctx->fs_tind_count++;
3582 if (inode->i_block[EXT2_IND_BLOCK] ||
3583 inode->i_block[EXT2_DIND_BLOCK] ||
3584 inode->i_block[EXT2_TIND_BLOCK] ||
3585 inode->i_file_acl) {
3586 inodes_to_process[process_inode_count].ino = ino;
3587 inodes_to_process[process_inode_count].inode = *inode;
3588 process_inode_count++;
3589 } else
3590 check_blocks(ctx, &pctx, block_buf);
3591
3592 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3593 return;
3594
3595 if (process_inode_count >= ctx->process_inode_size) {
3596 process_inodes(ctx, block_buf);
3597
3598 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3599 return;
3600 }
3601 }
3602 process_inodes(ctx, block_buf);
3603 ext2fs_close_inode_scan(scan);
3604 ehandler_operation(0);
3605
3606 /*
3607 * If any extended attribute blocks' reference counts need to
3608 * be adjusted, either up (ctx->refcount_extra), or down
3609 * (ctx->refcount), then fix them.
3610 */
3611 if (ctx->refcount) {
3612 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3613 ea_refcount_free(ctx->refcount);
3614 ctx->refcount = 0;
3615 }
3616 if (ctx->refcount_extra) {
3617 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3618 block_buf, +1);
3619 ea_refcount_free(ctx->refcount_extra);
3620 ctx->refcount_extra = 0;
3621 }
3622
3623 if (ctx->invalid_bitmaps)
3624 handle_fs_bad_blocks(ctx);
3625
3626 /* We don't need the block_ea_map any more */
3627 ext2fs_free_block_bitmap(ctx->block_ea_map);
3628 ctx->block_ea_map = 0;
3629
3630 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3631 ext2fs_block_bitmap save_bmap;
3632
3633 save_bmap = fs->block_map;
3634 fs->block_map = ctx->block_found_map;
3635 clear_problem_context(&pctx);
3636 pctx.errcode = ext2fs_create_resize_inode(fs);
3637 if (pctx.errcode) {
3638 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3639 /* Should never get here */
3640 ctx->flags |= E2F_FLAG_ABORT;
3641 return;
3642 }
3643 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3644 "recreate inode");
Denis Vlasenko04158e02009-02-02 10:48:06 +00003645 inode->i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003646 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3647 "recreate inode");
3648 fs->block_map = save_bmap;
3649 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3650 }
3651
3652 if (ctx->flags & E2F_FLAG_RESTART) {
3653 /*
3654 * Only the master copy of the superblock and block
3655 * group descriptors are going to be written during a
3656 * restart, so set the superblock to be used to be the
3657 * master superblock.
3658 */
3659 ctx->use_superblock = 0;
3660 unwind_pass1();
3661 goto endit;
3662 }
3663
3664 if (ctx->block_dup_map) {
3665 if (ctx->options & E2F_OPT_PREEN) {
3666 clear_problem_context(&pctx);
3667 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3668 }
3669 e2fsck_pass1_dupblocks(ctx, block_buf);
3670 }
3671 ext2fs_free_mem(&inodes_to_process);
3672endit:
3673 e2fsck_use_inode_shortcuts(ctx, 0);
3674
3675 ext2fs_free_mem(&block_buf);
3676 ext2fs_free_mem(&inode);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003677}
3678
3679/*
3680 * When the inode_scan routines call this callback at the end of the
3681 * glock group, call process_inodes.
3682 */
3683static errcode_t scan_callback(ext2_filsys fs,
3684 dgrp_t group, void * priv_data)
3685{
3686 struct scan_callback_struct *scan_struct;
3687 e2fsck_t ctx;
3688
3689 scan_struct = (struct scan_callback_struct *) priv_data;
3690 ctx = scan_struct->ctx;
3691
3692 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3693
3694 if (ctx->progress)
3695 if ((ctx->progress)(ctx, 1, group+1,
3696 ctx->fs->group_desc_count))
3697 return EXT2_ET_CANCEL_REQUESTED;
3698
3699 return 0;
3700}
3701
3702/*
3703 * Process the inodes in the "inodes to process" list.
3704 */
3705static void process_inodes(e2fsck_t ctx, char *block_buf)
3706{
3707 int i;
3708 struct ext2_inode *old_stashed_inode;
3709 ext2_ino_t old_stashed_ino;
3710 const char *old_operation;
3711 char buf[80];
3712 struct problem_context pctx;
3713
3714 /* begin process_inodes */
3715 if (process_inode_count == 0)
3716 return;
3717 old_operation = ehandler_operation(0);
3718 old_stashed_inode = ctx->stashed_inode;
3719 old_stashed_ino = ctx->stashed_ino;
3720 qsort(inodes_to_process, process_inode_count,
3721 sizeof(struct process_inode_block), process_inode_cmp);
3722 clear_problem_context(&pctx);
3723 for (i=0; i < process_inode_count; i++) {
3724 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3725 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3726 sprintf(buf, _("reading indirect blocks of inode %u"),
3727 pctx.ino);
3728 ehandler_operation(buf);
3729 check_blocks(ctx, &pctx, block_buf);
3730 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3731 break;
3732 }
3733 ctx->stashed_inode = old_stashed_inode;
3734 ctx->stashed_ino = old_stashed_ino;
3735 process_inode_count = 0;
3736 /* end process inodes */
3737
3738 ehandler_operation(old_operation);
3739}
3740
3741static int process_inode_cmp(const void *a, const void *b)
3742{
3743 const struct process_inode_block *ib_a =
3744 (const struct process_inode_block *) a;
3745 const struct process_inode_block *ib_b =
3746 (const struct process_inode_block *) b;
3747 int ret;
3748
3749 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3750 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3751 if (ret == 0)
3752 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3753 return ret;
3754}
3755
3756/*
3757 * Mark an inode as being bad in some what
3758 */
3759static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3760{
3761 struct problem_context pctx;
3762
3763 if (!ctx->inode_bad_map) {
3764 clear_problem_context(&pctx);
3765
3766 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3767 _("bad inode map"), &ctx->inode_bad_map);
3768 if (pctx.errcode) {
3769 pctx.num = 3;
3770 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3771 /* Should never get here */
3772 ctx->flags |= E2F_FLAG_ABORT;
3773 return;
3774 }
3775 }
3776 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3777}
3778
3779
3780/*
3781 * This procedure will allocate the inode imagic table
3782 */
3783static void alloc_imagic_map(e2fsck_t ctx)
3784{
3785 struct problem_context pctx;
3786
3787 clear_problem_context(&pctx);
3788 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3789 _("imagic inode map"),
3790 &ctx->inode_imagic_map);
3791 if (pctx.errcode) {
3792 pctx.num = 5;
3793 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3794 /* Should never get here */
3795 ctx->flags |= E2F_FLAG_ABORT;
3796 return;
3797 }
3798}
3799
3800/*
3801 * Marks a block as in use, setting the dup_map if it's been set
3802 * already. Called by process_block and process_bad_block.
3803 *
3804 * WARNING: Assumes checks have already been done to make sure block
3805 * is valid. This is true in both process_block and process_bad_block.
3806 */
3807static void mark_block_used(e2fsck_t ctx, blk_t block)
3808{
3809 struct problem_context pctx;
3810
3811 clear_problem_context(&pctx);
3812
3813 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3814 if (!ctx->block_dup_map) {
3815 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3816 _("multiply claimed block map"),
3817 &ctx->block_dup_map);
3818 if (pctx.errcode) {
3819 pctx.num = 3;
3820 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3821 &pctx);
3822 /* Should never get here */
3823 ctx->flags |= E2F_FLAG_ABORT;
3824 return;
3825 }
3826 }
3827 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3828 } else {
3829 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3830 }
3831}
3832
3833/*
3834 * Adjust the extended attribute block's reference counts at the end
3835 * of pass 1, either by subtracting out references for EA blocks that
3836 * are still referenced in ctx->refcount, or by adding references for
3837 * EA blocks that had extra references as accounted for in
3838 * ctx->refcount_extra.
3839 */
3840static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3841 char *block_buf, int adjust_sign)
3842{
3843 struct ext2_ext_attr_header *header;
3844 struct problem_context pctx;
3845 ext2_filsys fs = ctx->fs;
3846 blk_t blk;
3847 __u32 should_be;
3848 int count;
3849
3850 clear_problem_context(&pctx);
3851
3852 ea_refcount_intr_begin(refcount);
3853 while (1) {
3854 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3855 break;
3856 pctx.blk = blk;
3857 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3858 if (pctx.errcode) {
3859 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3860 return;
3861 }
3862 header = (struct ext2_ext_attr_header *) block_buf;
3863 pctx.blkcount = header->h_refcount;
3864 should_be = header->h_refcount + adjust_sign * count;
3865 pctx.num = should_be;
3866 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3867 header->h_refcount = should_be;
3868 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3869 block_buf);
3870 if (pctx.errcode) {
3871 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3872 continue;
3873 }
3874 }
3875 }
3876}
3877
3878/*
3879 * Handle processing the extended attribute blocks
3880 */
3881static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3882 char *block_buf)
3883{
3884 ext2_filsys fs = ctx->fs;
3885 ext2_ino_t ino = pctx->ino;
3886 struct ext2_inode *inode = pctx->inode;
3887 blk_t blk;
3888 char * end;
3889 struct ext2_ext_attr_header *header;
3890 struct ext2_ext_attr_entry *entry;
3891 int count;
3892 region_t region;
3893
3894 blk = inode->i_file_acl;
3895 if (blk == 0)
3896 return 0;
3897
3898 /*
3899 * If the Extended attribute flag isn't set, then a non-zero
3900 * file acl means that the inode is corrupted.
3901 *
3902 * Or if the extended attribute block is an invalid block,
3903 * then the inode is also corrupted.
3904 */
3905 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3906 (blk < fs->super->s_first_data_block) ||
3907 (blk >= fs->super->s_blocks_count)) {
3908 mark_inode_bad(ctx, ino);
3909 return 0;
3910 }
3911
3912 /* If ea bitmap hasn't been allocated, create it */
3913 if (!ctx->block_ea_map) {
3914 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3915 _("ext attr block map"),
3916 &ctx->block_ea_map);
3917 if (pctx->errcode) {
3918 pctx->num = 2;
3919 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3920 ctx->flags |= E2F_FLAG_ABORT;
3921 return 0;
3922 }
3923 }
3924
3925 /* Create the EA refcount structure if necessary */
3926 if (!ctx->refcount) {
3927 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3928 if (pctx->errcode) {
3929 pctx->num = 1;
3930 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3931 ctx->flags |= E2F_FLAG_ABORT;
3932 return 0;
3933 }
3934 }
3935
3936 /* Have we seen this EA block before? */
3937 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3938 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3939 return 1;
3940 /* Ooops, this EA was referenced more than it stated */
3941 if (!ctx->refcount_extra) {
3942 pctx->errcode = ea_refcount_create(0,
3943 &ctx->refcount_extra);
3944 if (pctx->errcode) {
3945 pctx->num = 2;
3946 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3947 ctx->flags |= E2F_FLAG_ABORT;
3948 return 0;
3949 }
3950 }
3951 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3952 return 1;
3953 }
3954
3955 /*
3956 * OK, we haven't seen this EA block yet. So we need to
3957 * validate it
3958 */
3959 pctx->blk = blk;
3960 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3961 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3962 goto clear_extattr;
3963 header = (struct ext2_ext_attr_header *) block_buf;
3964 pctx->blk = inode->i_file_acl;
3965 if (((ctx->ext_attr_ver == 1) &&
3966 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3967 ((ctx->ext_attr_ver == 2) &&
3968 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3969 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3970 goto clear_extattr;
3971 }
3972
3973 if (header->h_blocks != 1) {
3974 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3975 goto clear_extattr;
3976 }
3977
3978 region = region_create(0, fs->blocksize);
3979 if (!region) {
3980 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3981 ctx->flags |= E2F_FLAG_ABORT;
3982 return 0;
3983 }
3984 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3985 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3986 goto clear_extattr;
3987 }
3988
3989 entry = (struct ext2_ext_attr_entry *)(header+1);
3990 end = block_buf + fs->blocksize;
3991 while ((char *)entry < end && *(__u32 *)entry) {
3992 if (region_allocate(region, (char *)entry - (char *)header,
3993 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
3994 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3995 goto clear_extattr;
3996 }
3997 if ((ctx->ext_attr_ver == 1 &&
3998 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
3999 (ctx->ext_attr_ver == 2 &&
4000 entry->e_name_index == 0)) {
4001 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4002 goto clear_extattr;
4003 }
4004 if (entry->e_value_block != 0) {
4005 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4006 goto clear_extattr;
4007 }
4008 if (entry->e_value_size &&
4009 region_allocate(region, entry->e_value_offs,
4010 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4011 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4012 goto clear_extattr;
4013 }
4014 entry = EXT2_EXT_ATTR_NEXT(entry);
4015 }
4016 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4017 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4018 goto clear_extattr;
4019 }
4020 region_free(region);
4021
4022 count = header->h_refcount - 1;
4023 if (count)
4024 ea_refcount_store(ctx->refcount, blk, count);
4025 mark_block_used(ctx, blk);
4026 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4027
4028 return 1;
4029
4030clear_extattr:
4031 inode->i_file_acl = 0;
4032 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4033 return 0;
4034}
4035
4036/* Returns 1 if bad htree, 0 if OK */
4037static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4038 ext2_ino_t ino FSCK_ATTR((unused)),
4039 struct ext2_inode *inode,
4040 char *block_buf)
4041{
4042 struct ext2_dx_root_info *root;
4043 ext2_filsys fs = ctx->fs;
4044 errcode_t retval;
4045 blk_t blk;
4046
4047 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4048 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4049 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4050 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4051 return 1;
4052
4053 blk = inode->i_block[0];
4054 if (((blk == 0) ||
4055 (blk < fs->super->s_first_data_block) ||
4056 (blk >= fs->super->s_blocks_count)) &&
4057 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4058 return 1;
4059
4060 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4061 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4062 return 1;
4063
4064 /* XXX should check that beginning matches a directory */
4065 root = (struct ext2_dx_root_info *) (block_buf + 24);
4066
4067 if ((root->reserved_zero || root->info_length < 8) &&
4068 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4069 return 1;
4070
4071 pctx->num = root->hash_version;
4072 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4073 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4074 (root->hash_version != EXT2_HASH_TEA) &&
4075 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4076 return 1;
4077
4078 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4079 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4080 return 1;
4081
4082 pctx->num = root->indirect_levels;
4083 if ((root->indirect_levels > 1) &&
4084 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4085 return 1;
4086
4087 return 0;
4088}
4089
4090/*
4091 * This subroutine is called on each inode to account for all of the
4092 * blocks used by that inode.
4093 */
4094static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4095 char *block_buf)
4096{
4097 ext2_filsys fs = ctx->fs;
4098 struct process_block_struct_1 pb;
4099 ext2_ino_t ino = pctx->ino;
4100 struct ext2_inode *inode = pctx->inode;
4101 int bad_size = 0;
4102 int dirty_inode = 0;
4103 __u64 size;
4104
4105 pb.ino = ino;
4106 pb.num_blocks = 0;
4107 pb.last_block = -1;
4108 pb.num_illegal_blocks = 0;
4109 pb.suppress = 0; pb.clear = 0;
4110 pb.fragmented = 0;
4111 pb.compressed = 0;
4112 pb.previous_block = 0;
4113 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4114 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4115 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4116 pb.inode = inode;
4117 pb.pctx = pctx;
4118 pb.ctx = ctx;
4119 pctx->ino = ino;
4120 pctx->errcode = 0;
4121
4122 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4123 if (fs->super->s_feature_incompat &
4124 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4125 pb.compressed = 1;
4126 else {
4127 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4128 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4129 dirty_inode++;
4130 }
4131 }
4132 }
4133
4134 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4135 pb.num_blocks++;
4136
4137 if (ext2fs_inode_has_valid_blocks(inode))
4138 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4139 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4140 block_buf, process_block, &pb);
4141 end_problem_latch(ctx, PR_LATCH_BLOCK);
4142 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4143 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4144 goto out;
4145 if (pctx->errcode)
4146 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4147
4148 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4149 ctx->fs_fragmented++;
4150
4151 if (pb.clear) {
4152 inode->i_links_count = 0;
4153 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004154 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004155 dirty_inode++;
4156 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4157 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4158 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4159 /*
4160 * The inode was probably partially accounted for
4161 * before processing was aborted, so we need to
4162 * restart the pass 1 scan.
4163 */
4164 ctx->flags |= E2F_FLAG_RESTART;
4165 goto out;
4166 }
4167
4168 if (inode->i_flags & EXT2_INDEX_FL) {
4169 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4170 inode->i_flags &= ~EXT2_INDEX_FL;
4171 dirty_inode++;
4172 } else {
4173#ifdef ENABLE_HTREE
4174 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4175#endif
4176 }
4177 }
4178 if (ctx->dirs_to_hash && pb.is_dir &&
4179 !(inode->i_flags & EXT2_INDEX_FL) &&
4180 ((inode->i_size / fs->blocksize) >= 3))
4181 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4182
4183 if (!pb.num_blocks && pb.is_dir) {
4184 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4185 inode->i_links_count = 0;
4186 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004187 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004188 dirty_inode++;
4189 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4190 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4191 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4192 ctx->fs_directory_count--;
4193 goto out;
4194 }
4195 }
4196
4197 pb.num_blocks *= (fs->blocksize / 512);
4198
4199 if (pb.is_dir) {
4200 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4201 if (nblock > (pb.last_block + 1))
4202 bad_size = 1;
4203 else if (nblock < (pb.last_block + 1)) {
4204 if (((pb.last_block + 1) - nblock) >
4205 fs->super->s_prealloc_dir_blocks)
4206 bad_size = 2;
4207 }
4208 } else {
4209 size = EXT2_I_SIZE(inode);
4210 if ((pb.last_block >= 0) &&
4211 (size < (__u64) pb.last_block * fs->blocksize))
4212 bad_size = 3;
4213 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4214 bad_size = 4;
4215 }
4216 /* i_size for symlinks is checked elsewhere */
4217 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4218 pctx->num = (pb.last_block+1) * fs->blocksize;
4219 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4220 inode->i_size = pctx->num;
4221 if (!LINUX_S_ISDIR(inode->i_mode))
4222 inode->i_size_high = pctx->num >> 32;
4223 dirty_inode++;
4224 }
4225 pctx->num = 0;
4226 }
4227 if (LINUX_S_ISREG(inode->i_mode) &&
4228 (inode->i_size_high || inode->i_size & 0x80000000UL))
4229 ctx->large_files++;
4230 if (pb.num_blocks != inode->i_blocks) {
4231 pctx->num = pb.num_blocks;
4232 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4233 inode->i_blocks = pb.num_blocks;
4234 dirty_inode++;
4235 }
4236 pctx->num = 0;
4237 }
4238out:
4239 if (dirty_inode)
4240 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4241}
4242
4243
4244/*
4245 * This is a helper function for check_blocks().
4246 */
4247static int process_block(ext2_filsys fs,
4248 blk_t *block_nr,
4249 e2_blkcnt_t blockcnt,
4250 blk_t ref_block FSCK_ATTR((unused)),
4251 int ref_offset FSCK_ATTR((unused)),
4252 void *priv_data)
4253{
4254 struct process_block_struct_1 *p;
4255 struct problem_context *pctx;
4256 blk_t blk = *block_nr;
4257 int ret_code = 0;
4258 int problem = 0;
4259 e2fsck_t ctx;
4260
4261 p = (struct process_block_struct_1 *) priv_data;
4262 pctx = p->pctx;
4263 ctx = p->ctx;
4264
4265 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4266 /* todo: Check that the comprblk_fl is high, that the
4267 blkaddr pattern looks right (all non-holes up to
4268 first EXT2FS_COMPRESSED_BLKADDR, then all
4269 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4270 that the feature_incompat bit is high, and that the
4271 inode is a regular file. If we're doing a "full
4272 check" (a concept introduced to e2fsck by e2compr,
4273 meaning that we look at data blocks as well as
4274 metadata) then call some library routine that
4275 checks the compressed data. I'll have to think
4276 about this, because one particularly important
4277 problem to be able to fix is to recalculate the
4278 cluster size if necessary. I think that perhaps
4279 we'd better do most/all e2compr-specific checks
4280 separately, after the non-e2compr checks. If not
4281 doing a full check, it may be useful to test that
4282 the personality is linux; e.g. if it isn't then
4283 perhaps this really is just an illegal block. */
4284 return 0;
4285 }
4286
4287 if (blk == 0) {
4288 if (p->is_dir == 0) {
4289 /*
4290 * Should never happen, since only directories
4291 * get called with BLOCK_FLAG_HOLE
4292 */
4293#ifdef DEBUG_E2FSCK
4294 printf("process_block() called with blk == 0, "
4295 "blockcnt=%d, inode %lu???\n",
4296 blockcnt, p->ino);
4297#endif
4298 return 0;
4299 }
4300 if (blockcnt < 0)
4301 return 0;
4302 if (blockcnt * fs->blocksize < p->inode->i_size) {
4303 goto mark_dir;
4304 }
4305 return 0;
4306 }
4307
4308 /*
4309 * Simplistic fragmentation check. We merely require that the
4310 * file be contiguous. (Which can never be true for really
4311 * big files that are greater than a block group.)
4312 */
4313 if (!HOLE_BLKADDR(p->previous_block)) {
4314 if (p->previous_block+1 != blk)
4315 p->fragmented = 1;
4316 }
4317 p->previous_block = blk;
4318
4319 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4320 problem = PR_1_TOOBIG_DIR;
4321 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4322 problem = PR_1_TOOBIG_REG;
4323 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4324 problem = PR_1_TOOBIG_SYMLINK;
4325
4326 if (blk < fs->super->s_first_data_block ||
4327 blk >= fs->super->s_blocks_count)
4328 problem = PR_1_ILLEGAL_BLOCK_NUM;
4329
4330 if (problem) {
4331 p->num_illegal_blocks++;
4332 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4333 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4334 p->clear = 1;
4335 return BLOCK_ABORT;
4336 }
4337 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4338 p->suppress = 1;
4339 set_latch_flags(PR_LATCH_BLOCK,
4340 PRL_SUPPRESS, 0);
4341 }
4342 }
4343 pctx->blk = blk;
4344 pctx->blkcount = blockcnt;
4345 if (fix_problem(ctx, problem, pctx)) {
4346 blk = *block_nr = 0;
4347 ret_code = BLOCK_CHANGED;
4348 goto mark_dir;
4349 } else
4350 return 0;
4351 }
4352
4353 if (p->ino == EXT2_RESIZE_INO) {
4354 /*
4355 * The resize inode has already be sanity checked
4356 * during pass #0 (the superblock checks). All we
4357 * have to do is mark the double indirect block as
4358 * being in use; all of the other blocks are handled
4359 * by mark_table_blocks()).
4360 */
4361 if (blockcnt == BLOCK_COUNT_DIND)
4362 mark_block_used(ctx, blk);
4363 } else
4364 mark_block_used(ctx, blk);
4365 p->num_blocks++;
4366 if (blockcnt >= 0)
4367 p->last_block = blockcnt;
4368mark_dir:
4369 if (p->is_dir && (blockcnt >= 0)) {
4370 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4371 blk, blockcnt);
4372 if (pctx->errcode) {
4373 pctx->blk = blk;
4374 pctx->num = blockcnt;
4375 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4376 /* Should never get here */
4377 ctx->flags |= E2F_FLAG_ABORT;
4378 return BLOCK_ABORT;
4379 }
4380 }
4381 return ret_code;
4382}
4383
4384static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4385 blk_t *block_nr,
4386 e2_blkcnt_t blockcnt,
4387 blk_t ref_block FSCK_ATTR((unused)),
4388 int ref_offset FSCK_ATTR((unused)),
4389 void *priv_data EXT2FS_ATTR((unused)))
4390{
4391 /*
4392 * Note: This function processes blocks for the bad blocks
4393 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4394 */
4395
4396 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4397 return BLOCK_ERROR;
4398}
4399
4400/*
4401 * This routine gets called at the end of pass 1 if bad blocks are
4402 * detected in the superblock, group descriptors, inode_bitmaps, or
4403 * block bitmaps. At this point, all of the blocks have been mapped
4404 * out, so we can try to allocate new block(s) to replace the bad
4405 * blocks.
4406 */
4407static void handle_fs_bad_blocks(e2fsck_t ctx)
4408{
4409 printf("Bad blocks detected on your filesystem\n"
4410 "You should get your data off as the device will soon die\n");
4411}
4412
4413/*
4414 * This routine marks all blocks which are used by the superblock,
4415 * group descriptors, inode bitmaps, and block bitmaps.
4416 */
4417static void mark_table_blocks(e2fsck_t ctx)
4418{
4419 ext2_filsys fs = ctx->fs;
4420 blk_t block, b;
4421 dgrp_t i;
4422 int j;
4423 struct problem_context pctx;
4424
4425 clear_problem_context(&pctx);
4426
4427 block = fs->super->s_first_data_block;
4428 for (i = 0; i < fs->group_desc_count; i++) {
4429 pctx.group = i;
4430
4431 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4432
4433 /*
4434 * Mark the blocks used for the inode table
4435 */
4436 if (fs->group_desc[i].bg_inode_table) {
4437 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4438 j < fs->inode_blocks_per_group;
4439 j++, b++) {
4440 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4441 b)) {
4442 pctx.blk = b;
4443 if (fix_problem(ctx,
4444 PR_1_ITABLE_CONFLICT, &pctx)) {
4445 ctx->invalid_inode_table_flag[i]++;
4446 ctx->invalid_bitmaps++;
4447 }
4448 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004449 ext2fs_mark_block_bitmap(ctx->block_found_map, b);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004450 }
4451 }
4452 }
4453
4454 /*
4455 * Mark block used for the block bitmap
4456 */
4457 if (fs->group_desc[i].bg_block_bitmap) {
4458 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4459 fs->group_desc[i].bg_block_bitmap)) {
4460 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4461 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4462 ctx->invalid_block_bitmap_flag[i]++;
4463 ctx->invalid_bitmaps++;
4464 }
4465 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004466 ext2fs_mark_block_bitmap(ctx->block_found_map,
4467 fs->group_desc[i].bg_block_bitmap);
4468 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004469 }
4470 /*
4471 * Mark block used for the inode bitmap
4472 */
4473 if (fs->group_desc[i].bg_inode_bitmap) {
4474 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4475 fs->group_desc[i].bg_inode_bitmap)) {
4476 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4477 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4478 ctx->invalid_inode_bitmap_flag[i]++;
4479 ctx->invalid_bitmaps++;
4480 }
4481 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004482 ext2fs_mark_block_bitmap(ctx->block_found_map,
4483 fs->group_desc[i].bg_inode_bitmap);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004484 }
4485 }
4486 block += fs->super->s_blocks_per_group;
4487 }
4488}
4489
4490/*
4491 * Thes subroutines short circuits ext2fs_get_blocks and
4492 * ext2fs_check_directory; we use them since we already have the inode
4493 * structure, so there's no point in letting the ext2fs library read
4494 * the inode again.
4495 */
4496static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4497 blk_t *blocks)
4498{
4499 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4500 int i;
4501
4502 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4503 return EXT2_ET_CALLBACK_NOTHANDLED;
4504
4505 for (i=0; i < EXT2_N_BLOCKS; i++)
4506 blocks[i] = ctx->stashed_inode->i_block[i];
4507 return 0;
4508}
4509
4510static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4511 struct ext2_inode *inode)
4512{
4513 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4514
4515 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4516 return EXT2_ET_CALLBACK_NOTHANDLED;
4517 *inode = *ctx->stashed_inode;
4518 return 0;
4519}
4520
4521static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4522 struct ext2_inode *inode)
4523{
4524 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4525
4526 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4527 *ctx->stashed_inode = *inode;
4528 return EXT2_ET_CALLBACK_NOTHANDLED;
4529}
4530
4531static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
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
4538 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4539 return EXT2_ET_NO_DIRECTORY;
4540 return 0;
4541}
4542
4543void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4544{
4545 ext2_filsys fs = ctx->fs;
4546
4547 if (bool) {
4548 fs->get_blocks = pass1_get_blocks;
4549 fs->check_directory = pass1_check_directory;
4550 fs->read_inode = pass1_read_inode;
4551 fs->write_inode = pass1_write_inode;
4552 ctx->stashed_ino = 0;
4553 } else {
4554 fs->get_blocks = 0;
4555 fs->check_directory = 0;
4556 fs->read_inode = 0;
4557 fs->write_inode = 0;
4558 }
4559}
4560
4561/*
4562 * pass1b.c --- Pass #1b of e2fsck
4563 *
4564 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4565 * only invoked if pass 1 discovered blocks which are in use by more
4566 * than one inode.
4567 *
4568 * Pass1B scans the data blocks of all the inodes again, generating a
4569 * complete list of duplicate blocks and which inodes have claimed
4570 * them.
4571 *
4572 * Pass1C does a tree-traversal of the filesystem, to determine the
4573 * parent directories of these inodes. This step is necessary so that
4574 * e2fsck can print out the pathnames of affected inodes.
4575 *
4576 * Pass1D is a reconciliation pass. For each inode with duplicate
4577 * blocks, the user is prompted if s/he would like to clone the file
4578 * (so that the file gets a fresh copy of the duplicated blocks) or
4579 * simply to delete the file.
4580 *
4581 */
4582
4583
4584/* Needed for architectures where sizeof(int) != sizeof(void *) */
4585#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4586#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4587
4588/* Define an extension to the ext2 library's block count information */
4589#define BLOCK_COUNT_EXTATTR (-5)
4590
4591struct block_el {
4592 blk_t block;
4593 struct block_el *next;
4594};
4595
4596struct inode_el {
4597 ext2_ino_t inode;
4598 struct inode_el *next;
4599};
4600
4601struct dup_block {
4602 int num_bad;
4603 struct inode_el *inode_list;
4604};
4605
4606/*
4607 * This structure stores information about a particular inode which
4608 * is sharing blocks with other inodes. This information is collected
4609 * to display to the user, so that the user knows what files he or she
4610 * is dealing with, when trying to decide how to resolve the conflict
4611 * of multiply-claimed blocks.
4612 */
4613struct dup_inode {
4614 ext2_ino_t dir;
4615 int num_dupblocks;
4616 struct ext2_inode inode;
4617 struct block_el *block_list;
4618};
4619
4620static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4621 e2_blkcnt_t blockcnt, blk_t ref_blk,
4622 int ref_offset, void *priv_data);
4623static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4624 struct dup_inode *dp, char *block_buf);
4625static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4626 struct dup_inode *dp, char* block_buf);
4627static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4628
4629static void pass1b(e2fsck_t ctx, char *block_buf);
4630static void pass1c(e2fsck_t ctx, char *block_buf);
4631static void pass1d(e2fsck_t ctx, char *block_buf);
4632
4633static int dup_inode_count = 0;
4634
4635static dict_t blk_dict, ino_dict;
4636
4637static ext2fs_inode_bitmap inode_dup_map;
4638
4639static int dict_int_cmp(const void *a, const void *b)
4640{
4641 intptr_t ia, ib;
4642
4643 ia = (intptr_t)a;
4644 ib = (intptr_t)b;
4645
4646 return (ia-ib);
4647}
4648
4649/*
4650 * Add a duplicate block record
4651 */
4652static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4653 struct ext2_inode *inode)
4654{
4655 dnode_t *n;
4656 struct dup_block *db;
4657 struct dup_inode *di;
4658 struct block_el *blk_el;
4659 struct inode_el *ino_el;
4660
4661 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4662 if (n)
4663 db = (struct dup_block *) dnode_get(n);
4664 else {
4665 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4666 sizeof(struct dup_block), "duplicate block header");
4667 db->num_bad = 0;
4668 db->inode_list = 0;
4669 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4670 }
4671 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4672 sizeof(struct inode_el), "inode element");
4673 ino_el->inode = ino;
4674 ino_el->next = db->inode_list;
4675 db->inode_list = ino_el;
4676 db->num_bad++;
4677
4678 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4679 if (n)
4680 di = (struct dup_inode *) dnode_get(n);
4681 else {
4682 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4683 sizeof(struct dup_inode), "duplicate inode header");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00004684 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004685 di->num_dupblocks = 0;
4686 di->block_list = 0;
4687 di->inode = *inode;
4688 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4689 }
4690 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4691 sizeof(struct block_el), "block element");
4692 blk_el->block = blk;
4693 blk_el->next = di->block_list;
4694 di->block_list = blk_el;
4695 di->num_dupblocks++;
4696}
4697
4698/*
4699 * Free a duplicate inode record
4700 */
4701static void inode_dnode_free(dnode_t *node)
4702{
4703 struct dup_inode *di;
4704 struct block_el *p, *next;
4705
4706 di = (struct dup_inode *) dnode_get(node);
4707 for (p = di->block_list; p; p = next) {
4708 next = p->next;
4709 free(p);
4710 }
4711 free(node);
4712}
4713
4714/*
4715 * Free a duplicate block record
4716 */
4717static void block_dnode_free(dnode_t *node)
4718{
4719 struct dup_block *db;
4720 struct inode_el *p, *next;
4721
4722 db = (struct dup_block *) dnode_get(node);
4723 for (p = db->inode_list; p; p = next) {
4724 next = p->next;
4725 free(p);
4726 }
4727 free(node);
4728}
4729
4730
4731/*
4732 * Main procedure for handling duplicate blocks
4733 */
4734void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4735{
4736 ext2_filsys fs = ctx->fs;
4737 struct problem_context pctx;
4738
4739 clear_problem_context(&pctx);
4740
4741 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4742 _("multiply claimed inode map"), &inode_dup_map);
4743 if (pctx.errcode) {
4744 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4745 ctx->flags |= E2F_FLAG_ABORT;
4746 return;
4747 }
4748
4749 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4750 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4751 dict_set_allocator(&ino_dict, inode_dnode_free);
4752 dict_set_allocator(&blk_dict, block_dnode_free);
4753
4754 pass1b(ctx, block_buf);
4755 pass1c(ctx, block_buf);
4756 pass1d(ctx, block_buf);
4757
4758 /*
4759 * Time to free all of the accumulated data structures that we
4760 * don't need anymore.
4761 */
4762 dict_free_nodes(&ino_dict);
4763 dict_free_nodes(&blk_dict);
4764}
4765
4766/*
4767 * Scan the inodes looking for inodes that contain duplicate blocks.
4768 */
4769struct process_block_struct_1b {
4770 e2fsck_t ctx;
4771 ext2_ino_t ino;
4772 int dup_blocks;
4773 struct ext2_inode *inode;
4774 struct problem_context *pctx;
4775};
4776
4777static void pass1b(e2fsck_t ctx, char *block_buf)
4778{
4779 ext2_filsys fs = ctx->fs;
4780 ext2_ino_t ino;
4781 struct ext2_inode inode;
4782 ext2_inode_scan scan;
4783 struct process_block_struct_1b pb;
4784 struct problem_context pctx;
4785
4786 clear_problem_context(&pctx);
4787
4788 if (!(ctx->options & E2F_OPT_PREEN))
4789 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4790 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4791 &scan);
4792 if (pctx.errcode) {
4793 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4794 ctx->flags |= E2F_FLAG_ABORT;
4795 return;
4796 }
4797 ctx->stashed_inode = &inode;
4798 pb.ctx = ctx;
4799 pb.pctx = &pctx;
4800 pctx.str = "pass1b";
4801 while (1) {
4802 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4803 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4804 continue;
4805 if (pctx.errcode) {
4806 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4807 ctx->flags |= E2F_FLAG_ABORT;
4808 return;
4809 }
4810 if (!ino)
4811 break;
4812 pctx.ino = ctx->stashed_ino = ino;
4813 if ((ino != EXT2_BAD_INO) &&
4814 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4815 continue;
4816
4817 pb.ino = ino;
4818 pb.dup_blocks = 0;
4819 pb.inode = &inode;
4820
4821 if (ext2fs_inode_has_valid_blocks(&inode) ||
4822 (ino == EXT2_BAD_INO))
4823 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4824 0, block_buf, process_pass1b_block, &pb);
4825 if (inode.i_file_acl)
4826 process_pass1b_block(fs, &inode.i_file_acl,
4827 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4828 if (pb.dup_blocks) {
4829 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4830 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4831 ino == EXT2_ROOT_INO)
4832 dup_inode_count++;
4833 }
4834 if (pctx.errcode)
4835 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4836 }
4837 ext2fs_close_inode_scan(scan);
4838 e2fsck_use_inode_shortcuts(ctx, 0);
4839}
4840
4841static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4842 blk_t *block_nr,
4843 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4844 blk_t ref_blk FSCK_ATTR((unused)),
4845 int ref_offset FSCK_ATTR((unused)),
4846 void *priv_data)
4847{
4848 struct process_block_struct_1b *p;
4849 e2fsck_t ctx;
4850
4851 if (HOLE_BLKADDR(*block_nr))
4852 return 0;
4853 p = (struct process_block_struct_1b *) priv_data;
4854 ctx = p->ctx;
4855
4856 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4857 return 0;
4858
4859 /* OK, this is a duplicate block */
4860 if (p->ino != EXT2_BAD_INO) {
4861 p->pctx->blk = *block_nr;
4862 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4863 }
4864 p->dup_blocks++;
4865 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4866
4867 add_dupe(ctx, p->ino, *block_nr, p->inode);
4868
4869 return 0;
4870}
4871
4872/*
4873 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4874 * is used so that we can print pathnames when prompting the user for
4875 * what to do.
4876 */
4877struct search_dir_struct {
4878 int count;
4879 ext2_ino_t first_inode;
4880 ext2_ino_t max_inode;
4881};
4882
4883static int search_dirent_proc(ext2_ino_t dir, int entry,
4884 struct ext2_dir_entry *dirent,
4885 int offset FSCK_ATTR((unused)),
4886 int blocksize FSCK_ATTR((unused)),
4887 char *buf FSCK_ATTR((unused)),
4888 void *priv_data)
4889{
4890 struct search_dir_struct *sd;
4891 struct dup_inode *p;
4892 dnode_t *n;
4893
4894 sd = (struct search_dir_struct *) priv_data;
4895
4896 if (dirent->inode > sd->max_inode)
4897 /* Should abort this inode, but not everything */
4898 return 0;
4899
4900 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4901 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4902 return 0;
4903
4904 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4905 if (!n)
4906 return 0;
4907 p = (struct dup_inode *) dnode_get(n);
4908 p->dir = dir;
4909 sd->count--;
4910
4911 return sd->count ? 0 : DIRENT_ABORT;
4912}
4913
4914
4915static void pass1c(e2fsck_t ctx, char *block_buf)
4916{
4917 ext2_filsys fs = ctx->fs;
4918 struct search_dir_struct sd;
4919 struct problem_context pctx;
4920
4921 clear_problem_context(&pctx);
4922
4923 if (!(ctx->options & E2F_OPT_PREEN))
4924 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4925
4926 /*
4927 * Search through all directories to translate inodes to names
4928 * (by searching for the containing directory for that inode.)
4929 */
4930 sd.count = dup_inode_count;
4931 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4932 sd.max_inode = fs->super->s_inodes_count;
4933 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4934 search_dirent_proc, &sd);
4935}
4936
4937static void pass1d(e2fsck_t ctx, char *block_buf)
4938{
4939 ext2_filsys fs = ctx->fs;
4940 struct dup_inode *p, *t;
4941 struct dup_block *q;
4942 ext2_ino_t *shared, ino;
4943 int shared_len;
4944 int i;
4945 int file_ok;
4946 int meta_data = 0;
4947 struct problem_context pctx;
4948 dnode_t *n, *m;
4949 struct block_el *s;
4950 struct inode_el *r;
4951
4952 clear_problem_context(&pctx);
4953
4954 if (!(ctx->options & E2F_OPT_PREEN))
4955 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4956 e2fsck_read_bitmaps(ctx);
4957
4958 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4959 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4960 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4961 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4962 "Shared inode list");
4963 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4964 p = (struct dup_inode *) dnode_get(n);
4965 shared_len = 0;
4966 file_ok = 1;
4967 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4968 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4969 continue;
4970
4971 /*
4972 * Find all of the inodes which share blocks with this
4973 * one. First we find all of the duplicate blocks
4974 * belonging to this inode, and then search each block
4975 * get the list of inodes, and merge them together.
4976 */
4977 for (s = p->block_list; s; s = s->next) {
4978 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4979 if (!m)
4980 continue; /* Should never happen... */
4981 q = (struct dup_block *) dnode_get(m);
4982 if (q->num_bad > 1)
4983 file_ok = 0;
4984 if (check_if_fs_block(ctx, s->block)) {
4985 file_ok = 0;
4986 meta_data = 1;
4987 }
4988
4989 /*
4990 * Add all inodes used by this block to the
4991 * shared[] --- which is a unique list, so
4992 * if an inode is already in shared[], don't
4993 * add it again.
4994 */
4995 for (r = q->inode_list; r; r = r->next) {
4996 if (r->inode == ino)
4997 continue;
4998 for (i = 0; i < shared_len; i++)
4999 if (shared[i] == r->inode)
5000 break;
5001 if (i == shared_len) {
5002 shared[shared_len++] = r->inode;
5003 }
5004 }
5005 }
5006
5007 /*
5008 * Report the inode that we are working on
5009 */
5010 pctx.inode = &p->inode;
5011 pctx.ino = ino;
5012 pctx.dir = p->dir;
5013 pctx.blkcount = p->num_dupblocks;
5014 pctx.num = meta_data ? shared_len+1 : shared_len;
5015 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5016 pctx.blkcount = 0;
5017 pctx.num = 0;
5018
5019 if (meta_data)
5020 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5021
5022 for (i = 0; i < shared_len; i++) {
5023 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5024 if (!m)
5025 continue; /* should never happen */
5026 t = (struct dup_inode *) dnode_get(m);
5027 /*
5028 * Report the inode that we are sharing with
5029 */
5030 pctx.inode = &t->inode;
5031 pctx.ino = shared[i];
5032 pctx.dir = t->dir;
5033 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5034 }
5035 if (file_ok) {
5036 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5037 continue;
5038 }
5039 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5040 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5041 if (pctx.errcode)
5042 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5043 else
5044 continue;
5045 }
5046 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5047 delete_file(ctx, ino, p, block_buf);
5048 else
5049 ext2fs_unmark_valid(fs);
5050 }
5051 ext2fs_free_mem(&shared);
5052}
5053
5054/*
5055 * Drop the refcount on the dup_block structure, and clear the entry
5056 * in the block_dup_map if appropriate.
5057 */
5058static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5059{
5060 p->num_bad--;
5061 if (p->num_bad <= 0 ||
5062 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5063 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5064}
5065
5066static int delete_file_block(ext2_filsys fs,
5067 blk_t *block_nr,
5068 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5069 blk_t ref_block FSCK_ATTR((unused)),
5070 int ref_offset FSCK_ATTR((unused)),
5071 void *priv_data)
5072{
5073 struct process_block_struct_1b *pb;
5074 struct dup_block *p;
5075 dnode_t *n;
5076 e2fsck_t ctx;
5077
5078 pb = (struct process_block_struct_1b *) priv_data;
5079 ctx = pb->ctx;
5080
5081 if (HOLE_BLKADDR(*block_nr))
5082 return 0;
5083
5084 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5085 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5086 if (n) {
5087 p = (struct dup_block *) dnode_get(n);
5088 decrement_badcount(ctx, *block_nr, p);
5089 } else
5090 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5091 *block_nr);
5092 } else {
5093 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5094 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5095 }
5096
5097 return 0;
5098}
5099
5100static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5101 struct dup_inode *dp, char* block_buf)
5102{
5103 ext2_filsys fs = ctx->fs;
5104 struct process_block_struct_1b pb;
5105 struct ext2_inode inode;
5106 struct problem_context pctx;
5107 unsigned int count;
5108
5109 clear_problem_context(&pctx);
5110 pctx.ino = pb.ino = ino;
5111 pb.dup_blocks = dp->num_dupblocks;
5112 pb.ctx = ctx;
5113 pctx.str = "delete_file";
5114
5115 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5116 if (ext2fs_inode_has_valid_blocks(&inode))
5117 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5118 delete_file_block, &pb);
5119 if (pctx.errcode)
5120 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5121 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5122 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5123 if (ctx->inode_bad_map)
5124 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5125 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5126
5127 /* Inode may have changed by block_iterate, so reread it */
5128 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5129 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00005130 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005131 if (inode.i_file_acl &&
5132 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5133 count = 1;
5134 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5135 block_buf, -1, &count);
5136 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5137 pctx.errcode = 0;
5138 count = 1;
5139 }
5140 if (pctx.errcode) {
5141 pctx.blk = inode.i_file_acl;
5142 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5143 }
5144 /*
5145 * If the count is zero, then arrange to have the
5146 * block deleted. If the block is in the block_dup_map,
5147 * also call delete_file_block since it will take care
5148 * of keeping the accounting straight.
5149 */
5150 if ((count == 0) ||
5151 ext2fs_test_block_bitmap(ctx->block_dup_map,
5152 inode.i_file_acl))
5153 delete_file_block(fs, &inode.i_file_acl,
5154 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5155 }
5156 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5157}
5158
5159struct clone_struct {
5160 errcode_t errcode;
5161 ext2_ino_t dir;
5162 char *buf;
5163 e2fsck_t ctx;
5164};
5165
5166static int clone_file_block(ext2_filsys fs,
5167 blk_t *block_nr,
5168 e2_blkcnt_t blockcnt,
5169 blk_t ref_block FSCK_ATTR((unused)),
5170 int ref_offset FSCK_ATTR((unused)),
5171 void *priv_data)
5172{
5173 struct dup_block *p;
5174 blk_t new_block;
5175 errcode_t retval;
5176 struct clone_struct *cs = (struct clone_struct *) priv_data;
5177 dnode_t *n;
5178 e2fsck_t ctx;
5179
5180 ctx = cs->ctx;
5181
5182 if (HOLE_BLKADDR(*block_nr))
5183 return 0;
5184
5185 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5186 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5187 if (n) {
5188 p = (struct dup_block *) dnode_get(n);
5189 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5190 &new_block);
5191 if (retval) {
5192 cs->errcode = retval;
5193 return BLOCK_ABORT;
5194 }
5195 if (cs->dir && (blockcnt >= 0)) {
5196 retval = ext2fs_set_dir_block(fs->dblist,
5197 cs->dir, new_block, blockcnt);
5198 if (retval) {
5199 cs->errcode = retval;
5200 return BLOCK_ABORT;
5201 }
5202 }
5203
5204 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5205 cs->buf);
5206 if (retval) {
5207 cs->errcode = retval;
5208 return BLOCK_ABORT;
5209 }
5210 retval = io_channel_write_blk(fs->io, new_block, 1,
5211 cs->buf);
5212 if (retval) {
5213 cs->errcode = retval;
5214 return BLOCK_ABORT;
5215 }
5216 decrement_badcount(ctx, *block_nr, p);
5217 *block_nr = new_block;
5218 ext2fs_mark_block_bitmap(ctx->block_found_map,
5219 new_block);
5220 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5221 return BLOCK_CHANGED;
5222 } else
5223 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5224 *block_nr);
5225 }
5226 return 0;
5227}
5228
5229static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5230 struct dup_inode *dp, char* block_buf)
5231{
5232 ext2_filsys fs = ctx->fs;
5233 errcode_t retval;
5234 struct clone_struct cs;
5235 struct problem_context pctx;
5236 blk_t blk;
5237 dnode_t *n;
5238 struct inode_el *ino_el;
5239 struct dup_block *db;
5240 struct dup_inode *di;
5241
5242 clear_problem_context(&pctx);
5243 cs.errcode = 0;
5244 cs.dir = 0;
5245 cs.ctx = ctx;
5246 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5247 if (retval)
5248 return retval;
5249
5250 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5251 cs.dir = ino;
5252
5253 pctx.ino = ino;
5254 pctx.str = "clone_file";
5255 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5256 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5257 clone_file_block, &cs);
5258 ext2fs_mark_bb_dirty(fs);
5259 if (pctx.errcode) {
5260 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5261 retval = pctx.errcode;
5262 goto errout;
5263 }
5264 if (cs.errcode) {
5265 bb_error_msg(_("returned from clone_file_block"));
5266 retval = cs.errcode;
5267 goto errout;
5268 }
5269 /* The inode may have changed on disk, so we have to re-read it */
5270 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5271 blk = dp->inode.i_file_acl;
5272 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5273 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5274 BLOCK_CHANGED)) {
5275 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5276 /*
5277 * If we cloned the EA block, find all other inodes
5278 * which refered to that EA block, and modify
5279 * them to point to the new EA block.
5280 */
5281 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5282 db = (struct dup_block *) dnode_get(n);
5283 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5284 if (ino_el->inode == ino)
5285 continue;
5286 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5287 di = (struct dup_inode *) dnode_get(n);
5288 if (di->inode.i_file_acl == blk) {
5289 di->inode.i_file_acl = dp->inode.i_file_acl;
5290 e2fsck_write_inode(ctx, ino_el->inode,
5291 &di->inode, "clone file EA");
5292 decrement_badcount(ctx, blk, db);
5293 }
5294 }
5295 }
5296 retval = 0;
5297errout:
5298 ext2fs_free_mem(&cs.buf);
5299 return retval;
5300}
5301
5302/*
5303 * This routine returns 1 if a block overlaps with one of the superblocks,
5304 * group descriptors, inode bitmaps, or block bitmaps.
5305 */
5306static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5307{
5308 ext2_filsys fs = ctx->fs;
5309 blk_t block;
5310 dgrp_t i;
5311
5312 block = fs->super->s_first_data_block;
5313 for (i = 0; i < fs->group_desc_count; i++) {
5314
5315 /* Check superblocks/block group descriptros */
5316 if (ext2fs_bg_has_super(fs, i)) {
5317 if (test_block >= block &&
5318 (test_block <= block + fs->desc_blocks))
5319 return 1;
5320 }
5321
5322 /* Check the inode table */
5323 if ((fs->group_desc[i].bg_inode_table) &&
5324 (test_block >= fs->group_desc[i].bg_inode_table) &&
5325 (test_block < (fs->group_desc[i].bg_inode_table +
5326 fs->inode_blocks_per_group)))
5327 return 1;
5328
5329 /* Check the bitmap blocks */
5330 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5331 (test_block == fs->group_desc[i].bg_inode_bitmap))
5332 return 1;
5333
5334 block += fs->super->s_blocks_per_group;
5335 }
5336 return 0;
5337}
5338/*
5339 * pass2.c --- check directory structure
5340 *
5341 * Pass 2 of e2fsck iterates through all active directory inodes, and
5342 * applies to following tests to each directory entry in the directory
5343 * blocks in the inodes:
5344 *
5345 * - The length of the directory entry (rec_len) should be at
5346 * least 8 bytes, and no more than the remaining space
5347 * left in the directory block.
5348 * - The length of the name in the directory entry (name_len)
5349 * should be less than (rec_len - 8).
5350 * - The inode number in the directory entry should be within
5351 * legal bounds.
5352 * - The inode number should refer to a in-use inode.
5353 * - The first entry should be '.', and its inode should be
5354 * the inode of the directory.
5355 * - The second entry should be '..'.
5356 *
5357 * To minimize disk seek time, the directory blocks are processed in
5358 * sorted order of block numbers.
5359 *
5360 * Pass 2 also collects the following information:
5361 * - The inode numbers of the subdirectories for each directory.
5362 *
5363 * Pass 2 relies on the following information from previous passes:
5364 * - The directory information collected in pass 1.
5365 * - The inode_used_map bitmap
5366 * - The inode_bad_map bitmap
5367 * - The inode_dir_map bitmap
5368 *
5369 * Pass 2 frees the following data structures
5370 * - The inode_bad_map bitmap
5371 * - The inode_reg_map bitmap
5372 */
5373
5374/*
5375 * Keeps track of how many times an inode is referenced.
5376 */
5377static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5378static int check_dir_block(ext2_filsys fs,
5379 struct ext2_db_entry *dir_blocks_info,
5380 void *priv_data);
5381static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5382 struct problem_context *pctx);
5383static int update_dir_block(ext2_filsys fs,
5384 blk_t *block_nr,
5385 e2_blkcnt_t blockcnt,
5386 blk_t ref_block,
5387 int ref_offset,
5388 void *priv_data);
5389static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5390static int htree_depth(struct dx_dir_info *dx_dir,
5391 struct dx_dirblock_info *dx_db);
5392static int special_dir_block_cmp(const void *a, const void *b);
5393
5394struct check_dir_struct {
5395 char *buf;
5396 struct problem_context pctx;
5397 int count, max;
5398 e2fsck_t ctx;
5399};
5400
5401static void e2fsck_pass2(e2fsck_t ctx)
5402{
5403 struct ext2_super_block *sb = ctx->fs->super;
5404 struct problem_context pctx;
5405 ext2_filsys fs = ctx->fs;
5406 char *buf;
5407 struct dir_info *dir;
5408 struct check_dir_struct cd;
5409 struct dx_dir_info *dx_dir;
5410 struct dx_dirblock_info *dx_db, *dx_parent;
5411 int b;
5412 int i, depth;
5413 problem_t code;
5414 int bad_dir;
5415
5416 clear_problem_context(&cd.pctx);
5417
5418 /* Pass 2 */
5419
5420 if (!(ctx->options & E2F_OPT_PREEN))
5421 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5422
5423 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5424 0, ctx->inode_link_info,
5425 &ctx->inode_count);
5426 if (cd.pctx.errcode) {
5427 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5428 ctx->flags |= E2F_FLAG_ABORT;
5429 return;
5430 }
5431 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5432 "directory scan buffer");
5433
5434 /*
5435 * Set up the parent pointer for the root directory, if
5436 * present. (If the root directory is not present, we will
5437 * create it in pass 3.)
5438 */
5439 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5440 if (dir)
5441 dir->parent = EXT2_ROOT_INO;
5442
5443 cd.buf = buf;
5444 cd.ctx = ctx;
5445 cd.count = 1;
5446 cd.max = ext2fs_dblist_count(fs->dblist);
5447
5448 if (ctx->progress)
5449 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5450
5451 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5452 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5453
5454 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5455 &cd);
5456 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5457 return;
5458 if (cd.pctx.errcode) {
5459 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5460 ctx->flags |= E2F_FLAG_ABORT;
5461 return;
5462 }
5463
5464#ifdef ENABLE_HTREE
5465 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5466 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5467 return;
5468 if (dx_dir->numblocks == 0)
5469 continue;
5470 clear_problem_context(&pctx);
5471 bad_dir = 0;
5472 pctx.dir = dx_dir->ino;
5473 dx_db = dx_dir->dx_block;
5474 if (dx_db->flags & DX_FLAG_REFERENCED)
5475 dx_db->flags |= DX_FLAG_DUP_REF;
5476 else
5477 dx_db->flags |= DX_FLAG_REFERENCED;
5478 /*
5479 * Find all of the first and last leaf blocks, and
5480 * update their parent's min and max hash values
5481 */
5482 for (b=0, dx_db = dx_dir->dx_block;
5483 b < dx_dir->numblocks;
5484 b++, dx_db++) {
5485 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5486 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5487 continue;
5488 dx_parent = &dx_dir->dx_block[dx_db->parent];
5489 /*
5490 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5491 */
5492 if (dx_db->flags & DX_FLAG_FIRST)
5493 dx_parent->min_hash = dx_db->min_hash;
5494 /*
5495 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5496 */
5497 if (dx_db->flags & DX_FLAG_LAST)
5498 dx_parent->max_hash = dx_db->max_hash;
5499 }
5500
5501 for (b=0, dx_db = dx_dir->dx_block;
5502 b < dx_dir->numblocks;
5503 b++, dx_db++) {
5504 pctx.blkcount = b;
5505 pctx.group = dx_db->parent;
5506 code = 0;
5507 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5508 (dx_db->min_hash < dx_db->node_min_hash)) {
5509 pctx.blk = dx_db->min_hash;
5510 pctx.blk2 = dx_db->node_min_hash;
5511 code = PR_2_HTREE_MIN_HASH;
5512 fix_problem(ctx, code, &pctx);
5513 bad_dir++;
5514 }
5515 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5516 depth = htree_depth(dx_dir, dx_db);
5517 if (depth != dx_dir->depth) {
5518 code = PR_2_HTREE_BAD_DEPTH;
5519 fix_problem(ctx, code, &pctx);
5520 bad_dir++;
5521 }
5522 }
5523 /*
5524 * This test doesn't apply for the root block
5525 * at block #0
5526 */
5527 if (b &&
5528 (dx_db->max_hash > dx_db->node_max_hash)) {
5529 pctx.blk = dx_db->max_hash;
5530 pctx.blk2 = dx_db->node_max_hash;
5531 code = PR_2_HTREE_MAX_HASH;
5532 fix_problem(ctx, code, &pctx);
5533 bad_dir++;
5534 }
5535 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5536 code = PR_2_HTREE_NOTREF;
5537 fix_problem(ctx, code, &pctx);
5538 bad_dir++;
5539 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5540 code = PR_2_HTREE_DUPREF;
5541 fix_problem(ctx, code, &pctx);
5542 bad_dir++;
5543 }
5544 if (code == 0)
5545 continue;
5546 }
5547 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5548 clear_htree(ctx, dx_dir->ino);
5549 dx_dir->numblocks = 0;
5550 }
5551 }
5552#endif
5553 ext2fs_free_mem(&buf);
5554 ext2fs_free_dblist(fs->dblist);
5555
5556 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5557 ctx->inode_bad_map = 0;
5558 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5559 ctx->inode_reg_map = 0;
5560
5561 clear_problem_context(&pctx);
5562 if (ctx->large_files) {
5563 if (!(sb->s_feature_ro_compat &
5564 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5565 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5566 sb->s_feature_ro_compat |=
5567 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5568 ext2fs_mark_super_dirty(fs);
5569 }
5570 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5571 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5572 ext2fs_update_dynamic_rev(fs);
5573 ext2fs_mark_super_dirty(fs);
5574 }
5575 } else if (!ctx->large_files &&
5576 (sb->s_feature_ro_compat &
5577 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5578 if (fs->flags & EXT2_FLAG_RW) {
5579 sb->s_feature_ro_compat &=
5580 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5581 ext2fs_mark_super_dirty(fs);
5582 }
5583 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005584}
5585
5586#define MAX_DEPTH 32000
5587static int htree_depth(struct dx_dir_info *dx_dir,
5588 struct dx_dirblock_info *dx_db)
5589{
5590 int depth = 0;
5591
5592 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5593 dx_db = &dx_dir->dx_block[dx_db->parent];
5594 depth++;
5595 }
5596 return depth;
5597}
5598
5599static int dict_de_cmp(const void *a, const void *b)
5600{
5601 const struct ext2_dir_entry *de_a, *de_b;
5602 int a_len, b_len;
5603
5604 de_a = (const struct ext2_dir_entry *) a;
5605 a_len = de_a->name_len & 0xFF;
5606 de_b = (const struct ext2_dir_entry *) b;
5607 b_len = de_b->name_len & 0xFF;
5608
5609 if (a_len != b_len)
5610 return (a_len - b_len);
5611
5612 return strncmp(de_a->name, de_b->name, a_len);
5613}
5614
5615/*
5616 * This is special sort function that makes sure that directory blocks
5617 * with a dirblock of zero are sorted to the beginning of the list.
5618 * This guarantees that the root node of the htree directories are
5619 * processed first, so we know what hash version to use.
5620 */
5621static int special_dir_block_cmp(const void *a, const void *b)
5622{
5623 const struct ext2_db_entry *db_a =
5624 (const struct ext2_db_entry *) a;
5625 const struct ext2_db_entry *db_b =
5626 (const struct ext2_db_entry *) b;
5627
5628 if (db_a->blockcnt && !db_b->blockcnt)
5629 return 1;
5630
5631 if (!db_a->blockcnt && db_b->blockcnt)
5632 return -1;
5633
5634 if (db_a->blk != db_b->blk)
5635 return (int) (db_a->blk - db_b->blk);
5636
5637 if (db_a->ino != db_b->ino)
5638 return (int) (db_a->ino - db_b->ino);
5639
5640 return (int) (db_a->blockcnt - db_b->blockcnt);
5641}
5642
5643
5644/*
5645 * Make sure the first entry in the directory is '.', and that the
5646 * directory entry is sane.
5647 */
5648static int check_dot(e2fsck_t ctx,
5649 struct ext2_dir_entry *dirent,
5650 ext2_ino_t ino, struct problem_context *pctx)
5651{
5652 struct ext2_dir_entry *nextdir;
5653 int status = 0;
5654 int created = 0;
5655 int new_len;
5656 int problem = 0;
5657
5658 if (!dirent->inode)
5659 problem = PR_2_MISSING_DOT;
5660 else if (((dirent->name_len & 0xFF) != 1) ||
5661 (dirent->name[0] != '.'))
5662 problem = PR_2_1ST_NOT_DOT;
5663 else if (dirent->name[1] != '\0')
5664 problem = PR_2_DOT_NULL_TERM;
5665
5666 if (problem) {
5667 if (fix_problem(ctx, problem, pctx)) {
5668 if (dirent->rec_len < 12)
5669 dirent->rec_len = 12;
5670 dirent->inode = ino;
5671 dirent->name_len = 1;
5672 dirent->name[0] = '.';
5673 dirent->name[1] = '\0';
5674 status = 1;
5675 created = 1;
5676 }
5677 }
5678 if (dirent->inode != ino) {
5679 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5680 dirent->inode = ino;
5681 status = 1;
5682 }
5683 }
5684 if (dirent->rec_len > 12) {
5685 new_len = dirent->rec_len - 12;
5686 if (new_len > 12) {
5687 if (created ||
5688 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5689 nextdir = (struct ext2_dir_entry *)
5690 ((char *) dirent + 12);
5691 dirent->rec_len = 12;
5692 nextdir->rec_len = new_len;
5693 nextdir->inode = 0;
5694 nextdir->name_len = 0;
5695 status = 1;
5696 }
5697 }
5698 }
5699 return status;
5700}
5701
5702/*
5703 * Make sure the second entry in the directory is '..', and that the
5704 * directory entry is sane. We do not check the inode number of '..'
5705 * here; this gets done in pass 3.
5706 */
5707static int check_dotdot(e2fsck_t ctx,
5708 struct ext2_dir_entry *dirent,
5709 struct dir_info *dir, struct problem_context *pctx)
5710{
5711 int problem = 0;
5712
5713 if (!dirent->inode)
5714 problem = PR_2_MISSING_DOT_DOT;
5715 else if (((dirent->name_len & 0xFF) != 2) ||
5716 (dirent->name[0] != '.') ||
5717 (dirent->name[1] != '.'))
5718 problem = PR_2_2ND_NOT_DOT_DOT;
5719 else if (dirent->name[2] != '\0')
5720 problem = PR_2_DOT_DOT_NULL_TERM;
5721
5722 if (problem) {
5723 if (fix_problem(ctx, problem, pctx)) {
5724 if (dirent->rec_len < 12)
5725 dirent->rec_len = 12;
5726 /*
5727 * Note: we don't have the parent inode just
5728 * yet, so we will fill it in with the root
5729 * inode. This will get fixed in pass 3.
5730 */
5731 dirent->inode = EXT2_ROOT_INO;
5732 dirent->name_len = 2;
5733 dirent->name[0] = '.';
5734 dirent->name[1] = '.';
5735 dirent->name[2] = '\0';
5736 return 1;
5737 }
5738 return 0;
5739 }
5740 dir->dotdot = dirent->inode;
5741 return 0;
5742}
5743
5744/*
5745 * Check to make sure a directory entry doesn't contain any illegal
5746 * characters.
5747 */
5748static int check_name(e2fsck_t ctx,
5749 struct ext2_dir_entry *dirent,
5750 struct problem_context *pctx)
5751{
5752 int i;
5753 int fixup = -1;
5754 int ret = 0;
5755
5756 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5757 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5758 if (fixup < 0) {
5759 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5760 }
5761 if (fixup) {
5762 dirent->name[i] = '.';
5763 ret = 1;
5764 }
5765 }
5766 }
5767 return ret;
5768}
5769
5770/*
5771 * Check the directory filetype (if present)
5772 */
5773
5774/*
5775 * Given a mode, return the ext2 file type
5776 */
5777static int ext2_file_type(unsigned int mode)
5778{
5779 if (LINUX_S_ISREG(mode))
5780 return EXT2_FT_REG_FILE;
5781
5782 if (LINUX_S_ISDIR(mode))
5783 return EXT2_FT_DIR;
5784
5785 if (LINUX_S_ISCHR(mode))
5786 return EXT2_FT_CHRDEV;
5787
5788 if (LINUX_S_ISBLK(mode))
5789 return EXT2_FT_BLKDEV;
5790
5791 if (LINUX_S_ISLNK(mode))
5792 return EXT2_FT_SYMLINK;
5793
5794 if (LINUX_S_ISFIFO(mode))
5795 return EXT2_FT_FIFO;
5796
5797 if (LINUX_S_ISSOCK(mode))
5798 return EXT2_FT_SOCK;
5799
5800 return 0;
5801}
5802
5803static int check_filetype(e2fsck_t ctx,
5804 struct ext2_dir_entry *dirent,
5805 struct problem_context *pctx)
5806{
5807 int filetype = dirent->name_len >> 8;
5808 int should_be = EXT2_FT_UNKNOWN;
5809 struct ext2_inode inode;
5810
5811 if (!(ctx->fs->super->s_feature_incompat &
5812 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5813 if (filetype == 0 ||
5814 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5815 return 0;
5816 dirent->name_len = dirent->name_len & 0xFF;
5817 return 1;
5818 }
5819
5820 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5821 should_be = EXT2_FT_DIR;
5822 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5823 dirent->inode)) {
5824 should_be = EXT2_FT_REG_FILE;
5825 } else if (ctx->inode_bad_map &&
5826 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5827 dirent->inode))
5828 should_be = 0;
5829 else {
5830 e2fsck_read_inode(ctx, dirent->inode, &inode,
5831 "check_filetype");
5832 should_be = ext2_file_type(inode.i_mode);
5833 }
5834 if (filetype == should_be)
5835 return 0;
5836 pctx->num = should_be;
5837
5838 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5839 pctx) == 0)
5840 return 0;
5841
5842 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5843 return 1;
5844}
5845
5846#ifdef ENABLE_HTREE
5847static void parse_int_node(ext2_filsys fs,
5848 struct ext2_db_entry *db,
5849 struct check_dir_struct *cd,
5850 struct dx_dir_info *dx_dir,
5851 char *block_buf)
5852{
5853 struct ext2_dx_root_info *root;
5854 struct ext2_dx_entry *ent;
5855 struct ext2_dx_countlimit *limit;
5856 struct dx_dirblock_info *dx_db;
5857 int i, expect_limit, count;
5858 blk_t blk;
5859 ext2_dirhash_t min_hash = 0xffffffff;
5860 ext2_dirhash_t max_hash = 0;
5861 ext2_dirhash_t hash = 0, prev_hash;
5862
5863 if (db->blockcnt == 0) {
5864 root = (struct ext2_dx_root_info *) (block_buf + 24);
5865 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5866 } else {
5867 ent = (struct ext2_dx_entry *) (block_buf+8);
5868 }
5869 limit = (struct ext2_dx_countlimit *) ent;
5870
5871 count = ext2fs_le16_to_cpu(limit->count);
5872 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5873 sizeof(struct ext2_dx_entry);
5874 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5875 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5876 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5877 goto clear_and_exit;
5878 }
5879 if (count > expect_limit) {
5880 cd->pctx.num = count;
5881 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5882 goto clear_and_exit;
5883 count = expect_limit;
5884 }
5885
5886 for (i=0; i < count; i++) {
5887 prev_hash = hash;
5888 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5889 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5890 /* Check to make sure the block is valid */
5891 if (blk > (blk_t) dx_dir->numblocks) {
5892 cd->pctx.blk = blk;
5893 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5894 &cd->pctx))
5895 goto clear_and_exit;
5896 }
5897 if (hash < prev_hash &&
5898 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5899 goto clear_and_exit;
5900 dx_db = &dx_dir->dx_block[blk];
5901 if (dx_db->flags & DX_FLAG_REFERENCED) {
5902 dx_db->flags |= DX_FLAG_DUP_REF;
5903 } else {
5904 dx_db->flags |= DX_FLAG_REFERENCED;
5905 dx_db->parent = db->blockcnt;
5906 }
5907 if (hash < min_hash)
5908 min_hash = hash;
5909 if (hash > max_hash)
5910 max_hash = hash;
5911 dx_db->node_min_hash = hash;
5912 if ((i+1) < count)
5913 dx_db->node_max_hash =
5914 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5915 else {
5916 dx_db->node_max_hash = 0xfffffffe;
5917 dx_db->flags |= DX_FLAG_LAST;
5918 }
5919 if (i == 0)
5920 dx_db->flags |= DX_FLAG_FIRST;
5921 }
5922 dx_db = &dx_dir->dx_block[db->blockcnt];
5923 dx_db->min_hash = min_hash;
5924 dx_db->max_hash = max_hash;
5925 return;
5926
5927clear_and_exit:
5928 clear_htree(cd->ctx, cd->pctx.ino);
5929 dx_dir->numblocks = 0;
5930}
5931#endif /* ENABLE_HTREE */
5932
5933/*
5934 * Given a busted directory, try to salvage it somehow.
5935 *
5936 */
5937static void salvage_directory(ext2_filsys fs,
5938 struct ext2_dir_entry *dirent,
5939 struct ext2_dir_entry *prev,
5940 unsigned int *offset)
5941{
5942 char *cp = (char *) dirent;
5943 int left = fs->blocksize - *offset - dirent->rec_len;
5944 int name_len = dirent->name_len & 0xFF;
5945
5946 /*
5947 * Special case of directory entry of size 8: copy what's left
5948 * of the directory block up to cover up the invalid hole.
5949 */
5950 if ((left >= 12) && (dirent->rec_len == 8)) {
5951 memmove(cp, cp+8, left);
5952 memset(cp + left, 0, 8);
5953 return;
5954 }
5955 /*
5956 * If the directory entry overruns the end of the directory
5957 * block, and the name is small enough to fit, then adjust the
5958 * record length.
5959 */
5960 if ((left < 0) &&
5961 (name_len + 8 <= dirent->rec_len + left) &&
5962 dirent->inode <= fs->super->s_inodes_count &&
5963 strnlen(dirent->name, name_len) == name_len) {
5964 dirent->rec_len += left;
5965 return;
5966 }
5967 /*
5968 * If the directory entry is a multiple of four, so it is
5969 * valid, let the previous directory entry absorb the invalid
5970 * one.
5971 */
5972 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5973 prev->rec_len += dirent->rec_len;
5974 *offset += dirent->rec_len;
5975 return;
5976 }
5977 /*
5978 * Default salvage method --- kill all of the directory
5979 * entries for the rest of the block. We will either try to
5980 * absorb it into the previous directory entry, or create a
5981 * new empty directory entry the rest of the directory block.
5982 */
5983 if (prev) {
5984 prev->rec_len += fs->blocksize - *offset;
5985 *offset = fs->blocksize;
5986 } else {
5987 dirent->rec_len = fs->blocksize - *offset;
5988 dirent->name_len = 0;
5989 dirent->inode = 0;
5990 }
5991}
5992
5993static int check_dir_block(ext2_filsys fs,
5994 struct ext2_db_entry *db,
5995 void *priv_data)
5996{
5997 struct dir_info *subdir, *dir;
5998 struct dx_dir_info *dx_dir;
5999#ifdef ENABLE_HTREE
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01006000 struct dx_dirblock_info *dx_db = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006001#endif /* ENABLE_HTREE */
6002 struct ext2_dir_entry *dirent, *prev;
6003 ext2_dirhash_t hash;
6004 unsigned int offset = 0;
6005 int dir_modified = 0;
6006 int dot_state;
6007 blk_t block_nr = db->blk;
6008 ext2_ino_t ino = db->ino;
6009 __u16 links;
6010 struct check_dir_struct *cd;
6011 char *buf;
6012 e2fsck_t ctx;
6013 int problem;
6014 struct ext2_dx_root_info *root;
6015 struct ext2_dx_countlimit *limit;
6016 static dict_t de_dict;
6017 struct problem_context pctx;
6018 int dups_found = 0;
6019
6020 cd = (struct check_dir_struct *) priv_data;
6021 buf = cd->buf;
6022 ctx = cd->ctx;
6023
6024 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6025 return DIRENT_ABORT;
6026
6027 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6028 return DIRENT_ABORT;
6029
6030 /*
6031 * Make sure the inode is still in use (could have been
6032 * deleted in the duplicate/bad blocks pass.
6033 */
6034 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6035 return 0;
6036
6037 cd->pctx.ino = ino;
6038 cd->pctx.blk = block_nr;
6039 cd->pctx.blkcount = db->blockcnt;
6040 cd->pctx.ino2 = 0;
6041 cd->pctx.dirent = 0;
6042 cd->pctx.num = 0;
6043
6044 if (db->blk == 0) {
6045 if (allocate_dir_block(ctx, db, &cd->pctx))
6046 return 0;
6047 block_nr = db->blk;
6048 }
6049
6050 if (db->blockcnt)
6051 dot_state = 2;
6052 else
6053 dot_state = 0;
6054
6055 if (ctx->dirs_to_hash &&
6056 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6057 dups_found++;
6058
6059 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6060 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6061 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6062 if (cd->pctx.errcode) {
6063 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6064 ctx->flags |= E2F_FLAG_ABORT;
6065 return DIRENT_ABORT;
6066 }
6067 memset(buf, 0, fs->blocksize);
6068 }
6069#ifdef ENABLE_HTREE
6070 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6071 if (dx_dir && dx_dir->numblocks) {
6072 if (db->blockcnt >= dx_dir->numblocks) {
6073 printf("XXX should never happen!!!\n");
6074 abort();
6075 }
6076 dx_db = &dx_dir->dx_block[db->blockcnt];
6077 dx_db->type = DX_DIRBLOCK_LEAF;
6078 dx_db->phys = block_nr;
6079 dx_db->min_hash = ~0;
6080 dx_db->max_hash = 0;
6081
6082 dirent = (struct ext2_dir_entry *) buf;
6083 limit = (struct ext2_dx_countlimit *) (buf+8);
6084 if (db->blockcnt == 0) {
6085 root = (struct ext2_dx_root_info *) (buf + 24);
6086 dx_db->type = DX_DIRBLOCK_ROOT;
6087 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6088 if ((root->reserved_zero ||
6089 root->info_length < 8 ||
6090 root->indirect_levels > 1) &&
6091 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6092 clear_htree(ctx, ino);
6093 dx_dir->numblocks = 0;
6094 dx_db = 0;
6095 }
6096 dx_dir->hashversion = root->hash_version;
6097 dx_dir->depth = root->indirect_levels + 1;
6098 } else if ((dirent->inode == 0) &&
6099 (dirent->rec_len == fs->blocksize) &&
6100 (dirent->name_len == 0) &&
6101 (ext2fs_le16_to_cpu(limit->limit) ==
6102 ((fs->blocksize-8) /
6103 sizeof(struct ext2_dx_entry))))
6104 dx_db->type = DX_DIRBLOCK_NODE;
6105 }
6106#endif /* ENABLE_HTREE */
6107
6108 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6109 prev = 0;
6110 do {
6111 problem = 0;
6112 dirent = (struct ext2_dir_entry *) (buf + offset);
6113 cd->pctx.dirent = dirent;
6114 cd->pctx.num = offset;
6115 if (((offset + dirent->rec_len) > fs->blocksize) ||
6116 (dirent->rec_len < 12) ||
6117 ((dirent->rec_len % 4) != 0) ||
6118 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6119 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6120 salvage_directory(fs, dirent, prev, &offset);
6121 dir_modified++;
6122 continue;
6123 } else
6124 goto abort_free_dict;
6125 }
6126 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6127 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6128 dirent->name_len = EXT2_NAME_LEN;
6129 dir_modified++;
6130 }
6131 }
6132
6133 if (dot_state == 0) {
6134 if (check_dot(ctx, dirent, ino, &cd->pctx))
6135 dir_modified++;
6136 } else if (dot_state == 1) {
6137 dir = e2fsck_get_dir_info(ctx, ino);
6138 if (!dir) {
6139 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6140 goto abort_free_dict;
6141 }
6142 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6143 dir_modified++;
6144 } else if (dirent->inode == ino) {
6145 problem = PR_2_LINK_DOT;
6146 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6147 dirent->inode = 0;
6148 dir_modified++;
6149 goto next;
6150 }
6151 }
6152 if (!dirent->inode)
6153 goto next;
6154
6155 /*
6156 * Make sure the inode listed is a legal one.
6157 */
6158 if (((dirent->inode != EXT2_ROOT_INO) &&
6159 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6160 (dirent->inode > fs->super->s_inodes_count)) {
6161 problem = PR_2_BAD_INO;
6162 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6163 dirent->inode))) {
6164 /*
6165 * If the inode is unused, offer to clear it.
6166 */
6167 problem = PR_2_UNUSED_INODE;
6168 } else if ((dot_state > 1) &&
6169 ((dirent->name_len & 0xFF) == 1) &&
6170 (dirent->name[0] == '.')) {
6171 /*
6172 * If there's a '.' entry in anything other
6173 * than the first directory entry, it's a
6174 * duplicate entry that should be removed.
6175 */
6176 problem = PR_2_DUP_DOT;
6177 } else if ((dot_state > 1) &&
6178 ((dirent->name_len & 0xFF) == 2) &&
6179 (dirent->name[0] == '.') &&
6180 (dirent->name[1] == '.')) {
6181 /*
6182 * If there's a '..' entry in anything other
6183 * than the second directory entry, it's a
6184 * duplicate entry that should be removed.
6185 */
6186 problem = PR_2_DUP_DOT_DOT;
6187 } else if ((dot_state > 1) &&
6188 (dirent->inode == EXT2_ROOT_INO)) {
6189 /*
6190 * Don't allow links to the root directory.
6191 * We check this specially to make sure we
6192 * catch this error case even if the root
6193 * directory hasn't been created yet.
6194 */
6195 problem = PR_2_LINK_ROOT;
6196 } else if ((dot_state > 1) &&
6197 (dirent->name_len & 0xFF) == 0) {
6198 /*
6199 * Don't allow zero-length directory names.
6200 */
6201 problem = PR_2_NULL_NAME;
6202 }
6203
6204 if (problem) {
6205 if (fix_problem(ctx, problem, &cd->pctx)) {
6206 dirent->inode = 0;
6207 dir_modified++;
6208 goto next;
6209 } else {
6210 ext2fs_unmark_valid(fs);
6211 if (problem == PR_2_BAD_INO)
6212 goto next;
6213 }
6214 }
6215
6216 /*
6217 * If the inode was marked as having bad fields in
6218 * pass1, process it and offer to fix/clear it.
6219 * (We wait until now so that we can display the
6220 * pathname to the user.)
6221 */
6222 if (ctx->inode_bad_map &&
6223 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6224 dirent->inode)) {
6225 if (e2fsck_process_bad_inode(ctx, ino,
6226 dirent->inode,
6227 buf + fs->blocksize)) {
6228 dirent->inode = 0;
6229 dir_modified++;
6230 goto next;
6231 }
6232 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6233 return DIRENT_ABORT;
6234 }
6235
6236 if (check_name(ctx, dirent, &cd->pctx))
6237 dir_modified++;
6238
6239 if (check_filetype(ctx, dirent, &cd->pctx))
6240 dir_modified++;
6241
6242#ifdef ENABLE_HTREE
6243 if (dx_db) {
6244 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6245 (dirent->name_len & 0xFF),
6246 fs->super->s_hash_seed, &hash, 0);
6247 if (hash < dx_db->min_hash)
6248 dx_db->min_hash = hash;
6249 if (hash > dx_db->max_hash)
6250 dx_db->max_hash = hash;
6251 }
6252#endif
6253
6254 /*
6255 * If this is a directory, then mark its parent in its
6256 * dir_info structure. If the parent field is already
6257 * filled in, then this directory has more than one
6258 * hard link. We assume the first link is correct,
6259 * and ask the user if he/she wants to clear this one.
6260 */
6261 if ((dot_state > 1) &&
6262 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6263 dirent->inode))) {
6264 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6265 if (!subdir) {
6266 cd->pctx.ino = dirent->inode;
6267 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6268 goto abort_free_dict;
6269 }
6270 if (subdir->parent) {
6271 cd->pctx.ino2 = subdir->parent;
6272 if (fix_problem(ctx, PR_2_LINK_DIR,
6273 &cd->pctx)) {
6274 dirent->inode = 0;
6275 dir_modified++;
6276 goto next;
6277 }
6278 cd->pctx.ino2 = 0;
6279 } else
6280 subdir->parent = ino;
6281 }
6282
6283 if (dups_found) {
6284 ;
6285 } else if (dict_lookup(&de_dict, dirent)) {
6286 clear_problem_context(&pctx);
6287 pctx.ino = ino;
6288 pctx.dirent = dirent;
6289 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6290 if (!ctx->dirs_to_hash)
6291 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6292 if (ctx->dirs_to_hash)
6293 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6294 dups_found++;
6295 } else
6296 dict_alloc_insert(&de_dict, dirent, dirent);
6297
6298 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6299 &links);
6300 if (links > 1)
6301 ctx->fs_links_count++;
6302 ctx->fs_total_count++;
6303 next:
6304 prev = dirent;
6305 offset += dirent->rec_len;
6306 dot_state++;
6307 } while (offset < fs->blocksize);
6308#ifdef ENABLE_HTREE
6309 if (dx_db) {
6310 cd->pctx.dir = cd->pctx.ino;
6311 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6312 (dx_db->type == DX_DIRBLOCK_NODE))
6313 parse_int_node(fs, db, cd, dx_dir, buf);
6314 }
6315#endif /* ENABLE_HTREE */
6316 if (offset != fs->blocksize) {
6317 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6318 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6319 dirent->rec_len = cd->pctx.num;
6320 dir_modified++;
6321 }
6322 }
6323 if (dir_modified) {
6324 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6325 if (cd->pctx.errcode) {
6326 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6327 &cd->pctx))
6328 goto abort_free_dict;
6329 }
6330 ext2fs_mark_changed(fs);
6331 }
6332 dict_free_nodes(&de_dict);
6333 return 0;
6334abort_free_dict:
6335 dict_free_nodes(&de_dict);
6336 ctx->flags |= E2F_FLAG_ABORT;
6337 return DIRENT_ABORT;
6338}
6339
6340/*
6341 * This function is called to deallocate a block, and is an interator
6342 * functioned called by deallocate inode via ext2fs_iterate_block().
6343 */
6344static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6345 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6346 blk_t ref_block FSCK_ATTR((unused)),
6347 int ref_offset FSCK_ATTR((unused)),
6348 void *priv_data)
6349{
6350 e2fsck_t ctx = (e2fsck_t) priv_data;
6351
6352 if (HOLE_BLKADDR(*block_nr))
6353 return 0;
6354 if ((*block_nr < fs->super->s_first_data_block) ||
6355 (*block_nr >= fs->super->s_blocks_count))
6356 return 0;
6357 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6358 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6359 return 0;
6360}
6361
6362/*
6363 * This fuction deallocates an inode
6364 */
6365static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6366{
6367 ext2_filsys fs = ctx->fs;
6368 struct ext2_inode inode;
6369 struct problem_context pctx;
6370 __u32 count;
6371
6372 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6373 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6374 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006375 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006376 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6377 clear_problem_context(&pctx);
6378 pctx.ino = ino;
6379
6380 /*
6381 * Fix up the bitmaps...
6382 */
6383 e2fsck_read_bitmaps(ctx);
6384 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6385 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6386 if (ctx->inode_bad_map)
6387 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6388 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6389
6390 if (inode.i_file_acl &&
6391 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6392 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6393 block_buf, -1, &count);
6394 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6395 pctx.errcode = 0;
6396 count = 1;
6397 }
6398 if (pctx.errcode) {
6399 pctx.blk = inode.i_file_acl;
6400 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6401 ctx->flags |= E2F_FLAG_ABORT;
6402 return;
6403 }
6404 if (count == 0) {
6405 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6406 inode.i_file_acl);
6407 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6408 }
6409 inode.i_file_acl = 0;
6410 }
6411
6412 if (!ext2fs_inode_has_valid_blocks(&inode))
6413 return;
6414
6415 if (LINUX_S_ISREG(inode.i_mode) &&
6416 (inode.i_size_high || inode.i_size & 0x80000000UL))
6417 ctx->large_files--;
6418
6419 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6420 deallocate_inode_block, ctx);
6421 if (pctx.errcode) {
6422 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6423 ctx->flags |= E2F_FLAG_ABORT;
6424 return;
6425 }
6426}
6427
6428/*
6429 * This fuction clears the htree flag on an inode
6430 */
6431static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6432{
6433 struct ext2_inode inode;
6434
6435 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6436 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6437 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6438 if (ctx->dirs_to_hash)
6439 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6440}
6441
6442
6443static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6444 ext2_ino_t ino, char *buf)
6445{
6446 ext2_filsys fs = ctx->fs;
6447 struct ext2_inode inode;
6448 int inode_modified = 0;
6449 int not_fixed = 0;
6450 unsigned char *frag, *fsize;
6451 struct problem_context pctx;
6452 int problem = 0;
6453
6454 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6455
6456 clear_problem_context(&pctx);
6457 pctx.ino = ino;
6458 pctx.dir = dir;
6459 pctx.inode = &inode;
6460
6461 if (inode.i_file_acl &&
6462 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6463 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6464 inode.i_file_acl = 0;
6465#if BB_BIG_ENDIAN
6466 /*
6467 * This is a special kludge to deal with long symlinks
6468 * on big endian systems. i_blocks had already been
6469 * decremented earlier in pass 1, but since i_file_acl
6470 * hadn't yet been cleared, ext2fs_read_inode()
6471 * assumed that the file was short symlink and would
6472 * not have byte swapped i_block[0]. Hence, we have
6473 * to byte-swap it here.
6474 */
6475 if (LINUX_S_ISLNK(inode.i_mode) &&
6476 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6477 (inode.i_blocks == fs->blocksize >> 9))
6478 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6479#endif
6480 inode_modified++;
6481 } else
6482 not_fixed++;
6483
6484 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6485 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6486 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6487 !(LINUX_S_ISSOCK(inode.i_mode)))
6488 problem = PR_2_BAD_MODE;
6489 else if (LINUX_S_ISCHR(inode.i_mode)
6490 && !e2fsck_pass1_check_device_inode(fs, &inode))
6491 problem = PR_2_BAD_CHAR_DEV;
6492 else if (LINUX_S_ISBLK(inode.i_mode)
6493 && !e2fsck_pass1_check_device_inode(fs, &inode))
6494 problem = PR_2_BAD_BLOCK_DEV;
6495 else if (LINUX_S_ISFIFO(inode.i_mode)
6496 && !e2fsck_pass1_check_device_inode(fs, &inode))
6497 problem = PR_2_BAD_FIFO;
6498 else if (LINUX_S_ISSOCK(inode.i_mode)
6499 && !e2fsck_pass1_check_device_inode(fs, &inode))
6500 problem = PR_2_BAD_SOCKET;
6501 else if (LINUX_S_ISLNK(inode.i_mode)
6502 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6503 problem = PR_2_INVALID_SYMLINK;
6504 }
6505
6506 if (problem) {
6507 if (fix_problem(ctx, problem, &pctx)) {
6508 deallocate_inode(ctx, ino, 0);
6509 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6510 return 0;
6511 return 1;
6512 } else
6513 not_fixed++;
6514 problem = 0;
6515 }
6516
6517 if (inode.i_faddr) {
6518 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6519 inode.i_faddr = 0;
6520 inode_modified++;
6521 } else
6522 not_fixed++;
6523 }
6524
6525 switch (fs->super->s_creator_os) {
6526 case EXT2_OS_LINUX:
6527 frag = &inode.osd2.linux2.l_i_frag;
6528 fsize = &inode.osd2.linux2.l_i_fsize;
6529 break;
6530 case EXT2_OS_HURD:
6531 frag = &inode.osd2.hurd2.h_i_frag;
6532 fsize = &inode.osd2.hurd2.h_i_fsize;
6533 break;
6534 case EXT2_OS_MASIX:
6535 frag = &inode.osd2.masix2.m_i_frag;
6536 fsize = &inode.osd2.masix2.m_i_fsize;
6537 break;
6538 default:
6539 frag = fsize = 0;
6540 }
6541 if (frag && *frag) {
6542 pctx.num = *frag;
6543 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6544 *frag = 0;
6545 inode_modified++;
6546 } else
6547 not_fixed++;
6548 pctx.num = 0;
6549 }
6550 if (fsize && *fsize) {
6551 pctx.num = *fsize;
6552 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6553 *fsize = 0;
6554 inode_modified++;
6555 } else
6556 not_fixed++;
6557 pctx.num = 0;
6558 }
6559
6560 if (inode.i_file_acl &&
6561 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6562 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6563 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6564 inode.i_file_acl = 0;
6565 inode_modified++;
6566 } else
6567 not_fixed++;
6568 }
6569 if (inode.i_dir_acl &&
6570 LINUX_S_ISDIR(inode.i_mode)) {
6571 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6572 inode.i_dir_acl = 0;
6573 inode_modified++;
6574 } else
6575 not_fixed++;
6576 }
6577
6578 if (inode_modified)
6579 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6580 if (!not_fixed)
6581 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6582 return 0;
6583}
6584
6585
6586/*
6587 * allocate_dir_block --- this function allocates a new directory
6588 * block for a particular inode; this is done if a directory has
6589 * a "hole" in it, or if a directory has a illegal block number
6590 * that was zeroed out and now needs to be replaced.
6591 */
6592static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6593 struct problem_context *pctx)
6594{
6595 ext2_filsys fs = ctx->fs;
6596 blk_t blk;
6597 char *block;
6598 struct ext2_inode inode;
6599
6600 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6601 return 1;
6602
6603 /*
6604 * Read the inode and block bitmaps in; we'll be messing with
6605 * them.
6606 */
6607 e2fsck_read_bitmaps(ctx);
6608
6609 /*
6610 * First, find a free block
6611 */
6612 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6613 if (pctx->errcode) {
6614 pctx->str = "ext2fs_new_block";
6615 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6616 return 1;
6617 }
6618 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6619 ext2fs_mark_block_bitmap(fs->block_map, blk);
6620 ext2fs_mark_bb_dirty(fs);
6621
6622 /*
6623 * Now let's create the actual data block for the inode
6624 */
6625 if (db->blockcnt)
6626 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6627 else
6628 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6629 EXT2_ROOT_INO, &block);
6630
6631 if (pctx->errcode) {
6632 pctx->str = "ext2fs_new_dir_block";
6633 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6634 return 1;
6635 }
6636
6637 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6638 ext2fs_free_mem(&block);
6639 if (pctx->errcode) {
6640 pctx->str = "ext2fs_write_dir_block";
6641 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6642 return 1;
6643 }
6644
6645 /*
6646 * Update the inode block count
6647 */
6648 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6649 inode.i_blocks += fs->blocksize / 512;
6650 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6651 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6652 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6653
6654 /*
6655 * Finally, update the block pointers for the inode
6656 */
6657 db->blk = blk;
6658 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6659 0, update_dir_block, db);
6660 if (pctx->errcode) {
6661 pctx->str = "ext2fs_block_iterate";
6662 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663 return 1;
6664 }
6665
6666 return 0;
6667}
6668
6669/*
6670 * This is a helper function for allocate_dir_block().
6671 */
6672static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6673 blk_t *block_nr,
6674 e2_blkcnt_t blockcnt,
6675 blk_t ref_block FSCK_ATTR((unused)),
6676 int ref_offset FSCK_ATTR((unused)),
6677 void *priv_data)
6678{
6679 struct ext2_db_entry *db;
6680
6681 db = (struct ext2_db_entry *) priv_data;
6682 if (db->blockcnt == (int) blockcnt) {
6683 *block_nr = db->blk;
6684 return BLOCK_CHANGED;
6685 }
6686 return 0;
6687}
6688
6689/*
6690 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6691 *
6692 * Pass #3 assures that all directories are connected to the
6693 * filesystem tree, using the following algorithm:
6694 *
6695 * First, the root directory is checked to make sure it exists; if
6696 * not, e2fsck will offer to create a new one. It is then marked as
6697 * "done".
6698 *
6699 * Then, pass3 interates over all directory inodes; for each directory
6700 * it attempts to trace up the filesystem tree, using dirinfo.parent
6701 * until it reaches a directory which has been marked "done". If it
6702 * cannot do so, then the directory must be disconnected, and e2fsck
6703 * will offer to reconnect it to /lost+found. While it is chasing
6704 * parent pointers up the filesystem tree, if pass3 sees a directory
6705 * twice, then it has detected a filesystem loop, and it will again
6706 * offer to reconnect the directory to /lost+found in to break the
6707 * filesystem loop.
6708 *
6709 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6710 * reconnect inodes to /lost+found; this subroutine is also used by
6711 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6712 * is responsible for creating /lost+found if it does not exist.
6713 *
6714 * Pass 3 frees the following data structures:
6715 * - The dirinfo directory information cache.
6716 */
6717
6718static void check_root(e2fsck_t ctx);
6719static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6720 struct problem_context *pctx);
6721static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6722
6723static ext2fs_inode_bitmap inode_loop_detect;
6724static ext2fs_inode_bitmap inode_done_map;
6725
6726static void e2fsck_pass3(e2fsck_t ctx)
6727{
6728 ext2_filsys fs = ctx->fs;
6729 int i;
6730 struct problem_context pctx;
6731 struct dir_info *dir;
6732 unsigned long maxdirs, count;
6733
6734 clear_problem_context(&pctx);
6735
6736 /* Pass 3 */
6737
6738 if (!(ctx->options & E2F_OPT_PREEN))
6739 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6740
6741 /*
6742 * Allocate some bitmaps to do loop detection.
6743 */
6744 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6745 &inode_done_map);
6746 if (pctx.errcode) {
6747 pctx.num = 2;
6748 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6749 ctx->flags |= E2F_FLAG_ABORT;
6750 goto abort_exit;
6751 }
6752 check_root(ctx);
6753 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6754 goto abort_exit;
6755
6756 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6757
6758 maxdirs = e2fsck_get_num_dirinfo(ctx);
6759 count = 1;
6760
6761 if (ctx->progress)
6762 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6763 goto abort_exit;
6764
6765 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6766 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6767 goto abort_exit;
6768 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6769 goto abort_exit;
6770 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6771 if (check_directory(ctx, dir, &pctx))
6772 goto abort_exit;
6773 }
6774
6775 /*
6776 * Force the creation of /lost+found if not present
6777 */
6778 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6779 e2fsck_get_lost_and_found(ctx, 1);
6780
6781 /*
6782 * If there are any directories that need to be indexed or
6783 * optimized, do it here.
6784 */
6785 e2fsck_rehash_directories(ctx);
6786
6787abort_exit:
6788 e2fsck_free_dir_info(ctx);
6789 ext2fs_free_inode_bitmap(inode_loop_detect);
6790 inode_loop_detect = 0;
6791 ext2fs_free_inode_bitmap(inode_done_map);
6792 inode_done_map = 0;
6793}
6794
6795/*
6796 * This makes sure the root inode is present; if not, we ask if the
6797 * user wants us to create it. Not creating it is a fatal error.
6798 */
6799static void check_root(e2fsck_t ctx)
6800{
6801 ext2_filsys fs = ctx->fs;
6802 blk_t blk;
6803 struct ext2_inode inode;
6804 char * block;
6805 struct problem_context pctx;
6806
6807 clear_problem_context(&pctx);
6808
6809 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6810 /*
6811 * If the root inode is not a directory, die here. The
6812 * user must have answered 'no' in pass1 when we
6813 * offered to clear it.
6814 */
6815 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6816 EXT2_ROOT_INO))) {
6817 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6818 ctx->flags |= E2F_FLAG_ABORT;
6819 }
6820 return;
6821 }
6822
6823 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6824 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6825 ctx->flags |= E2F_FLAG_ABORT;
6826 return;
6827 }
6828
6829 e2fsck_read_bitmaps(ctx);
6830
6831 /*
6832 * First, find a free block
6833 */
6834 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6835 if (pctx.errcode) {
6836 pctx.str = "ext2fs_new_block";
6837 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6838 ctx->flags |= E2F_FLAG_ABORT;
6839 return;
6840 }
6841 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6842 ext2fs_mark_block_bitmap(fs->block_map, blk);
6843 ext2fs_mark_bb_dirty(fs);
6844
6845 /*
6846 * Now let's create the actual data block for the inode
6847 */
6848 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6849 &block);
6850 if (pctx.errcode) {
6851 pctx.str = "ext2fs_new_dir_block";
6852 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6853 ctx->flags |= E2F_FLAG_ABORT;
6854 return;
6855 }
6856
6857 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6858 if (pctx.errcode) {
6859 pctx.str = "ext2fs_write_dir_block";
6860 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6861 ctx->flags |= E2F_FLAG_ABORT;
6862 return;
6863 }
6864 ext2fs_free_mem(&block);
6865
6866 /*
6867 * Set up the inode structure
6868 */
6869 memset(&inode, 0, sizeof(inode));
6870 inode.i_mode = 040755;
6871 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006872 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006873 inode.i_links_count = 2;
6874 inode.i_blocks = fs->blocksize / 512;
6875 inode.i_block[0] = blk;
6876
6877 /*
6878 * Write out the inode.
6879 */
6880 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6881 if (pctx.errcode) {
6882 pctx.str = "ext2fs_write_inode";
6883 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6884 ctx->flags |= E2F_FLAG_ABORT;
6885 return;
6886 }
6887
6888 /*
6889 * Miscellaneous bookkeeping...
6890 */
6891 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6892 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6893 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6894
6895 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6896 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6897 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6898 ext2fs_mark_ib_dirty(fs);
6899}
6900
6901/*
6902 * This subroutine is responsible for making sure that a particular
6903 * directory is connected to the root; if it isn't we trace it up as
6904 * far as we can go, and then offer to connect the resulting parent to
6905 * the lost+found. We have to do loop detection; if we ever discover
6906 * a loop, we treat that as a disconnected directory and offer to
6907 * reparent it to lost+found.
6908 *
6909 * However, loop detection is expensive, because for very large
6910 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6911 * is non-trivial. Loops in filesystems are also a rare error case,
6912 * and we shouldn't optimize for error cases. So we try two passes of
6913 * the algorithm. The first time, we ignore loop detection and merely
6914 * increment a counter; if the counter exceeds some extreme threshold,
6915 * then we try again with the loop detection bitmap enabled.
6916 */
6917static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6918 struct problem_context *pctx)
6919{
6920 ext2_filsys fs = ctx->fs;
6921 struct dir_info *p = dir;
6922 int loop_pass = 0, parent_count = 0;
6923
6924 if (!p)
6925 return 0;
6926
6927 while (1) {
6928 /*
6929 * Mark this inode as being "done"; by the time we
6930 * return from this function, the inode we either be
6931 * verified as being connected to the directory tree,
6932 * or we will have offered to reconnect this to
6933 * lost+found.
6934 *
6935 * If it was marked done already, then we've reached a
6936 * parent we've already checked.
6937 */
6938 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6939 break;
6940
6941 /*
6942 * If this directory doesn't have a parent, or we've
6943 * seen the parent once already, then offer to
6944 * reparent it to lost+found
6945 */
6946 if (!p->parent ||
6947 (loop_pass &&
6948 (ext2fs_test_inode_bitmap(inode_loop_detect,
6949 p->parent)))) {
6950 pctx->ino = p->ino;
6951 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6952 if (e2fsck_reconnect_file(ctx, pctx->ino))
6953 ext2fs_unmark_valid(fs);
6954 else {
6955 p = e2fsck_get_dir_info(ctx, pctx->ino);
6956 p->parent = ctx->lost_and_found;
6957 fix_dotdot(ctx, p, ctx->lost_and_found);
6958 }
6959 }
6960 break;
6961 }
6962 p = e2fsck_get_dir_info(ctx, p->parent);
6963 if (!p) {
6964 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6965 return 0;
6966 }
6967 if (loop_pass) {
6968 ext2fs_mark_inode_bitmap(inode_loop_detect,
6969 p->ino);
6970 } else if (parent_count++ > 2048) {
6971 /*
6972 * If we've run into a path depth that's
6973 * greater than 2048, try again with the inode
6974 * loop bitmap turned on and start from the
6975 * top.
6976 */
6977 loop_pass = 1;
6978 if (inode_loop_detect)
6979 ext2fs_clear_inode_bitmap(inode_loop_detect);
6980 else {
6981 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6982 if (pctx->errcode) {
6983 pctx->num = 1;
6984 fix_problem(ctx,
6985 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6986 ctx->flags |= E2F_FLAG_ABORT;
6987 return -1;
6988 }
6989 }
6990 p = dir;
6991 }
6992 }
6993
6994 /*
6995 * Make sure that .. and the parent directory are the same;
6996 * offer to fix it if not.
6997 */
6998 if (dir->parent != dir->dotdot) {
6999 pctx->ino = dir->ino;
7000 pctx->ino2 = dir->dotdot;
7001 pctx->dir = dir->parent;
7002 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7003 fix_dotdot(ctx, dir, dir->parent);
7004 }
7005 return 0;
7006}
7007
7008/*
7009 * This routine gets the lost_and_found inode, making it a directory
7010 * if necessary
7011 */
7012ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7013{
7014 ext2_filsys fs = ctx->fs;
7015 ext2_ino_t ino;
7016 blk_t blk;
7017 errcode_t retval;
7018 struct ext2_inode inode;
7019 char * block;
7020 static const char name[] = "lost+found";
7021 struct problem_context pctx;
7022 struct dir_info *dirinfo;
7023
7024 if (ctx->lost_and_found)
7025 return ctx->lost_and_found;
7026
7027 clear_problem_context(&pctx);
7028
7029 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7030 sizeof(name)-1, 0, &ino);
7031 if (retval && !fix)
7032 return 0;
7033 if (!retval) {
7034 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7035 ctx->lost_and_found = ino;
7036 return ino;
7037 }
7038
7039 /* Lost+found isn't a directory! */
7040 if (!fix)
7041 return 0;
7042 pctx.ino = ino;
7043 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7044 return 0;
7045
7046 /* OK, unlink the old /lost+found file. */
7047 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7048 if (pctx.errcode) {
7049 pctx.str = "ext2fs_unlink";
7050 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7051 return 0;
7052 }
7053 dirinfo = e2fsck_get_dir_info(ctx, ino);
7054 if (dirinfo)
7055 dirinfo->parent = 0;
7056 e2fsck_adjust_inode_count(ctx, ino, -1);
7057 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7058 pctx.errcode = retval;
7059 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7060 }
7061 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7062 return 0;
7063
7064 /*
7065 * Read the inode and block bitmaps in; we'll be messing with
7066 * them.
7067 */
7068 e2fsck_read_bitmaps(ctx);
7069
7070 /*
7071 * First, find a free block
7072 */
7073 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7074 if (retval) {
7075 pctx.errcode = retval;
7076 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7077 return 0;
7078 }
7079 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7080 ext2fs_block_alloc_stats(fs, blk, +1);
7081
7082 /*
7083 * Next find a free inode.
7084 */
7085 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7086 ctx->inode_used_map, &ino);
7087 if (retval) {
7088 pctx.errcode = retval;
7089 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7090 return 0;
7091 }
7092 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7093 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7094 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7095
7096 /*
7097 * Now let's create the actual data block for the inode
7098 */
7099 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7100 if (retval) {
7101 pctx.errcode = retval;
7102 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7103 return 0;
7104 }
7105
7106 retval = ext2fs_write_dir_block(fs, blk, block);
7107 ext2fs_free_mem(&block);
7108 if (retval) {
7109 pctx.errcode = retval;
7110 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7111 return 0;
7112 }
7113
7114 /*
7115 * Set up the inode structure
7116 */
7117 memset(&inode, 0, sizeof(inode));
7118 inode.i_mode = 040700;
7119 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007120 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007121 inode.i_links_count = 2;
7122 inode.i_blocks = fs->blocksize / 512;
7123 inode.i_block[0] = blk;
7124
7125 /*
7126 * Next, write out the inode.
7127 */
7128 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7129 if (pctx.errcode) {
7130 pctx.str = "ext2fs_write_inode";
7131 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7132 return 0;
7133 }
7134 /*
7135 * Finally, create the directory link
7136 */
7137 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7138 if (pctx.errcode) {
7139 pctx.str = "ext2fs_link";
7140 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7141 return 0;
7142 }
7143
7144 /*
7145 * Miscellaneous bookkeeping that needs to be kept straight.
7146 */
7147 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7148 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7149 ext2fs_icount_store(ctx->inode_count, ino, 2);
7150 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7151 ctx->lost_and_found = ino;
7152 return ino;
7153}
7154
7155/*
7156 * This routine will connect a file to lost+found
7157 */
7158int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7159{
7160 ext2_filsys fs = ctx->fs;
7161 errcode_t retval;
7162 char name[80];
7163 struct problem_context pctx;
7164 struct ext2_inode inode;
7165 int file_type = 0;
7166
7167 clear_problem_context(&pctx);
7168 pctx.ino = ino;
7169
7170 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7171 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7172 ctx->bad_lost_and_found++;
7173 }
7174 if (ctx->bad_lost_and_found) {
7175 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7176 return 1;
7177 }
7178
7179 sprintf(name, "#%u", ino);
7180 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7181 file_type = ext2_file_type(inode.i_mode);
7182 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7183 if (retval == EXT2_ET_DIR_NO_SPACE) {
7184 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7185 return 1;
7186 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7187 1, 0);
7188 if (retval) {
7189 pctx.errcode = retval;
7190 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7191 return 1;
7192 }
7193 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7194 ino, file_type);
7195 }
7196 if (retval) {
7197 pctx.errcode = retval;
7198 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7199 return 1;
7200 }
7201 e2fsck_adjust_inode_count(ctx, ino, 1);
7202
7203 return 0;
7204}
7205
7206/*
7207 * Utility routine to adjust the inode counts on an inode.
7208 */
7209errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7210{
7211 ext2_filsys fs = ctx->fs;
7212 errcode_t retval;
7213 struct ext2_inode inode;
7214
7215 if (!ino)
7216 return 0;
7217
7218 retval = ext2fs_read_inode(fs, ino, &inode);
7219 if (retval)
7220 return retval;
7221
7222 if (adj == 1) {
7223 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7224 if (inode.i_links_count == (__u16) ~0)
7225 return 0;
7226 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7227 inode.i_links_count++;
7228 } else if (adj == -1) {
7229 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7230 if (inode.i_links_count == 0)
7231 return 0;
7232 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7233 inode.i_links_count--;
7234 }
7235
7236 retval = ext2fs_write_inode(fs, ino, &inode);
7237 if (retval)
7238 return retval;
7239
7240 return 0;
7241}
7242
7243/*
7244 * Fix parent --- this routine fixes up the parent of a directory.
7245 */
7246struct fix_dotdot_struct {
7247 ext2_filsys fs;
7248 ext2_ino_t parent;
7249 int done;
7250 e2fsck_t ctx;
7251};
7252
7253static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7254 int offset FSCK_ATTR((unused)),
7255 int blocksize FSCK_ATTR((unused)),
7256 char *buf FSCK_ATTR((unused)),
7257 void *priv_data)
7258{
7259 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7260 errcode_t retval;
7261 struct problem_context pctx;
7262
7263 if ((dirent->name_len & 0xFF) != 2)
7264 return 0;
7265 if (strncmp(dirent->name, "..", 2))
7266 return 0;
7267
7268 clear_problem_context(&pctx);
7269
7270 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7271 if (retval) {
7272 pctx.errcode = retval;
7273 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7274 }
7275 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7276 if (retval) {
7277 pctx.errcode = retval;
7278 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7279 }
7280 dirent->inode = fp->parent;
7281
7282 fp->done++;
7283 return DIRENT_ABORT | DIRENT_CHANGED;
7284}
7285
7286static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7287{
7288 ext2_filsys fs = ctx->fs;
7289 errcode_t retval;
7290 struct fix_dotdot_struct fp;
7291 struct problem_context pctx;
7292
7293 fp.fs = fs;
7294 fp.parent = parent;
7295 fp.done = 0;
7296 fp.ctx = ctx;
7297
7298 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7299 0, fix_dotdot_proc, &fp);
7300 if (retval || !fp.done) {
7301 clear_problem_context(&pctx);
7302 pctx.ino = dir->ino;
7303 pctx.errcode = retval;
7304 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7305 PR_3_FIX_PARENT_NOFIND, &pctx);
7306 ext2fs_unmark_valid(fs);
7307 }
7308 dir->dotdot = parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007309}
7310
7311/*
7312 * These routines are responsible for expanding a /lost+found if it is
7313 * too small.
7314 */
7315
7316struct expand_dir_struct {
7317 int num;
7318 int guaranteed_size;
7319 int newblocks;
7320 int last_block;
7321 errcode_t err;
7322 e2fsck_t ctx;
7323};
7324
7325static int expand_dir_proc(ext2_filsys fs,
7326 blk_t *blocknr,
7327 e2_blkcnt_t blockcnt,
7328 blk_t ref_block FSCK_ATTR((unused)),
7329 int ref_offset FSCK_ATTR((unused)),
7330 void *priv_data)
7331{
7332 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7333 blk_t new_blk;
7334 static blk_t last_blk = 0;
7335 char *block;
7336 errcode_t retval;
7337 e2fsck_t ctx;
7338
7339 ctx = es->ctx;
7340
7341 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7342 return BLOCK_ABORT;
7343
7344 if (blockcnt > 0)
7345 es->last_block = blockcnt;
7346 if (*blocknr) {
7347 last_blk = *blocknr;
7348 return 0;
7349 }
7350 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7351 &new_blk);
7352 if (retval) {
7353 es->err = retval;
7354 return BLOCK_ABORT;
7355 }
7356 if (blockcnt > 0) {
7357 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7358 if (retval) {
7359 es->err = retval;
7360 return BLOCK_ABORT;
7361 }
7362 es->num--;
7363 retval = ext2fs_write_dir_block(fs, new_blk, block);
7364 } else {
7365 retval = ext2fs_get_mem(fs->blocksize, &block);
7366 if (retval) {
7367 es->err = retval;
7368 return BLOCK_ABORT;
7369 }
7370 memset(block, 0, fs->blocksize);
7371 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7372 }
7373 if (retval) {
7374 es->err = retval;
7375 return BLOCK_ABORT;
7376 }
7377 ext2fs_free_mem(&block);
7378 *blocknr = new_blk;
7379 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7380 ext2fs_block_alloc_stats(fs, new_blk, +1);
7381 es->newblocks++;
7382
7383 if (es->num == 0)
7384 return (BLOCK_CHANGED | BLOCK_ABORT);
7385 else
7386 return BLOCK_CHANGED;
7387}
7388
7389errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7390 int num, int guaranteed_size)
7391{
7392 ext2_filsys fs = ctx->fs;
7393 errcode_t retval;
7394 struct expand_dir_struct es;
7395 struct ext2_inode inode;
7396
7397 if (!(fs->flags & EXT2_FLAG_RW))
7398 return EXT2_ET_RO_FILSYS;
7399
7400 /*
7401 * Read the inode and block bitmaps in; we'll be messing with
7402 * them.
7403 */
7404 e2fsck_read_bitmaps(ctx);
7405
7406 retval = ext2fs_check_directory(fs, dir);
7407 if (retval)
7408 return retval;
7409
7410 es.num = num;
7411 es.guaranteed_size = guaranteed_size;
7412 es.last_block = 0;
7413 es.err = 0;
7414 es.newblocks = 0;
7415 es.ctx = ctx;
7416
7417 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7418 0, expand_dir_proc, &es);
7419
7420 if (es.err)
7421 return es.err;
7422
7423 /*
7424 * Update the size and block count fields in the inode.
7425 */
7426 retval = ext2fs_read_inode(fs, dir, &inode);
7427 if (retval)
7428 return retval;
7429
7430 inode.i_size = (es.last_block + 1) * fs->blocksize;
7431 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7432
7433 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7434
7435 return 0;
7436}
7437
7438/*
7439 * pass4.c -- pass #4 of e2fsck: Check reference counts
7440 *
7441 * Pass 4 frees the following data structures:
7442 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7443 */
7444
7445/*
7446 * This routine is called when an inode is not connected to the
7447 * directory tree.
7448 *
7449 * This subroutine returns 1 then the caller shouldn't bother with the
7450 * rest of the pass 4 tests.
7451 */
7452static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7453{
7454 ext2_filsys fs = ctx->fs;
7455 struct ext2_inode inode;
7456 struct problem_context pctx;
7457
7458 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7459 clear_problem_context(&pctx);
7460 pctx.ino = i;
7461 pctx.inode = &inode;
7462
7463 /*
7464 * Offer to delete any zero-length files that does not have
7465 * blocks. If there is an EA block, it might have useful
7466 * information, so we won't prompt to delete it, but let it be
7467 * reconnected to lost+found.
7468 */
7469 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7470 LINUX_S_ISDIR(inode.i_mode))) {
7471 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7472 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7473 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007474 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007475 e2fsck_write_inode(ctx, i, &inode,
7476 "disconnect_inode");
7477 /*
7478 * Fix up the bitmaps...
7479 */
7480 e2fsck_read_bitmaps(ctx);
7481 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7482 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7483 ext2fs_inode_alloc_stats2(fs, i, -1,
7484 LINUX_S_ISDIR(inode.i_mode));
7485 return 0;
7486 }
7487 }
7488
7489 /*
7490 * Prompt to reconnect.
7491 */
7492 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7493 if (e2fsck_reconnect_file(ctx, i))
7494 ext2fs_unmark_valid(fs);
7495 } else {
7496 /*
7497 * If we don't attach the inode, then skip the
7498 * i_links_test since there's no point in trying to
7499 * force i_links_count to zero.
7500 */
7501 ext2fs_unmark_valid(fs);
7502 return 1;
7503 }
7504 return 0;
7505}
7506
7507
7508static void e2fsck_pass4(e2fsck_t ctx)
7509{
7510 ext2_filsys fs = ctx->fs;
7511 ext2_ino_t i;
7512 struct ext2_inode inode;
7513 struct problem_context pctx;
7514 __u16 link_count, link_counted;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01007515 char *buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007516 int group, maxgroup;
7517
7518 /* Pass 4 */
7519
7520 clear_problem_context(&pctx);
7521
7522 if (!(ctx->options & E2F_OPT_PREEN))
7523 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7524
7525 group = 0;
7526 maxgroup = fs->group_desc_count;
7527 if (ctx->progress)
7528 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7529 return;
7530
7531 for (i=1; i <= fs->super->s_inodes_count; i++) {
7532 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7533 return;
7534 if ((i % fs->super->s_inodes_per_group) == 0) {
7535 group++;
7536 if (ctx->progress)
7537 if ((ctx->progress)(ctx, 4, group, maxgroup))
7538 return;
7539 }
7540 if (i == EXT2_BAD_INO ||
7541 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7542 continue;
7543 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7544 (ctx->inode_imagic_map &&
7545 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7546 continue;
7547 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7548 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7549 if (link_counted == 0) {
7550 if (!buf)
7551 buf = e2fsck_allocate_memory(ctx,
7552 fs->blocksize, "bad_inode buffer");
7553 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7554 continue;
7555 if (disconnect_inode(ctx, i))
7556 continue;
7557 ext2fs_icount_fetch(ctx->inode_link_info, i,
7558 &link_count);
7559 ext2fs_icount_fetch(ctx->inode_count, i,
7560 &link_counted);
7561 }
7562 if (link_counted != link_count) {
7563 e2fsck_read_inode(ctx, i, &inode, "pass4");
7564 pctx.ino = i;
7565 pctx.inode = &inode;
7566 if (link_count != inode.i_links_count) {
7567 pctx.num = link_count;
7568 fix_problem(ctx,
7569 PR_4_INCONSISTENT_COUNT, &pctx);
7570 }
7571 pctx.num = link_counted;
7572 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7573 inode.i_links_count = link_counted;
7574 e2fsck_write_inode(ctx, i, &inode, "pass4");
7575 }
7576 }
7577 }
7578 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7579 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7580 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7581 ctx->inode_imagic_map = 0;
7582 ext2fs_free_mem(&buf);
7583}
7584
7585/*
7586 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7587 */
7588
7589#define NO_BLK ((blk_t) -1)
7590
7591static void print_bitmap_problem(e2fsck_t ctx, int problem,
7592 struct problem_context *pctx)
7593{
7594 switch (problem) {
7595 case PR_5_BLOCK_UNUSED:
7596 if (pctx->blk == pctx->blk2)
7597 pctx->blk2 = 0;
7598 else
7599 problem = PR_5_BLOCK_RANGE_UNUSED;
7600 break;
7601 case PR_5_BLOCK_USED:
7602 if (pctx->blk == pctx->blk2)
7603 pctx->blk2 = 0;
7604 else
7605 problem = PR_5_BLOCK_RANGE_USED;
7606 break;
7607 case PR_5_INODE_UNUSED:
7608 if (pctx->ino == pctx->ino2)
7609 pctx->ino2 = 0;
7610 else
7611 problem = PR_5_INODE_RANGE_UNUSED;
7612 break;
7613 case PR_5_INODE_USED:
7614 if (pctx->ino == pctx->ino2)
7615 pctx->ino2 = 0;
7616 else
7617 problem = PR_5_INODE_RANGE_USED;
7618 break;
7619 }
7620 fix_problem(ctx, problem, pctx);
7621 pctx->blk = pctx->blk2 = NO_BLK;
7622 pctx->ino = pctx->ino2 = 0;
7623}
7624
7625static void check_block_bitmaps(e2fsck_t ctx)
7626{
7627 ext2_filsys fs = ctx->fs;
7628 blk_t i;
7629 int *free_array;
7630 int group = 0;
7631 unsigned int blocks = 0;
7632 unsigned int free_blocks = 0;
7633 int group_free = 0;
7634 int actual, bitmap;
7635 struct problem_context pctx;
7636 int problem, save_problem, fixit, had_problem;
7637 errcode_t retval;
7638
7639 clear_problem_context(&pctx);
7640 free_array = (int *) e2fsck_allocate_memory(ctx,
7641 fs->group_desc_count * sizeof(int), "free block count array");
7642
7643 if ((fs->super->s_first_data_block <
7644 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7645 (fs->super->s_blocks_count-1 >
7646 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7647 pctx.num = 1;
7648 pctx.blk = fs->super->s_first_data_block;
7649 pctx.blk2 = fs->super->s_blocks_count -1;
7650 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7651 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7652 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7653
7654 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7655 return;
7656 }
7657
7658 if ((fs->super->s_first_data_block <
7659 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7660 (fs->super->s_blocks_count-1 >
7661 ext2fs_get_block_bitmap_end(fs->block_map))) {
7662 pctx.num = 2;
7663 pctx.blk = fs->super->s_first_data_block;
7664 pctx.blk2 = fs->super->s_blocks_count -1;
7665 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7666 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7667 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7668
7669 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7670 return;
7671 }
7672
7673redo_counts:
7674 had_problem = 0;
7675 save_problem = 0;
7676 pctx.blk = pctx.blk2 = NO_BLK;
7677 for (i = fs->super->s_first_data_block;
7678 i < fs->super->s_blocks_count;
7679 i++) {
7680 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7681 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7682
7683 if (actual == bitmap)
7684 goto do_counts;
7685
7686 if (!actual && bitmap) {
7687 /*
7688 * Block not used, but marked in use in the bitmap.
7689 */
7690 problem = PR_5_BLOCK_UNUSED;
7691 } else {
7692 /*
7693 * Block used, but not marked in use in the bitmap.
7694 */
7695 problem = PR_5_BLOCK_USED;
7696 }
7697 if (pctx.blk == NO_BLK) {
7698 pctx.blk = pctx.blk2 = i;
7699 save_problem = problem;
7700 } else {
7701 if ((problem == save_problem) &&
7702 (pctx.blk2 == i-1))
7703 pctx.blk2++;
7704 else {
7705 print_bitmap_problem(ctx, save_problem, &pctx);
7706 pctx.blk = pctx.blk2 = i;
7707 save_problem = problem;
7708 }
7709 }
7710 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7711 had_problem++;
7712
7713 do_counts:
7714 if (!bitmap) {
7715 group_free++;
7716 free_blocks++;
7717 }
7718 blocks ++;
7719 if ((blocks == fs->super->s_blocks_per_group) ||
7720 (i == fs->super->s_blocks_count-1)) {
7721 free_array[group] = group_free;
7722 group ++;
7723 blocks = 0;
7724 group_free = 0;
7725 if (ctx->progress)
7726 if ((ctx->progress)(ctx, 5, group,
7727 fs->group_desc_count*2))
7728 return;
7729 }
7730 }
7731 if (pctx.blk != NO_BLK)
7732 print_bitmap_problem(ctx, save_problem, &pctx);
7733 if (had_problem)
7734 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7735 else
7736 fixit = -1;
7737 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7738
7739 if (fixit == 1) {
7740 ext2fs_free_block_bitmap(fs->block_map);
7741 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7742 &fs->block_map);
7743 if (retval) {
7744 clear_problem_context(&pctx);
7745 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7746 ctx->flags |= E2F_FLAG_ABORT;
7747 return;
7748 }
7749 ext2fs_set_bitmap_padding(fs->block_map);
7750 ext2fs_mark_bb_dirty(fs);
7751
7752 /* Redo the counts */
7753 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7754 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7755 goto redo_counts;
7756 } else if (fixit == 0)
7757 ext2fs_unmark_valid(fs);
7758
7759 for (i = 0; i < fs->group_desc_count; i++) {
7760 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7761 pctx.group = i;
7762 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7763 pctx.blk2 = free_array[i];
7764
7765 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7766 &pctx)) {
7767 fs->group_desc[i].bg_free_blocks_count =
7768 free_array[i];
7769 ext2fs_mark_super_dirty(fs);
7770 } else
7771 ext2fs_unmark_valid(fs);
7772 }
7773 }
7774 if (free_blocks != fs->super->s_free_blocks_count) {
7775 pctx.group = 0;
7776 pctx.blk = fs->super->s_free_blocks_count;
7777 pctx.blk2 = free_blocks;
7778
7779 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7780 fs->super->s_free_blocks_count = free_blocks;
7781 ext2fs_mark_super_dirty(fs);
7782 } else
7783 ext2fs_unmark_valid(fs);
7784 }
7785 ext2fs_free_mem(&free_array);
7786}
7787
7788static void check_inode_bitmaps(e2fsck_t ctx)
7789{
7790 ext2_filsys fs = ctx->fs;
7791 ext2_ino_t i;
7792 unsigned int free_inodes = 0;
7793 int group_free = 0;
7794 int dirs_count = 0;
7795 int group = 0;
7796 unsigned int inodes = 0;
7797 int *free_array;
7798 int *dir_array;
7799 int actual, bitmap;
7800 errcode_t retval;
7801 struct problem_context pctx;
7802 int problem, save_problem, fixit, had_problem;
7803
7804 clear_problem_context(&pctx);
7805 free_array = (int *) e2fsck_allocate_memory(ctx,
7806 fs->group_desc_count * sizeof(int), "free inode count array");
7807
7808 dir_array = (int *) e2fsck_allocate_memory(ctx,
7809 fs->group_desc_count * sizeof(int), "directory count array");
7810
7811 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7812 (fs->super->s_inodes_count >
7813 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7814 pctx.num = 3;
7815 pctx.blk = 1;
7816 pctx.blk2 = fs->super->s_inodes_count;
7817 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7818 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7819 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7820
7821 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7822 return;
7823 }
7824 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7825 (fs->super->s_inodes_count >
7826 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7827 pctx.num = 4;
7828 pctx.blk = 1;
7829 pctx.blk2 = fs->super->s_inodes_count;
7830 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7831 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7832 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7833
7834 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7835 return;
7836 }
7837
7838redo_counts:
7839 had_problem = 0;
7840 save_problem = 0;
7841 pctx.ino = pctx.ino2 = 0;
7842 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7843 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7844 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7845
7846 if (actual == bitmap)
7847 goto do_counts;
7848
7849 if (!actual && bitmap) {
7850 /*
7851 * Inode wasn't used, but marked in bitmap
7852 */
7853 problem = PR_5_INODE_UNUSED;
7854 } else /* if (actual && !bitmap) */ {
7855 /*
7856 * Inode used, but not in bitmap
7857 */
7858 problem = PR_5_INODE_USED;
7859 }
7860 if (pctx.ino == 0) {
7861 pctx.ino = pctx.ino2 = i;
7862 save_problem = problem;
7863 } else {
7864 if ((problem == save_problem) &&
7865 (pctx.ino2 == i-1))
7866 pctx.ino2++;
7867 else {
7868 print_bitmap_problem(ctx, save_problem, &pctx);
7869 pctx.ino = pctx.ino2 = i;
7870 save_problem = problem;
7871 }
7872 }
7873 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7874 had_problem++;
7875
7876do_counts:
7877 if (!bitmap) {
7878 group_free++;
7879 free_inodes++;
7880 } else {
7881 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7882 dirs_count++;
7883 }
7884 inodes++;
7885 if ((inodes == fs->super->s_inodes_per_group) ||
7886 (i == fs->super->s_inodes_count)) {
7887 free_array[group] = group_free;
7888 dir_array[group] = dirs_count;
7889 group ++;
7890 inodes = 0;
7891 group_free = 0;
7892 dirs_count = 0;
7893 if (ctx->progress)
7894 if ((ctx->progress)(ctx, 5,
7895 group + fs->group_desc_count,
7896 fs->group_desc_count*2))
7897 return;
7898 }
7899 }
7900 if (pctx.ino)
7901 print_bitmap_problem(ctx, save_problem, &pctx);
7902
7903 if (had_problem)
7904 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7905 else
7906 fixit = -1;
7907 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7908
7909 if (fixit == 1) {
7910 ext2fs_free_inode_bitmap(fs->inode_map);
7911 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7912 &fs->inode_map);
7913 if (retval) {
7914 clear_problem_context(&pctx);
7915 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7916 ctx->flags |= E2F_FLAG_ABORT;
7917 return;
7918 }
7919 ext2fs_set_bitmap_padding(fs->inode_map);
7920 ext2fs_mark_ib_dirty(fs);
7921
7922 /* redo counts */
7923 inodes = 0; free_inodes = 0; group_free = 0;
7924 dirs_count = 0; group = 0;
7925 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7926 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7927 goto redo_counts;
7928 } else if (fixit == 0)
7929 ext2fs_unmark_valid(fs);
7930
7931 for (i = 0; i < fs->group_desc_count; i++) {
7932 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7933 pctx.group = i;
7934 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7935 pctx.ino2 = free_array[i];
7936 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7937 &pctx)) {
7938 fs->group_desc[i].bg_free_inodes_count =
7939 free_array[i];
7940 ext2fs_mark_super_dirty(fs);
7941 } else
7942 ext2fs_unmark_valid(fs);
7943 }
7944 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7945 pctx.group = i;
7946 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7947 pctx.ino2 = dir_array[i];
7948
7949 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7950 &pctx)) {
7951 fs->group_desc[i].bg_used_dirs_count =
7952 dir_array[i];
7953 ext2fs_mark_super_dirty(fs);
7954 } else
7955 ext2fs_unmark_valid(fs);
7956 }
7957 }
7958 if (free_inodes != fs->super->s_free_inodes_count) {
7959 pctx.group = -1;
7960 pctx.ino = fs->super->s_free_inodes_count;
7961 pctx.ino2 = free_inodes;
7962
7963 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7964 fs->super->s_free_inodes_count = free_inodes;
7965 ext2fs_mark_super_dirty(fs);
7966 } else
7967 ext2fs_unmark_valid(fs);
7968 }
7969 ext2fs_free_mem(&free_array);
7970 ext2fs_free_mem(&dir_array);
7971}
7972
7973static void check_inode_end(e2fsck_t ctx)
7974{
7975 ext2_filsys fs = ctx->fs;
7976 ext2_ino_t end, save_inodes_count, i;
7977 struct problem_context pctx;
7978
7979 clear_problem_context(&pctx);
7980
7981 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7982 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7983 &save_inodes_count);
7984 if (pctx.errcode) {
7985 pctx.num = 1;
7986 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7987 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7988 return;
7989 }
7990 if (save_inodes_count == end)
7991 return;
7992
7993 for (i = save_inodes_count + 1; i <= end; i++) {
7994 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
7995 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
7996 for (i = save_inodes_count + 1; i <= end; i++)
7997 ext2fs_mark_inode_bitmap(fs->inode_map,
7998 i);
7999 ext2fs_mark_ib_dirty(fs);
8000 } else
8001 ext2fs_unmark_valid(fs);
8002 break;
8003 }
8004 }
8005
8006 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8007 save_inodes_count, 0);
8008 if (pctx.errcode) {
8009 pctx.num = 2;
8010 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8011 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8012 return;
8013 }
8014}
8015
8016static void check_block_end(e2fsck_t ctx)
8017{
8018 ext2_filsys fs = ctx->fs;
8019 blk_t end, save_blocks_count, i;
8020 struct problem_context pctx;
8021
8022 clear_problem_context(&pctx);
8023
8024 end = fs->block_map->start +
8025 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8026 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8027 &save_blocks_count);
8028 if (pctx.errcode) {
8029 pctx.num = 3;
8030 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8031 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8032 return;
8033 }
8034 if (save_blocks_count == end)
8035 return;
8036
8037 for (i = save_blocks_count + 1; i <= end; i++) {
8038 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8039 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8040 for (i = save_blocks_count + 1; i <= end; i++)
8041 ext2fs_mark_block_bitmap(fs->block_map,
8042 i);
8043 ext2fs_mark_bb_dirty(fs);
8044 } else
8045 ext2fs_unmark_valid(fs);
8046 break;
8047 }
8048 }
8049
8050 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8051 save_blocks_count, 0);
8052 if (pctx.errcode) {
8053 pctx.num = 4;
8054 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8055 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8056 return;
8057 }
8058}
8059
8060static void e2fsck_pass5(e2fsck_t ctx)
8061{
8062 struct problem_context pctx;
8063
8064 /* Pass 5 */
8065
8066 clear_problem_context(&pctx);
8067
8068 if (!(ctx->options & E2F_OPT_PREEN))
8069 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8070
8071 if (ctx->progress)
8072 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8073 return;
8074
8075 e2fsck_read_bitmaps(ctx);
8076
8077 check_block_bitmaps(ctx);
8078 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8079 return;
8080 check_inode_bitmaps(ctx);
8081 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8082 return;
8083 check_inode_end(ctx);
8084 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8085 return;
8086 check_block_end(ctx);
8087 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8088 return;
8089
8090 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8091 ctx->inode_used_map = 0;
8092 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8093 ctx->inode_dir_map = 0;
8094 ext2fs_free_block_bitmap(ctx->block_found_map);
8095 ctx->block_found_map = 0;
8096}
8097
8098/*
8099 * problem.c --- report filesystem problems to the user
8100 */
8101
8102#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8103#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8104#define PR_NO_DEFAULT 0x000004 /* Default to no */
8105#define PR_MSG_ONLY 0x000008 /* Print message only */
8106
8107/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8108
8109#define PR_FATAL 0x001000 /* Fatal error */
8110#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8111 /* ask another */
8112#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8113#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8114#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8115#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8116#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8117
8118
8119#define PROMPT_NONE 0
8120#define PROMPT_FIX 1
8121#define PROMPT_CLEAR 2
8122#define PROMPT_RELOCATE 3
8123#define PROMPT_ALLOCATE 4
8124#define PROMPT_EXPAND 5
8125#define PROMPT_CONNECT 6
8126#define PROMPT_CREATE 7
8127#define PROMPT_SALVAGE 8
8128#define PROMPT_TRUNCATE 9
8129#define PROMPT_CLEAR_INODE 10
8130#define PROMPT_ABORT 11
8131#define PROMPT_SPLIT 12
8132#define PROMPT_CONTINUE 13
8133#define PROMPT_CLONE 14
8134#define PROMPT_DELETE 15
8135#define PROMPT_SUPPRESS 16
8136#define PROMPT_UNLINK 17
8137#define PROMPT_CLEAR_HTREE 18
8138#define PROMPT_RECREATE 19
8139#define PROMPT_NULL 20
8140
8141struct e2fsck_problem {
8142 problem_t e2p_code;
8143 const char * e2p_description;
8144 char prompt;
8145 int flags;
8146 problem_t second_code;
8147};
8148
8149struct latch_descr {
8150 int latch_code;
8151 problem_t question;
8152 problem_t end_message;
8153 int flags;
8154};
8155
8156/*
8157 * These are the prompts which are used to ask the user if they want
8158 * to fix a problem.
8159 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008160static const char *const prompt[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008161 N_("(no prompt)"), /* 0 */
8162 N_("Fix"), /* 1 */
8163 N_("Clear"), /* 2 */
8164 N_("Relocate"), /* 3 */
8165 N_("Allocate"), /* 4 */
8166 N_("Expand"), /* 5 */
8167 N_("Connect to /lost+found"), /* 6 */
8168 N_("Create"), /* 7 */
8169 N_("Salvage"), /* 8 */
8170 N_("Truncate"), /* 9 */
8171 N_("Clear inode"), /* 10 */
8172 N_("Abort"), /* 11 */
8173 N_("Split"), /* 12 */
8174 N_("Continue"), /* 13 */
8175 N_("Clone multiply-claimed blocks"), /* 14 */
8176 N_("Delete file"), /* 15 */
8177 N_("Suppress messages"),/* 16 */
8178 N_("Unlink"), /* 17 */
8179 N_("Clear HTree index"),/* 18 */
8180 N_("Recreate"), /* 19 */
8181 "", /* 20 */
8182};
8183
8184/*
8185 * These messages are printed when we are preen mode and we will be
8186 * automatically fixing the problem.
8187 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008188static const char *const preen_msg[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008189 N_("(NONE)"), /* 0 */
8190 N_("FIXED"), /* 1 */
8191 N_("CLEARED"), /* 2 */
8192 N_("RELOCATED"), /* 3 */
8193 N_("ALLOCATED"), /* 4 */
8194 N_("EXPANDED"), /* 5 */
8195 N_("RECONNECTED"), /* 6 */
8196 N_("CREATED"), /* 7 */
8197 N_("SALVAGED"), /* 8 */
8198 N_("TRUNCATED"), /* 9 */
8199 N_("INODE CLEARED"), /* 10 */
8200 N_("ABORTED"), /* 11 */
8201 N_("SPLIT"), /* 12 */
8202 N_("CONTINUING"), /* 13 */
8203 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8204 N_("FILE DELETED"), /* 15 */
8205 N_("SUPPRESSED"), /* 16 */
8206 N_("UNLINKED"), /* 17 */
8207 N_("HTREE INDEX CLEARED"),/* 18 */
8208 N_("WILL RECREATE"), /* 19 */
8209 "", /* 20 */
8210};
8211
8212static const struct e2fsck_problem problem_table[] = {
8213
8214 /* Pre-Pass 1 errors */
8215
8216 /* Block bitmap not in group */
8217 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8218 PROMPT_RELOCATE, PR_LATCH_RELOC },
8219
8220 /* Inode bitmap not in group */
8221 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8222 PROMPT_RELOCATE, PR_LATCH_RELOC },
8223
8224 /* Inode table not in group */
8225 { PR_0_ITABLE_NOT_GROUP,
8226 N_("@i table for @g %g is not in @g. (@b %b)\n"
8227 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8228 PROMPT_RELOCATE, PR_LATCH_RELOC },
8229
8230 /* Superblock corrupt */
8231 { PR_0_SB_CORRUPT,
8232 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8233 "@f. If the @v is valid and it really contains an ext2\n"
8234 "@f (and not swap or ufs or something else), then the @S\n"
8235 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8236 " e2fsck -b %S <@v>\n\n"),
8237 PROMPT_NONE, PR_FATAL },
8238
8239 /* Filesystem size is wrong */
8240 { PR_0_FS_SIZE_WRONG,
8241 N_("The @f size (according to the @S) is %b @bs\n"
8242 "The physical size of the @v is %c @bs\n"
8243 "Either the @S or the partition table is likely to be corrupt!\n"),
8244 PROMPT_ABORT, 0 },
8245
8246 /* Fragments not supported */
8247 { PR_0_NO_FRAGMENTS,
8248 N_("@S @b_size = %b, fragsize = %c.\n"
8249 "This version of e2fsck does not support fragment sizes different\n"
8250 "from the @b size.\n"),
8251 PROMPT_NONE, PR_FATAL },
8252
8253 /* Bad blocks_per_group */
8254 { PR_0_BLOCKS_PER_GROUP,
8255 N_("@S @bs_per_group = %b, should have been %c\n"),
8256 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8257
8258 /* Bad first_data_block */
8259 { PR_0_FIRST_DATA_BLOCK,
8260 N_("@S first_data_@b = %b, should have been %c\n"),
8261 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8262
8263 /* Adding UUID to filesystem */
8264 { PR_0_ADD_UUID,
8265 N_("@f did not have a UUID; generating one.\n\n"),
8266 PROMPT_NONE, 0 },
8267
8268 /* Relocate hint */
8269 { PR_0_RELOCATE_HINT,
8270 N_("Note: if several inode or block bitmap blocks or part\n"
8271 "of the inode table require relocation, you may wish to try\n"
8272 "running e2fsck with the '-b %S' option first. The problem\n"
8273 "may lie only with the primary block group descriptors, and\n"
8274 "the backup block group descriptors may be OK.\n\n"),
8275 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8276
8277 /* Miscellaneous superblock corruption */
8278 { PR_0_MISC_CORRUPT_SUPER,
8279 N_("Corruption found in @S. (%s = %N).\n"),
8280 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8281
8282 /* Error determing physical device size of filesystem */
8283 { PR_0_GETSIZE_ERROR,
8284 N_("Error determining size of the physical @v: %m\n"),
8285 PROMPT_NONE, PR_FATAL },
8286
8287 /* Inode count in superblock is incorrect */
8288 { PR_0_INODE_COUNT_WRONG,
8289 N_("@i count in @S is %i, @s %j.\n"),
8290 PROMPT_FIX, 0 },
8291
8292 { PR_0_HURD_CLEAR_FILETYPE,
8293 N_("The Hurd does not support the filetype feature.\n"),
8294 PROMPT_CLEAR, 0 },
8295
8296 /* Journal inode is invalid */
8297 { PR_0_JOURNAL_BAD_INODE,
8298 N_("@S has an @n ext3 @j (@i %i).\n"),
8299 PROMPT_CLEAR, PR_PREEN_OK },
8300
8301 /* The external journal has (unsupported) multiple filesystems */
8302 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8303 N_("External @j has multiple @f users (unsupported).\n"),
8304 PROMPT_NONE, PR_FATAL },
8305
8306 /* Can't find external journal */
8307 { PR_0_CANT_FIND_JOURNAL,
8308 N_("Can't find external @j\n"),
8309 PROMPT_NONE, PR_FATAL },
8310
8311 /* External journal has bad superblock */
8312 { PR_0_EXT_JOURNAL_BAD_SUPER,
8313 N_("External @j has bad @S\n"),
8314 PROMPT_NONE, PR_FATAL },
8315
8316 /* Superblock has a bad journal UUID */
8317 { PR_0_JOURNAL_BAD_UUID,
8318 N_("External @j does not support this @f\n"),
8319 PROMPT_NONE, PR_FATAL },
8320
8321 /* Journal has an unknown superblock type */
8322 { PR_0_JOURNAL_UNSUPP_SUPER,
8323 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8324 "It is likely that your copy of e2fsck is old and/or doesn't "
8325 "support this @j format.\n"
8326 "It is also possible the @j @S is corrupt.\n"),
8327 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8328
8329 /* Journal superblock is corrupt */
8330 { PR_0_JOURNAL_BAD_SUPER,
8331 N_("Ext3 @j @S is corrupt.\n"),
8332 PROMPT_FIX, PR_PREEN_OK },
8333
8334 /* Superblock flag should be cleared */
8335 { PR_0_JOURNAL_HAS_JOURNAL,
8336 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8337 PROMPT_CLEAR, PR_PREEN_OK },
8338
8339 /* Superblock flag is incorrect */
8340 { PR_0_JOURNAL_RECOVER_SET,
8341 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8342 PROMPT_CLEAR, PR_PREEN_OK },
8343
8344 /* Journal has data, but recovery flag is clear */
8345 { PR_0_JOURNAL_RECOVERY_CLEAR,
8346 N_("ext3 recovery flag is clear, but @j has data.\n"),
8347 PROMPT_NONE, 0 },
8348
8349 /* Ask if we should clear the journal */
8350 { PR_0_JOURNAL_RESET_JOURNAL,
8351 N_("Clear @j"),
8352 PROMPT_NULL, PR_PREEN_NOMSG },
8353
8354 /* Ask if we should run the journal anyway */
8355 { PR_0_JOURNAL_RUN,
8356 N_("Run @j anyway"),
8357 PROMPT_NULL, 0 },
8358
8359 /* Run the journal by default */
8360 { PR_0_JOURNAL_RUN_DEFAULT,
8361 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8362 PROMPT_NONE, 0 },
8363
8364 /* Clearing orphan inode */
8365 { PR_0_ORPHAN_CLEAR_INODE,
8366 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8367 PROMPT_NONE, 0 },
8368
8369 /* Illegal block found in orphaned inode */
8370 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8371 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8372 PROMPT_NONE, 0 },
8373
8374 /* Already cleared block found in orphaned inode */
8375 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8376 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8377 PROMPT_NONE, 0 },
8378
8379 /* Illegal orphan inode in superblock */
8380 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8381 N_("@I @o @i %i in @S.\n"),
8382 PROMPT_NONE, 0 },
8383
8384 /* Illegal inode in orphaned inode list */
8385 { PR_0_ORPHAN_ILLEGAL_INODE,
8386 N_("@I @i %i in @o @i list.\n"),
8387 PROMPT_NONE, 0 },
8388
8389 /* Filesystem revision is 0, but feature flags are set */
8390 { PR_0_FS_REV_LEVEL,
8391 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8392 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8393
8394 /* Journal superblock has an unknown read-only feature flag set */
8395 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8396 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8397 PROMPT_ABORT, 0 },
8398
8399 /* Journal superblock has an unknown incompatible feature flag set */
8400 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8401 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8402 PROMPT_ABORT, 0 },
8403
8404 /* Journal has unsupported version number */
8405 { PR_0_JOURNAL_UNSUPP_VERSION,
8406 N_("@j version not supported by this e2fsck.\n"),
8407 PROMPT_ABORT, 0 },
8408
8409 /* Moving journal to hidden file */
8410 { PR_0_MOVE_JOURNAL,
8411 N_("Moving @j from /%s to hidden @i.\n\n"),
8412 PROMPT_NONE, 0 },
8413
8414 /* Error moving journal to hidden file */
8415 { PR_0_ERR_MOVE_JOURNAL,
8416 N_("Error moving @j: %m\n\n"),
8417 PROMPT_NONE, 0 },
8418
8419 /* Clearing V2 journal superblock */
8420 { PR_0_CLEAR_V2_JOURNAL,
8421 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8422 "Clearing fields beyond the V1 @j @S...\n\n"),
8423 PROMPT_NONE, 0 },
8424
8425 /* Backup journal inode blocks */
8426 { PR_0_BACKUP_JNL,
8427 N_("Backing up @j @i @b information.\n\n"),
8428 PROMPT_NONE, 0 },
8429
8430 /* Reserved blocks w/o resize_inode */
8431 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8432 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8433 "is %N; @s zero. "),
8434 PROMPT_FIX, 0 },
8435
8436 /* Resize_inode not enabled, but resize inode is non-zero */
8437 { PR_0_CLEAR_RESIZE_INODE,
8438 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8439 PROMPT_CLEAR, 0 },
8440
8441 /* Resize inode invalid */
8442 { PR_0_RESIZE_INODE_INVALID,
8443 N_("Resize @i not valid. "),
8444 PROMPT_RECREATE, 0 },
8445
8446 /* Pass 1 errors */
8447
8448 /* Pass 1: Checking inodes, blocks, and sizes */
8449 { PR_1_PASS_HEADER,
8450 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8451 PROMPT_NONE, 0 },
8452
8453 /* Root directory is not an inode */
8454 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8455 PROMPT_CLEAR, 0 },
8456
8457 /* Root directory has dtime set */
8458 { PR_1_ROOT_DTIME,
8459 N_("@r has dtime set (probably due to old mke2fs). "),
8460 PROMPT_FIX, PR_PREEN_OK },
8461
8462 /* Reserved inode has bad mode */
8463 { PR_1_RESERVED_BAD_MODE,
8464 N_("Reserved @i %i (%Q) has @n mode. "),
8465 PROMPT_CLEAR, PR_PREEN_OK },
8466
8467 /* Deleted inode has zero dtime */
8468 { PR_1_ZERO_DTIME,
8469 N_("@D @i %i has zero dtime. "),
8470 PROMPT_FIX, PR_PREEN_OK },
8471
8472 /* Inode in use, but dtime set */
8473 { PR_1_SET_DTIME,
8474 N_("@i %i is in use, but has dtime set. "),
8475 PROMPT_FIX, PR_PREEN_OK },
8476
8477 /* Zero-length directory */
8478 { PR_1_ZERO_LENGTH_DIR,
8479 N_("@i %i is a @z @d. "),
8480 PROMPT_CLEAR, PR_PREEN_OK },
8481
8482 /* Block bitmap conflicts with some other fs block */
8483 { PR_1_BB_CONFLICT,
8484 N_("@g %g's @b @B at %b @C.\n"),
8485 PROMPT_RELOCATE, 0 },
8486
8487 /* Inode bitmap conflicts with some other fs block */
8488 { PR_1_IB_CONFLICT,
8489 N_("@g %g's @i @B at %b @C.\n"),
8490 PROMPT_RELOCATE, 0 },
8491
8492 /* Inode table conflicts with some other fs block */
8493 { PR_1_ITABLE_CONFLICT,
8494 N_("@g %g's @i table at %b @C.\n"),
8495 PROMPT_RELOCATE, 0 },
8496
8497 /* Block bitmap is on a bad block */
8498 { PR_1_BB_BAD_BLOCK,
8499 N_("@g %g's @b @B (%b) is bad. "),
8500 PROMPT_RELOCATE, 0 },
8501
8502 /* Inode bitmap is on a bad block */
8503 { PR_1_IB_BAD_BLOCK,
8504 N_("@g %g's @i @B (%b) is bad. "),
8505 PROMPT_RELOCATE, 0 },
8506
8507 /* Inode has incorrect i_size */
8508 { PR_1_BAD_I_SIZE,
8509 N_("@i %i, i_size is %Is, @s %N. "),
8510 PROMPT_FIX, PR_PREEN_OK },
8511
8512 /* Inode has incorrect i_blocks */
8513 { PR_1_BAD_I_BLOCKS,
8514 N_("@i %i, i_@bs is %Ib, @s %N. "),
8515 PROMPT_FIX, PR_PREEN_OK },
8516
8517 /* Illegal blocknumber in inode */
8518 { PR_1_ILLEGAL_BLOCK_NUM,
8519 N_("@I @b #%B (%b) in @i %i. "),
8520 PROMPT_CLEAR, PR_LATCH_BLOCK },
8521
8522 /* Block number overlaps fs metadata */
8523 { PR_1_BLOCK_OVERLAPS_METADATA,
8524 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8525 PROMPT_CLEAR, PR_LATCH_BLOCK },
8526
8527 /* Inode has illegal blocks (latch question) */
8528 { PR_1_INODE_BLOCK_LATCH,
8529 N_("@i %i has illegal @b(s). "),
8530 PROMPT_CLEAR, 0 },
8531
8532 /* Too many bad blocks in inode */
8533 { PR_1_TOO_MANY_BAD_BLOCKS,
8534 N_("Too many illegal @bs in @i %i.\n"),
8535 PROMPT_CLEAR_INODE, PR_NO_OK },
8536
8537 /* Illegal block number in bad block inode */
8538 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8539 N_("@I @b #%B (%b) in bad @b @i. "),
8540 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8541
8542 /* Bad block inode has illegal blocks (latch question) */
8543 { PR_1_INODE_BBLOCK_LATCH,
8544 N_("Bad @b @i has illegal @b(s). "),
8545 PROMPT_CLEAR, 0 },
8546
8547 /* Duplicate or bad blocks in use! */
8548 { PR_1_DUP_BLOCKS_PREENSTOP,
8549 N_("Duplicate or bad @b in use!\n"),
8550 PROMPT_NONE, 0 },
8551
8552 /* Bad block used as bad block indirect block */
8553 { PR_1_BBINODE_BAD_METABLOCK,
8554 N_("Bad @b %b used as bad @b @i indirect @b. "),
8555 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8556
8557 /* Inconsistency can't be fixed prompt */
8558 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8559 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8560 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8561 "in the @f.\n"),
8562 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8563
8564 /* Bad primary block */
8565 { PR_1_BAD_PRIMARY_BLOCK,
8566 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8567 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8568
8569 /* Bad primary block prompt */
8570 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8571 N_("You can remove this @b from the bad @b list and hope\n"
8572 "that the @b is really OK. But there are no guarantees.\n\n"),
8573 PROMPT_CLEAR, PR_PREEN_NOMSG },
8574
8575 /* Bad primary superblock */
8576 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8577 N_("The primary @S (%b) is on the bad @b list.\n"),
8578 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8579
8580 /* Bad primary block group descriptors */
8581 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8582 N_("Block %b in the primary @g descriptors "
8583 "is on the bad @b list\n"),
8584 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8585
8586 /* Bad superblock in group */
8587 { PR_1_BAD_SUPERBLOCK,
8588 N_("Warning: Group %g's @S (%b) is bad.\n"),
8589 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8590
8591 /* Bad block group descriptors in group */
8592 { PR_1_BAD_GROUP_DESCRIPTORS,
8593 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8594 "@b (%b).\n"),
8595 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8596
8597 /* Block claimed for no reason */
8598 { PR_1_PROGERR_CLAIMED_BLOCK,
8599 N_("Programming error? @b #%b claimed for no reason in "
8600 "process_bad_@b.\n"),
8601 PROMPT_NONE, PR_PREEN_OK },
8602
8603 /* Error allocating blocks for relocating metadata */
8604 { PR_1_RELOC_BLOCK_ALLOCATE,
8605 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8606 PROMPT_NONE, PR_PREEN_OK },
8607
8608 /* Error allocating block buffer during relocation process */
8609 { PR_1_RELOC_MEMORY_ALLOCATE,
8610 N_("@A @b buffer for relocating %s\n"),
8611 PROMPT_NONE, PR_PREEN_OK },
8612
8613 /* Relocating metadata group information from X to Y */
8614 { PR_1_RELOC_FROM_TO,
8615 N_("Relocating @g %g's %s from %b to %c...\n"),
8616 PROMPT_NONE, PR_PREEN_OK },
8617
8618 /* Relocating metatdata group information to X */
8619 { PR_1_RELOC_TO,
8620 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8621 PROMPT_NONE, PR_PREEN_OK },
8622
8623 /* Block read error during relocation process */
8624 { PR_1_RELOC_READ_ERR,
8625 N_("Warning: could not read @b %b of %s: %m\n"),
8626 PROMPT_NONE, PR_PREEN_OK },
8627
8628 /* Block write error during relocation process */
8629 { PR_1_RELOC_WRITE_ERR,
8630 N_("Warning: could not write @b %b for %s: %m\n"),
8631 PROMPT_NONE, PR_PREEN_OK },
8632
8633 /* Error allocating inode bitmap */
8634 { PR_1_ALLOCATE_IBITMAP_ERROR,
8635 N_("@A @i @B (%N): %m\n"),
8636 PROMPT_NONE, PR_FATAL },
8637
8638 /* Error allocating block bitmap */
8639 { PR_1_ALLOCATE_BBITMAP_ERROR,
8640 N_("@A @b @B (%N): %m\n"),
8641 PROMPT_NONE, PR_FATAL },
8642
8643 /* Error allocating icount structure */
8644 { PR_1_ALLOCATE_ICOUNT,
8645 N_("@A icount link information: %m\n"),
8646 PROMPT_NONE, PR_FATAL },
8647
8648 /* Error allocating dbcount */
8649 { PR_1_ALLOCATE_DBCOUNT,
8650 N_("@A @d @b array: %m\n"),
8651 PROMPT_NONE, PR_FATAL },
8652
8653 /* Error while scanning inodes */
8654 { PR_1_ISCAN_ERROR,
8655 N_("Error while scanning @is (%i): %m\n"),
8656 PROMPT_NONE, PR_FATAL },
8657
8658 /* Error while iterating over blocks */
8659 { PR_1_BLOCK_ITERATE,
8660 N_("Error while iterating over @bs in @i %i: %m\n"),
8661 PROMPT_NONE, PR_FATAL },
8662
8663 /* Error while storing inode count information */
8664 { PR_1_ICOUNT_STORE,
8665 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8666 PROMPT_NONE, PR_FATAL },
8667
8668 /* Error while storing directory block information */
8669 { PR_1_ADD_DBLOCK,
8670 N_("Error storing @d @b information "
8671 "(@i=%i, @b=%b, num=%N): %m\n"),
8672 PROMPT_NONE, PR_FATAL },
8673
8674 /* Error while reading inode (for clearing) */
8675 { PR_1_READ_INODE,
8676 N_("Error reading @i %i: %m\n"),
8677 PROMPT_NONE, PR_FATAL },
8678
8679 /* Suppress messages prompt */
8680 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8681
8682 /* Imagic flag set on an inode when filesystem doesn't support it */
8683 { PR_1_SET_IMAGIC,
8684 N_("@i %i has imagic flag set. "),
8685 PROMPT_CLEAR, 0 },
8686
8687 /* Immutable flag set on a device or socket inode */
8688 { PR_1_SET_IMMUTABLE,
8689 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8690 "or append-only flag set. "),
8691 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8692
8693 /* Compression flag set on an inode when filesystem doesn't support it */
8694 { PR_1_COMPR_SET,
8695 N_("@i %i has @cion flag set on @f without @cion support. "),
8696 PROMPT_CLEAR, 0 },
8697
8698 /* Non-zero size for device, fifo or socket inode */
8699 { PR_1_SET_NONZSIZE,
8700 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8701 PROMPT_FIX, PR_PREEN_OK },
8702
8703 /* Filesystem revision is 0, but feature flags are set */
8704 { PR_1_FS_REV_LEVEL,
8705 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8706 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8707
8708 /* Journal inode is not in use, but contains data */
8709 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8710 N_("@j @i is not in use, but contains data. "),
8711 PROMPT_CLEAR, PR_PREEN_OK },
8712
8713 /* Journal has bad mode */
8714 { PR_1_JOURNAL_BAD_MODE,
8715 N_("@j is not regular file. "),
8716 PROMPT_FIX, PR_PREEN_OK },
8717
8718 /* Deal with inodes that were part of orphan linked list */
8719 { PR_1_LOW_DTIME,
8720 N_("@i %i was part of the @o @i list. "),
8721 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8722
8723 /* Deal with inodes that were part of corrupted orphan linked
8724 list (latch question) */
8725 { PR_1_ORPHAN_LIST_REFUGEES,
8726 N_("@is that were part of a corrupted orphan linked list found. "),
8727 PROMPT_FIX, 0 },
8728
8729 /* Error allocating refcount structure */
8730 { PR_1_ALLOCATE_REFCOUNT,
8731 N_("@A refcount structure (%N): %m\n"),
8732 PROMPT_NONE, PR_FATAL },
8733
8734 /* Error reading extended attribute block */
8735 { PR_1_READ_EA_BLOCK,
8736 N_("Error reading @a @b %b for @i %i. "),
8737 PROMPT_CLEAR, 0 },
8738
8739 /* Invalid extended attribute block */
8740 { PR_1_BAD_EA_BLOCK,
8741 N_("@i %i has a bad @a @b %b. "),
8742 PROMPT_CLEAR, 0 },
8743
8744 /* Error reading Extended Attribute block while fixing refcount */
8745 { PR_1_EXTATTR_READ_ABORT,
8746 N_("Error reading @a @b %b (%m). "),
8747 PROMPT_ABORT, 0 },
8748
8749 /* Extended attribute reference count incorrect */
8750 { PR_1_EXTATTR_REFCOUNT,
8751 N_("@a @b %b has reference count %B, @s %N. "),
8752 PROMPT_FIX, 0 },
8753
8754 /* Error writing Extended Attribute block while fixing refcount */
8755 { PR_1_EXTATTR_WRITE,
8756 N_("Error writing @a @b %b (%m). "),
8757 PROMPT_ABORT, 0 },
8758
8759 /* Multiple EA blocks not supported */
8760 { PR_1_EA_MULTI_BLOCK,
8761 N_("@a @b %b has h_@bs > 1. "),
8762 PROMPT_CLEAR, 0},
8763
8764 /* Error allocating EA region allocation structure */
8765 { PR_1_EA_ALLOC_REGION,
8766 N_("@A @a @b %b. "),
8767 PROMPT_ABORT, 0},
8768
8769 /* Error EA allocation collision */
8770 { PR_1_EA_ALLOC_COLLISION,
8771 N_("@a @b %b is corrupt (allocation collision). "),
8772 PROMPT_CLEAR, 0},
8773
8774 /* Bad extended attribute name */
8775 { PR_1_EA_BAD_NAME,
8776 N_("@a @b %b is corrupt (@n name). "),
8777 PROMPT_CLEAR, 0},
8778
8779 /* Bad extended attribute value */
8780 { PR_1_EA_BAD_VALUE,
8781 N_("@a @b %b is corrupt (@n value). "),
8782 PROMPT_CLEAR, 0},
8783
8784 /* Inode too big (latch question) */
8785 { PR_1_INODE_TOOBIG,
8786 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8787
8788 /* Directory too big */
8789 { PR_1_TOOBIG_DIR,
8790 N_("@b #%B (%b) causes @d to be too big. "),
8791 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8792
8793 /* Regular file too big */
8794 { PR_1_TOOBIG_REG,
8795 N_("@b #%B (%b) causes file to be too big. "),
8796 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8797
8798 /* Symlink too big */
8799 { PR_1_TOOBIG_SYMLINK,
8800 N_("@b #%B (%b) causes symlink to be too big. "),
8801 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8802
8803 /* INDEX_FL flag set on a non-HTREE filesystem */
8804 { PR_1_HTREE_SET,
8805 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8806 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8807
8808 /* INDEX_FL flag set on a non-directory */
8809 { PR_1_HTREE_NODIR,
8810 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8811 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8812
8813 /* Invalid root node in HTREE directory */
8814 { PR_1_HTREE_BADROOT,
8815 N_("@h %i has an @n root node.\n"),
8816 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8817
8818 /* Unsupported hash version in HTREE directory */
8819 { PR_1_HTREE_HASHV,
8820 N_("@h %i has an unsupported hash version (%N)\n"),
8821 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8822
8823 /* Incompatible flag in HTREE root node */
8824 { PR_1_HTREE_INCOMPAT,
8825 N_("@h %i uses an incompatible htree root node flag.\n"),
8826 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8827
8828 /* HTREE too deep */
8829 { PR_1_HTREE_DEPTH,
8830 N_("@h %i has a tree depth (%N) which is too big\n"),
8831 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8832
8833 /* Bad block has indirect block that conflicts with filesystem block */
8834 { PR_1_BB_FS_BLOCK,
8835 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8836 "@f metadata. "),
8837 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8838
8839 /* Resize inode failed */
8840 { PR_1_RESIZE_INODE_CREATE,
8841 N_("Resize @i (re)creation failed: %m."),
8842 PROMPT_ABORT, 0 },
8843
8844 /* invalid inode->i_extra_isize */
8845 { PR_1_EXTRA_ISIZE,
8846 N_("@i %i has a extra size (%IS) which is @n\n"),
8847 PROMPT_FIX, PR_PREEN_OK },
8848
8849 /* invalid ea entry->e_name_len */
8850 { PR_1_ATTR_NAME_LEN,
8851 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8852 PROMPT_CLEAR, PR_PREEN_OK },
8853
8854 /* invalid ea entry->e_value_size */
8855 { PR_1_ATTR_VALUE_SIZE,
8856 N_("@a in @i %i has a value size (%N) which is @n\n"),
8857 PROMPT_CLEAR, PR_PREEN_OK },
8858
8859 /* invalid ea entry->e_value_offs */
8860 { PR_1_ATTR_VALUE_OFFSET,
8861 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8862 PROMPT_CLEAR, PR_PREEN_OK },
8863
8864 /* invalid ea entry->e_value_block */
8865 { PR_1_ATTR_VALUE_BLOCK,
8866 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8867 PROMPT_CLEAR, PR_PREEN_OK },
8868
8869 /* invalid ea entry->e_hash */
8870 { PR_1_ATTR_HASH,
8871 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8872 PROMPT_CLEAR, PR_PREEN_OK },
8873
8874 /* Pass 1b errors */
8875
8876 /* Pass 1B: Rescan for duplicate/bad blocks */
8877 { PR_1B_PASS_HEADER,
8878 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8879 "Pass 1B: Rescanning for @m @bs\n"),
8880 PROMPT_NONE, 0 },
8881
8882 /* Duplicate/bad block(s) header */
8883 { PR_1B_DUP_BLOCK_HEADER,
8884 N_("@m @b(s) in @i %i:"),
8885 PROMPT_NONE, 0 },
8886
8887 /* Duplicate/bad block(s) in inode */
8888 { PR_1B_DUP_BLOCK,
8889 " %b",
8890 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8891
8892 /* Duplicate/bad block(s) end */
8893 { PR_1B_DUP_BLOCK_END,
8894 "\n",
8895 PROMPT_NONE, PR_PREEN_NOHDR },
8896
8897 /* Error while scanning inodes */
8898 { PR_1B_ISCAN_ERROR,
8899 N_("Error while scanning inodes (%i): %m\n"),
8900 PROMPT_NONE, PR_FATAL },
8901
8902 /* Error allocating inode bitmap */
8903 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8904 N_("@A @i @B (@i_dup_map): %m\n"),
8905 PROMPT_NONE, PR_FATAL },
8906
8907 /* Error while iterating over blocks */
8908 { PR_1B_BLOCK_ITERATE,
8909 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8910 PROMPT_NONE, 0 },
8911
8912 /* Error adjusting EA refcount */
8913 { PR_1B_ADJ_EA_REFCOUNT,
8914 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8915 PROMPT_NONE, 0 },
8916
8917
8918 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8919 { PR_1C_PASS_HEADER,
8920 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8921 PROMPT_NONE, 0 },
8922
8923
8924 /* Pass 1D: Reconciling multiply-claimed blocks */
8925 { PR_1D_PASS_HEADER,
8926 N_("Pass 1D: Reconciling @m @bs\n"),
8927 PROMPT_NONE, 0 },
8928
8929 /* File has duplicate blocks */
8930 { PR_1D_DUP_FILE,
8931 N_("File %Q (@i #%i, mod time %IM)\n"
8932 " has %B @m @b(s), shared with %N file(s):\n"),
8933 PROMPT_NONE, 0 },
8934
8935 /* List of files sharing duplicate blocks */
8936 { PR_1D_DUP_FILE_LIST,
8937 N_("\t%Q (@i #%i, mod time %IM)\n"),
8938 PROMPT_NONE, 0 },
8939
8940 /* File sharing blocks with filesystem metadata */
8941 { PR_1D_SHARE_METADATA,
8942 N_("\t<@f metadata>\n"),
8943 PROMPT_NONE, 0 },
8944
8945 /* Report of how many duplicate/bad inodes */
8946 { PR_1D_NUM_DUP_INODES,
8947 N_("(There are %N @is containing @m @bs.)\n\n"),
8948 PROMPT_NONE, 0 },
8949
8950 /* Duplicated blocks already reassigned or cloned. */
8951 { PR_1D_DUP_BLOCKS_DEALT,
8952 N_("@m @bs already reassigned or cloned.\n\n"),
8953 PROMPT_NONE, 0 },
8954
8955 /* Clone duplicate/bad blocks? */
8956 { PR_1D_CLONE_QUESTION,
8957 "", PROMPT_CLONE, PR_NO_OK },
8958
8959 /* Delete file? */
8960 { PR_1D_DELETE_QUESTION,
8961 "", PROMPT_DELETE, 0 },
8962
8963 /* Couldn't clone file (error) */
8964 { PR_1D_CLONE_ERROR,
8965 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8966
8967 /* Pass 2 errors */
8968
8969 /* Pass 2: Checking directory structure */
8970 { PR_2_PASS_HEADER,
8971 N_("Pass 2: Checking @d structure\n"),
8972 PROMPT_NONE, 0 },
8973
8974 /* Bad inode number for '.' */
8975 { PR_2_BAD_INODE_DOT,
8976 N_("@n @i number for '.' in @d @i %i.\n"),
8977 PROMPT_FIX, 0 },
8978
8979 /* Directory entry has bad inode number */
8980 { PR_2_BAD_INO,
8981 N_("@E has @n @i #: %Di.\n"),
8982 PROMPT_CLEAR, 0 },
8983
8984 /* Directory entry has deleted or unused inode */
8985 { PR_2_UNUSED_INODE,
8986 N_("@E has @D/unused @i %Di. "),
8987 PROMPT_CLEAR, PR_PREEN_OK },
8988
8989 /* Directry entry is link to '.' */
8990 { PR_2_LINK_DOT,
8991 N_("@E @L to '.' "),
8992 PROMPT_CLEAR, 0 },
8993
8994 /* Directory entry points to inode now located in a bad block */
8995 { PR_2_BB_INODE,
8996 N_("@E points to @i (%Di) located in a bad @b.\n"),
8997 PROMPT_CLEAR, 0 },
8998
8999 /* Directory entry contains a link to a directory */
9000 { PR_2_LINK_DIR,
9001 N_("@E @L to @d %P (%Di).\n"),
9002 PROMPT_CLEAR, 0 },
9003
9004 /* Directory entry contains a link to the root directry */
9005 { PR_2_LINK_ROOT,
9006 N_("@E @L to the @r.\n"),
9007 PROMPT_CLEAR, 0 },
9008
9009 /* Directory entry has illegal characters in its name */
9010 { PR_2_BAD_NAME,
9011 N_("@E has illegal characters in its name.\n"),
9012 PROMPT_FIX, 0 },
9013
9014 /* Missing '.' in directory inode */
9015 { PR_2_MISSING_DOT,
9016 N_("Missing '.' in @d @i %i.\n"),
9017 PROMPT_FIX, 0 },
9018
9019 /* Missing '..' in directory inode */
9020 { PR_2_MISSING_DOT_DOT,
9021 N_("Missing '..' in @d @i %i.\n"),
9022 PROMPT_FIX, 0 },
9023
9024 /* First entry in directory inode doesn't contain '.' */
9025 { PR_2_1ST_NOT_DOT,
9026 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9027 PROMPT_FIX, 0 },
9028
9029 /* Second entry in directory inode doesn't contain '..' */
9030 { PR_2_2ND_NOT_DOT_DOT,
9031 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9032 PROMPT_FIX, 0 },
9033
9034 /* i_faddr should be zero */
9035 { PR_2_FADDR_ZERO,
9036 N_("i_faddr @F %IF, @s zero.\n"),
9037 PROMPT_CLEAR, 0 },
9038
9039 /* i_file_acl should be zero */
9040 { PR_2_FILE_ACL_ZERO,
9041 N_("i_file_acl @F %If, @s zero.\n"),
9042 PROMPT_CLEAR, 0 },
9043
9044 /* i_dir_acl should be zero */
9045 { PR_2_DIR_ACL_ZERO,
9046 N_("i_dir_acl @F %Id, @s zero.\n"),
9047 PROMPT_CLEAR, 0 },
9048
9049 /* i_frag should be zero */
9050 { PR_2_FRAG_ZERO,
9051 N_("i_frag @F %N, @s zero.\n"),
9052 PROMPT_CLEAR, 0 },
9053
9054 /* i_fsize should be zero */
9055 { PR_2_FSIZE_ZERO,
9056 N_("i_fsize @F %N, @s zero.\n"),
9057 PROMPT_CLEAR, 0 },
9058
9059 /* inode has bad mode */
9060 { PR_2_BAD_MODE,
9061 N_("@i %i (%Q) has @n mode (%Im).\n"),
9062 PROMPT_CLEAR, 0 },
9063
9064 /* directory corrupted */
9065 { PR_2_DIR_CORRUPTED,
9066 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9067 PROMPT_SALVAGE, 0 },
9068
9069 /* filename too long */
9070 { PR_2_FILENAME_LONG,
9071 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9072 PROMPT_TRUNCATE, 0 },
9073
9074 /* Directory inode has a missing block (hole) */
9075 { PR_2_DIRECTORY_HOLE,
9076 N_("@d @i %i has an unallocated @b #%B. "),
9077 PROMPT_ALLOCATE, 0 },
9078
9079 /* '.' is not NULL terminated */
9080 { PR_2_DOT_NULL_TERM,
9081 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9082 PROMPT_FIX, 0 },
9083
9084 /* '..' is not NULL terminated */
9085 { PR_2_DOT_DOT_NULL_TERM,
9086 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9087 PROMPT_FIX, 0 },
9088
9089 /* Illegal character device inode */
9090 { PR_2_BAD_CHAR_DEV,
9091 N_("@i %i (%Q) is an @I character @v.\n"),
9092 PROMPT_CLEAR, 0 },
9093
9094 /* Illegal block device inode */
9095 { PR_2_BAD_BLOCK_DEV,
9096 N_("@i %i (%Q) is an @I @b @v.\n"),
9097 PROMPT_CLEAR, 0 },
9098
9099 /* Duplicate '.' entry */
9100 { PR_2_DUP_DOT,
9101 N_("@E is duplicate '.' @e.\n"),
9102 PROMPT_FIX, 0 },
9103
9104 /* Duplicate '..' entry */
9105 { PR_2_DUP_DOT_DOT,
9106 N_("@E is duplicate '..' @e.\n"),
9107 PROMPT_FIX, 0 },
9108
9109 /* Internal error: couldn't find dir_info */
9110 { PR_2_NO_DIRINFO,
9111 N_("Internal error: cannot find dir_info for %i.\n"),
9112 PROMPT_NONE, PR_FATAL },
9113
9114 /* Final rec_len is wrong */
9115 { PR_2_FINAL_RECLEN,
9116 N_("@E has rec_len of %Dr, @s %N.\n"),
9117 PROMPT_FIX, 0 },
9118
9119 /* Error allocating icount structure */
9120 { PR_2_ALLOCATE_ICOUNT,
9121 N_("@A icount structure: %m\n"),
9122 PROMPT_NONE, PR_FATAL },
9123
9124 /* Error iterating over directory blocks */
9125 { PR_2_DBLIST_ITERATE,
9126 N_("Error iterating over @d @bs: %m\n"),
9127 PROMPT_NONE, PR_FATAL },
9128
9129 /* Error reading directory block */
9130 { PR_2_READ_DIRBLOCK,
9131 N_("Error reading @d @b %b (@i %i): %m\n"),
9132 PROMPT_CONTINUE, 0 },
9133
9134 /* Error writing directory block */
9135 { PR_2_WRITE_DIRBLOCK,
9136 N_("Error writing @d @b %b (@i %i): %m\n"),
9137 PROMPT_CONTINUE, 0 },
9138
9139 /* Error allocating new directory block */
9140 { PR_2_ALLOC_DIRBOCK,
9141 N_("@A new @d @b for @i %i (%s): %m\n"),
9142 PROMPT_NONE, 0 },
9143
9144 /* Error deallocating inode */
9145 { PR_2_DEALLOC_INODE,
9146 N_("Error deallocating @i %i: %m\n"),
9147 PROMPT_NONE, PR_FATAL },
9148
9149 /* Directory entry for '.' is big. Split? */
9150 { PR_2_SPLIT_DOT,
9151 N_("@d @e for '.' is big. "),
9152 PROMPT_SPLIT, PR_NO_OK },
9153
9154 /* Illegal FIFO inode */
9155 { PR_2_BAD_FIFO,
9156 N_("@i %i (%Q) is an @I FIFO.\n"),
9157 PROMPT_CLEAR, 0 },
9158
9159 /* Illegal socket inode */
9160 { PR_2_BAD_SOCKET,
9161 N_("@i %i (%Q) is an @I socket.\n"),
9162 PROMPT_CLEAR, 0 },
9163
9164 /* Directory filetype not set */
9165 { PR_2_SET_FILETYPE,
9166 N_("Setting filetype for @E to %N.\n"),
9167 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9168
9169 /* Directory filetype incorrect */
9170 { PR_2_BAD_FILETYPE,
9171 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9172 PROMPT_FIX, 0 },
9173
9174 /* Directory filetype set on filesystem */
9175 { PR_2_CLEAR_FILETYPE,
9176 N_("@E has filetype set.\n"),
9177 PROMPT_CLEAR, PR_PREEN_OK },
9178
9179 /* Directory filename is null */
9180 { PR_2_NULL_NAME,
9181 N_("@E has a @z name.\n"),
9182 PROMPT_CLEAR, 0 },
9183
9184 /* Invalid symlink */
9185 { PR_2_INVALID_SYMLINK,
9186 N_("Symlink %Q (@i #%i) is @n.\n"),
9187 PROMPT_CLEAR, 0 },
9188
9189 /* i_file_acl (extended attribute block) is bad */
9190 { PR_2_FILE_ACL_BAD,
9191 N_("@a @b @F @n (%If).\n"),
9192 PROMPT_CLEAR, 0 },
9193
9194 /* Filesystem contains large files, but has no such flag in sb */
9195 { PR_2_FEATURE_LARGE_FILES,
9196 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9197 PROMPT_FIX, 0 },
9198
9199 /* Node in HTREE directory not referenced */
9200 { PR_2_HTREE_NOTREF,
9201 N_("@p @h %d: node (%B) not referenced\n"),
9202 PROMPT_NONE, 0 },
9203
9204 /* Node in HTREE directory referenced twice */
9205 { PR_2_HTREE_DUPREF,
9206 N_("@p @h %d: node (%B) referenced twice\n"),
9207 PROMPT_NONE, 0 },
9208
9209 /* Node in HTREE directory has bad min hash */
9210 { PR_2_HTREE_MIN_HASH,
9211 N_("@p @h %d: node (%B) has bad min hash\n"),
9212 PROMPT_NONE, 0 },
9213
9214 /* Node in HTREE directory has bad max hash */
9215 { PR_2_HTREE_MAX_HASH,
9216 N_("@p @h %d: node (%B) has bad max hash\n"),
9217 PROMPT_NONE, 0 },
9218
9219 /* Clear invalid HTREE directory */
9220 { PR_2_HTREE_CLEAR,
9221 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9222
9223 /* Bad block in htree interior node */
9224 { PR_2_HTREE_BADBLK,
9225 N_("@p @h %d (%q): bad @b number %b.\n"),
9226 PROMPT_CLEAR_HTREE, 0 },
9227
9228 /* Error adjusting EA refcount */
9229 { PR_2_ADJ_EA_REFCOUNT,
9230 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9231 PROMPT_NONE, PR_FATAL },
9232
9233 /* Invalid HTREE root node */
9234 { PR_2_HTREE_BAD_ROOT,
9235 N_("@p @h %d: root node is @n\n"),
9236 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9237
9238 /* Invalid HTREE limit */
9239 { PR_2_HTREE_BAD_LIMIT,
9240 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9241 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9242
9243 /* Invalid HTREE count */
9244 { PR_2_HTREE_BAD_COUNT,
9245 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9246 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9247
9248 /* HTREE interior node has out-of-order hashes in table */
9249 { PR_2_HTREE_HASH_ORDER,
9250 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9251 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9252
9253 /* Node in HTREE directory has invalid depth */
9254 { PR_2_HTREE_BAD_DEPTH,
9255 N_("@p @h %d: node (%B) has @n depth\n"),
9256 PROMPT_NONE, 0 },
9257
9258 /* Duplicate directory entry found */
9259 { PR_2_DUPLICATE_DIRENT,
9260 N_("Duplicate @E found. "),
9261 PROMPT_CLEAR, 0 },
9262
9263 /* Non-unique filename found */
9264 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9265 N_("@E has a non-unique filename.\nRename to %s"),
9266 PROMPT_NULL, 0 },
9267
9268 /* Duplicate directory entry found */
9269 { PR_2_REPORT_DUP_DIRENT,
9270 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9271 PROMPT_NONE, 0 },
9272
9273 /* Pass 3 errors */
9274
9275 /* Pass 3: Checking directory connectivity */
9276 { PR_3_PASS_HEADER,
9277 N_("Pass 3: Checking @d connectivity\n"),
9278 PROMPT_NONE, 0 },
9279
9280 /* Root inode not allocated */
9281 { PR_3_NO_ROOT_INODE,
9282 N_("@r not allocated. "),
9283 PROMPT_ALLOCATE, 0 },
9284
9285 /* No room in lost+found */
9286 { PR_3_EXPAND_LF_DIR,
9287 N_("No room in @l @d. "),
9288 PROMPT_EXPAND, 0 },
9289
9290 /* Unconnected directory inode */
9291 { PR_3_UNCONNECTED_DIR,
9292 N_("Unconnected @d @i %i (%p)\n"),
9293 PROMPT_CONNECT, 0 },
9294
9295 /* /lost+found not found */
9296 { PR_3_NO_LF_DIR,
9297 N_("/@l not found. "),
9298 PROMPT_CREATE, PR_PREEN_OK },
9299
9300 /* .. entry is incorrect */
9301 { PR_3_BAD_DOT_DOT,
9302 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9303 PROMPT_FIX, 0 },
9304
9305 /* Bad or non-existent /lost+found. Cannot reconnect */
9306 { PR_3_NO_LPF,
9307 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9308 PROMPT_NONE, 0 },
9309
9310 /* Could not expand /lost+found */
9311 { PR_3_CANT_EXPAND_LPF,
9312 N_("Could not expand /@l: %m\n"),
9313 PROMPT_NONE, 0 },
9314
9315 /* Could not reconnect inode */
9316 { PR_3_CANT_RECONNECT,
9317 N_("Could not reconnect %i: %m\n"),
9318 PROMPT_NONE, 0 },
9319
9320 /* Error while trying to find /lost+found */
9321 { PR_3_ERR_FIND_LPF,
9322 N_("Error while trying to find /@l: %m\n"),
9323 PROMPT_NONE, 0 },
9324
9325 /* Error in ext2fs_new_block while creating /lost+found */
9326 { PR_3_ERR_LPF_NEW_BLOCK,
9327 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9328 PROMPT_NONE, 0 },
9329
9330 /* Error in ext2fs_new_inode while creating /lost+found */
9331 { PR_3_ERR_LPF_NEW_INODE,
9332 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9333 PROMPT_NONE, 0 },
9334
9335 /* Error in ext2fs_new_dir_block while creating /lost+found */
9336 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9337 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9338 PROMPT_NONE, 0 },
9339
9340 /* Error while writing directory block for /lost+found */
9341 { PR_3_ERR_LPF_WRITE_BLOCK,
9342 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9343 PROMPT_NONE, 0 },
9344
9345 /* Error while adjusting inode count */
9346 { PR_3_ADJUST_INODE,
9347 N_("Error while adjusting @i count on @i %i\n"),
9348 PROMPT_NONE, 0 },
9349
9350 /* Couldn't fix parent directory -- error */
9351 { PR_3_FIX_PARENT_ERR,
9352 N_("Couldn't fix parent of @i %i: %m\n\n"),
9353 PROMPT_NONE, 0 },
9354
9355 /* Couldn't fix parent directory -- couldn't find it */
9356 { PR_3_FIX_PARENT_NOFIND,
9357 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9358 PROMPT_NONE, 0 },
9359
9360 /* Error allocating inode bitmap */
9361 { PR_3_ALLOCATE_IBITMAP_ERROR,
9362 N_("@A @i @B (%N): %m\n"),
9363 PROMPT_NONE, PR_FATAL },
9364
9365 /* Error creating root directory */
9366 { PR_3_CREATE_ROOT_ERROR,
9367 N_("Error creating root @d (%s): %m\n"),
9368 PROMPT_NONE, PR_FATAL },
9369
9370 /* Error creating lost and found directory */
9371 { PR_3_CREATE_LPF_ERROR,
9372 N_("Error creating /@l @d (%s): %m\n"),
9373 PROMPT_NONE, PR_FATAL },
9374
9375 /* Root inode is not directory; aborting */
9376 { PR_3_ROOT_NOT_DIR_ABORT,
9377 N_("@r is not a @d; aborting.\n"),
9378 PROMPT_NONE, PR_FATAL },
9379
9380 /* Cannot proceed without a root inode. */
9381 { PR_3_NO_ROOT_INODE_ABORT,
Denys Vlasenko6331cf02009-11-13 09:08:27 +01009382 N_("can't proceed without a @r.\n"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009383 PROMPT_NONE, PR_FATAL },
9384
9385 /* Internal error: couldn't find dir_info */
9386 { PR_3_NO_DIRINFO,
9387 N_("Internal error: cannot find dir_info for %i.\n"),
9388 PROMPT_NONE, PR_FATAL },
9389
9390 /* Lost+found not a directory */
9391 { PR_3_LPF_NOTDIR,
9392 N_("/@l is not a @d (ino=%i)\n"),
9393 PROMPT_UNLINK, 0 },
9394
9395 /* Pass 3A Directory Optimization */
9396
9397 /* Pass 3A: Optimizing directories */
9398 { PR_3A_PASS_HEADER,
9399 N_("Pass 3A: Optimizing directories\n"),
9400 PROMPT_NONE, PR_PREEN_NOMSG },
9401
9402 /* Error iterating over directories */
9403 { PR_3A_OPTIMIZE_ITER,
9404 N_("Failed to create dirs_to_hash iterator: %m"),
9405 PROMPT_NONE, 0 },
9406
9407 /* Error rehash directory */
9408 { PR_3A_OPTIMIZE_DIR_ERR,
9409 N_("Failed to optimize directory %q (%d): %m"),
9410 PROMPT_NONE, 0 },
9411
9412 /* Rehashing dir header */
9413 { PR_3A_OPTIMIZE_DIR_HEADER,
9414 N_("Optimizing directories: "),
9415 PROMPT_NONE, PR_MSG_ONLY },
9416
9417 /* Rehashing directory %d */
9418 { PR_3A_OPTIMIZE_DIR,
9419 " %d",
9420 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9421
9422 /* Rehashing dir end */
9423 { PR_3A_OPTIMIZE_DIR_END,
9424 "\n",
9425 PROMPT_NONE, PR_PREEN_NOHDR },
9426
9427 /* Pass 4 errors */
9428
9429 /* Pass 4: Checking reference counts */
9430 { PR_4_PASS_HEADER,
9431 N_("Pass 4: Checking reference counts\n"),
9432 PROMPT_NONE, 0 },
9433
9434 /* Unattached zero-length inode */
9435 { PR_4_ZERO_LEN_INODE,
9436 N_("@u @z @i %i. "),
9437 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9438
9439 /* Unattached inode */
9440 { PR_4_UNATTACHED_INODE,
9441 N_("@u @i %i\n"),
9442 PROMPT_CONNECT, 0 },
9443
9444 /* Inode ref count wrong */
9445 { PR_4_BAD_REF_COUNT,
9446 N_("@i %i ref count is %Il, @s %N. "),
9447 PROMPT_FIX, PR_PREEN_OK },
9448
9449 { PR_4_INCONSISTENT_COUNT,
9450 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9451 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9452 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9453 "They @s the same!\n"),
9454 PROMPT_NONE, 0 },
9455
9456 /* Pass 5 errors */
9457
9458 /* Pass 5: Checking group summary information */
9459 { PR_5_PASS_HEADER,
9460 N_("Pass 5: Checking @g summary information\n"),
9461 PROMPT_NONE, 0 },
9462
9463 /* Padding at end of inode bitmap is not set. */
9464 { PR_5_INODE_BMAP_PADDING,
9465 N_("Padding at end of @i @B is not set. "),
9466 PROMPT_FIX, PR_PREEN_OK },
9467
9468 /* Padding at end of block bitmap is not set. */
9469 { PR_5_BLOCK_BMAP_PADDING,
9470 N_("Padding at end of @b @B is not set. "),
9471 PROMPT_FIX, PR_PREEN_OK },
9472
9473 /* Block bitmap differences header */
9474 { PR_5_BLOCK_BITMAP_HEADER,
9475 N_("@b @B differences: "),
9476 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9477
9478 /* Block not used, but marked in bitmap */
9479 { PR_5_BLOCK_UNUSED,
9480 " -%b",
9481 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9482
9483 /* Block used, but not marked used in bitmap */
9484 { PR_5_BLOCK_USED,
9485 " +%b",
9486 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9487
9488 /* Block bitmap differences end */
9489 { PR_5_BLOCK_BITMAP_END,
9490 "\n",
9491 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9492
9493 /* Inode bitmap differences header */
9494 { PR_5_INODE_BITMAP_HEADER,
9495 N_("@i @B differences: "),
9496 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9497
9498 /* Inode not used, but marked in bitmap */
9499 { PR_5_INODE_UNUSED,
9500 " -%i",
9501 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9502
9503 /* Inode used, but not marked used in bitmap */
9504 { PR_5_INODE_USED,
9505 " +%i",
9506 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9507
9508 /* Inode bitmap differences end */
9509 { PR_5_INODE_BITMAP_END,
9510 "\n",
9511 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9512
9513 /* Free inodes count for group wrong */
9514 { PR_5_FREE_INODE_COUNT_GROUP,
9515 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9516 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9517
9518 /* Directories count for group wrong */
9519 { PR_5_FREE_DIR_COUNT_GROUP,
9520 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9521 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9522
9523 /* Free inodes count wrong */
9524 { PR_5_FREE_INODE_COUNT,
9525 N_("Free @is count wrong (%i, counted=%j).\n"),
9526 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9527
9528 /* Free blocks count for group wrong */
9529 { PR_5_FREE_BLOCK_COUNT_GROUP,
9530 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9531 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9532
9533 /* Free blocks count wrong */
9534 { PR_5_FREE_BLOCK_COUNT,
9535 N_("Free @bs count wrong (%b, counted=%c).\n"),
9536 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9537
9538 /* Programming error: bitmap endpoints don't match */
9539 { PR_5_BMAP_ENDPOINTS,
9540 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9541 "match calculated @B endpoints (%i, %j)\n"),
9542 PROMPT_NONE, PR_FATAL },
9543
9544 /* Internal error: fudging end of bitmap */
9545 { PR_5_FUDGE_BITMAP_ERROR,
9546 N_("Internal error: fudging end of bitmap (%N)\n"),
9547 PROMPT_NONE, PR_FATAL },
9548
9549 /* Error copying in replacement inode bitmap */
9550 { PR_5_COPY_IBITMAP_ERROR,
9551 N_("Error copying in replacement @i @B: %m\n"),
9552 PROMPT_NONE, PR_FATAL },
9553
9554 /* Error copying in replacement block bitmap */
9555 { PR_5_COPY_BBITMAP_ERROR,
9556 N_("Error copying in replacement @b @B: %m\n"),
9557 PROMPT_NONE, PR_FATAL },
9558
9559 /* Block range not used, but marked in bitmap */
9560 { PR_5_BLOCK_RANGE_UNUSED,
9561 " -(%b--%c)",
9562 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9563
9564 /* Block range used, but not marked used in bitmap */
9565 { PR_5_BLOCK_RANGE_USED,
9566 " +(%b--%c)",
9567 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9568
9569 /* Inode range not used, but marked in bitmap */
9570 { PR_5_INODE_RANGE_UNUSED,
9571 " -(%i--%j)",
9572 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9573
9574 /* Inode range used, but not marked used in bitmap */
9575 { PR_5_INODE_RANGE_USED,
9576 " +(%i--%j)",
9577 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9578
9579 { 0 }
9580};
9581
9582/*
9583 * This is the latch flags register. It allows several problems to be
9584 * "latched" together. This means that the user has to answer but one
9585 * question for the set of problems, and all of the associated
9586 * problems will be either fixed or not fixed.
9587 */
9588static struct latch_descr pr_latch_info[] = {
9589 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9590 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9591 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9592 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9593 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9594 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9595 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9596 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9597 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9598 { -1, 0, 0 },
9599};
9600
9601static const struct e2fsck_problem *find_problem(problem_t code)
9602{
9603 int i;
9604
9605 for (i=0; problem_table[i].e2p_code; i++) {
9606 if (problem_table[i].e2p_code == code)
9607 return &problem_table[i];
9608 }
9609 return 0;
9610}
9611
9612static struct latch_descr *find_latch(int code)
9613{
9614 int i;
9615
9616 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9617 if (pr_latch_info[i].latch_code == code)
9618 return &pr_latch_info[i];
9619 }
9620 return 0;
9621}
9622
9623int end_problem_latch(e2fsck_t ctx, int mask)
9624{
9625 struct latch_descr *ldesc;
9626 struct problem_context pctx;
9627 int answer = -1;
9628
9629 ldesc = find_latch(mask);
9630 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9631 clear_problem_context(&pctx);
9632 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9633 }
9634 ldesc->flags &= ~(PRL_VARIABLE);
9635 return answer;
9636}
9637
9638int set_latch_flags(int mask, int setflags, int clearflags)
9639{
9640 struct latch_descr *ldesc;
9641
9642 ldesc = find_latch(mask);
9643 if (!ldesc)
9644 return -1;
9645 ldesc->flags |= setflags;
9646 ldesc->flags &= ~clearflags;
9647 return 0;
9648}
9649
9650void clear_problem_context(struct problem_context *ctx)
9651{
9652 memset(ctx, 0, sizeof(struct problem_context));
9653 ctx->blkcount = -1;
9654 ctx->group = -1;
9655}
9656
9657int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9658{
9659 ext2_filsys fs = ctx->fs;
9660 const struct e2fsck_problem *ptr;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01009661 struct latch_descr *ldesc = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009662 const char *message;
9663 int def_yn, answer, ans;
9664 int print_answer = 0;
9665 int suppress = 0;
9666
9667 ptr = find_problem(code);
9668 if (!ptr) {
9669 printf(_("Unhandled error code (0x%x)!\n"), code);
9670 return 0;
9671 }
9672 def_yn = 1;
9673 if ((ptr->flags & PR_NO_DEFAULT) ||
9674 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9675 (ctx->options & E2F_OPT_NO))
9676 def_yn= 0;
9677
9678 /*
9679 * Do special latch processing. This is where we ask the
9680 * latch question, if it exists
9681 */
9682 if (ptr->flags & PR_LATCH_MASK) {
9683 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9684 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9685 ans = fix_problem(ctx, ldesc->question, pctx);
9686 if (ans == 1)
9687 ldesc->flags |= PRL_YES;
9688 if (ans == 0)
9689 ldesc->flags |= PRL_NO;
9690 ldesc->flags |= PRL_LATCHED;
9691 }
9692 if (ldesc->flags & PRL_SUPPRESS)
9693 suppress++;
9694 }
9695 if ((ptr->flags & PR_PREEN_NOMSG) &&
9696 (ctx->options & E2F_OPT_PREEN))
9697 suppress++;
9698 if ((ptr->flags & PR_NO_NOMSG) &&
9699 (ctx->options & E2F_OPT_NO))
9700 suppress++;
9701 if (!suppress) {
9702 message = ptr->e2p_description;
9703 if ((ctx->options & E2F_OPT_PREEN) &&
9704 !(ptr->flags & PR_PREEN_NOHDR)) {
9705 printf("%s: ", ctx->device_name ?
9706 ctx->device_name : ctx->filesystem_name);
9707 }
9708 if (*message)
9709 print_e2fsck_message(ctx, _(message), pctx, 1);
9710 }
9711 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9712 preenhalt(ctx);
9713
9714 if (ptr->flags & PR_FATAL)
9715 bb_error_msg_and_die(0);
9716
9717 if (ptr->prompt == PROMPT_NONE) {
9718 if (ptr->flags & PR_NOCOLLATE)
9719 answer = -1;
9720 else
9721 answer = def_yn;
9722 } else {
9723 if (ctx->options & E2F_OPT_PREEN) {
9724 answer = def_yn;
9725 if (!(ptr->flags & PR_PREEN_NOMSG))
9726 print_answer = 1;
9727 } else if ((ptr->flags & PR_LATCH_MASK) &&
9728 (ldesc->flags & (PRL_YES | PRL_NO))) {
9729 if (!suppress)
9730 print_answer = 1;
9731 if (ldesc->flags & PRL_YES)
9732 answer = 1;
9733 else
9734 answer = 0;
9735 } else
9736 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9737 if (!answer && !(ptr->flags & PR_NO_OK))
9738 ext2fs_unmark_valid(fs);
9739
9740 if (print_answer)
9741 printf("%s.\n", answer ?
9742 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009743 }
9744
9745 if ((ptr->prompt == PROMPT_ABORT) && answer)
9746 bb_error_msg_and_die(0);
9747
9748 if (ptr->flags & PR_AFTER_CODE)
9749 answer = fix_problem(ctx, ptr->second_code, pctx);
9750
9751 return answer;
9752}
9753
9754/*
9755 * linux/fs/recovery.c
9756 *
9757 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9758 */
9759
9760/*
9761 * Maintain information about the progress of the recovery job, so that
9762 * the different passes can carry information between them.
9763 */
9764struct recovery_info
9765{
9766 tid_t start_transaction;
9767 tid_t end_transaction;
9768
9769 int nr_replays;
9770 int nr_revokes;
9771 int nr_revoke_hits;
9772};
9773
9774enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9775static int do_one_pass(journal_t *journal,
9776 struct recovery_info *info, enum passtype pass);
9777static int scan_revoke_records(journal_t *, struct buffer_head *,
9778 tid_t, struct recovery_info *);
9779
9780/*
9781 * Read a block from the journal
9782 */
9783
9784static int jread(struct buffer_head **bhp, journal_t *journal,
9785 unsigned int offset)
9786{
9787 int err;
9788 unsigned long blocknr;
9789 struct buffer_head *bh;
9790
9791 *bhp = NULL;
9792
9793 err = journal_bmap(journal, offset, &blocknr);
9794
9795 if (err) {
9796 printf("JBD: bad block at offset %u\n", offset);
9797 return err;
9798 }
9799
9800 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9801 if (!bh)
9802 return -ENOMEM;
9803
9804 if (!buffer_uptodate(bh)) {
9805 /* If this is a brand new buffer, start readahead.
9806 Otherwise, we assume we are already reading it. */
9807 if (!buffer_req(bh))
9808 do_readahead(journal, offset);
9809 wait_on_buffer(bh);
9810 }
9811
9812 if (!buffer_uptodate(bh)) {
9813 printf("JBD: Failed to read block at offset %u\n", offset);
9814 brelse(bh);
9815 return -EIO;
9816 }
9817
9818 *bhp = bh;
9819 return 0;
9820}
9821
9822
9823/*
9824 * Count the number of in-use tags in a journal descriptor block.
9825 */
9826
9827static int count_tags(struct buffer_head *bh, int size)
9828{
9829 char * tagp;
9830 journal_block_tag_t * tag;
9831 int nr = 0;
9832
9833 tagp = &bh->b_data[sizeof(journal_header_t)];
9834
9835 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9836 tag = (journal_block_tag_t *) tagp;
9837
9838 nr++;
9839 tagp += sizeof(journal_block_tag_t);
9840 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9841 tagp += 16;
9842
9843 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9844 break;
9845 }
9846
9847 return nr;
9848}
9849
9850
9851/* Make sure we wrap around the log correctly! */
9852#define wrap(journal, var) \
9853do { \
9854 if (var >= (journal)->j_last) \
9855 var -= ((journal)->j_last - (journal)->j_first); \
9856} while (0)
9857
9858/**
9859 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9860 * @journal: the journal to recover
9861 *
9862 * The primary function for recovering the log contents when mounting a
9863 * journaled device.
9864 *
9865 * Recovery is done in three passes. In the first pass, we look for the
9866 * end of the log. In the second, we assemble the list of revoke
9867 * blocks. In the third and final pass, we replay any un-revoked blocks
9868 * in the log.
9869 */
9870int journal_recover(journal_t *journal)
9871{
9872 int err;
9873 journal_superblock_t * sb;
9874
9875 struct recovery_info info;
9876
9877 memset(&info, 0, sizeof(info));
9878 sb = journal->j_superblock;
9879
9880 /*
9881 * The journal superblock's s_start field (the current log head)
9882 * is always zero if, and only if, the journal was cleanly
9883 * unmounted.
9884 */
9885
9886 if (!sb->s_start) {
9887 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9888 return 0;
9889 }
9890
9891 err = do_one_pass(journal, &info, PASS_SCAN);
9892 if (!err)
9893 err = do_one_pass(journal, &info, PASS_REVOKE);
9894 if (!err)
9895 err = do_one_pass(journal, &info, PASS_REPLAY);
9896
9897 /* Restart the log at the next transaction ID, thus invalidating
9898 * any existing commit records in the log. */
9899 journal->j_transaction_sequence = ++info.end_transaction;
9900
9901 journal_clear_revoke(journal);
9902 sync_blockdev(journal->j_fs_dev);
9903 return err;
9904}
9905
9906static int do_one_pass(journal_t *journal,
9907 struct recovery_info *info, enum passtype pass)
9908{
9909 unsigned int first_commit_ID, next_commit_ID;
9910 unsigned long next_log_block;
9911 int err, success = 0;
9912 journal_superblock_t * sb;
9913 journal_header_t * tmp;
9914 struct buffer_head * bh;
9915 unsigned int sequence;
9916 int blocktype;
9917
9918 /* Precompute the maximum metadata descriptors in a descriptor block */
9919 int MAX_BLOCKS_PER_DESC;
9920 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9921 / sizeof(journal_block_tag_t));
9922
9923 /*
9924 * First thing is to establish what we expect to find in the log
9925 * (in terms of transaction IDs), and where (in terms of log
9926 * block offsets): query the superblock.
9927 */
9928
9929 sb = journal->j_superblock;
9930 next_commit_ID = ntohl(sb->s_sequence);
9931 next_log_block = ntohl(sb->s_start);
9932
9933 first_commit_ID = next_commit_ID;
9934 if (pass == PASS_SCAN)
9935 info->start_transaction = first_commit_ID;
9936
9937 /*
9938 * Now we walk through the log, transaction by transaction,
9939 * making sure that each transaction has a commit block in the
9940 * expected place. Each complete transaction gets replayed back
9941 * into the main filesystem.
9942 */
9943
9944 while (1) {
9945 int flags;
9946 char * tagp;
9947 journal_block_tag_t * tag;
9948 struct buffer_head * obh;
9949 struct buffer_head * nbh;
9950
9951 /* If we already know where to stop the log traversal,
9952 * check right now that we haven't gone past the end of
9953 * the log. */
9954
9955 if (pass != PASS_SCAN)
9956 if (tid_geq(next_commit_ID, info->end_transaction))
9957 break;
9958
9959 /* Skip over each chunk of the transaction looking
9960 * either the next descriptor block or the final commit
9961 * record. */
9962
9963 err = jread(&bh, journal, next_log_block);
9964 if (err)
9965 goto failed;
9966
9967 next_log_block++;
9968 wrap(journal, next_log_block);
9969
9970 /* What kind of buffer is it?
9971 *
9972 * If it is a descriptor block, check that it has the
9973 * expected sequence number. Otherwise, we're all done
9974 * here. */
9975
9976 tmp = (journal_header_t *)bh->b_data;
9977
9978 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9979 brelse(bh);
9980 break;
9981 }
9982
9983 blocktype = ntohl(tmp->h_blocktype);
9984 sequence = ntohl(tmp->h_sequence);
9985
9986 if (sequence != next_commit_ID) {
9987 brelse(bh);
9988 break;
9989 }
9990
9991 /* OK, we have a valid descriptor block which matches
9992 * all of the sequence number checks. What are we going
9993 * to do with it? That depends on the pass... */
9994
Denis Vlasenkobb045062008-09-27 14:06:06 +00009995 switch (blocktype) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009996 case JFS_DESCRIPTOR_BLOCK:
9997 /* If it is a valid descriptor block, replay it
9998 * in pass REPLAY; otherwise, just skip over the
9999 * blocks it describes. */
10000 if (pass != PASS_REPLAY) {
10001 next_log_block +=
10002 count_tags(bh, journal->j_blocksize);
10003 wrap(journal, next_log_block);
10004 brelse(bh);
10005 continue;
10006 }
10007
10008 /* A descriptor block: we can now write all of
10009 * the data blocks. Yay, useful work is finally
10010 * getting done here! */
10011
10012 tagp = &bh->b_data[sizeof(journal_header_t)];
10013 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10014 <= journal->j_blocksize) {
10015 unsigned long io_block;
10016
10017 tag = (journal_block_tag_t *) tagp;
10018 flags = ntohl(tag->t_flags);
10019
10020 io_block = next_log_block++;
10021 wrap(journal, next_log_block);
10022 err = jread(&obh, journal, io_block);
10023 if (err) {
10024 /* Recover what we can, but
10025 * report failure at the end. */
10026 success = err;
10027 printf("JBD: IO error %d recovering "
10028 "block %ld in log\n",
10029 err, io_block);
10030 } else {
10031 unsigned long blocknr;
10032
10033 blocknr = ntohl(tag->t_blocknr);
10034
10035 /* If the block has been
10036 * revoked, then we're all done
10037 * here. */
10038 if (journal_test_revoke
10039 (journal, blocknr,
10040 next_commit_ID)) {
10041 brelse(obh);
10042 ++info->nr_revoke_hits;
10043 goto skip_write;
10044 }
10045
10046 /* Find a buffer for the new
10047 * data being restored */
10048 nbh = getblk(journal->j_fs_dev,
10049 blocknr,
10050 journal->j_blocksize);
10051 if (nbh == NULL) {
10052 printf("JBD: Out of memory "
10053 "during recovery.\n");
10054 err = -ENOMEM;
10055 brelse(bh);
10056 brelse(obh);
10057 goto failed;
10058 }
10059
10060 lock_buffer(nbh);
10061 memcpy(nbh->b_data, obh->b_data,
10062 journal->j_blocksize);
10063 if (flags & JFS_FLAG_ESCAPE) {
10064 *((unsigned int *)bh->b_data) =
10065 htonl(JFS_MAGIC_NUMBER);
10066 }
10067
10068 mark_buffer_uptodate(nbh, 1);
10069 mark_buffer_dirty(nbh);
10070 ++info->nr_replays;
10071 /* ll_rw_block(WRITE, 1, &nbh); */
10072 unlock_buffer(nbh);
10073 brelse(obh);
10074 brelse(nbh);
10075 }
10076
10077 skip_write:
10078 tagp += sizeof(journal_block_tag_t);
10079 if (!(flags & JFS_FLAG_SAME_UUID))
10080 tagp += 16;
10081
10082 if (flags & JFS_FLAG_LAST_TAG)
10083 break;
10084 }
10085
10086 brelse(bh);
10087 continue;
10088
10089 case JFS_COMMIT_BLOCK:
10090 /* Found an expected commit block: not much to
10091 * do other than move on to the next sequence
10092 * number. */
10093 brelse(bh);
10094 next_commit_ID++;
10095 continue;
10096
10097 case JFS_REVOKE_BLOCK:
10098 /* If we aren't in the REVOKE pass, then we can
10099 * just skip over this block. */
10100 if (pass != PASS_REVOKE) {
10101 brelse(bh);
10102 continue;
10103 }
10104
10105 err = scan_revoke_records(journal, bh,
10106 next_commit_ID, info);
10107 brelse(bh);
10108 if (err)
10109 goto failed;
10110 continue;
10111
10112 default:
10113 goto done;
10114 }
10115 }
10116
10117 done:
10118 /*
10119 * We broke out of the log scan loop: either we came to the
10120 * known end of the log or we found an unexpected block in the
10121 * log. If the latter happened, then we know that the "current"
10122 * transaction marks the end of the valid log.
10123 */
10124
10125 if (pass == PASS_SCAN)
10126 info->end_transaction = next_commit_ID;
10127 else {
10128 /* It's really bad news if different passes end up at
10129 * different places (but possible due to IO errors). */
10130 if (info->end_transaction != next_commit_ID) {
10131 printf("JBD: recovery pass %d ended at "
10132 "transaction %u, expected %u\n",
10133 pass, next_commit_ID, info->end_transaction);
10134 if (!success)
10135 success = -EIO;
10136 }
10137 }
10138
10139 return success;
10140
10141 failed:
10142 return err;
10143}
10144
10145
10146/* Scan a revoke record, marking all blocks mentioned as revoked. */
10147
10148static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10149 tid_t sequence, struct recovery_info *info)
10150{
10151 journal_revoke_header_t *header;
10152 int offset, max;
10153
10154 header = (journal_revoke_header_t *) bh->b_data;
10155 offset = sizeof(journal_revoke_header_t);
10156 max = ntohl(header->r_count);
10157
10158 while (offset < max) {
10159 unsigned long blocknr;
10160 int err;
10161
10162 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10163 offset += 4;
10164 err = journal_set_revoke(journal, blocknr, sequence);
10165 if (err)
10166 return err;
10167 ++info->nr_revokes;
10168 }
10169 return 0;
10170}
10171
10172
10173/*
10174 * rehash.c --- rebuild hash tree directories
10175 *
10176 * This algorithm is designed for simplicity of implementation and to
10177 * pack the directory as much as possible. It however requires twice
10178 * as much memory as the size of the directory. The maximum size
10179 * directory supported using a 4k blocksize is roughly a gigabyte, and
10180 * so there may very well be problems with machines that don't have
10181 * virtual memory, and obscenely large directories.
10182 *
10183 * An alternate algorithm which is much more disk intensive could be
10184 * written, and probably will need to be written in the future. The
10185 * design goals of such an algorithm are: (a) use (roughly) constant
10186 * amounts of memory, no matter how large the directory, (b) the
10187 * directory must be safe at all times, even if e2fsck is interrupted
10188 * in the middle, (c) we must use minimal amounts of extra disk
10189 * blocks. This pretty much requires an incremental approach, where
10190 * we are reading from one part of the directory, and inserting into
10191 * the front half. So the algorithm will have to keep track of a
10192 * moving block boundary between the new tree and the old tree, and
10193 * files will need to be moved from the old directory and inserted
10194 * into the new tree. If the new directory requires space which isn't
10195 * yet available, blocks from the beginning part of the old directory
10196 * may need to be moved to the end of the directory to make room for
10197 * the new tree:
10198 *
10199 * --------------------------------------------------------
10200 * | new tree | | old tree |
10201 * --------------------------------------------------------
10202 * ^ ptr ^ptr
10203 * tail new head old
10204 *
10205 * This is going to be a pain in the tuckus to implement, and will
10206 * require a lot more disk accesses. So I'm going to skip it for now;
10207 * it's only really going to be an issue for really, really big
10208 * filesystems (when we reach the level of tens of millions of files
10209 * in a single directory). It will probably be easier to simply
10210 * require that e2fsck use VM first.
10211 */
10212
10213struct fill_dir_struct {
10214 char *buf;
10215 struct ext2_inode *inode;
10216 int err;
10217 e2fsck_t ctx;
10218 struct hash_entry *harray;
10219 int max_array, num_array;
10220 int dir_size;
10221 int compress;
10222 ino_t parent;
10223};
10224
10225struct hash_entry {
10226 ext2_dirhash_t hash;
10227 ext2_dirhash_t minor_hash;
10228 struct ext2_dir_entry *dir;
10229};
10230
10231struct out_dir {
10232 int num;
10233 int max;
10234 char *buf;
10235 ext2_dirhash_t *hashes;
10236};
10237
10238static int fill_dir_block(ext2_filsys fs,
10239 blk_t *block_nr,
10240 e2_blkcnt_t blockcnt,
10241 blk_t ref_block FSCK_ATTR((unused)),
10242 int ref_offset FSCK_ATTR((unused)),
10243 void *priv_data)
10244{
10245 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10246 struct hash_entry *new_array, *ent;
10247 struct ext2_dir_entry *dirent;
10248 char *dir;
10249 unsigned int offset, dir_offset;
10250
10251 if (blockcnt < 0)
10252 return 0;
10253
10254 offset = blockcnt * fs->blocksize;
10255 if (offset + fs->blocksize > fd->inode->i_size) {
10256 fd->err = EXT2_ET_DIR_CORRUPTED;
10257 return BLOCK_ABORT;
10258 }
10259 dir = (fd->buf+offset);
10260 if (HOLE_BLKADDR(*block_nr)) {
10261 memset(dir, 0, fs->blocksize);
10262 dirent = (struct ext2_dir_entry *) dir;
10263 dirent->rec_len = fs->blocksize;
10264 } else {
10265 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10266 if (fd->err)
10267 return BLOCK_ABORT;
10268 }
10269 /* While the directory block is "hot", index it. */
10270 dir_offset = 0;
10271 while (dir_offset < fs->blocksize) {
10272 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10273 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10274 (dirent->rec_len < 8) ||
10275 ((dirent->rec_len % 4) != 0) ||
10276 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10277 fd->err = EXT2_ET_DIR_CORRUPTED;
10278 return BLOCK_ABORT;
10279 }
10280 dir_offset += dirent->rec_len;
10281 if (dirent->inode == 0)
10282 continue;
10283 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10284 (dirent->name[0] == '.'))
10285 continue;
10286 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10287 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10288 fd->parent = dirent->inode;
10289 continue;
10290 }
10291 if (fd->num_array >= fd->max_array) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010292 new_array = xrealloc(fd->harray,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010293 sizeof(struct hash_entry) * (fd->max_array+500));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010294 fd->harray = new_array;
10295 fd->max_array += 500;
10296 }
10297 ent = fd->harray + fd->num_array++;
10298 ent->dir = dirent;
10299 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10300 if (fd->compress)
10301 ent->hash = ent->minor_hash = 0;
10302 else {
10303 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10304 dirent->name,
10305 dirent->name_len & 0xFF,
10306 fs->super->s_hash_seed,
10307 &ent->hash, &ent->minor_hash);
10308 if (fd->err)
10309 return BLOCK_ABORT;
10310 }
10311 }
10312
10313 return 0;
10314}
10315
10316/* Used for sorting the hash entry */
10317static int name_cmp(const void *a, const void *b)
10318{
10319 const struct hash_entry *he_a = (const struct hash_entry *) a;
10320 const struct hash_entry *he_b = (const struct hash_entry *) b;
10321 int ret;
10322 int min_len;
10323
10324 min_len = he_a->dir->name_len;
10325 if (min_len > he_b->dir->name_len)
10326 min_len = he_b->dir->name_len;
10327
10328 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10329 if (ret == 0) {
10330 if (he_a->dir->name_len > he_b->dir->name_len)
10331 ret = 1;
10332 else if (he_a->dir->name_len < he_b->dir->name_len)
10333 ret = -1;
10334 else
10335 ret = he_b->dir->inode - he_a->dir->inode;
10336 }
10337 return ret;
10338}
10339
10340/* Used for sorting the hash entry */
10341static int hash_cmp(const void *a, const void *b)
10342{
10343 const struct hash_entry *he_a = (const struct hash_entry *) a;
10344 const struct hash_entry *he_b = (const struct hash_entry *) b;
10345 int ret;
10346
10347 if (he_a->hash > he_b->hash)
10348 ret = 1;
10349 else if (he_a->hash < he_b->hash)
10350 ret = -1;
10351 else {
10352 if (he_a->minor_hash > he_b->minor_hash)
10353 ret = 1;
10354 else if (he_a->minor_hash < he_b->minor_hash)
10355 ret = -1;
10356 else
10357 ret = name_cmp(a, b);
10358 }
10359 return ret;
10360}
10361
10362static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10363 int blocks)
10364{
10365 void *new_mem;
10366
10367 if (outdir->max) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010368 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010369 outdir->buf = new_mem;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010370 new_mem = xrealloc(outdir->hashes,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010371 blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010372 outdir->hashes = new_mem;
10373 } else {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010374 outdir->buf = xmalloc(blocks * fs->blocksize);
10375 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010376 outdir->num = 0;
10377 }
10378 outdir->max = blocks;
10379 return 0;
10380}
10381
10382static void free_out_dir(struct out_dir *outdir)
10383{
10384 free(outdir->buf);
10385 free(outdir->hashes);
10386 outdir->max = 0;
10387 outdir->num =0;
10388}
10389
10390static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10391 char ** ret)
10392{
10393 errcode_t retval;
10394
10395 if (outdir->num >= outdir->max) {
10396 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10397 if (retval)
10398 return retval;
10399 }
10400 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10401 memset(*ret, 0, fs->blocksize);
10402 return 0;
10403}
10404
10405/*
10406 * This function is used to make a unique filename. We do this by
10407 * appending ~0, and then incrementing the number. However, we cannot
10408 * expand the length of the filename beyond the padding available in
10409 * the directory entry.
10410 */
10411static void mutate_name(char *str, __u16 *len)
10412{
10413 int i;
10414 __u16 l = *len & 0xFF, h = *len & 0xff00;
10415
10416 /*
10417 * First check to see if it looks the name has been mutated
10418 * already
10419 */
10420 for (i = l-1; i > 0; i--) {
10421 if (!isdigit(str[i]))
10422 break;
10423 }
10424 if ((i == l-1) || (str[i] != '~')) {
10425 if (((l-1) & 3) < 2)
10426 l += 2;
10427 else
10428 l = (l+3) & ~3;
10429 str[l-2] = '~';
10430 str[l-1] = '0';
10431 *len = l | h;
10432 return;
10433 }
10434 for (i = l-1; i >= 0; i--) {
10435 if (isdigit(str[i])) {
10436 if (str[i] == '9')
10437 str[i] = '0';
10438 else {
10439 str[i]++;
10440 return;
10441 }
10442 continue;
10443 }
10444 if (i == 1) {
10445 if (str[0] == 'z')
10446 str[0] = 'A';
10447 else if (str[0] == 'Z') {
10448 str[0] = '~';
10449 str[1] = '0';
10450 } else
10451 str[0]++;
10452 } else if (i > 0) {
10453 str[i] = '1';
10454 str[i-1] = '~';
10455 } else {
10456 if (str[0] == '~')
10457 str[0] = 'a';
10458 else
10459 str[0]++;
10460 }
10461 break;
10462 }
10463}
10464
10465static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10466 ext2_ino_t ino,
10467 struct fill_dir_struct *fd)
10468{
10469 struct problem_context pctx;
10470 struct hash_entry *ent, *prev;
10471 int i, j;
10472 int fixed = 0;
10473 char new_name[256];
10474 __u16 new_len;
10475
10476 clear_problem_context(&pctx);
10477 pctx.ino = ino;
10478
10479 for (i=1; i < fd->num_array; i++) {
10480 ent = fd->harray + i;
10481 prev = ent - 1;
10482 if (!ent->dir->inode ||
10483 ((ent->dir->name_len & 0xFF) !=
10484 (prev->dir->name_len & 0xFF)) ||
10485 (strncmp(ent->dir->name, prev->dir->name,
10486 ent->dir->name_len & 0xFF)))
10487 continue;
10488 pctx.dirent = ent->dir;
10489 if ((ent->dir->inode == prev->dir->inode) &&
10490 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10491 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10492 ent->dir->inode = 0;
10493 fixed++;
10494 continue;
10495 }
10496 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10497 new_len = ent->dir->name_len;
10498 mutate_name(new_name, &new_len);
10499 for (j=0; j < fd->num_array; j++) {
10500 if ((i==j) ||
10501 ((ent->dir->name_len & 0xFF) !=
10502 (fd->harray[j].dir->name_len & 0xFF)) ||
10503 (strncmp(new_name, fd->harray[j].dir->name,
10504 new_len & 0xFF)))
10505 continue;
10506 mutate_name(new_name, &new_len);
10507
10508 j = -1;
10509 }
10510 new_name[new_len & 0xFF] = 0;
10511 pctx.str = new_name;
10512 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10513 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10514 ent->dir->name_len = new_len;
10515 ext2fs_dirhash(fs->super->s_def_hash_version,
10516 ent->dir->name,
10517 ent->dir->name_len & 0xFF,
10518 fs->super->s_hash_seed,
10519 &ent->hash, &ent->minor_hash);
10520 fixed++;
10521 }
10522 }
10523 return fixed;
10524}
10525
10526
10527static errcode_t copy_dir_entries(ext2_filsys fs,
10528 struct fill_dir_struct *fd,
10529 struct out_dir *outdir)
10530{
10531 errcode_t retval;
10532 char *block_start;
10533 struct hash_entry *ent;
10534 struct ext2_dir_entry *dirent;
10535 int i, rec_len, left;
10536 ext2_dirhash_t prev_hash;
10537 int offset;
10538
10539 outdir->max = 0;
10540 retval = alloc_size_dir(fs, outdir,
10541 (fd->dir_size / fs->blocksize) + 2);
10542 if (retval)
10543 return retval;
10544 outdir->num = fd->compress ? 0 : 1;
10545 offset = 0;
10546 outdir->hashes[0] = 0;
10547 prev_hash = 1;
10548 if ((retval = get_next_block(fs, outdir, &block_start)))
10549 return retval;
10550 dirent = (struct ext2_dir_entry *) block_start;
10551 left = fs->blocksize;
10552 for (i=0; i < fd->num_array; i++) {
10553 ent = fd->harray + i;
10554 if (ent->dir->inode == 0)
10555 continue;
10556 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10557 if (rec_len > left) {
10558 if (left)
10559 dirent->rec_len += left;
10560 if ((retval = get_next_block(fs, outdir,
10561 &block_start)))
10562 return retval;
10563 offset = 0;
10564 }
10565 left = fs->blocksize - offset;
10566 dirent = (struct ext2_dir_entry *) (block_start + offset);
10567 if (offset == 0) {
10568 if (ent->hash == prev_hash)
10569 outdir->hashes[outdir->num-1] = ent->hash | 1;
10570 else
10571 outdir->hashes[outdir->num-1] = ent->hash;
10572 }
10573 dirent->inode = ent->dir->inode;
10574 dirent->name_len = ent->dir->name_len;
10575 dirent->rec_len = rec_len;
10576 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10577 offset += rec_len;
10578 left -= rec_len;
10579 if (left < 12) {
10580 dirent->rec_len += left;
10581 offset += left;
10582 left = 0;
10583 }
10584 prev_hash = ent->hash;
10585 }
10586 if (left)
10587 dirent->rec_len += left;
10588
10589 return 0;
10590}
10591
10592
10593static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10594 ext2_ino_t ino, ext2_ino_t parent)
10595{
10596 struct ext2_dir_entry *dir;
10597 struct ext2_dx_root_info *root;
10598 struct ext2_dx_countlimit *limits;
10599 int filetype = 0;
10600
10601 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10602 filetype = EXT2_FT_DIR << 8;
10603
10604 memset(buf, 0, fs->blocksize);
10605 dir = (struct ext2_dir_entry *) buf;
10606 dir->inode = ino;
10607 dir->name[0] = '.';
10608 dir->name_len = 1 | filetype;
10609 dir->rec_len = 12;
10610 dir = (struct ext2_dir_entry *) (buf + 12);
10611 dir->inode = parent;
10612 dir->name[0] = '.';
10613 dir->name[1] = '.';
10614 dir->name_len = 2 | filetype;
10615 dir->rec_len = fs->blocksize - 12;
10616
10617 root = (struct ext2_dx_root_info *) (buf+24);
10618 root->reserved_zero = 0;
10619 root->hash_version = fs->super->s_def_hash_version;
10620 root->info_length = 8;
10621 root->indirect_levels = 0;
10622 root->unused_flags = 0;
10623
10624 limits = (struct ext2_dx_countlimit *) (buf+32);
10625 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10626 limits->count = 0;
10627
10628 return root;
10629}
10630
10631
10632static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10633{
10634 struct ext2_dir_entry *dir;
10635 struct ext2_dx_countlimit *limits;
10636
10637 memset(buf, 0, fs->blocksize);
10638 dir = (struct ext2_dir_entry *) buf;
10639 dir->inode = 0;
10640 dir->rec_len = fs->blocksize;
10641
10642 limits = (struct ext2_dx_countlimit *) (buf+8);
10643 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10644 limits->count = 0;
10645
10646 return (struct ext2_dx_entry *) limits;
10647}
10648
10649/*
10650 * This function takes the leaf nodes which have been written in
10651 * outdir, and populates the root node and any necessary interior nodes.
10652 */
10653static errcode_t calculate_tree(ext2_filsys fs,
10654 struct out_dir *outdir,
10655 ext2_ino_t ino,
10656 ext2_ino_t parent)
10657{
10658 struct ext2_dx_root_info *root_info;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010659 struct ext2_dx_entry *root, *dx_ent = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010660 struct ext2_dx_countlimit *root_limit, *limit;
10661 errcode_t retval;
10662 char * block_start;
10663 int i, c1, c2, nblks;
10664 int limit_offset, root_offset;
10665
10666 root_info = set_root_node(fs, outdir->buf, ino, parent);
10667 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10668 root_info->info_length;
10669 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10670 c1 = root_limit->limit;
10671 nblks = outdir->num;
10672
10673 /* Write out the pointer blocks */
10674 if (nblks-1 <= c1) {
10675 /* Just write out the root block, and we're done */
10676 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10677 for (i=1; i < nblks; i++) {
10678 root->block = ext2fs_cpu_to_le32(i);
10679 if (i != 1)
10680 root->hash =
10681 ext2fs_cpu_to_le32(outdir->hashes[i]);
10682 root++;
10683 c1--;
10684 }
10685 } else {
10686 c2 = 0;
10687 limit = 0;
10688 root_info->indirect_levels = 1;
10689 for (i=1; i < nblks; i++) {
10690 if (c1 == 0)
10691 return ENOSPC;
10692 if (c2 == 0) {
10693 if (limit)
10694 limit->limit = limit->count =
10695 ext2fs_cpu_to_le16(limit->limit);
10696 root = (struct ext2_dx_entry *)
10697 (outdir->buf + root_offset);
10698 root->block = ext2fs_cpu_to_le32(outdir->num);
10699 if (i != 1)
10700 root->hash =
10701 ext2fs_cpu_to_le32(outdir->hashes[i]);
10702 if ((retval = get_next_block(fs, outdir,
10703 &block_start)))
10704 return retval;
10705 dx_ent = set_int_node(fs, block_start);
10706 limit = (struct ext2_dx_countlimit *) dx_ent;
10707 c2 = limit->limit;
10708 root_offset += sizeof(struct ext2_dx_entry);
10709 c1--;
10710 }
10711 dx_ent->block = ext2fs_cpu_to_le32(i);
10712 if (c2 != limit->limit)
10713 dx_ent->hash =
10714 ext2fs_cpu_to_le32(outdir->hashes[i]);
10715 dx_ent++;
10716 c2--;
10717 }
10718 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10719 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10720 }
10721 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10722 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10723 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10724
10725 return 0;
10726}
10727
10728struct write_dir_struct {
10729 struct out_dir *outdir;
10730 errcode_t err;
10731 e2fsck_t ctx;
10732 int cleared;
10733};
10734
10735/*
10736 * Helper function which writes out a directory block.
10737 */
10738static int write_dir_block(ext2_filsys fs,
10739 blk_t *block_nr,
10740 e2_blkcnt_t blockcnt,
10741 blk_t ref_block FSCK_ATTR((unused)),
10742 int ref_offset FSCK_ATTR((unused)),
10743 void *priv_data)
10744{
10745 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10746 blk_t blk;
10747 char *dir;
10748
10749 if (*block_nr == 0)
10750 return 0;
10751 if (blockcnt >= wd->outdir->num) {
10752 e2fsck_read_bitmaps(wd->ctx);
10753 blk = *block_nr;
10754 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10755 ext2fs_block_alloc_stats(fs, blk, -1);
10756 *block_nr = 0;
10757 wd->cleared++;
10758 return BLOCK_CHANGED;
10759 }
10760 if (blockcnt < 0)
10761 return 0;
10762
10763 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10764 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10765 if (wd->err)
10766 return BLOCK_ABORT;
10767 return 0;
10768}
10769
10770static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10771 struct out_dir *outdir,
10772 ext2_ino_t ino, int compress)
10773{
10774 struct write_dir_struct wd;
10775 errcode_t retval;
10776 struct ext2_inode inode;
10777
10778 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10779 if (retval)
10780 return retval;
10781
10782 wd.outdir = outdir;
10783 wd.err = 0;
10784 wd.ctx = ctx;
10785 wd.cleared = 0;
10786
10787 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10788 write_dir_block, &wd);
10789 if (retval)
10790 return retval;
10791 if (wd.err)
10792 return wd.err;
10793
10794 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10795 if (compress)
10796 inode.i_flags &= ~EXT2_INDEX_FL;
10797 else
10798 inode.i_flags |= EXT2_INDEX_FL;
10799 inode.i_size = outdir->num * fs->blocksize;
10800 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10801 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10802
10803 return 0;
10804}
10805
10806static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10807{
10808 ext2_filsys fs = ctx->fs;
10809 errcode_t retval;
10810 struct ext2_inode inode;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010811 char *dir_buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010812 struct fill_dir_struct fd;
10813 struct out_dir outdir;
10814
10815 outdir.max = outdir.num = 0;
10816 outdir.buf = 0;
10817 outdir.hashes = 0;
10818 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10819
10820 retval = ENOMEM;
10821 fd.harray = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010822 dir_buf = xmalloc(inode.i_size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010823
10824 fd.max_array = inode.i_size / 32;
10825 fd.num_array = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010826 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010827
10828 fd.ctx = ctx;
10829 fd.buf = dir_buf;
10830 fd.inode = &inode;
10831 fd.err = 0;
10832 fd.dir_size = 0;
10833 fd.compress = 0;
10834 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10835 (inode.i_size / fs->blocksize) < 2)
10836 fd.compress = 1;
10837 fd.parent = 0;
10838
10839 /* Read in the entire directory into memory */
10840 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10841 fill_dir_block, &fd);
10842 if (fd.err) {
10843 retval = fd.err;
10844 goto errout;
10845 }
10846
10847 /* Sort the list */
10848resort:
10849 if (fd.compress)
10850 qsort(fd.harray+2, fd.num_array-2,
10851 sizeof(struct hash_entry), name_cmp);
10852 else
10853 qsort(fd.harray, fd.num_array,
10854 sizeof(struct hash_entry), hash_cmp);
10855
10856 /*
10857 * Look for duplicates
10858 */
10859 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10860 goto resort;
10861
10862 if (ctx->options & E2F_OPT_NO) {
10863 retval = 0;
10864 goto errout;
10865 }
10866
10867 /*
10868 * Copy the directory entries. In a htree directory these
10869 * will become the leaf nodes.
10870 */
10871 retval = copy_dir_entries(fs, &fd, &outdir);
10872 if (retval)
10873 goto errout;
10874
10875 free(dir_buf); dir_buf = 0;
10876
10877 if (!fd.compress) {
10878 /* Calculate the interior nodes */
10879 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10880 if (retval)
10881 goto errout;
10882 }
10883
10884 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10885
10886errout:
10887 free(dir_buf);
10888 free(fd.harray);
10889
10890 free_out_dir(&outdir);
10891 return retval;
10892}
10893
10894void e2fsck_rehash_directories(e2fsck_t ctx)
10895{
10896 struct problem_context pctx;
10897 struct dir_info *dir;
10898 ext2_u32_iterate iter;
10899 ext2_ino_t ino;
10900 errcode_t retval;
10901 int i, cur, max, all_dirs, dir_index, first = 1;
10902
10903 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10904
10905 if (!ctx->dirs_to_hash && !all_dirs)
10906 return;
10907
10908 e2fsck_get_lost_and_found(ctx, 0);
10909
10910 clear_problem_context(&pctx);
10911
10912 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10913 cur = 0;
10914 if (all_dirs) {
10915 i = 0;
10916 max = e2fsck_get_num_dirinfo(ctx);
10917 } else {
10918 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10919 &iter);
10920 if (retval) {
10921 pctx.errcode = retval;
10922 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10923 return;
10924 }
10925 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10926 }
10927 while (1) {
10928 if (all_dirs) {
10929 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10930 break;
10931 ino = dir->ino;
10932 } else {
10933 if (!ext2fs_u32_list_iterate(iter, &ino))
10934 break;
10935 }
10936 if (ino == ctx->lost_and_found)
10937 continue;
10938 pctx.dir = ino;
10939 if (first) {
10940 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10941 first = 0;
10942 }
10943 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10944 if (pctx.errcode) {
10945 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10946 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10947 }
10948 if (ctx->progress && !ctx->progress_fd)
10949 e2fsck_simple_progress(ctx, "Rebuilding directory",
10950 100.0 * (float) (++cur) / (float) max, ino);
10951 }
10952 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10953 if (!all_dirs)
10954 ext2fs_u32_list_iterate_end(iter);
10955
10956 ext2fs_u32_list_free(ctx->dirs_to_hash);
10957 ctx->dirs_to_hash = 0;
10958}
10959
10960/*
10961 * linux/fs/revoke.c
10962 *
10963 * Journal revoke routines for the generic filesystem journaling code;
10964 * part of the ext2fs journaling system.
10965 *
10966 * Revoke is the mechanism used to prevent old log records for deleted
10967 * metadata from being replayed on top of newer data using the same
10968 * blocks. The revoke mechanism is used in two separate places:
10969 *
10970 * + Commit: during commit we write the entire list of the current
10971 * transaction's revoked blocks to the journal
10972 *
10973 * + Recovery: during recovery we record the transaction ID of all
10974 * revoked blocks. If there are multiple revoke records in the log
10975 * for a single block, only the last one counts, and if there is a log
10976 * entry for a block beyond the last revoke, then that log entry still
10977 * gets replayed.
10978 *
10979 * We can get interactions between revokes and new log data within a
10980 * single transaction:
10981 *
10982 * Block is revoked and then journaled:
10983 * The desired end result is the journaling of the new block, so we
10984 * cancel the revoke before the transaction commits.
10985 *
10986 * Block is journaled and then revoked:
10987 * The revoke must take precedence over the write of the block, so we
10988 * need either to cancel the journal entry or to write the revoke
10989 * later in the log than the log block. In this case, we choose the
10990 * latter: journaling a block cancels any revoke record for that block
10991 * in the current transaction, so any revoke for that block in the
10992 * transaction must have happened after the block was journaled and so
10993 * the revoke must take precedence.
10994 *
10995 * Block is revoked and then written as data:
10996 * The data write is allowed to succeed, but the revoke is _not_
10997 * cancelled. We still need to prevent old log records from
10998 * overwriting the new data. We don't even need to clear the revoke
10999 * bit here.
11000 *
11001 * Revoke information on buffers is a tri-state value:
11002 *
11003 * RevokeValid clear: no cached revoke status, need to look it up
11004 * RevokeValid set, Revoked clear:
11005 * buffer has not been revoked, and cancel_revoke
11006 * need do nothing.
11007 * RevokeValid set, Revoked set:
11008 * buffer has been revoked.
11009 */
11010
11011static kmem_cache_t *revoke_record_cache;
11012static kmem_cache_t *revoke_table_cache;
11013
11014/* Each revoke record represents one single revoked block. During
11015 journal replay, this involves recording the transaction ID of the
11016 last transaction to revoke this block. */
11017
11018struct jbd_revoke_record_s
11019{
11020 struct list_head hash;
11021 tid_t sequence; /* Used for recovery only */
11022 unsigned long blocknr;
11023};
11024
11025
11026/* The revoke table is just a simple hash table of revoke records. */
11027struct jbd_revoke_table_s
11028{
11029 /* It is conceivable that we might want a larger hash table
11030 * for recovery. Must be a power of two. */
11031 int hash_size;
11032 int hash_shift;
11033 struct list_head *hash_table;
11034};
11035
11036
11037/* Utility functions to maintain the revoke table */
11038
11039/* Borrowed from buffer.c: this is a tried and tested block hash function */
11040static int hash(journal_t *journal, unsigned long block)
11041{
11042 struct jbd_revoke_table_s *table = journal->j_revoke;
11043 int hash_shift = table->hash_shift;
11044
11045 return ((block << (hash_shift - 6)) ^
11046 (block >> 13) ^
11047 (block << (hash_shift - 12))) & (table->hash_size - 1);
11048}
11049
11050static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11051 tid_t seq)
11052{
11053 struct list_head *hash_list;
11054 struct jbd_revoke_record_s *record;
11055
11056 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11057 if (!record)
11058 goto oom;
11059
11060 record->sequence = seq;
11061 record->blocknr = blocknr;
11062 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11063 list_add(&record->hash, hash_list);
11064 return 0;
11065
11066oom:
11067 return -ENOMEM;
11068}
11069
11070/* Find a revoke record in the journal's hash table. */
11071
11072static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11073 unsigned long blocknr)
11074{
11075 struct list_head *hash_list;
11076 struct jbd_revoke_record_s *record;
11077
11078 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11079
11080 record = (struct jbd_revoke_record_s *) hash_list->next;
11081 while (&(record->hash) != hash_list) {
11082 if (record->blocknr == blocknr)
11083 return record;
11084 record = (struct jbd_revoke_record_s *) record->hash.next;
11085 }
11086 return NULL;
11087}
11088
11089int journal_init_revoke_caches(void)
11090{
11091 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11092 if (revoke_record_cache == 0)
11093 return -ENOMEM;
11094
11095 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11096 if (revoke_table_cache == 0) {
11097 do_cache_destroy(revoke_record_cache);
11098 revoke_record_cache = NULL;
11099 return -ENOMEM;
11100 }
11101 return 0;
11102}
11103
11104void journal_destroy_revoke_caches(void)
11105{
11106 do_cache_destroy(revoke_record_cache);
11107 revoke_record_cache = 0;
11108 do_cache_destroy(revoke_table_cache);
11109 revoke_table_cache = 0;
11110}
11111
11112/* Initialise the revoke table for a given journal to a given size. */
11113
11114int journal_init_revoke(journal_t *journal, int hash_size)
11115{
11116 int shift, tmp;
11117
11118 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11119 if (!journal->j_revoke)
11120 return -ENOMEM;
11121
11122 /* Check that the hash_size is a power of two */
11123 journal->j_revoke->hash_size = hash_size;
11124
11125 shift = 0;
11126 tmp = hash_size;
Denis Vlasenkobb045062008-09-27 14:06:06 +000011127 while ((tmp >>= 1UL) != 0UL)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011128 shift++;
11129 journal->j_revoke->hash_shift = shift;
11130
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010011131 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011132
11133 for (tmp = 0; tmp < hash_size; tmp++)
11134 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11135
11136 return 0;
11137}
11138
11139/* Destoy a journal's revoke table. The table must already be empty! */
11140
11141void journal_destroy_revoke(journal_t *journal)
11142{
11143 struct jbd_revoke_table_s *table;
11144 struct list_head *hash_list;
11145 int i;
11146
11147 table = journal->j_revoke;
11148 if (!table)
11149 return;
11150
11151 for (i=0; i<table->hash_size; i++) {
11152 hash_list = &table->hash_table[i];
11153 }
11154
11155 free(table->hash_table);
11156 free(table);
11157 journal->j_revoke = NULL;
11158}
11159
11160/*
11161 * Revoke support for recovery.
11162 *
11163 * Recovery needs to be able to:
11164 *
11165 * record all revoke records, including the tid of the latest instance
11166 * of each revoke in the journal
11167 *
11168 * check whether a given block in a given transaction should be replayed
11169 * (ie. has not been revoked by a revoke record in that or a subsequent
11170 * transaction)
11171 *
11172 * empty the revoke table after recovery.
11173 */
11174
11175/*
11176 * First, setting revoke records. We create a new revoke record for
11177 * every block ever revoked in the log as we scan it for recovery, and
11178 * we update the existing records if we find multiple revokes for a
11179 * single block.
11180 */
11181
11182int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11183 tid_t sequence)
11184{
11185 struct jbd_revoke_record_s *record;
11186
11187 record = find_revoke_record(journal, blocknr);
11188 if (record) {
11189 /* If we have multiple occurences, only record the
11190 * latest sequence number in the hashed record */
11191 if (tid_gt(sequence, record->sequence))
11192 record->sequence = sequence;
11193 return 0;
11194 }
11195 return insert_revoke_hash(journal, blocknr, sequence);
11196}
11197
11198/*
11199 * Test revoke records. For a given block referenced in the log, has
11200 * that block been revoked? A revoke record with a given transaction
11201 * sequence number revokes all blocks in that transaction and earlier
11202 * ones, but later transactions still need replayed.
11203 */
11204
11205int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11206 tid_t sequence)
11207{
11208 struct jbd_revoke_record_s *record;
11209
11210 record = find_revoke_record(journal, blocknr);
11211 if (!record)
11212 return 0;
11213 if (tid_gt(sequence, record->sequence))
11214 return 0;
11215 return 1;
11216}
11217
11218/*
11219 * Finally, once recovery is over, we need to clear the revoke table so
11220 * that it can be reused by the running filesystem.
11221 */
11222
11223void journal_clear_revoke(journal_t *journal)
11224{
11225 int i;
11226 struct list_head *hash_list;
11227 struct jbd_revoke_record_s *record;
11228 struct jbd_revoke_table_s *revoke_var;
11229
11230 revoke_var = journal->j_revoke;
11231
11232 for (i = 0; i < revoke_var->hash_size; i++) {
11233 hash_list = &revoke_var->hash_table[i];
11234 while (!list_empty(hash_list)) {
11235 record = (struct jbd_revoke_record_s*) hash_list->next;
11236 list_del(&record->hash);
11237 free(record);
11238 }
11239 }
11240}
11241
11242/*
11243 * e2fsck.c - superblock checks
11244 */
11245
11246#define MIN_CHECK 1
11247#define MAX_CHECK 2
11248
11249static void check_super_value(e2fsck_t ctx, const char *descr,
11250 unsigned long value, int flags,
11251 unsigned long min_val, unsigned long max_val)
11252{
11253 struct problem_context pctx;
11254
11255 if (((flags & MIN_CHECK) && (value < min_val)) ||
11256 ((flags & MAX_CHECK) && (value > max_val))) {
11257 clear_problem_context(&pctx);
11258 pctx.num = value;
11259 pctx.str = descr;
11260 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11261 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11262 }
11263}
11264
11265/*
11266 * This routine may get stubbed out in special compilations of the
11267 * e2fsck code..
11268 */
11269#ifndef EXT2_SPECIAL_DEVICE_SIZE
11270static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11271{
11272 return (ext2fs_get_device_size(ctx->filesystem_name,
11273 EXT2_BLOCK_SIZE(ctx->fs->super),
11274 &ctx->num_blocks));
11275}
11276#endif
11277
11278/*
11279 * helper function to release an inode
11280 */
11281struct process_block_struct {
11282 e2fsck_t ctx;
11283 char *buf;
11284 struct problem_context *pctx;
11285 int truncating;
11286 int truncate_offset;
11287 e2_blkcnt_t truncate_block;
11288 int truncated_blocks;
11289 int abort;
11290 errcode_t errcode;
11291};
11292
11293static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11294 e2_blkcnt_t blockcnt,
11295 blk_t ref_blk FSCK_ATTR((unused)),
11296 int ref_offset FSCK_ATTR((unused)),
11297 void *priv_data)
11298{
11299 struct process_block_struct *pb;
11300 e2fsck_t ctx;
11301 struct problem_context *pctx;
11302 blk_t blk = *block_nr;
11303 int retval = 0;
11304
11305 pb = (struct process_block_struct *) priv_data;
11306 ctx = pb->ctx;
11307 pctx = pb->pctx;
11308
11309 pctx->blk = blk;
11310 pctx->blkcount = blockcnt;
11311
11312 if (HOLE_BLKADDR(blk))
11313 return 0;
11314
11315 if ((blk < fs->super->s_first_data_block) ||
11316 (blk >= fs->super->s_blocks_count)) {
11317 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011318 return_abort:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011319 pb->abort = 1;
11320 return BLOCK_ABORT;
11321 }
11322
11323 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11324 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11325 goto return_abort;
11326 }
11327
11328 /*
11329 * If we are deleting an orphan, then we leave the fields alone.
11330 * If we are truncating an orphan, then update the inode fields
11331 * and clean up any partial block data.
11332 */
11333 if (pb->truncating) {
11334 /*
11335 * We only remove indirect blocks if they are
11336 * completely empty.
11337 */
11338 if (blockcnt < 0) {
11339 int i, limit;
11340 blk_t *bp;
11341
11342 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11343 pb->buf);
11344 if (pb->errcode)
11345 goto return_abort;
11346
11347 limit = fs->blocksize >> 2;
11348 for (i = 0, bp = (blk_t *) pb->buf;
11349 i < limit; i++, bp++)
11350 if (*bp)
11351 return 0;
11352 }
11353 /*
11354 * We don't remove direct blocks until we've reached
11355 * the truncation block.
11356 */
11357 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11358 return 0;
11359 /*
11360 * If part of the last block needs truncating, we do
11361 * it here.
11362 */
11363 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11364 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11365 pb->buf);
11366 if (pb->errcode)
11367 goto return_abort;
11368 memset(pb->buf + pb->truncate_offset, 0,
11369 fs->blocksize - pb->truncate_offset);
11370 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11371 pb->buf);
11372 if (pb->errcode)
11373 goto return_abort;
11374 }
11375 pb->truncated_blocks++;
11376 *block_nr = 0;
11377 retval |= BLOCK_CHANGED;
11378 }
11379
11380 ext2fs_block_alloc_stats(fs, blk, -1);
11381 return retval;
11382}
11383
11384/*
11385 * This function releases an inode. Returns 1 if an inconsistency was
11386 * found. If the inode has a link count, then it is being truncated and
11387 * not deleted.
11388 */
11389static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11390 struct ext2_inode *inode, char *block_buf,
11391 struct problem_context *pctx)
11392{
11393 struct process_block_struct pb;
11394 ext2_filsys fs = ctx->fs;
11395 errcode_t retval;
11396 __u32 count;
11397
11398 if (!ext2fs_inode_has_valid_blocks(inode))
11399 return 0;
11400
11401 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11402 pb.ctx = ctx;
11403 pb.abort = 0;
11404 pb.errcode = 0;
11405 pb.pctx = pctx;
11406 if (inode->i_links_count) {
11407 pb.truncating = 1;
11408 pb.truncate_block = (e2_blkcnt_t)
11409 ((((long long)inode->i_size_high << 32) +
11410 inode->i_size + fs->blocksize - 1) /
11411 fs->blocksize);
11412 pb.truncate_offset = inode->i_size % fs->blocksize;
11413 } else {
11414 pb.truncating = 0;
11415 pb.truncate_block = 0;
11416 pb.truncate_offset = 0;
11417 }
11418 pb.truncated_blocks = 0;
11419 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11420 block_buf, release_inode_block, &pb);
11421 if (retval) {
11422 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11423 ino);
11424 return 1;
11425 }
11426 if (pb.abort)
11427 return 1;
11428
11429 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11430 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11431
11432 if (pb.truncated_blocks)
11433 inode->i_blocks -= pb.truncated_blocks *
11434 (fs->blocksize / 512);
11435
11436 if (inode->i_file_acl) {
11437 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11438 block_buf, -1, &count);
11439 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11440 retval = 0;
11441 count = 1;
11442 }
11443 if (retval) {
11444 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11445 ino);
11446 return 1;
11447 }
11448 if (count == 0)
11449 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11450 inode->i_file_acl = 0;
11451 }
11452 return 0;
11453}
11454
11455/*
11456 * This function releases all of the orphan inodes. It returns 1 if
11457 * it hit some error, and 0 on success.
11458 */
11459static int release_orphan_inodes(e2fsck_t ctx)
11460{
11461 ext2_filsys fs = ctx->fs;
11462 ext2_ino_t ino, next_ino;
11463 struct ext2_inode inode;
11464 struct problem_context pctx;
11465 char *block_buf;
11466
11467 if ((ino = fs->super->s_last_orphan) == 0)
11468 return 0;
11469
11470 /*
11471 * Win or lose, we won't be using the head of the orphan inode
11472 * list again.
11473 */
11474 fs->super->s_last_orphan = 0;
11475 ext2fs_mark_super_dirty(fs);
11476
11477 /*
11478 * If the filesystem contains errors, don't run the orphan
11479 * list, since the orphan list can't be trusted; and we're
11480 * going to be running a full e2fsck run anyway...
11481 */
11482 if (fs->super->s_state & EXT2_ERROR_FS)
11483 return 0;
11484
11485 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11486 (ino > fs->super->s_inodes_count)) {
11487 clear_problem_context(&pctx);
11488 pctx.ino = ino;
11489 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11490 return 1;
11491 }
11492
11493 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11494 "block iterate buffer");
11495 e2fsck_read_bitmaps(ctx);
11496
11497 while (ino) {
11498 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11499 clear_problem_context(&pctx);
11500 pctx.ino = ino;
11501 pctx.inode = &inode;
11502 pctx.str = inode.i_links_count ? _("Truncating") :
11503 _("Clearing");
11504
11505 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11506
11507 next_ino = inode.i_dtime;
11508 if (next_ino &&
11509 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11510 (next_ino > fs->super->s_inodes_count))) {
11511 pctx.ino = next_ino;
11512 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11513 goto return_abort;
11514 }
11515
11516 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11517 goto return_abort;
11518
11519 if (!inode.i_links_count) {
11520 ext2fs_inode_alloc_stats2(fs, ino, -1,
11521 LINUX_S_ISDIR(inode.i_mode));
Denis Vlasenko04158e02009-02-02 10:48:06 +000011522 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011523 } else {
11524 inode.i_dtime = 0;
11525 }
11526 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11527 ino = next_ino;
11528 }
11529 ext2fs_free_mem(&block_buf);
11530 return 0;
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011531 return_abort:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011532 ext2fs_free_mem(&block_buf);
11533 return 1;
11534}
11535
11536/*
11537 * Check the resize inode to make sure it is sane. We check both for
11538 * the case where on-line resizing is not enabled (in which case the
11539 * resize inode should be cleared) as well as the case where on-line
11540 * resizing is enabled.
11541 */
11542static void check_resize_inode(e2fsck_t ctx)
11543{
11544 ext2_filsys fs = ctx->fs;
11545 struct ext2_inode inode;
11546 struct problem_context pctx;
11547 int i, j, gdt_off, ind_off;
11548 blk_t blk, pblk, expect;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010011549 __u32 *dind_buf = NULL, *ind_buf;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011550 errcode_t retval;
11551
11552 clear_problem_context(&pctx);
11553
11554 /*
11555 * If the resize inode feature isn't set, then
11556 * s_reserved_gdt_blocks must be zero.
11557 */
11558 if (!(fs->super->s_feature_compat &
11559 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11560 if (fs->super->s_reserved_gdt_blocks) {
11561 pctx.num = fs->super->s_reserved_gdt_blocks;
11562 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11563 &pctx)) {
11564 fs->super->s_reserved_gdt_blocks = 0;
11565 ext2fs_mark_super_dirty(fs);
11566 }
11567 }
11568 }
11569
11570 /* Read the resize inode */
11571 pctx.ino = EXT2_RESIZE_INO;
11572 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11573 if (retval) {
11574 if (fs->super->s_feature_compat &
11575 EXT2_FEATURE_COMPAT_RESIZE_INODE)
11576 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11577 return;
11578 }
11579
11580 /*
11581 * If the resize inode feature isn't set, check to make sure
11582 * the resize inode is cleared; then we're done.
11583 */
11584 if (!(fs->super->s_feature_compat &
11585 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11586 for (i=0; i < EXT2_N_BLOCKS; i++) {
11587 if (inode.i_block[i])
11588 break;
11589 }
11590 if ((i < EXT2_N_BLOCKS) &&
11591 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11592 memset(&inode, 0, sizeof(inode));
11593 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11594 "clear_resize");
11595 }
11596 return;
11597 }
11598
11599 /*
11600 * The resize inode feature is enabled; check to make sure the
11601 * only block in use is the double indirect block
11602 */
11603 blk = inode.i_block[EXT2_DIND_BLOCK];
11604 for (i=0; i < EXT2_N_BLOCKS; i++) {
11605 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11606 break;
11607 }
11608 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11609 !(inode.i_mode & LINUX_S_IFREG) ||
11610 (blk < fs->super->s_first_data_block ||
11611 blk >= fs->super->s_blocks_count)) {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011612 resize_inode_invalid:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011613 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11614 memset(&inode, 0, sizeof(inode));
11615 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11616 "clear_resize");
11617 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11618 }
11619 if (!(ctx->options & E2F_OPT_READONLY)) {
11620 fs->super->s_state &= ~EXT2_VALID_FS;
11621 ext2fs_mark_super_dirty(fs);
11622 }
11623 goto cleanup;
11624 }
11625 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11626 "resize dind buffer");
11627 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11628
11629 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11630 if (retval)
11631 goto resize_inode_invalid;
11632
11633 gdt_off = fs->desc_blocks;
11634 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11635 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11636 i++, gdt_off++, pblk++) {
11637 gdt_off %= fs->blocksize/4;
11638 if (dind_buf[gdt_off] != pblk)
11639 goto resize_inode_invalid;
11640 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11641 if (retval)
11642 goto resize_inode_invalid;
11643 ind_off = 0;
11644 for (j = 1; j < fs->group_desc_count; j++) {
11645 if (!ext2fs_bg_has_super(fs, j))
11646 continue;
11647 expect = pblk + (j * fs->super->s_blocks_per_group);
11648 if (ind_buf[ind_off] != expect)
11649 goto resize_inode_invalid;
11650 ind_off++;
11651 }
11652 }
11653
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011654 cleanup:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011655 ext2fs_free_mem(&dind_buf);
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011656}
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011657
11658static void check_super_block(e2fsck_t ctx)
11659{
11660 ext2_filsys fs = ctx->fs;
11661 blk_t first_block, last_block;
11662 struct ext2_super_block *sb = fs->super;
11663 struct ext2_group_desc *gd;
11664 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11665 blk_t bpg_max;
11666 int inodes_per_block;
11667 int ipg_max;
11668 int inode_size;
11669 dgrp_t i;
11670 blk_t should_be;
11671 struct problem_context pctx;
11672 __u32 free_blocks = 0, free_inodes = 0;
11673
11674 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11675 ipg_max = inodes_per_block * (blocks_per_group - 4);
11676 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11677 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11678 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11679 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11680 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11681
11682 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11683 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11684 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11685 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11686 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11687 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11688
11689 clear_problem_context(&pctx);
11690
11691 /*
11692 * Verify the super block constants...
11693 */
11694 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11695 MIN_CHECK, 1, 0);
11696 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11697 MIN_CHECK, 1, 0);
11698 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11699 MAX_CHECK, 0, sb->s_blocks_count);
11700 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11701 MIN_CHECK | MAX_CHECK, 0,
11702 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11703 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11704 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11705 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11706 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11707 bpg_max);
11708 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11709 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11710 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11711 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11712 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11713 MAX_CHECK, 0, sb->s_blocks_count / 2);
11714 check_super_value(ctx, "reserved_gdt_blocks",
11715 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11716 fs->blocksize/4);
11717 inode_size = EXT2_INODE_SIZE(sb);
11718 check_super_value(ctx, "inode_size",
11719 inode_size, MIN_CHECK | MAX_CHECK,
11720 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11721 if (inode_size & (inode_size - 1)) {
11722 pctx.num = inode_size;
11723 pctx.str = "inode_size";
11724 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11725 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11726 return;
11727 }
11728
11729 if (!ctx->num_blocks) {
11730 pctx.errcode = e2fsck_get_device_size(ctx);
11731 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11732 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11733 ctx->flags |= E2F_FLAG_ABORT;
11734 return;
11735 }
11736 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11737 (ctx->num_blocks < sb->s_blocks_count)) {
11738 pctx.blk = sb->s_blocks_count;
11739 pctx.blk2 = ctx->num_blocks;
11740 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11741 ctx->flags |= E2F_FLAG_ABORT;
11742 return;
11743 }
11744 }
11745 }
11746
11747 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11748 pctx.blk = EXT2_BLOCK_SIZE(sb);
11749 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11750 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11751 ctx->flags |= E2F_FLAG_ABORT;
11752 return;
11753 }
11754
11755 should_be = sb->s_frags_per_group >>
11756 (sb->s_log_block_size - sb->s_log_frag_size);
11757 if (sb->s_blocks_per_group != should_be) {
11758 pctx.blk = sb->s_blocks_per_group;
11759 pctx.blk2 = should_be;
11760 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11761 ctx->flags |= E2F_FLAG_ABORT;
11762 return;
11763 }
11764
11765 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11766 if (sb->s_first_data_block != should_be) {
11767 pctx.blk = sb->s_first_data_block;
11768 pctx.blk2 = should_be;
11769 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11770 ctx->flags |= E2F_FLAG_ABORT;
11771 return;
11772 }
11773
11774 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11775 if (sb->s_inodes_count != should_be) {
11776 pctx.ino = sb->s_inodes_count;
11777 pctx.ino2 = should_be;
11778 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11779 sb->s_inodes_count = should_be;
11780 ext2fs_mark_super_dirty(fs);
11781 }
11782 }
11783
11784 /*
11785 * Verify the group descriptors....
11786 */
11787 first_block = sb->s_first_data_block;
11788 last_block = first_block + blocks_per_group;
11789
11790 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11791 pctx.group = i;
11792
11793 if (i == fs->group_desc_count - 1)
11794 last_block = sb->s_blocks_count;
11795 if ((gd->bg_block_bitmap < first_block) ||
11796 (gd->bg_block_bitmap >= last_block)) {
11797 pctx.blk = gd->bg_block_bitmap;
11798 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11799 gd->bg_block_bitmap = 0;
11800 }
11801 if (gd->bg_block_bitmap == 0) {
11802 ctx->invalid_block_bitmap_flag[i]++;
11803 ctx->invalid_bitmaps++;
11804 }
11805 if ((gd->bg_inode_bitmap < first_block) ||
11806 (gd->bg_inode_bitmap >= last_block)) {
11807 pctx.blk = gd->bg_inode_bitmap;
11808 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11809 gd->bg_inode_bitmap = 0;
11810 }
11811 if (gd->bg_inode_bitmap == 0) {
11812 ctx->invalid_inode_bitmap_flag[i]++;
11813 ctx->invalid_bitmaps++;
11814 }
11815 if ((gd->bg_inode_table < first_block) ||
11816 ((gd->bg_inode_table +
11817 fs->inode_blocks_per_group - 1) >= last_block)) {
11818 pctx.blk = gd->bg_inode_table;
11819 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11820 gd->bg_inode_table = 0;
11821 }
11822 if (gd->bg_inode_table == 0) {
11823 ctx->invalid_inode_table_flag[i]++;
11824 ctx->invalid_bitmaps++;
11825 }
11826 free_blocks += gd->bg_free_blocks_count;
11827 free_inodes += gd->bg_free_inodes_count;
11828 first_block += sb->s_blocks_per_group;
11829 last_block += sb->s_blocks_per_group;
11830
11831 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11832 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11833 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11834 ext2fs_unmark_valid(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011835 }
11836
11837 /*
11838 * Update the global counts from the block group counts. This
11839 * is needed for an experimental patch which eliminates
11840 * locking the entire filesystem when allocating blocks or
11841 * inodes; if the filesystem is not unmounted cleanly, the
11842 * global counts may not be accurate.
11843 */
11844 if ((free_blocks != sb->s_free_blocks_count) ||
11845 (free_inodes != sb->s_free_inodes_count)) {
11846 if (ctx->options & E2F_OPT_READONLY)
11847 ext2fs_unmark_valid(fs);
11848 else {
11849 sb->s_free_blocks_count = free_blocks;
11850 sb->s_free_inodes_count = free_inodes;
11851 ext2fs_mark_super_dirty(fs);
11852 }
11853 }
11854
11855 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11856 (sb->s_free_inodes_count > sb->s_inodes_count))
11857 ext2fs_unmark_valid(fs);
11858
11859
11860 /*
11861 * If we have invalid bitmaps, set the error state of the
11862 * filesystem.
11863 */
11864 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11865 sb->s_state &= ~EXT2_VALID_FS;
11866 ext2fs_mark_super_dirty(fs);
11867 }
11868
11869 clear_problem_context(&pctx);
11870
11871 /*
11872 * If the UUID field isn't assigned, assign it.
11873 */
11874 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11875 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11876 uuid_generate(sb->s_uuid);
11877 ext2fs_mark_super_dirty(fs);
11878 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11879 }
11880 }
11881
11882 /* FIXME - HURD support?
11883 * For the Hurd, check to see if the filetype option is set,
11884 * since it doesn't support it.
11885 */
11886 if (!(ctx->options & E2F_OPT_READONLY) &&
11887 fs->super->s_creator_os == EXT2_OS_HURD &&
11888 (fs->super->s_feature_incompat &
11889 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11890 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11891 fs->super->s_feature_incompat &=
11892 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11893 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011894 }
11895 }
11896
11897 /*
11898 * If we have any of the compatibility flags set, we need to have a
11899 * revision 1 filesystem. Most kernels will not check the flags on
11900 * a rev 0 filesystem and we may have corruption issues because of
11901 * the incompatible changes to the filesystem.
11902 */
11903 if (!(ctx->options & E2F_OPT_READONLY) &&
11904 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11905 (fs->super->s_feature_compat ||
11906 fs->super->s_feature_ro_compat ||
11907 fs->super->s_feature_incompat) &&
11908 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11909 ext2fs_update_dynamic_rev(fs);
11910 ext2fs_mark_super_dirty(fs);
11911 }
11912
11913 check_resize_inode(ctx);
11914
11915 /*
11916 * Clean up any orphan inodes, if present.
11917 */
11918 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11919 fs->super->s_state &= ~EXT2_VALID_FS;
11920 ext2fs_mark_super_dirty(fs);
11921 }
11922
11923 /*
11924 * Move the ext3 journal file, if necessary.
11925 */
11926 e2fsck_move_ext3_journal(ctx);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011927}
11928
11929/*
11930 * swapfs.c --- byte-swap an ext2 filesystem
11931 */
11932
11933#ifdef ENABLE_SWAPFS
11934
11935struct swap_block_struct {
11936 ext2_ino_t ino;
11937 int isdir;
11938 errcode_t errcode;
11939 char *dir_buf;
11940 struct ext2_inode *inode;
11941};
11942
11943/*
11944 * This is a helper function for block_iterate. We mark all of the
11945 * indirect and direct blocks as changed, so that block_iterate will
11946 * write them out.
11947 */
11948static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11949 void *priv_data)
11950{
11951 errcode_t retval;
11952
11953 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11954
11955 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11956 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11957 if (retval) {
11958 sb->errcode = retval;
11959 return BLOCK_ABORT;
11960 }
11961 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11962 if (retval) {
11963 sb->errcode = retval;
11964 return BLOCK_ABORT;
11965 }
11966 }
11967 if (blockcnt >= 0) {
11968 if (blockcnt < EXT2_NDIR_BLOCKS)
11969 return 0;
11970 return BLOCK_CHANGED;
11971 }
11972 if (blockcnt == BLOCK_COUNT_IND) {
11973 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11974 return 0;
11975 return BLOCK_CHANGED;
11976 }
11977 if (blockcnt == BLOCK_COUNT_DIND) {
11978 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11979 return 0;
11980 return BLOCK_CHANGED;
11981 }
11982 if (blockcnt == BLOCK_COUNT_TIND) {
11983 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
11984 return 0;
11985 return BLOCK_CHANGED;
11986 }
11987 return BLOCK_CHANGED;
11988}
11989
11990/*
11991 * This function is responsible for byte-swapping all of the indirect,
11992 * block pointers. It is also responsible for byte-swapping directories.
11993 */
11994static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
11995 struct ext2_inode *inode)
11996{
11997 errcode_t retval;
11998 struct swap_block_struct sb;
11999
12000 sb.ino = ino;
12001 sb.inode = inode;
12002 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12003 sb.errcode = 0;
12004 sb.isdir = 0;
12005 if (LINUX_S_ISDIR(inode->i_mode))
12006 sb.isdir = 1;
12007
12008 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12009 swap_block, &sb);
12010 if (retval) {
12011 bb_error_msg(_("while calling ext2fs_block_iterate"));
12012 ctx->flags |= E2F_FLAG_ABORT;
12013 return;
12014 }
12015 if (sb.errcode) {
12016 bb_error_msg(_("while calling iterator function"));
12017 ctx->flags |= E2F_FLAG_ABORT;
12018 return;
12019 }
12020}
12021
12022static void swap_inodes(e2fsck_t ctx)
12023{
12024 ext2_filsys fs = ctx->fs;
12025 dgrp_t group;
12026 unsigned int i;
12027 ext2_ino_t ino = 1;
12028 char *buf, *block_buf;
12029 errcode_t retval;
12030 struct ext2_inode * inode;
12031
12032 e2fsck_use_inode_shortcuts(ctx, 1);
12033
12034 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12035 &buf);
12036 if (retval) {
12037 bb_error_msg(_("while allocating inode buffer"));
12038 ctx->flags |= E2F_FLAG_ABORT;
12039 return;
12040 }
12041 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12042 "block interate buffer");
12043 for (group = 0; group < fs->group_desc_count; group++) {
12044 retval = io_channel_read_blk(fs->io,
12045 fs->group_desc[group].bg_inode_table,
12046 fs->inode_blocks_per_group, buf);
12047 if (retval) {
12048 bb_error_msg(_("while reading inode table (group %d)"),
12049 group);
12050 ctx->flags |= E2F_FLAG_ABORT;
12051 return;
12052 }
12053 inode = (struct ext2_inode *) buf;
12054 for (i=0; i < fs->super->s_inodes_per_group;
12055 i++, ino++, inode++) {
12056 ctx->stashed_ino = ino;
12057 ctx->stashed_inode = inode;
12058
12059 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12060 ext2fs_swap_inode(fs, inode, inode, 0);
12061
12062 /*
12063 * Skip deleted files.
12064 */
12065 if (inode->i_links_count == 0)
12066 continue;
12067
12068 if (LINUX_S_ISDIR(inode->i_mode) ||
12069 ((inode->i_block[EXT2_IND_BLOCK] ||
12070 inode->i_block[EXT2_DIND_BLOCK] ||
12071 inode->i_block[EXT2_TIND_BLOCK]) &&
12072 ext2fs_inode_has_valid_blocks(inode)))
12073 swap_inode_blocks(ctx, ino, block_buf, inode);
12074
12075 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12076 return;
12077
12078 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12079 ext2fs_swap_inode(fs, inode, inode, 1);
12080 }
12081 retval = io_channel_write_blk(fs->io,
12082 fs->group_desc[group].bg_inode_table,
12083 fs->inode_blocks_per_group, buf);
12084 if (retval) {
12085 bb_error_msg(_("while writing inode table (group %d)"),
12086 group);
12087 ctx->flags |= E2F_FLAG_ABORT;
12088 return;
12089 }
12090 }
12091 ext2fs_free_mem(&buf);
12092 ext2fs_free_mem(&block_buf);
12093 e2fsck_use_inode_shortcuts(ctx, 0);
12094 ext2fs_flush_icache(fs);
12095}
12096
12097#if defined(__powerpc__) && BB_BIG_ENDIAN
12098/*
12099 * On the PowerPC, the big-endian variant of the ext2 filesystem
12100 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12101 * of each word. Thus a bitmap with only bit 0 set would be, as
12102 * a string of bytes, 00 00 00 01 00 ...
12103 * To cope with this, we byte-reverse each word of a bitmap if
12104 * we have a big-endian filesystem, that is, if we are *not*
12105 * byte-swapping other word-sized numbers.
12106 */
12107#define EXT2_BIG_ENDIAN_BITMAPS
12108#endif
12109
12110#ifdef EXT2_BIG_ENDIAN_BITMAPS
12111static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12112{
12113 __u32 *p = (__u32 *) bmap->bitmap;
12114 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12115
12116 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12117 *p = ext2fs_swab32(*p);
12118}
12119#endif
12120
12121
12122#ifdef ENABLE_SWAPFS
12123static void swap_filesys(e2fsck_t ctx)
12124{
12125 ext2_filsys fs = ctx->fs;
12126 if (!(ctx->options & E2F_OPT_PREEN))
12127 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12128
12129 /* Byte swap */
12130
12131 if (fs->super->s_mnt_count) {
12132 fprintf(stderr, _("%s: the filesystem must be freshly "
12133 "checked using fsck\n"
12134 "and not mounted before trying to "
12135 "byte-swap it.\n"), ctx->device_name);
12136 ctx->flags |= E2F_FLAG_ABORT;
12137 return;
12138 }
12139 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12140 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12141 EXT2_FLAG_SWAP_BYTES_WRITE);
12142 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12143 } else {
12144 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12145 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12146 }
12147 swap_inodes(ctx);
12148 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12149 return;
12150 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12151 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12152 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12153 EXT2_FLAG_SWAP_BYTES_WRITE);
12154
12155#ifdef EXT2_BIG_ENDIAN_BITMAPS
12156 e2fsck_read_bitmaps(ctx);
12157 ext2fs_swap_bitmap(fs->inode_map);
12158 ext2fs_swap_bitmap(fs->block_map);
12159 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12160#endif
12161 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12162 ext2fs_flush(fs);
12163 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12164}
12165#endif /* ENABLE_SWAPFS */
12166
12167#endif
12168
12169/*
12170 * util.c --- miscellaneous utilities
12171 */
12172
12173
12174void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12175 const char *description)
12176{
12177 void *ret;
12178 char buf[256];
12179
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012180 ret = xzalloc(size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012181 return ret;
12182}
12183
12184static char *string_copy(const char *str, int len)
12185{
12186 char *ret;
12187
12188 if (!str)
12189 return NULL;
12190 if (!len)
12191 len = strlen(str);
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012192 ret = xmalloc(len+1);
12193 strncpy(ret, str, len);
12194 ret[len] = 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012195 return ret;
12196}
12197
12198#ifndef HAVE_CONIO_H
12199static int read_a_char(void)
12200{
12201 char c;
12202 int r;
12203 int fail = 0;
12204
Denis Vlasenkobb045062008-09-27 14:06:06 +000012205 while (1) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012206 if (e2fsck_global_ctx &&
12207 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12208 return 3;
12209 }
12210 r = read(0, &c, 1);
12211 if (r == 1)
12212 return c;
12213 if (fail++ > 100)
12214 break;
12215 }
12216 return EOF;
12217}
12218#endif
12219
12220static int ask_yn(const char * string, int def)
12221{
12222 int c;
12223 const char *defstr;
12224 static const char short_yes[] = "yY";
12225 static const char short_no[] = "nN";
12226
12227#ifdef HAVE_TERMIOS_H
12228 struct termios termios, tmp;
12229
12230 tcgetattr (0, &termios);
12231 tmp = termios;
12232 tmp.c_lflag &= ~(ICANON | ECHO);
12233 tmp.c_cc[VMIN] = 1;
12234 tmp.c_cc[VTIME] = 0;
Denis Vlasenko202ac502008-11-05 13:20:58 +000012235 tcsetattr_stdin_TCSANOW(&tmp);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012236#endif
12237
12238 if (def == 1)
12239 defstr = "<y>";
12240 else if (def == 0)
12241 defstr = "<n>";
12242 else
12243 defstr = " (y/n)";
12244 printf("%s%s? ", string, defstr);
12245 while (1) {
12246 fflush (stdout);
12247 if ((c = read_a_char()) == EOF)
12248 break;
12249 if (c == 3) {
12250#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012251 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012252#endif
12253 if (e2fsck_global_ctx &&
12254 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12255 puts("\n");
12256 longjmp(e2fsck_global_ctx->abort_loc, 1);
12257 }
12258 puts(_("cancelled!\n"));
12259 return 0;
12260 }
12261 if (strchr(short_yes, (char) c)) {
12262 def = 1;
12263 break;
12264 }
12265 else if (strchr(short_no, (char) c)) {
12266 def = 0;
12267 break;
12268 }
12269 else if ((c == ' ' || c == '\n') && (def != -1))
12270 break;
12271 }
12272 if (def)
12273 puts("yes\n");
12274 else
12275 puts ("no\n");
12276#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012277 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012278#endif
12279 return def;
12280}
12281
12282int ask (e2fsck_t ctx, const char * string, int def)
12283{
12284 if (ctx->options & E2F_OPT_NO) {
12285 printf(_("%s? no\n\n"), string);
12286 return 0;
12287 }
12288 if (ctx->options & E2F_OPT_YES) {
12289 printf(_("%s? yes\n\n"), string);
12290 return 1;
12291 }
12292 if (ctx->options & E2F_OPT_PREEN) {
12293 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12294 return def;
12295 }
12296 return ask_yn(string, def);
12297}
12298
12299void e2fsck_read_bitmaps(e2fsck_t ctx)
12300{
12301 ext2_filsys fs = ctx->fs;
12302 errcode_t retval;
12303
12304 if (ctx->invalid_bitmaps) {
12305 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12306 ctx->device_name);
12307 bb_error_msg_and_die(0);
12308 }
12309
12310 ehandler_operation(_("reading inode and block bitmaps"));
12311 retval = ext2fs_read_bitmaps(fs);
12312 ehandler_operation(0);
12313 if (retval) {
12314 bb_error_msg(_("while retrying to read bitmaps for %s"),
12315 ctx->device_name);
12316 bb_error_msg_and_die(0);
12317 }
12318}
12319
12320static void e2fsck_write_bitmaps(e2fsck_t ctx)
12321{
12322 ext2_filsys fs = ctx->fs;
12323 errcode_t retval;
12324
12325 if (ext2fs_test_bb_dirty(fs)) {
12326 ehandler_operation(_("writing block bitmaps"));
12327 retval = ext2fs_write_block_bitmap(fs);
12328 ehandler_operation(0);
12329 if (retval) {
12330 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12331 ctx->device_name);
12332 bb_error_msg_and_die(0);
12333 }
12334 }
12335
12336 if (ext2fs_test_ib_dirty(fs)) {
12337 ehandler_operation(_("writing inode bitmaps"));
12338 retval = ext2fs_write_inode_bitmap(fs);
12339 ehandler_operation(0);
12340 if (retval) {
12341 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12342 ctx->device_name);
12343 bb_error_msg_and_die(0);
12344 }
12345 }
12346}
12347
12348void preenhalt(e2fsck_t ctx)
12349{
12350 ext2_filsys fs = ctx->fs;
12351
12352 if (!(ctx->options & E2F_OPT_PREEN))
12353 return;
12354 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12355 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12356 ctx->device_name);
12357 if (fs != NULL) {
12358 fs->super->s_state |= EXT2_ERROR_FS;
12359 ext2fs_mark_super_dirty(fs);
12360 ext2fs_close(fs);
12361 }
12362 exit(EXIT_UNCORRECTED);
12363}
12364
12365void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12366 struct ext2_inode * inode, const char *proc)
12367{
12368 int retval;
12369
12370 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12371 if (retval) {
12372 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12373 bb_error_msg_and_die(0);
12374 }
12375}
12376
12377extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12378 struct ext2_inode * inode, int bufsize,
12379 const char *proc)
12380{
12381 int retval;
12382
12383 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12384 if (retval) {
12385 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12386 bb_error_msg_and_die(0);
12387 }
12388}
12389
12390extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12391 struct ext2_inode * inode, const char *proc)
12392{
12393 int retval;
12394
12395 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12396 if (retval) {
12397 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12398 bb_error_msg_and_die(0);
12399 }
12400}
12401
12402blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12403 io_manager manager)
12404{
12405 struct ext2_super_block *sb;
12406 io_channel io = NULL;
12407 void *buf = NULL;
12408 int blocksize;
12409 blk_t superblock, ret_sb = 8193;
12410
12411 if (fs && fs->super) {
12412 ret_sb = (fs->super->s_blocks_per_group +
12413 fs->super->s_first_data_block);
12414 if (ctx) {
12415 ctx->superblock = ret_sb;
12416 ctx->blocksize = fs->blocksize;
12417 }
12418 return ret_sb;
12419 }
12420
12421 if (ctx) {
12422 if (ctx->blocksize) {
12423 ret_sb = ctx->blocksize * 8;
12424 if (ctx->blocksize == 1024)
12425 ret_sb++;
12426 ctx->superblock = ret_sb;
12427 return ret_sb;
12428 }
12429 ctx->superblock = ret_sb;
12430 ctx->blocksize = 1024;
12431 }
12432
12433 if (!name || !manager)
12434 goto cleanup;
12435
12436 if (manager->open(name, 0, &io) != 0)
12437 goto cleanup;
12438
12439 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12440 goto cleanup;
12441 sb = (struct ext2_super_block *) buf;
12442
12443 for (blocksize = EXT2_MIN_BLOCK_SIZE;
Denis Vlasenkob71c6682007-07-21 15:08:09 +000012444 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012445 superblock = blocksize*8;
12446 if (blocksize == 1024)
12447 superblock++;
12448 io_channel_set_blksize(io, blocksize);
12449 if (io_channel_read_blk(io, superblock,
12450 -SUPERBLOCK_SIZE, buf))
12451 continue;
12452#if BB_BIG_ENDIAN
12453 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12454 ext2fs_swap_super(sb);
12455#endif
12456 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12457 ret_sb = superblock;
12458 if (ctx) {
12459 ctx->superblock = superblock;
12460 ctx->blocksize = blocksize;
12461 }
12462 break;
12463 }
12464 }
12465
12466cleanup:
12467 if (io)
12468 io_channel_close(io);
12469 ext2fs_free_mem(&buf);
12470 return ret_sb;
12471}
12472
12473
12474/*
12475 * This function runs through the e2fsck passes and calls them all,
12476 * returning restart, abort, or cancel as necessary...
12477 */
12478typedef void (*pass_t)(e2fsck_t ctx);
12479
12480static const pass_t e2fsck_passes[] = {
12481 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12482 e2fsck_pass5, 0 };
12483
12484#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12485
12486static int e2fsck_run(e2fsck_t ctx)
12487{
12488 int i;
12489 pass_t e2fsck_pass;
12490
12491 if (setjmp(ctx->abort_loc)) {
12492 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12493 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12494 }
12495 ctx->flags |= E2F_FLAG_SETJMP_OK;
12496
12497 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12498 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12499 break;
12500 e2fsck_pass(ctx);
12501 if (ctx->progress)
12502 (void) (ctx->progress)(ctx, 0, 0, 0);
12503 }
12504 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12505
12506 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12507 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12508 return 0;
12509}
12510
12511
12512/*
12513 * unix.c - The unix-specific code for e2fsck
12514 */
12515
12516
12517/* Command line options */
12518static int swapfs;
12519#ifdef ENABLE_SWAPFS
12520static int normalize_swapfs;
12521#endif
12522static int cflag; /* check disk */
12523static int show_version_only;
12524static int verbose;
12525
12526#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12527
12528static void show_stats(e2fsck_t ctx)
12529{
12530 ext2_filsys fs = ctx->fs;
12531 int inodes, inodes_used, blocks, blocks_used;
12532 int dir_links;
12533 int num_files, num_links;
12534 int frag_percent;
12535
12536 dir_links = 2 * ctx->fs_directory_count - 1;
12537 num_files = ctx->fs_total_count - dir_links;
12538 num_links = ctx->fs_links_count - dir_links;
12539 inodes = fs->super->s_inodes_count;
12540 inodes_used = (fs->super->s_inodes_count -
12541 fs->super->s_free_inodes_count);
12542 blocks = fs->super->s_blocks_count;
12543 blocks_used = (fs->super->s_blocks_count -
12544 fs->super->s_free_blocks_count);
12545
12546 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12547 frag_percent = (frag_percent + 5) / 10;
12548
12549 if (!verbose) {
12550 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12551 ctx->device_name, inodes_used, inodes,
12552 frag_percent / 10, frag_percent % 10,
12553 blocks_used, blocks);
12554 return;
12555 }
12556 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12557 100 * inodes_used / inodes);
12558 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12559 P_E2("", "s", ctx->fs_fragmented),
12560 frag_percent / 10, frag_percent % 10);
12561 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12562 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12563 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12564 (int) ((long long) 100 * blocks_used / blocks));
12565 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12566 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12567 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12568 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12569 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12570 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12571 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12572 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12573 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12574 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12575 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12576}
12577
12578static void check_mount(e2fsck_t ctx)
12579{
12580 errcode_t retval;
12581 int cont;
12582
12583 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12584 &ctx->mount_flags);
12585 if (retval) {
Denis Vlasenko54d10052008-12-24 03:11:43 +000012586 bb_error_msg(_("while determining whether %s is mounted"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012587 ctx->filesystem_name);
12588 return;
12589 }
12590
12591 /*
12592 * If the filesystem isn't mounted, or it's the root filesystem
12593 * and it's mounted read-only, then everything's fine.
12594 */
12595 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12596 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12597 (ctx->mount_flags & EXT2_MF_READONLY)))
12598 return;
12599
12600 if (ctx->options & E2F_OPT_READONLY) {
12601 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12602 return;
12603 }
12604
12605 printf(_("%s is mounted. "), ctx->filesystem_name);
12606 if (!ctx->interactive)
Denys Vlasenko6331cf02009-11-13 09:08:27 +010012607 bb_error_msg_and_die(_("can't continue, aborting"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012608 printf(_("\n\n\007\007\007\007WARNING!!! "
12609 "Running e2fsck on a mounted filesystem may cause\n"
12610 "SEVERE filesystem damage.\007\007\007\n\n"));
12611 cont = ask_yn(_("Do you really want to continue"), -1);
12612 if (!cont) {
12613 printf(_("check aborted.\n"));
Denis Vlasenko6398cf42007-04-11 17:04:29 +000012614 exit(0);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012615 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012616}
12617
12618static int is_on_batt(void)
12619{
12620 FILE *f;
12621 DIR *d;
12622 char tmp[80], tmp2[80], fname[80];
12623 unsigned int acflag;
12624 struct dirent* de;
12625
Denis Vlasenko5415c852008-07-21 23:05:26 +000012626 f = fopen_for_read("/proc/apm");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012627 if (f) {
12628 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12629 acflag = 1;
12630 fclose(f);
12631 return (acflag != 1);
12632 }
12633 d = opendir("/proc/acpi/ac_adapter");
12634 if (d) {
12635 while ((de=readdir(d)) != NULL) {
12636 if (!strncmp(".", de->d_name, 1))
12637 continue;
12638 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12639 de->d_name);
Denis Vlasenko5415c852008-07-21 23:05:26 +000012640 f = fopen_for_read(fname);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012641 if (!f)
12642 continue;
12643 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12644 tmp[0] = 0;
12645 fclose(f);
12646 if (strncmp(tmp, "off-line", 8) == 0) {
12647 closedir(d);
12648 return 1;
12649 }
12650 }
12651 closedir(d);
12652 }
12653 return 0;
12654}
12655
12656/*
12657 * This routine checks to see if a filesystem can be skipped; if so,
12658 * it will exit with EXIT_OK. Under some conditions it will print a
12659 * message explaining why a check is being forced.
12660 */
12661static void check_if_skip(e2fsck_t ctx)
12662{
12663 ext2_filsys fs = ctx->fs;
12664 const char *reason = NULL;
12665 unsigned int reason_arg = 0;
12666 long next_check;
12667 int batt = is_on_batt();
Denis Vlasenko04158e02009-02-02 10:48:06 +000012668 time_t now = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012669
12670 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12671 return;
12672
12673 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12674 !ext2fs_test_valid(fs))
12675 reason = _(" contains a file system with errors");
12676 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12677 reason = _(" was not cleanly unmounted");
12678 else if ((fs->super->s_max_mnt_count > 0) &&
12679 (fs->super->s_mnt_count >=
12680 (unsigned) fs->super->s_max_mnt_count)) {
12681 reason = _(" has been mounted %u times without being checked");
12682 reason_arg = fs->super->s_mnt_count;
12683 if (batt && (fs->super->s_mnt_count <
12684 (unsigned) fs->super->s_max_mnt_count*2))
12685 reason = 0;
12686 } else if (fs->super->s_checkinterval &&
12687 ((now - fs->super->s_lastcheck) >=
12688 fs->super->s_checkinterval)) {
12689 reason = _(" has gone %u days without being checked");
12690 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12691 if (batt && ((now - fs->super->s_lastcheck) <
12692 fs->super->s_checkinterval*2))
12693 reason = 0;
12694 }
12695 if (reason) {
12696 fputs(ctx->device_name, stdout);
12697 printf(reason, reason_arg);
12698 fputs(_(", check forced.\n"), stdout);
12699 return;
12700 }
12701 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12702 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12703 fs->super->s_inodes_count,
12704 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12705 fs->super->s_blocks_count);
12706 next_check = 100000;
12707 if (fs->super->s_max_mnt_count > 0) {
12708 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12709 if (next_check <= 0)
12710 next_check = 1;
12711 }
12712 if (fs->super->s_checkinterval &&
12713 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12714 next_check = 1;
12715 if (next_check <= 5) {
12716 if (next_check == 1)
12717 fputs(_(" (check after next mount)"), stdout);
12718 else
12719 printf(_(" (check in %ld mounts)"), next_check);
12720 }
Denis Vlasenko4daad902007-09-27 10:20:47 +000012721 bb_putchar('\n');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012722 ext2fs_close(fs);
12723 ctx->fs = NULL;
12724 e2fsck_free_context(ctx);
12725 exit(EXIT_OK);
12726}
12727
12728/*
12729 * For completion notice
12730 */
12731struct percent_tbl {
12732 int max_pass;
12733 int table[32];
12734};
12735static const struct percent_tbl e2fsck_tbl = {
12736 5, { 0, 70, 90, 92, 95, 100 }
12737};
12738
12739static char bar[128], spaces[128];
12740
12741static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12742 int max)
12743{
12744 float percent;
12745
12746 if (pass <= 0)
12747 return 0.0;
12748 if (pass > tbl->max_pass || max == 0)
12749 return 100.0;
12750 percent = ((float) curr) / ((float) max);
12751 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12752 + tbl->table[pass-1]);
12753}
12754
12755void e2fsck_clear_progbar(e2fsck_t ctx)
12756{
12757 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12758 return;
12759
12760 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12761 ctx->stop_meta);
12762 fflush(stdout);
12763 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12764}
12765
12766int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12767 unsigned int dpynum)
12768{
12769 static const char spinner[] = "\\|/-";
12770 int i;
12771 unsigned int tick;
12772 struct timeval tv;
12773 int dpywidth;
12774 int fixed_percent;
12775
12776 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12777 return 0;
12778
12779 /*
12780 * Calculate the new progress position. If the
12781 * percentage hasn't changed, then we skip out right
12782 * away.
12783 */
12784 fixed_percent = (int) ((10 * percent) + 0.5);
12785 if (ctx->progress_last_percent == fixed_percent)
12786 return 0;
12787 ctx->progress_last_percent = fixed_percent;
12788
12789 /*
12790 * If we've already updated the spinner once within
12791 * the last 1/8th of a second, no point doing it
12792 * again.
12793 */
12794 gettimeofday(&tv, NULL);
12795 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12796 if ((tick == ctx->progress_last_time) &&
12797 (fixed_percent != 0) && (fixed_percent != 1000))
12798 return 0;
12799 ctx->progress_last_time = tick;
12800
12801 /*
12802 * Advance the spinner, and note that the progress bar
12803 * will be on the screen
12804 */
12805 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12806 ctx->flags |= E2F_FLAG_PROG_BAR;
12807
12808 dpywidth = 66 - strlen(label);
12809 dpywidth = 8 * (dpywidth / 8);
12810 if (dpynum)
12811 dpywidth -= 8;
12812
12813 i = ((percent * dpywidth) + 50) / 100;
12814 printf("%s%s: |%s%s", ctx->start_meta, label,
12815 bar + (sizeof(bar) - (i+1)),
12816 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12817 if (fixed_percent == 1000)
Denis Vlasenko4daad902007-09-27 10:20:47 +000012818 bb_putchar('|');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012819 else
Denis Vlasenko4daad902007-09-27 10:20:47 +000012820 bb_putchar(spinner[ctx->progress_pos & 3]);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012821 printf(" %4.1f%% ", percent);
12822 if (dpynum)
12823 printf("%u\r", dpynum);
12824 else
12825 fputs(" \r", stdout);
12826 fputs(ctx->stop_meta, stdout);
12827
12828 if (fixed_percent == 1000)
12829 e2fsck_clear_progbar(ctx);
12830 fflush(stdout);
12831
12832 return 0;
12833}
12834
12835static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12836 unsigned long cur, unsigned long max)
12837{
12838 char buf[80];
12839 float percent;
12840
12841 if (pass == 0)
12842 return 0;
12843
12844 if (ctx->progress_fd) {
12845 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
Denis Vlasenko73c571a2009-03-09 00:12:37 +000012846 xwrite_str(ctx->progress_fd, buf);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012847 } else {
12848 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12849 e2fsck_simple_progress(ctx, ctx->device_name,
12850 percent, 0);
12851 }
12852 return 0;
12853}
12854
12855static void reserve_stdio_fds(void)
12856{
12857 int fd;
12858
12859 while (1) {
12860 fd = open(bb_dev_null, O_RDWR);
12861 if (fd > 2)
12862 break;
12863 if (fd < 0) {
12864 fprintf(stderr, _("ERROR: Cannot open "
12865 "/dev/null (%s)\n"),
12866 strerror(errno));
12867 break;
12868 }
12869 }
12870 close(fd);
12871}
12872
12873static void signal_progress_on(int sig FSCK_ATTR((unused)))
12874{
12875 e2fsck_t ctx = e2fsck_global_ctx;
12876
12877 if (!ctx)
12878 return;
12879
12880 ctx->progress = e2fsck_update_progress;
12881 ctx->progress_fd = 0;
12882}
12883
12884static void signal_progress_off(int sig FSCK_ATTR((unused)))
12885{
12886 e2fsck_t ctx = e2fsck_global_ctx;
12887
12888 if (!ctx)
12889 return;
12890
12891 e2fsck_clear_progbar(ctx);
12892 ctx->progress = 0;
12893}
12894
12895static void signal_cancel(int sig FSCK_ATTR((unused)))
12896{
12897 e2fsck_t ctx = e2fsck_global_ctx;
12898
12899 if (!ctx)
12900 exit(FSCK_CANCELED);
12901
12902 ctx->flags |= E2F_FLAG_CANCEL;
12903}
12904
12905static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12906{
12907 char *buf, *token, *next, *p, *arg;
12908 int ea_ver;
12909 int extended_usage = 0;
12910
12911 buf = string_copy(opts, 0);
12912 for (token = buf; token && *token; token = next) {
12913 p = strchr(token, ',');
12914 next = 0;
12915 if (p) {
12916 *p = 0;
12917 next = p+1;
12918 }
12919 arg = strchr(token, '=');
12920 if (arg) {
12921 *arg = 0;
12922 arg++;
12923 }
12924 if (strcmp(token, "ea_ver") == 0) {
12925 if (!arg) {
12926 extended_usage++;
12927 continue;
12928 }
12929 ea_ver = strtoul(arg, &p, 0);
12930 if (*p ||
12931 ((ea_ver != 1) && (ea_ver != 2))) {
12932 fprintf(stderr,
12933 _("Invalid EA version.\n"));
12934 extended_usage++;
12935 continue;
12936 }
12937 ctx->ext_attr_ver = ea_ver;
12938 } else {
12939 fprintf(stderr, _("Unknown extended option: %s\n"),
12940 token);
12941 extended_usage++;
12942 }
12943 }
12944 if (extended_usage) {
12945 bb_error_msg_and_die(
12946 "Extended options are separated by commas, "
12947 "and may take an argument which\n"
12948 "is set off by an equals ('=') sign. "
12949 "Valid extended options are:\n"
12950 "\tea_ver=<ea_version (1 or 2)>\n\n");
12951 }
12952}
12953
12954
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000012955static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012956{
12957 int flush = 0;
12958 int c, fd;
12959 e2fsck_t ctx;
12960 errcode_t retval;
12961 struct sigaction sa;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010012962 char *extended_opts = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012963
12964 retval = e2fsck_allocate_context(&ctx);
12965 if (retval)
12966 return retval;
12967
12968 *ret_ctx = ctx;
12969
12970 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12971 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12972 if (isatty(0) && isatty(1)) {
12973 ctx->interactive = 1;
12974 } else {
12975 ctx->start_meta[0] = '\001';
12976 ctx->stop_meta[0] = '\002';
12977 }
12978 memset(bar, '=', sizeof(bar)-1);
12979 memset(spaces, ' ', sizeof(spaces)-1);
12980 blkid_get_cache(&ctx->blkid, NULL);
12981
12982 if (argc && *argv)
12983 ctx->program_name = *argv;
12984 else
12985 ctx->program_name = "e2fsck";
12986 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
12987 switch (c) {
12988 case 'C':
12989 ctx->progress = e2fsck_update_progress;
12990 ctx->progress_fd = atoi(optarg);
12991 if (!ctx->progress_fd)
12992 break;
12993 /* Validate the file descriptor to avoid disasters */
12994 fd = dup(ctx->progress_fd);
12995 if (fd < 0) {
12996 fprintf(stderr,
12997 _("Error validating file descriptor %d: %s\n"),
12998 ctx->progress_fd,
12999 error_message(errno));
13000 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13001 } else
13002 close(fd);
13003 break;
13004 case 'D':
13005 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13006 break;
13007 case 'E':
13008 extended_opts = optarg;
13009 break;
13010 case 'p':
13011 case 'a':
13012 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13013 conflict_opt:
Denis Vlasenko54d10052008-12-24 03:11:43 +000013014 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013015 }
13016 ctx->options |= E2F_OPT_PREEN;
13017 break;
13018 case 'n':
13019 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13020 goto conflict_opt;
13021 ctx->options |= E2F_OPT_NO;
13022 break;
13023 case 'y':
13024 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13025 goto conflict_opt;
13026 ctx->options |= E2F_OPT_YES;
13027 break;
13028 case 't':
13029 /* FIXME - This needs to go away in a future path - will change binary */
13030 fprintf(stderr, _("The -t option is not "
13031 "supported on this version of e2fsck.\n"));
13032 break;
13033 case 'c':
13034 if (cflag++)
13035 ctx->options |= E2F_OPT_WRITECHECK;
13036 ctx->options |= E2F_OPT_CHECKBLOCKS;
13037 break;
13038 case 'r':
13039 /* What we do by default, anyway! */
13040 break;
13041 case 'b':
13042 ctx->use_superblock = atoi(optarg);
13043 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13044 break;
13045 case 'B':
13046 ctx->blocksize = atoi(optarg);
13047 break;
13048 case 'I':
13049 ctx->inode_buffer_blocks = atoi(optarg);
13050 break;
13051 case 'j':
13052 ctx->journal_name = string_copy(optarg, 0);
13053 break;
13054 case 'P':
13055 ctx->process_inode_size = atoi(optarg);
13056 break;
13057 case 'd':
13058 ctx->options |= E2F_OPT_DEBUG;
13059 break;
13060 case 'f':
13061 ctx->options |= E2F_OPT_FORCE;
13062 break;
13063 case 'F':
13064 flush = 1;
13065 break;
13066 case 'v':
13067 verbose = 1;
13068 break;
13069 case 'V':
13070 show_version_only = 1;
13071 break;
13072 case 'N':
13073 ctx->device_name = optarg;
13074 break;
13075#ifdef ENABLE_SWAPFS
13076 case 's':
13077 normalize_swapfs = 1;
13078 case 'S':
13079 swapfs = 1;
13080 break;
13081#else
13082 case 's':
13083 case 'S':
13084 fprintf(stderr, _("Byte-swapping filesystems "
13085 "not compiled in this version "
13086 "of e2fsck\n"));
13087 exit(1);
13088#endif
13089 default:
13090 bb_show_usage();
13091 }
13092 if (show_version_only)
13093 return 0;
13094 if (optind != argc - 1)
13095 bb_show_usage();
13096 if ((ctx->options & E2F_OPT_NO) &&
13097 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13098 ctx->options |= E2F_OPT_READONLY;
13099 ctx->io_options = strchr(argv[optind], '?');
13100 if (ctx->io_options)
13101 *ctx->io_options++ = 0;
13102 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13103 if (!ctx->filesystem_name) {
13104 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13105 bb_error_msg_and_die(0);
13106 }
13107 if (extended_opts)
13108 parse_extended_opts(ctx, extended_opts);
13109
13110 if (flush) {
13111 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13112 if (fd < 0) {
13113 bb_error_msg(_("while opening %s for flushing"),
13114 ctx->filesystem_name);
13115 bb_error_msg_and_die(0);
13116 }
13117 if ((retval = ext2fs_sync_device(fd, 1))) {
13118 bb_error_msg(_("while trying to flush %s"),
13119 ctx->filesystem_name);
13120 bb_error_msg_and_die(0);
13121 }
13122 close(fd);
13123 }
13124#ifdef ENABLE_SWAPFS
13125 if (swapfs && cflag) {
13126 fprintf(stderr, _("Incompatible options not "
13127 "allowed when byte-swapping.\n"));
13128 exit(EXIT_USAGE);
13129 }
13130#endif
13131 /*
13132 * Set up signal action
13133 */
13134 memset(&sa, 0, sizeof(struct sigaction));
13135 sa.sa_handler = signal_cancel;
13136 sigaction(SIGINT, &sa, 0);
13137 sigaction(SIGTERM, &sa, 0);
13138#ifdef SA_RESTART
13139 sa.sa_flags = SA_RESTART;
13140#endif
13141 e2fsck_global_ctx = ctx;
13142 sa.sa_handler = signal_progress_on;
13143 sigaction(SIGUSR1, &sa, 0);
13144 sa.sa_handler = signal_progress_off;
13145 sigaction(SIGUSR2, &sa, 0);
13146
13147 /* Update our PATH to include /sbin if we need to run badblocks */
13148 if (cflag)
13149 e2fs_set_sbin_path();
13150 return 0;
13151}
13152
13153static const char my_ver_string[] = E2FSPROGS_VERSION;
13154static const char my_ver_date[] = E2FSPROGS_DATE;
13155
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013156int e2fsck_main (int argc, char **argv);
13157int e2fsck_main (int argc, char **argv)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013158{
13159 errcode_t retval;
13160 int exit_value = EXIT_OK;
13161 ext2_filsys fs = 0;
13162 io_manager io_ptr;
13163 struct ext2_super_block *sb;
13164 const char *lib_ver_date;
13165 int my_ver, lib_ver;
13166 e2fsck_t ctx;
13167 struct problem_context pctx;
13168 int flags, run_result;
13169
13170 clear_problem_context(&pctx);
13171
13172 my_ver = ext2fs_parse_version_string(my_ver_string);
13173 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13174 if (my_ver > lib_ver) {
13175 fprintf( stderr, _("Error: ext2fs library version "
13176 "out of date!\n"));
13177 show_version_only++;
13178 }
13179
13180 retval = PRS(argc, argv, &ctx);
13181 if (retval) {
13182 bb_error_msg(_("while trying to initialize program"));
13183 exit(EXIT_ERROR);
13184 }
13185 reserve_stdio_fds();
13186
13187 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13188 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13189 my_ver_date);
13190
13191 if (show_version_only) {
13192 fprintf(stderr, _("\tUsing %s, %s\n"),
13193 error_message(EXT2_ET_BASE), lib_ver_date);
13194 exit(EXIT_OK);
13195 }
13196
13197 check_mount(ctx);
13198
13199 if (!(ctx->options & E2F_OPT_PREEN) &&
13200 !(ctx->options & E2F_OPT_NO) &&
13201 !(ctx->options & E2F_OPT_YES)) {
13202 if (!ctx->interactive)
13203 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13204 }
13205 ctx->superblock = ctx->use_superblock;
13206restart:
13207#ifdef CONFIG_TESTIO_DEBUG
13208 io_ptr = test_io_manager;
13209 test_io_backing_manager = unix_io_manager;
13210#else
13211 io_ptr = unix_io_manager;
13212#endif
13213 flags = 0;
13214 if ((ctx->options & E2F_OPT_READONLY) == 0)
13215 flags |= EXT2_FLAG_RW;
13216
13217 if (ctx->superblock && ctx->blocksize) {
13218 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13219 flags, ctx->superblock, ctx->blocksize,
13220 io_ptr, &fs);
13221 } else if (ctx->superblock) {
13222 int blocksize;
13223 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13224 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13225 retval = ext2fs_open2(ctx->filesystem_name,
13226 ctx->io_options, flags,
13227 ctx->superblock, blocksize,
13228 io_ptr, &fs);
13229 if (!retval)
13230 break;
13231 }
13232 } else
13233 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13234 flags, 0, 0, io_ptr, &fs);
13235 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13236 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13237 ((retval == EXT2_ET_BAD_MAGIC) ||
13238 ((retval == 0) && ext2fs_check_desc(fs)))) {
13239 if (!fs || (fs->group_desc_count > 1)) {
13240 printf(_("%s trying backup blocks...\n"),
13241 retval ? _("Couldn't find ext2 superblock,") :
13242 _("Group descriptors look bad..."));
13243 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13244 if (fs)
13245 ext2fs_close(fs);
13246 goto restart;
13247 }
13248 }
13249 if (retval) {
13250 bb_error_msg(_("while trying to open %s"),
13251 ctx->filesystem_name);
13252 if (retval == EXT2_ET_REV_TOO_HIGH) {
13253 printf(_("The filesystem revision is apparently "
13254 "too high for this version of e2fsck.\n"
13255 "(Or the filesystem superblock "
13256 "is corrupt)\n\n"));
13257 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13258 } else if (retval == EXT2_ET_SHORT_READ)
13259 printf(_("Could this be a zero-length partition?\n"));
13260 else if ((retval == EPERM) || (retval == EACCES))
13261 printf(_("You must have %s access to the "
13262 "filesystem or be root\n"),
13263 (ctx->options & E2F_OPT_READONLY) ?
13264 "r/o" : "r/w");
13265 else if (retval == ENXIO)
13266 printf(_("Possibly non-existent or swap device?\n"));
13267#ifdef EROFS
13268 else if (retval == EROFS)
13269 printf(_("Disk write-protected; use the -n option "
13270 "to do a read-only\n"
13271 "check of the device.\n"));
13272#endif
13273 else
13274 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13275 bb_error_msg_and_die(0);
13276 }
13277 ctx->fs = fs;
13278 fs->priv_data = ctx;
13279 sb = fs->super;
13280 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13281 bb_error_msg(_("while trying to open %s"),
13282 ctx->filesystem_name);
13283 get_newer:
13284 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13285 }
13286
13287 /*
13288 * Set the device name, which is used whenever we print error
13289 * or informational messages to the user.
13290 */
13291 if (ctx->device_name == 0 &&
13292 (sb->s_volume_name[0] != 0)) {
13293 ctx->device_name = string_copy(sb->s_volume_name,
13294 sizeof(sb->s_volume_name));
13295 }
13296 if (ctx->device_name == 0)
13297 ctx->device_name = ctx->filesystem_name;
13298
13299 /*
13300 * Make sure the ext3 superblock fields are consistent.
13301 */
13302 retval = e2fsck_check_ext3_journal(ctx);
13303 if (retval) {
13304 bb_error_msg(_("while checking ext3 journal for %s"),
13305 ctx->device_name);
13306 bb_error_msg_and_die(0);
13307 }
13308
13309 /*
13310 * Check to see if we need to do ext3-style recovery. If so,
13311 * do it, and then restart the fsck.
13312 */
13313 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13314 if (ctx->options & E2F_OPT_READONLY) {
13315 printf(_("Warning: skipping journal recovery "
13316 "because doing a read-only filesystem "
13317 "check.\n"));
13318 io_channel_flush(ctx->fs->io);
13319 } else {
13320 if (ctx->flags & E2F_FLAG_RESTARTED) {
13321 /*
13322 * Whoops, we attempted to run the
13323 * journal twice. This should never
13324 * happen, unless the hardware or
13325 * device driver is being bogus.
13326 */
Denys Vlasenko6331cf02009-11-13 09:08:27 +010013327 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013328 bb_error_msg_and_die(0);
13329 }
13330 retval = e2fsck_run_ext3_journal(ctx);
13331 if (retval) {
13332 bb_error_msg(_("while recovering ext3 journal of %s"),
13333 ctx->device_name);
13334 bb_error_msg_and_die(0);
13335 }
13336 ext2fs_close(ctx->fs);
13337 ctx->fs = 0;
13338 ctx->flags |= E2F_FLAG_RESTARTED;
13339 goto restart;
13340 }
13341 }
13342
13343 /*
13344 * Check for compatibility with the feature sets. We need to
13345 * be more stringent than ext2fs_open().
13346 */
13347 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13348 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13349 bb_error_msg("(%s)", ctx->device_name);
13350 goto get_newer;
13351 }
13352 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13353 bb_error_msg("(%s)", ctx->device_name);
13354 goto get_newer;
13355 }
13356#ifdef ENABLE_COMPRESSION
13357 /* FIXME - do we support this at all? */
13358 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
Denis Vlasenko54d10052008-12-24 03:11:43 +000013359 bb_error_msg(_("warning: compression support is experimental"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013360#endif
13361#ifndef ENABLE_HTREE
13362 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13363 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13364 "but filesystem %s has HTREE directories."),
13365 ctx->device_name);
13366 goto get_newer;
13367 }
13368#endif
13369
13370 /*
13371 * If the user specified a specific superblock, presumably the
13372 * master superblock has been trashed. So we mark the
13373 * superblock as dirty, so it can be written out.
13374 */
13375 if (ctx->superblock &&
13376 !(ctx->options & E2F_OPT_READONLY))
13377 ext2fs_mark_super_dirty(fs);
13378
13379 /*
13380 * We only update the master superblock because (a) paranoia;
13381 * we don't want to corrupt the backup superblocks, and (b) we
13382 * don't need to update the mount count and last checked
13383 * fields in the backup superblock (the kernel doesn't
13384 * update the backup superblocks anyway).
13385 */
13386 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13387
13388 ehandler_init(fs->io);
13389
13390 if (ctx->superblock)
13391 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13392 ext2fs_mark_valid(fs);
13393 check_super_block(ctx);
13394 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13395 bb_error_msg_and_die(0);
13396 check_if_skip(ctx);
13397 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13398 bb_error_msg_and_die(0);
13399#ifdef ENABLE_SWAPFS
13400
13401#ifdef WORDS_BIGENDIAN
13402#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13403#else
13404#define NATIVE_FLAG 0
13405#endif
13406
13407
13408 if (normalize_swapfs) {
13409 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13410 fprintf(stderr, _("%s: Filesystem byte order "
13411 "already normalized.\n"), ctx->device_name);
13412 bb_error_msg_and_die(0);
13413 }
13414 }
13415 if (swapfs) {
13416 swap_filesys(ctx);
13417 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13418 bb_error_msg_and_die(0);
13419 }
13420#endif
13421
13422 /*
13423 * Mark the system as valid, 'til proven otherwise
13424 */
13425 ext2fs_mark_valid(fs);
13426
13427 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13428 if (retval) {
13429 bb_error_msg(_("while reading bad blocks inode"));
13430 preenhalt(ctx);
13431 printf(_("This doesn't bode well,"
13432 " but we'll try to go on...\n"));
13433 }
13434
13435 run_result = e2fsck_run(ctx);
13436 e2fsck_clear_progbar(ctx);
13437 if (run_result == E2F_FLAG_RESTART) {
13438 printf(_("Restarting e2fsck from the beginning...\n"));
13439 retval = e2fsck_reset_context(ctx);
13440 if (retval) {
13441 bb_error_msg(_("while resetting context"));
13442 bb_error_msg_and_die(0);
13443 }
13444 ext2fs_close(fs);
13445 goto restart;
13446 }
13447 if (run_result & E2F_FLAG_CANCEL) {
13448 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13449 ctx->device_name : ctx->filesystem_name);
13450 exit_value |= FSCK_CANCELED;
13451 }
13452 if (run_result & E2F_FLAG_ABORT)
13453 bb_error_msg_and_die(_("aborted"));
13454
13455 /* Cleanup */
13456 if (ext2fs_test_changed(fs)) {
13457 exit_value |= EXIT_NONDESTRUCT;
13458 if (!(ctx->options & E2F_OPT_PREEN))
13459 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13460 ctx->device_name);
13461 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13462 printf(_("%s: ***** REBOOT LINUX *****\n"),
13463 ctx->device_name);
13464 exit_value |= EXIT_DESTRUCT;
13465 }
13466 }
13467 if (!ext2fs_test_valid(fs)) {
13468 printf(_("\n%s: ********** WARNING: Filesystem still has "
13469 "errors **********\n\n"), ctx->device_name);
13470 exit_value |= EXIT_UNCORRECTED;
13471 exit_value &= ~EXIT_NONDESTRUCT;
13472 }
13473 if (exit_value & FSCK_CANCELED)
13474 exit_value &= ~EXIT_NONDESTRUCT;
13475 else {
13476 show_stats(ctx);
13477 if (!(ctx->options & E2F_OPT_READONLY)) {
13478 if (ext2fs_test_valid(fs)) {
13479 if (!(sb->s_state & EXT2_VALID_FS))
13480 exit_value |= EXIT_NONDESTRUCT;
13481 sb->s_state = EXT2_VALID_FS;
13482 } else
13483 sb->s_state &= ~EXT2_VALID_FS;
13484 sb->s_mnt_count = 0;
13485 sb->s_lastcheck = time(NULL);
13486 ext2fs_mark_super_dirty(fs);
13487 }
13488 }
13489
13490 e2fsck_write_bitmaps(ctx);
13491
13492 ext2fs_close(fs);
13493 ctx->fs = NULL;
13494 free(ctx->filesystem_name);
13495 free(ctx->journal_name);
13496 e2fsck_free_context(ctx);
13497
13498 return exit_value;
13499}