blob: 373e8ce916befadd97910e2232d3cec0a527799b [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 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +020029 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000030 */
31
Pere Orga5bc8c002011-04-11 03:29:49 +020032/*
33//usage:#define e2fsck_trivial_usage
34//usage: "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] "
35//usage: "[-I inode_buffer_blocks] [-P process_inode_size] "
36//usage: "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] "
37//usage: "[-E extended-options] device"
38//usage:#define e2fsck_full_usage "\n\n"
39//usage: "Check ext2/ext3 file system\n"
Pere Orga5bc8c002011-04-11 03:29:49 +020040//usage: "\n -p Automatic repair (no questions)"
41//usage: "\n -n Make no changes to the filesystem"
42//usage: "\n -y Assume 'yes' to all questions"
43//usage: "\n -c Check for bad blocks and add them to the badblock list"
44//usage: "\n -f Force checking even if filesystem is marked clean"
45//usage: "\n -v Verbose"
46//usage: "\n -b superblock Use alternative superblock"
47//usage: "\n -B blocksize Force blocksize when looking for superblock"
48//usage: "\n -j journal Set location of the external journal"
49//usage: "\n -l file Add to badblocks list"
50//usage: "\n -L file Set badblocks list"
51*/
52
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000053#include "e2fsck.h" /*Put all of our defines here to clean things up*/
54
55#define _(x) x
56#define N_(x) x
57
58/*
59 * Procedure declarations
60 */
61
62static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
63
64/* pass1.c */
65static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
66
67/* pass2.c */
68static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
69 ext2_ino_t ino, char *buf);
70
71/* pass3.c */
72static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
73static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
74 int num, int gauranteed_size);
75static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
76static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
77 int adj);
78
79/* rehash.c */
80static void e2fsck_rehash_directories(e2fsck_t ctx);
81
82/* util.c */
83static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
84 const char *description);
85static int ask(e2fsck_t ctx, const char * string, int def);
86static void e2fsck_read_bitmaps(e2fsck_t ctx);
87static void preenhalt(e2fsck_t ctx);
88static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
89 struct ext2_inode * inode, const char * proc);
90static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
91 struct ext2_inode * inode, const char * proc);
92static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
93 const char *name, io_manager manager);
94
95/* unix.c */
96static void e2fsck_clear_progbar(e2fsck_t ctx);
97static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
98 float percent, unsigned int dpynum);
99
100
101/*
102 * problem.h --- e2fsck problem error codes
103 */
104
105typedef __u32 problem_t;
106
107struct problem_context {
108 errcode_t errcode;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100109 ext2_ino_t ino, ino2, dir;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000110 struct ext2_inode *inode;
111 struct ext2_dir_entry *dirent;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100112 blk_t blk, blk2;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000113 e2_blkcnt_t blkcount;
114 int group;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100115 __u64 num;
116 const char *str;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000117};
118
119
120/*
121 * Function declarations
122 */
123static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
124static int end_problem_latch(e2fsck_t ctx, int mask);
125static int set_latch_flags(int mask, int setflags, int clearflags);
126static void clear_problem_context(struct problem_context *ctx);
127
128/*
129 * Dictionary Abstract Data Type
130 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
131 *
132 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
133 * kazlib_1_20
134 */
135
136#ifndef DICT_H
137#define DICT_H
138
139/*
140 * Blurb for inclusion into C++ translation units
141 */
142
143typedef unsigned long dictcount_t;
144#define DICTCOUNT_T_MAX ULONG_MAX
145
146/*
147 * The dictionary is implemented as a red-black tree
148 */
149
150typedef enum { dnode_red, dnode_black } dnode_color_t;
151
152typedef struct dnode_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100153 struct dnode_t *dict_left;
154 struct dnode_t *dict_right;
155 struct dnode_t *dict_parent;
156 dnode_color_t dict_color;
157 const void *dict_key;
158 void *dict_data;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000159} dnode_t;
160
161typedef int (*dict_comp_t)(const void *, const void *);
162typedef void (*dnode_free_t)(dnode_t *);
163
164typedef struct dict_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100165 dnode_t dict_nilnode;
166 dictcount_t dict_nodecount;
167 dictcount_t dict_maxcount;
168 dict_comp_t dict_compare;
169 dnode_free_t dict_freenode;
170 int dict_dupes;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000171} dict_t;
172
173typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
174
175typedef struct dict_load_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100176 dict_t *dict_dictptr;
177 dnode_t dict_nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000178} dict_load_t;
179
180#define dict_count(D) ((D)->dict_nodecount)
181#define dnode_get(N) ((N)->dict_data)
182#define dnode_getkey(N) ((N)->dict_key)
183
184#endif
185
186/*
187 * Compatibility header file for e2fsck which should be included
188 * instead of linux/jfs.h
189 *
190 * Copyright (C) 2000 Stephen C. Tweedie
191 */
192
193/*
194 * Pull in the definition of the e2fsck context structure
195 */
196
197struct buffer_head {
198 char b_data[8192];
199 e2fsck_t b_ctx;
200 io_channel b_io;
201 int b_size;
202 blk_t b_blocknr;
203 int b_dirty;
204 int b_uptodate;
205 int b_err;
206};
207
208
209#define K_DEV_FS 1
210#define K_DEV_JOURNAL 2
211
Denis Vlasenkobb045062008-09-27 14:06:06 +0000212#define lock_buffer(bh) do {} while (0)
213#define unlock_buffer(bh) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000214#define buffer_req(bh) 1
Denis Vlasenkobb045062008-09-27 14:06:06 +0000215#define do_readahead(journal, start) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000216
217static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
218
219typedef struct {
220 int object_length;
221} kmem_cache_t;
222
223#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
224
225/*
226 * We use the standard libext2fs portability tricks for inline
227 * functions.
228 */
229
230static kmem_cache_t * do_cache_create(int len)
231{
232 kmem_cache_t *new_cache;
233
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100234 new_cache = xmalloc(sizeof(*new_cache));
235 new_cache->object_length = len;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000236 return new_cache;
237}
238
239static void do_cache_destroy(kmem_cache_t *cache)
240{
241 free(cache);
242}
243
244
245/*
246 * Dictionary Abstract Data Type
247 */
248
249
250/*
251 * These macros provide short convenient names for structure members,
252 * which are embellished with dict_ prefixes so that they are
253 * properly confined to the documented namespace. It's legal for a
254 * program which uses dict to define, for instance, a macro called ``parent''.
255 * Such a macro would interfere with the dnode_t struct definition.
256 * In general, highly portable and reusable C modules which expose their
257 * structures need to confine structure member names to well-defined spaces.
258 * The resulting identifiers aren't necessarily convenient to use, nor
259 * readable, in the implementation, however!
260 */
261
262#define left dict_left
263#define right dict_right
264#define parent dict_parent
265#define color dict_color
266#define key dict_key
267#define data dict_data
268
269#define nilnode dict_nilnode
270#define maxcount dict_maxcount
271#define compare dict_compare
272#define dupes dict_dupes
273
274#define dict_root(D) ((D)->nilnode.left)
275#define dict_nil(D) (&(D)->nilnode)
276
277static void dnode_free(dnode_t *node);
278
279/*
280 * Perform a ``left rotation'' adjustment on the tree. The given node P and
281 * its right child C are rearranged so that the P instead becomes the left
282 * child of C. The left subtree of C is inherited as the new right subtree
283 * for P. The ordering of the keys within the tree is thus preserved.
284 */
285
286static void rotate_left(dnode_t *upper)
287{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100288 dnode_t *lower, *lowleft, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000289
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100290 lower = upper->right;
291 upper->right = lowleft = lower->left;
292 lowleft->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000293
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100294 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000295
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100296 /* don't need to check for root node here because root->parent is
297 the sentinel nil node, and root->parent->left points back to root */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000298
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100299 if (upper == upparent->left) {
300 upparent->left = lower;
301 } else {
302 assert (upper == upparent->right);
303 upparent->right = lower;
304 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000305
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100306 lower->left = upper;
307 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000308}
309
310/*
311 * This operation is the ``mirror'' image of rotate_left. It is
312 * the same procedure, but with left and right interchanged.
313 */
314
315static void rotate_right(dnode_t *upper)
316{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100317 dnode_t *lower, *lowright, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000318
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100319 lower = upper->left;
320 upper->left = lowright = lower->right;
321 lowright->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000322
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100323 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000324
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100325 if (upper == upparent->right) {
326 upparent->right = lower;
327 } else {
328 assert (upper == upparent->left);
329 upparent->left = lower;
330 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000331
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100332 lower->right = upper;
333 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000334}
335
336/*
337 * Do a postorder traversal of the tree rooted at the specified
338 * node and free everything under it. Used by dict_free().
339 */
340
341static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
342{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100343 if (node == nil)
344 return;
345 free_nodes(dict, node->left, nil);
346 free_nodes(dict, node->right, nil);
347 dict->dict_freenode(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000348}
349
350/*
351 * Verify that the tree contains the given node. This is done by
352 * traversing all of the nodes and comparing their pointers to the
353 * given pointer. Returns 1 if the node is found, otherwise
354 * returns zero. It is intended for debugging purposes.
355 */
356
357static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
358{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100359 if (root != nil) {
360 return root == node
361 || verify_dict_has_node(nil, root->left, node)
362 || verify_dict_has_node(nil, root->right, node);
363 }
364 return 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000365}
366
367
368/*
369 * Select a different set of node allocator routines.
370 */
371
372static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
373{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100374 assert(dict_count(dict) == 0);
375 dict->dict_freenode = fr;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000376}
377
378/*
379 * Free all the nodes in the dictionary by using the dictionary's
380 * installed free routine. The dictionary is emptied.
381 */
382
383static void dict_free_nodes(dict_t *dict)
384{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100385 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
386 free_nodes(dict, root, nil);
387 dict->dict_nodecount = 0;
388 dict->nilnode.left = &dict->nilnode;
389 dict->nilnode.right = &dict->nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000390}
391
392/*
393 * Initialize a user-supplied dictionary object.
394 */
395
396static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
397{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100398 dict->compare = comp;
399 dict->dict_freenode = dnode_free;
400 dict->dict_nodecount = 0;
401 dict->maxcount = maxcount;
402 dict->nilnode.left = &dict->nilnode;
403 dict->nilnode.right = &dict->nilnode;
404 dict->nilnode.parent = &dict->nilnode;
405 dict->nilnode.color = dnode_black;
406 dict->dupes = 0;
407 return dict;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000408}
409
410/*
411 * Locate a node in the dictionary having the given key.
412 * If the node is not found, a null a pointer is returned (rather than
413 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
414 * located node is returned.
415 */
416
417static dnode_t *dict_lookup(dict_t *dict, const void *key)
418{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100419 dnode_t *root = dict_root(dict);
420 dnode_t *nil = dict_nil(dict);
421 dnode_t *saved;
422 int result;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000423
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100424 /* simple binary search adapted for trees that contain duplicate keys */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000425
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100426 while (root != nil) {
427 result = dict->compare(key, root->key);
428 if (result < 0)
429 root = root->left;
430 else if (result > 0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000431 root = root->right;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100432 else {
433 if (!dict->dupes) { /* no duplicates, return match */
434 return root;
435 } else { /* could be dupes, find leftmost one */
436 do {
437 saved = root;
438 root = root->left;
439 while (root != nil && dict->compare(key, root->key))
440 root = root->right;
441 } while (root != nil);
442 return saved;
443 }
444 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000445 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000446
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100447 return NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000448}
449
450/*
451 * Insert a node into the dictionary. The node should have been
452 * initialized with a data field. All other fields are ignored.
453 * The behavior is undefined if the user attempts to insert into
454 * a dictionary that is already full (for which the dict_isfull()
455 * function returns true).
456 */
457
458static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
459{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100460 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
461 dnode_t *parent = nil, *uncle, *grandpa;
462 int result = -1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000463
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100464 node->key = key;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000465
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100466 /* basic binary tree insert */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000467
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100468 while (where != nil) {
469 parent = where;
470 result = dict->compare(key, where->key);
471 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
472 assert(dict->dupes || result != 0);
473 if (result < 0)
474 where = where->left;
475 else
476 where = where->right;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000477 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000478
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100479 assert(where == nil);
480
481 if (result < 0)
482 parent->left = node;
483 else
484 parent->right = node;
485
486 node->parent = parent;
487 node->left = nil;
488 node->right = nil;
489
490 dict->dict_nodecount++;
491
492 /* red black adjustments */
493
494 node->color = dnode_red;
495
496 while (parent->color == dnode_red) {
497 grandpa = parent->parent;
498 if (parent == grandpa->left) {
499 uncle = grandpa->right;
500 if (uncle->color == dnode_red) { /* red parent, red uncle */
501 parent->color = dnode_black;
502 uncle->color = dnode_black;
503 grandpa->color = dnode_red;
504 node = grandpa;
505 parent = grandpa->parent;
506 } else { /* red parent, black uncle */
507 if (node == parent->right) {
508 rotate_left(parent);
509 parent = node;
510 assert (grandpa == parent->parent);
511 /* rotation between parent and child preserves grandpa */
512 }
513 parent->color = dnode_black;
514 grandpa->color = dnode_red;
515 rotate_right(grandpa);
516 break;
517 }
518 } else { /* symmetric cases: parent == parent->parent->right */
519 uncle = grandpa->left;
520 if (uncle->color == dnode_red) {
521 parent->color = dnode_black;
522 uncle->color = dnode_black;
523 grandpa->color = dnode_red;
524 node = grandpa;
525 parent = grandpa->parent;
526 } else {
527 if (node == parent->left) {
528 rotate_right(parent);
529 parent = node;
530 assert (grandpa == parent->parent);
531 }
532 parent->color = dnode_black;
533 grandpa->color = dnode_red;
534 rotate_left(grandpa);
535 break;
536 }
537 }
538 }
539
540 dict_root(dict)->color = dnode_black;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000541}
542
543/*
544 * Allocate a node using the dictionary's allocator routine, give it
545 * the data item.
546 */
547
548static dnode_t *dnode_init(dnode_t *dnode, void *data)
549{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100550 dnode->data = data;
551 dnode->parent = NULL;
552 dnode->left = NULL;
553 dnode->right = NULL;
554 return dnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000555}
556
557static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
558{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100559 dnode_t *node = xmalloc(sizeof(dnode_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000560
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000561 dnode_init(node, data);
562 dict_insert(dict, node, key);
563 return 1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000564}
565
566/*
567 * Return the node with the lowest (leftmost) key. If the dictionary is empty
568 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
569 */
570
571static dnode_t *dict_first(dict_t *dict)
572{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100573 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000574
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100575 if (root != nil)
576 while ((left = root->left) != nil)
577 root = left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000578
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100579 return (root == nil) ? NULL : root;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000580}
581
582/*
583 * Return the given node's successor node---the node which has the
Marek Polacekb0b88842011-04-16 17:33:43 +0200584 * next key in the left to right ordering. If the node has
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000585 * no successor, a null pointer is returned rather than a pointer to
586 * the nil node.
587 */
588
589static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
590{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100591 dnode_t *nil = dict_nil(dict), *parent, *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000592
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100593 if (curr->right != nil) {
594 curr = curr->right;
595 while ((left = curr->left) != nil)
596 curr = left;
597 return curr;
598 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000599
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000600 parent = curr->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000601
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100602 while (parent != nil && curr == parent->right) {
603 curr = parent;
604 parent = curr->parent;
605 }
606
607 return (parent == nil) ? NULL : parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000608}
609
610
611static void dnode_free(dnode_t *node)
612{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100613 free(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000614}
615
616
617#undef left
618#undef right
619#undef parent
620#undef color
621#undef key
622#undef data
623
624#undef nilnode
625#undef maxcount
626#undef compare
627#undef dupes
628
629
630/*
631 * dirinfo.c --- maintains the directory information table for e2fsck.
632 */
633
634/*
635 * This subroutine is called during pass1 to create a directory info
636 * entry. During pass1, the passed-in parent is 0; it will get filled
637 * in during pass2.
638 */
639static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
640{
641 struct dir_info *dir;
642 int i, j;
643 ext2_ino_t num_dirs;
644 errcode_t retval;
645 unsigned long old_size;
646
647 if (!ctx->dir_info) {
648 ctx->dir_info_count = 0;
649 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
650 if (retval)
651 num_dirs = 1024; /* Guess */
652 ctx->dir_info_size = num_dirs + 10;
653 ctx->dir_info = (struct dir_info *)
654 e2fsck_allocate_memory(ctx, ctx->dir_info_size
655 * sizeof (struct dir_info),
656 "directory map");
657 }
658
659 if (ctx->dir_info_count >= ctx->dir_info_size) {
660 old_size = ctx->dir_info_size * sizeof(struct dir_info);
661 ctx->dir_info_size += 10;
662 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
663 sizeof(struct dir_info),
664 &ctx->dir_info);
665 if (retval) {
666 ctx->dir_info_size -= 10;
667 return;
668 }
669 }
670
671 /*
672 * Normally, add_dir_info is called with each inode in
673 * sequential order; but once in a while (like when pass 3
674 * needs to recreate the root directory or lost+found
675 * directory) it is called out of order. In those cases, we
676 * need to move the dir_info entries down to make room, since
677 * the dir_info array needs to be sorted by inode number for
678 * get_dir_info()'s sake.
679 */
680 if (ctx->dir_info_count &&
681 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
682 for (i = ctx->dir_info_count-1; i > 0; i--)
683 if (ctx->dir_info[i-1].ino < ino)
684 break;
685 dir = &ctx->dir_info[i];
686 if (dir->ino != ino)
687 for (j = ctx->dir_info_count++; j > i; j--)
688 ctx->dir_info[j] = ctx->dir_info[j-1];
689 } else
690 dir = &ctx->dir_info[ctx->dir_info_count++];
691
692 dir->ino = ino;
693 dir->dotdot = parent;
694 dir->parent = parent;
695}
696
697/*
698 * get_dir_info() --- given an inode number, try to find the directory
699 * information entry for it.
700 */
701static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
702{
703 int low, high, mid;
704
705 low = 0;
706 high = ctx->dir_info_count-1;
707 if (!ctx->dir_info)
708 return 0;
709 if (ino == ctx->dir_info[low].ino)
710 return &ctx->dir_info[low];
711 if (ino == ctx->dir_info[high].ino)
712 return &ctx->dir_info[high];
713
714 while (low < high) {
715 mid = (low+high)/2;
716 if (mid == low || mid == high)
717 break;
718 if (ino == ctx->dir_info[mid].ino)
719 return &ctx->dir_info[mid];
720 if (ino < ctx->dir_info[mid].ino)
721 high = mid;
722 else
723 low = mid;
724 }
725 return 0;
726}
727
728/*
729 * Free the dir_info structure when it isn't needed any more.
730 */
731static void e2fsck_free_dir_info(e2fsck_t ctx)
732{
733 ext2fs_free_mem(&ctx->dir_info);
734 ctx->dir_info_size = 0;
735 ctx->dir_info_count = 0;
736}
737
738/*
739 * Return the count of number of directories in the dir_info structure
740 */
741static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
742{
743 return ctx->dir_info_count;
744}
745
746/*
747 * A simple interator function
748 */
749static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
750{
751 if (*control >= ctx->dir_info_count)
752 return 0;
753
754 return ctx->dir_info + (*control)++;
755}
756
757/*
758 * dirinfo.c --- maintains the directory information table for e2fsck.
759 *
760 */
761
762#ifdef ENABLE_HTREE
763
764/*
765 * This subroutine is called during pass1 to create a directory info
766 * entry. During pass1, the passed-in parent is 0; it will get filled
767 * in during pass2.
768 */
769static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
770{
771 struct dx_dir_info *dir;
772 int i, j;
773 errcode_t retval;
774 unsigned long old_size;
775
776 if (!ctx->dx_dir_info) {
777 ctx->dx_dir_info_count = 0;
778 ctx->dx_dir_info_size = 100; /* Guess */
779 ctx->dx_dir_info = (struct dx_dir_info *)
780 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
781 * sizeof (struct dx_dir_info),
782 "directory map");
783 }
784
785 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
786 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
787 ctx->dx_dir_info_size += 10;
788 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
789 sizeof(struct dx_dir_info),
790 &ctx->dx_dir_info);
791 if (retval) {
792 ctx->dx_dir_info_size -= 10;
793 return;
794 }
795 }
796
797 /*
798 * Normally, add_dx_dir_info is called with each inode in
799 * sequential order; but once in a while (like when pass 3
800 * needs to recreate the root directory or lost+found
801 * directory) it is called out of order. In those cases, we
802 * need to move the dx_dir_info entries down to make room, since
803 * the dx_dir_info array needs to be sorted by inode number for
804 * get_dx_dir_info()'s sake.
805 */
806 if (ctx->dx_dir_info_count &&
807 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
808 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
809 if (ctx->dx_dir_info[i-1].ino < ino)
810 break;
811 dir = &ctx->dx_dir_info[i];
812 if (dir->ino != ino)
813 for (j = ctx->dx_dir_info_count++; j > i; j--)
814 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
815 } else
816 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
817
818 dir->ino = ino;
819 dir->numblocks = num_blocks;
820 dir->hashversion = 0;
821 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
822 * sizeof (struct dx_dirblock_info),
823 "dx_block info array");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000824}
825
826/*
827 * get_dx_dir_info() --- given an inode number, try to find the directory
828 * information entry for it.
829 */
830static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
831{
832 int low, high, mid;
833
834 low = 0;
835 high = ctx->dx_dir_info_count-1;
836 if (!ctx->dx_dir_info)
837 return 0;
838 if (ino == ctx->dx_dir_info[low].ino)
839 return &ctx->dx_dir_info[low];
840 if (ino == ctx->dx_dir_info[high].ino)
841 return &ctx->dx_dir_info[high];
842
843 while (low < high) {
844 mid = (low+high)/2;
845 if (mid == low || mid == high)
846 break;
847 if (ino == ctx->dx_dir_info[mid].ino)
848 return &ctx->dx_dir_info[mid];
849 if (ino < ctx->dx_dir_info[mid].ino)
850 high = mid;
851 else
852 low = mid;
853 }
854 return 0;
855}
856
857/*
858 * Free the dx_dir_info structure when it isn't needed any more.
859 */
860static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
861{
862 int i;
863 struct dx_dir_info *dir;
864
865 if (ctx->dx_dir_info) {
866 dir = ctx->dx_dir_info;
867 for (i=0; i < ctx->dx_dir_info_count; i++) {
868 ext2fs_free_mem(&dir->dx_block);
869 }
870 ext2fs_free_mem(&ctx->dx_dir_info);
871 }
872 ctx->dx_dir_info_size = 0;
873 ctx->dx_dir_info_count = 0;
874}
875
876/*
877 * A simple interator function
878 */
879static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
880{
881 if (*control >= ctx->dx_dir_info_count)
882 return 0;
883
884 return ctx->dx_dir_info + (*control)++;
885}
886
887#endif /* ENABLE_HTREE */
888/*
889 * e2fsck.c - a consistency checker for the new extended file system.
890 *
891 */
892
893/*
894 * This function allocates an e2fsck context
895 */
896static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
897{
898 e2fsck_t context;
899 errcode_t retval;
900
901 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
902 if (retval)
903 return retval;
904
905 memset(context, 0, sizeof(struct e2fsck_struct));
906
907 context->process_inode_size = 256;
908 context->ext_attr_ver = 2;
909
910 *ret = context;
911 return 0;
912}
913
914struct ea_refcount_el {
915 blk_t ea_blk;
916 int ea_count;
917};
918
919struct ea_refcount {
920 blk_t count;
921 blk_t size;
922 blk_t cursor;
923 struct ea_refcount_el *list;
924};
925
926static void ea_refcount_free(ext2_refcount_t refcount)
927{
928 if (!refcount)
929 return;
930
931 ext2fs_free_mem(&refcount->list);
932 ext2fs_free_mem(&refcount);
933}
934
935/*
936 * This function resets an e2fsck context; it is called when e2fsck
937 * needs to be restarted.
938 */
939static errcode_t e2fsck_reset_context(e2fsck_t ctx)
940{
941 ctx->flags = 0;
942 ctx->lost_and_found = 0;
943 ctx->bad_lost_and_found = 0;
944 ext2fs_free_inode_bitmap(ctx->inode_used_map);
945 ctx->inode_used_map = 0;
946 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
947 ctx->inode_dir_map = 0;
948 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
949 ctx->inode_reg_map = 0;
950 ext2fs_free_block_bitmap(ctx->block_found_map);
951 ctx->block_found_map = 0;
952 ext2fs_free_icount(ctx->inode_link_info);
953 ctx->inode_link_info = 0;
954 if (ctx->journal_io) {
955 if (ctx->fs && ctx->fs->io != ctx->journal_io)
956 io_channel_close(ctx->journal_io);
957 ctx->journal_io = 0;
958 }
959 if (ctx->fs) {
960 ext2fs_free_dblist(ctx->fs->dblist);
961 ctx->fs->dblist = 0;
962 }
963 e2fsck_free_dir_info(ctx);
964#ifdef ENABLE_HTREE
965 e2fsck_free_dx_dir_info(ctx);
966#endif
967 ea_refcount_free(ctx->refcount);
968 ctx->refcount = 0;
969 ea_refcount_free(ctx->refcount_extra);
970 ctx->refcount_extra = 0;
971 ext2fs_free_block_bitmap(ctx->block_dup_map);
972 ctx->block_dup_map = 0;
973 ext2fs_free_block_bitmap(ctx->block_ea_map);
974 ctx->block_ea_map = 0;
975 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
976 ctx->inode_bad_map = 0;
977 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
978 ctx->inode_imagic_map = 0;
979 ext2fs_u32_list_free(ctx->dirs_to_hash);
980 ctx->dirs_to_hash = 0;
981
982 /*
983 * Clear the array of invalid meta-data flags
984 */
985 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
986 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
987 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
988
989 /* Clear statistic counters */
990 ctx->fs_directory_count = 0;
991 ctx->fs_regular_count = 0;
992 ctx->fs_blockdev_count = 0;
993 ctx->fs_chardev_count = 0;
994 ctx->fs_links_count = 0;
995 ctx->fs_symlinks_count = 0;
996 ctx->fs_fast_symlinks_count = 0;
997 ctx->fs_fifo_count = 0;
998 ctx->fs_total_count = 0;
999 ctx->fs_sockets_count = 0;
1000 ctx->fs_ind_count = 0;
1001 ctx->fs_dind_count = 0;
1002 ctx->fs_tind_count = 0;
1003 ctx->fs_fragmented = 0;
1004 ctx->large_files = 0;
1005
1006 /* Reset the superblock to the user's requested value */
1007 ctx->superblock = ctx->use_superblock;
1008
1009 return 0;
1010}
1011
1012static void e2fsck_free_context(e2fsck_t ctx)
1013{
1014 if (!ctx)
1015 return;
1016
1017 e2fsck_reset_context(ctx);
1018 if (ctx->blkid)
1019 blkid_put_cache(ctx->blkid);
1020
1021 ext2fs_free_mem(&ctx);
1022}
1023
1024/*
1025 * ea_refcount.c
1026 */
1027
1028/*
1029 * The strategy we use for keeping track of EA refcounts is as
1030 * follows. We keep a sorted array of first EA blocks and its
1031 * reference counts. Once the refcount has dropped to zero, it is
1032 * removed from the array to save memory space. Once the EA block is
1033 * checked, its bit is set in the block_ea_map bitmap.
1034 */
1035
1036
1037static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1038{
1039 ext2_refcount_t refcount;
1040 errcode_t retval;
1041 size_t bytes;
1042
1043 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1044 if (retval)
1045 return retval;
1046 memset(refcount, 0, sizeof(struct ea_refcount));
1047
1048 if (!size)
1049 size = 500;
1050 refcount->size = size;
1051 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1052#ifdef DEBUG
1053 printf("Refcount allocated %d entries, %d bytes.\n",
1054 refcount->size, bytes);
1055#endif
1056 retval = ext2fs_get_mem(bytes, &refcount->list);
1057 if (retval)
1058 goto errout;
1059 memset(refcount->list, 0, bytes);
1060
1061 refcount->count = 0;
1062 refcount->cursor = 0;
1063
1064 *ret = refcount;
1065 return 0;
1066
1067errout:
1068 ea_refcount_free(refcount);
1069 return retval;
1070}
1071
1072/*
1073 * collapse_refcount() --- go through the refcount array, and get rid
1074 * of any count == zero entries
1075 */
1076static void refcount_collapse(ext2_refcount_t refcount)
1077{
1078 unsigned int i, j;
1079 struct ea_refcount_el *list;
1080
1081 list = refcount->list;
1082 for (i = 0, j = 0; i < refcount->count; i++) {
1083 if (list[i].ea_count) {
1084 if (i != j)
1085 list[j] = list[i];
1086 j++;
1087 }
1088 }
1089#if defined(DEBUG) || defined(TEST_PROGRAM)
1090 printf("Refcount_collapse: size was %d, now %d\n",
1091 refcount->count, j);
1092#endif
1093 refcount->count = j;
1094}
1095
1096
1097/*
1098 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1099 * specified position.
1100 */
1101static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1102 blk_t blk, int pos)
1103{
1104 struct ea_refcount_el *el;
1105 errcode_t retval;
1106 blk_t new_size = 0;
1107 int num;
1108
1109 if (refcount->count >= refcount->size) {
1110 new_size = refcount->size + 100;
1111#ifdef DEBUG
1112 printf("Reallocating refcount %d entries...\n", new_size);
1113#endif
1114 retval = ext2fs_resize_mem((size_t) refcount->size *
1115 sizeof(struct ea_refcount_el),
1116 (size_t) new_size *
1117 sizeof(struct ea_refcount_el),
1118 &refcount->list);
1119 if (retval)
1120 return 0;
1121 refcount->size = new_size;
1122 }
1123 num = (int) refcount->count - pos;
1124 if (num < 0)
1125 return 0; /* should never happen */
1126 if (num) {
1127 memmove(&refcount->list[pos+1], &refcount->list[pos],
1128 sizeof(struct ea_refcount_el) * num);
1129 }
1130 refcount->count++;
1131 el = &refcount->list[pos];
1132 el->ea_count = 0;
1133 el->ea_blk = blk;
1134 return el;
1135}
1136
1137
1138/*
1139 * get_refcount_el() --- given an block number, try to find refcount
1140 * information in the sorted list. If the create flag is set,
1141 * and we can't find an entry, create one in the sorted list.
1142 */
1143static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1144 blk_t blk, int create)
1145{
1146 float range;
1147 int low, high, mid;
1148 blk_t lowval, highval;
1149
1150 if (!refcount || !refcount->list)
1151 return 0;
1152retry:
1153 low = 0;
1154 high = (int) refcount->count-1;
1155 if (create && ((refcount->count == 0) ||
1156 (blk > refcount->list[high].ea_blk))) {
1157 if (refcount->count >= refcount->size)
1158 refcount_collapse(refcount);
1159
1160 return insert_refcount_el(refcount, blk,
1161 (unsigned) refcount->count);
1162 }
1163 if (refcount->count == 0)
1164 return 0;
1165
1166 if (refcount->cursor >= refcount->count)
1167 refcount->cursor = 0;
1168 if (blk == refcount->list[refcount->cursor].ea_blk)
1169 return &refcount->list[refcount->cursor++];
1170#ifdef DEBUG
1171 printf("Non-cursor get_refcount_el: %u\n", blk);
1172#endif
1173 while (low <= high) {
1174 if (low == high)
1175 mid = low;
1176 else {
1177 /* Interpolate for efficiency */
1178 lowval = refcount->list[low].ea_blk;
1179 highval = refcount->list[high].ea_blk;
1180
1181 if (blk < lowval)
1182 range = 0;
1183 else if (blk > highval)
1184 range = 1;
1185 else
1186 range = ((float) (blk - lowval)) /
1187 (highval - lowval);
1188 mid = low + ((int) (range * (high-low)));
1189 }
1190
1191 if (blk == refcount->list[mid].ea_blk) {
1192 refcount->cursor = mid+1;
1193 return &refcount->list[mid];
1194 }
1195 if (blk < refcount->list[mid].ea_blk)
1196 high = mid-1;
1197 else
1198 low = mid+1;
1199 }
1200 /*
1201 * If we need to create a new entry, it should be right at
1202 * low (where high will be left at low-1).
1203 */
1204 if (create) {
1205 if (refcount->count >= refcount->size) {
1206 refcount_collapse(refcount);
1207 if (refcount->count < refcount->size)
1208 goto retry;
1209 }
1210 return insert_refcount_el(refcount, blk, low);
1211 }
1212 return 0;
1213}
1214
1215static errcode_t
1216ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1217{
1218 struct ea_refcount_el *el;
1219
1220 el = get_refcount_el(refcount, blk, 1);
1221 if (!el)
1222 return EXT2_ET_NO_MEMORY;
1223 el->ea_count++;
1224
1225 if (ret)
1226 *ret = el->ea_count;
1227 return 0;
1228}
1229
1230static errcode_t
1231ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1232{
1233 struct ea_refcount_el *el;
1234
1235 el = get_refcount_el(refcount, blk, 0);
1236 if (!el || el->ea_count == 0)
1237 return EXT2_ET_INVALID_ARGUMENT;
1238
1239 el->ea_count--;
1240
1241 if (ret)
1242 *ret = el->ea_count;
1243 return 0;
1244}
1245
1246static errcode_t
1247ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1248{
1249 struct ea_refcount_el *el;
1250
1251 /*
1252 * Get the refcount element
1253 */
1254 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1255 if (!el)
1256 return count ? EXT2_ET_NO_MEMORY : 0;
1257 el->ea_count = count;
1258 return 0;
1259}
1260
1261static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1262{
1263 refcount->cursor = 0;
1264}
1265
1266
1267static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1268{
1269 struct ea_refcount_el *list;
1270
1271 while (1) {
1272 if (refcount->cursor >= refcount->count)
1273 return 0;
1274 list = refcount->list;
1275 if (list[refcount->cursor].ea_count) {
1276 if (ret)
1277 *ret = list[refcount->cursor].ea_count;
1278 return list[refcount->cursor++].ea_blk;
1279 }
1280 refcount->cursor++;
1281 }
1282}
1283
1284
1285/*
1286 * ehandler.c --- handle bad block errors which come up during the
1287 * course of an e2fsck session.
1288 */
1289
1290
1291static const char *operation;
1292
1293static errcode_t
1294e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1295 void *data, size_t size FSCK_ATTR((unused)),
1296 int actual FSCK_ATTR((unused)), errcode_t error)
1297{
1298 int i;
1299 char *p;
1300 ext2_filsys fs = (ext2_filsys) channel->app_data;
1301 e2fsck_t ctx;
1302
1303 ctx = (e2fsck_t) fs->priv_data;
1304
1305 /*
1306 * If more than one block was read, try reading each block
1307 * separately. We could use the actual bytes read to figure
1308 * out where to start, but we don't bother.
1309 */
1310 if (count > 1) {
1311 p = (char *) data;
1312 for (i=0; i < count; i++, p += channel->block_size, block++) {
1313 error = io_channel_read_blk(channel, block,
1314 1, p);
1315 if (error)
1316 return error;
1317 }
1318 return 0;
1319 }
1320 if (operation)
1321 printf(_("Error reading block %lu (%s) while %s. "), block,
1322 error_message(error), operation);
1323 else
1324 printf(_("Error reading block %lu (%s). "), block,
1325 error_message(error));
1326 preenhalt(ctx);
1327 if (ask(ctx, _("Ignore error"), 1)) {
1328 if (ask(ctx, _("Force rewrite"), 1))
1329 io_channel_write_blk(channel, block, 1, data);
1330 return 0;
1331 }
1332
1333 return error;
1334}
1335
1336static errcode_t
1337e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1338 const void *data, size_t size FSCK_ATTR((unused)),
1339 int actual FSCK_ATTR((unused)), errcode_t error)
1340{
1341 int i;
1342 const char *p;
1343 ext2_filsys fs = (ext2_filsys) channel->app_data;
1344 e2fsck_t ctx;
1345
1346 ctx = (e2fsck_t) fs->priv_data;
1347
1348 /*
1349 * If more than one block was written, try writing each block
1350 * separately. We could use the actual bytes read to figure
1351 * out where to start, but we don't bother.
1352 */
1353 if (count > 1) {
1354 p = (const char *) data;
1355 for (i=0; i < count; i++, p += channel->block_size, block++) {
1356 error = io_channel_write_blk(channel, block,
1357 1, p);
1358 if (error)
1359 return error;
1360 }
1361 return 0;
1362 }
1363
1364 if (operation)
1365 printf(_("Error writing block %lu (%s) while %s. "), block,
1366 error_message(error), operation);
1367 else
1368 printf(_("Error writing block %lu (%s). "), block,
1369 error_message(error));
1370 preenhalt(ctx);
1371 if (ask(ctx, _("Ignore error"), 1))
1372 return 0;
1373
1374 return error;
1375}
1376
1377static const char *ehandler_operation(const char *op)
1378{
1379 const char *ret = operation;
1380
1381 operation = op;
1382 return ret;
1383}
1384
1385static void ehandler_init(io_channel channel)
1386{
1387 channel->read_error = e2fsck_handle_read_error;
1388 channel->write_error = e2fsck_handle_write_error;
1389}
1390
1391/*
1392 * journal.c --- code for handling the "ext3" journal
1393 *
1394 * Copyright (C) 2000 Andreas Dilger
1395 * Copyright (C) 2000 Theodore Ts'o
1396 *
1397 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1398 * Copyright (C) 1999 Red Hat Software
1399 *
1400 * This file may be redistributed under the terms of the
1401 * GNU General Public License version 2 or at your discretion
1402 * any later version.
1403 */
1404
1405/*
1406 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1407 * This creates a larger static binary, and a smaller binary using
1408 * shared libraries. It's also probably slightly less CPU-efficient,
1409 * which is why it's not on by default. But, it's a good way of
1410 * testing the functions in inode_io.c and fileio.c.
1411 */
1412#undef USE_INODE_IO
1413
1414/* Kernel compatibility functions for handling the journal. These allow us
1415 * to use the recovery.c file virtually unchanged from the kernel, so we
1416 * don't have to do much to keep kernel and user recovery in sync.
1417 */
1418static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1419{
1420#ifdef USE_INODE_IO
1421 *phys = block;
1422 return 0;
1423#else
1424 struct inode *inode = journal->j_inode;
1425 errcode_t retval;
1426 blk_t pblk;
1427
1428 if (!inode) {
1429 *phys = block;
1430 return 0;
1431 }
1432
1433 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1434 &inode->i_ext2, NULL, 0, block, &pblk);
1435 *phys = pblk;
1436 return retval;
1437#endif
1438}
1439
1440static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1441{
1442 struct buffer_head *bh;
1443
1444 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1445 if (!bh)
1446 return NULL;
1447
1448 bh->b_ctx = kdev->k_ctx;
1449 if (kdev->k_dev == K_DEV_FS)
1450 bh->b_io = kdev->k_ctx->fs->io;
1451 else
1452 bh->b_io = kdev->k_ctx->journal_io;
1453 bh->b_size = blocksize;
1454 bh->b_blocknr = blocknr;
1455
1456 return bh;
1457}
1458
1459static void sync_blockdev(kdev_t kdev)
1460{
1461 io_channel io;
1462
1463 if (kdev->k_dev == K_DEV_FS)
1464 io = kdev->k_ctx->fs->io;
1465 else
1466 io = kdev->k_ctx->journal_io;
1467
1468 io_channel_flush(io);
1469}
1470
1471static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1472{
1473 int retval;
1474 struct buffer_head *bh;
1475
1476 for (; nr > 0; --nr) {
1477 bh = *bhp++;
1478 if (rw == READ && !bh->b_uptodate) {
1479 retval = io_channel_read_blk(bh->b_io,
1480 bh->b_blocknr,
1481 1, bh->b_data);
1482 if (retval) {
1483 bb_error_msg("while reading block %lu",
1484 (unsigned long) bh->b_blocknr);
1485 bh->b_err = retval;
1486 continue;
1487 }
1488 bh->b_uptodate = 1;
1489 } else if (rw == WRITE && bh->b_dirty) {
1490 retval = io_channel_write_blk(bh->b_io,
1491 bh->b_blocknr,
1492 1, bh->b_data);
1493 if (retval) {
1494 bb_error_msg("while writing block %lu",
1495 (unsigned long) bh->b_blocknr);
1496 bh->b_err = retval;
1497 continue;
1498 }
1499 bh->b_dirty = 0;
1500 bh->b_uptodate = 1;
1501 }
1502 }
1503}
1504
1505static void mark_buffer_dirty(struct buffer_head *bh)
1506{
1507 bh->b_dirty = 1;
1508}
1509
1510static inline void mark_buffer_clean(struct buffer_head * bh)
1511{
1512 bh->b_dirty = 0;
1513}
1514
1515static void brelse(struct buffer_head *bh)
1516{
1517 if (bh->b_dirty)
1518 ll_rw_block(WRITE, 1, &bh);
1519 ext2fs_free_mem(&bh);
1520}
1521
1522static int buffer_uptodate(struct buffer_head *bh)
1523{
1524 return bh->b_uptodate;
1525}
1526
1527static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1528{
1529 bh->b_uptodate = val;
1530}
1531
1532static void wait_on_buffer(struct buffer_head *bh)
1533{
1534 if (!bh->b_uptodate)
1535 ll_rw_block(READ, 1, &bh);
1536}
1537
1538
1539static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1540{
1541 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1542
1543 /* if we had an error doing journal recovery, we need a full fsck */
1544 if (error)
1545 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1546 ext2fs_mark_super_dirty(ctx->fs);
1547}
1548
1549static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1550{
1551 struct ext2_super_block *sb = ctx->fs->super;
1552 struct ext2_super_block jsuper;
1553 struct problem_context pctx;
1554 struct buffer_head *bh;
1555 struct inode *j_inode = NULL;
1556 struct kdev_s *dev_fs = NULL, *dev_journal;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01001557 const char *journal_name = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001558 journal_t *journal = NULL;
1559 errcode_t retval = 0;
1560 io_manager io_ptr = 0;
1561 unsigned long start = 0;
1562 blk_t blk;
1563 int ext_journal = 0;
1564 int tried_backup_jnl = 0;
1565 int i;
1566
1567 clear_problem_context(&pctx);
1568
1569 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1570 if (!journal) {
1571 return EXT2_ET_NO_MEMORY;
1572 }
1573
1574 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1575 if (!dev_fs) {
1576 retval = EXT2_ET_NO_MEMORY;
1577 goto errout;
1578 }
1579 dev_journal = dev_fs+1;
1580
1581 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1582 dev_fs->k_dev = K_DEV_FS;
1583 dev_journal->k_dev = K_DEV_JOURNAL;
1584
1585 journal->j_dev = dev_journal;
1586 journal->j_fs_dev = dev_fs;
1587 journal->j_inode = NULL;
1588 journal->j_blocksize = ctx->fs->blocksize;
1589
1590 if (uuid_is_null(sb->s_journal_uuid)) {
1591 if (!sb->s_journal_inum)
1592 return EXT2_ET_BAD_INODE_NUM;
1593 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1594 "journal inode");
1595 if (!j_inode) {
1596 retval = EXT2_ET_NO_MEMORY;
1597 goto errout;
1598 }
1599
1600 j_inode->i_ctx = ctx;
1601 j_inode->i_ino = sb->s_journal_inum;
1602
1603 if ((retval = ext2fs_read_inode(ctx->fs,
1604 sb->s_journal_inum,
1605 &j_inode->i_ext2))) {
1606 try_backup_journal:
1607 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1608 tried_backup_jnl)
1609 goto errout;
1610 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1611 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1612 EXT2_N_BLOCKS*4);
1613 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1614 j_inode->i_ext2.i_links_count = 1;
1615 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1616 tried_backup_jnl++;
1617 }
1618 if (!j_inode->i_ext2.i_links_count ||
1619 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1620 retval = EXT2_ET_NO_JOURNAL;
1621 goto try_backup_journal;
1622 }
1623 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1624 JFS_MIN_JOURNAL_BLOCKS) {
1625 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1626 goto try_backup_journal;
1627 }
1628 for (i=0; i < EXT2_N_BLOCKS; i++) {
1629 blk = j_inode->i_ext2.i_block[i];
1630 if (!blk) {
1631 if (i < EXT2_NDIR_BLOCKS) {
1632 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1633 goto try_backup_journal;
1634 }
1635 continue;
1636 }
1637 if (blk < sb->s_first_data_block ||
1638 blk >= sb->s_blocks_count) {
1639 retval = EXT2_ET_BAD_BLOCK_NUM;
1640 goto try_backup_journal;
1641 }
1642 }
1643 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1644
1645#ifdef USE_INODE_IO
1646 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1647 &j_inode->i_ext2,
1648 &journal_name);
1649 if (retval)
1650 goto errout;
1651
1652 io_ptr = inode_io_manager;
1653#else
1654 journal->j_inode = j_inode;
1655 ctx->journal_io = ctx->fs->io;
1656 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1657 goto errout;
1658#endif
1659 } else {
1660 ext_journal = 1;
1661 if (!ctx->journal_name) {
1662 char uuid[37];
1663
1664 uuid_unparse(sb->s_journal_uuid, uuid);
1665 ctx->journal_name = blkid_get_devname(ctx->blkid,
1666 "UUID", uuid);
1667 if (!ctx->journal_name)
1668 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1669 }
1670 journal_name = ctx->journal_name;
1671
1672 if (!journal_name) {
1673 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1674 return EXT2_ET_LOAD_EXT_JOURNAL;
1675 }
1676
1677 io_ptr = unix_io_manager;
1678 }
1679
1680#ifndef USE_INODE_IO
1681 if (ext_journal)
1682#endif
1683 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1684 &ctx->journal_io);
1685 if (retval)
1686 goto errout;
1687
1688 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1689
1690 if (ext_journal) {
1691 if (ctx->fs->blocksize == 1024)
1692 start = 1;
1693 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1694 if (!bh) {
1695 retval = EXT2_ET_NO_MEMORY;
1696 goto errout;
1697 }
1698 ll_rw_block(READ, 1, &bh);
1699 if ((retval = bh->b_err) != 0)
1700 goto errout;
1701 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1702 sizeof(jsuper));
1703 brelse(bh);
1704#if BB_BIG_ENDIAN
1705 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1706 ext2fs_swap_super(&jsuper);
1707#endif
1708 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1709 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1710 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1711 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1712 goto errout;
1713 }
1714 /* Make sure the journal UUID is correct */
1715 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1716 sizeof(jsuper.s_uuid))) {
1717 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1718 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1719 goto errout;
1720 }
1721
1722 journal->j_maxlen = jsuper.s_blocks_count;
1723 start++;
1724 }
1725
1726 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1727 retval = EXT2_ET_NO_MEMORY;
1728 goto errout;
1729 }
1730
1731 journal->j_sb_buffer = bh;
1732 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1733
1734#ifdef USE_INODE_IO
1735 ext2fs_free_mem(&j_inode);
1736#endif
1737
1738 *ret_journal = journal;
1739 return 0;
1740
1741errout:
1742 ext2fs_free_mem(&dev_fs);
1743 ext2fs_free_mem(&j_inode);
1744 ext2fs_free_mem(&journal);
1745 return retval;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001746}
1747
1748static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1749 struct problem_context *pctx)
1750{
1751 struct ext2_super_block *sb = ctx->fs->super;
1752 int recover = ctx->fs->super->s_feature_incompat &
1753 EXT3_FEATURE_INCOMPAT_RECOVER;
1754 int has_journal = ctx->fs->super->s_feature_compat &
1755 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1756
1757 if (has_journal || sb->s_journal_inum) {
1758 /* The journal inode is bogus, remove and force full fsck */
1759 pctx->ino = sb->s_journal_inum;
1760 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1761 if (has_journal && sb->s_journal_inum)
1762 printf("*** ext3 journal has been deleted - "
1763 "filesystem is now ext2 only ***\n\n");
1764 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1765 sb->s_journal_inum = 0;
1766 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1767 e2fsck_clear_recover(ctx, 1);
1768 return 0;
1769 }
1770 return EXT2_ET_BAD_INODE_NUM;
1771 } else if (recover) {
1772 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1773 e2fsck_clear_recover(ctx, 1);
1774 return 0;
1775 }
1776 return EXT2_ET_UNSUPP_FEATURE;
1777 }
1778 return 0;
1779}
1780
1781#define V1_SB_SIZE 0x0024
1782static void clear_v2_journal_fields(journal_t *journal)
1783{
1784 e2fsck_t ctx = journal->j_dev->k_ctx;
1785 struct problem_context pctx;
1786
1787 clear_problem_context(&pctx);
1788
1789 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1790 return;
1791
1792 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1793 ctx->fs->blocksize-V1_SB_SIZE);
1794 mark_buffer_dirty(journal->j_sb_buffer);
1795}
1796
1797
1798static errcode_t e2fsck_journal_load(journal_t *journal)
1799{
1800 e2fsck_t ctx = journal->j_dev->k_ctx;
1801 journal_superblock_t *jsb;
1802 struct buffer_head *jbh = journal->j_sb_buffer;
1803 struct problem_context pctx;
1804
1805 clear_problem_context(&pctx);
1806
1807 ll_rw_block(READ, 1, &jbh);
1808 if (jbh->b_err) {
1809 bb_error_msg(_("reading journal superblock"));
1810 return jbh->b_err;
1811 }
1812
1813 jsb = journal->j_superblock;
1814 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1815 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1816 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1817
1818 switch (ntohl(jsb->s_header.h_blocktype)) {
1819 case JFS_SUPERBLOCK_V1:
1820 journal->j_format_version = 1;
1821 if (jsb->s_feature_compat ||
1822 jsb->s_feature_incompat ||
1823 jsb->s_feature_ro_compat ||
1824 jsb->s_nr_users)
1825 clear_v2_journal_fields(journal);
1826 break;
1827
1828 case JFS_SUPERBLOCK_V2:
1829 journal->j_format_version = 2;
1830 if (ntohl(jsb->s_nr_users) > 1 &&
1831 uuid_is_null(ctx->fs->super->s_journal_uuid))
1832 clear_v2_journal_fields(journal);
1833 if (ntohl(jsb->s_nr_users) > 1) {
1834 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1835 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1836 }
1837 break;
1838
1839 /*
1840 * These should never appear in a journal super block, so if
1841 * they do, the journal is badly corrupted.
1842 */
1843 case JFS_DESCRIPTOR_BLOCK:
1844 case JFS_COMMIT_BLOCK:
1845 case JFS_REVOKE_BLOCK:
1846 return EXT2_ET_CORRUPT_SUPERBLOCK;
1847
1848 /* If we don't understand the superblock major type, but there
1849 * is a magic number, then it is likely to be a new format we
1850 * just don't understand, so leave it alone. */
1851 default:
1852 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1853 }
1854
1855 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1856 return EXT2_ET_UNSUPP_FEATURE;
1857
1858 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1859 return EXT2_ET_RO_UNSUPP_FEATURE;
1860
1861 /* We have now checked whether we know enough about the journal
1862 * format to be able to proceed safely, so any other checks that
1863 * fail we should attempt to recover from. */
1864 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1865 bb_error_msg(_("%s: no valid journal superblock found"),
1866 ctx->device_name);
1867 return EXT2_ET_CORRUPT_SUPERBLOCK;
1868 }
1869
1870 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1871 journal->j_maxlen = ntohl(jsb->s_maxlen);
1872 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1873 bb_error_msg(_("%s: journal too short"),
1874 ctx->device_name);
1875 return EXT2_ET_CORRUPT_SUPERBLOCK;
1876 }
1877
1878 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1879 journal->j_transaction_sequence = journal->j_tail_sequence;
1880 journal->j_tail = ntohl(jsb->s_start);
1881 journal->j_first = ntohl(jsb->s_first);
1882 journal->j_last = ntohl(jsb->s_maxlen);
1883
1884 return 0;
1885}
1886
1887static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1888 journal_t *journal)
1889{
1890 char *p;
1891 union {
1892 uuid_t uuid;
1893 __u32 val[4];
1894 } u;
1895 __u32 new_seq = 0;
1896 int i;
1897
1898 /* Leave a valid existing V1 superblock signature alone.
Denys Vlasenkob22bbff2009-07-04 16:50:43 +02001899 * Anything unrecognizable we overwrite with a new V2
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001900 * signature. */
1901
1902 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1903 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1904 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1905 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1906 }
1907
1908 /* Zero out everything else beyond the superblock header */
1909
1910 p = ((char *) jsb) + sizeof(journal_header_t);
1911 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1912
1913 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1914 jsb->s_maxlen = htonl(journal->j_maxlen);
1915 jsb->s_first = htonl(1);
1916
1917 /* Initialize the journal sequence number so that there is "no"
1918 * chance we will find old "valid" transactions in the journal.
1919 * This avoids the need to zero the whole journal (slow to do,
1920 * and risky when we are just recovering the filesystem).
1921 */
1922 uuid_generate(u.uuid);
1923 for (i = 0; i < 4; i ++)
1924 new_seq ^= u.val[i];
1925 jsb->s_sequence = htonl(new_seq);
1926
1927 mark_buffer_dirty(journal->j_sb_buffer);
1928 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1929}
1930
1931static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1932 journal_t *journal,
1933 struct problem_context *pctx)
1934{
1935 struct ext2_super_block *sb = ctx->fs->super;
1936 int recover = ctx->fs->super->s_feature_incompat &
1937 EXT3_FEATURE_INCOMPAT_RECOVER;
1938
1939 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1940 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1941 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1942 journal);
1943 journal->j_transaction_sequence = 1;
1944 e2fsck_clear_recover(ctx, recover);
1945 return 0;
1946 }
1947 return EXT2_ET_CORRUPT_SUPERBLOCK;
1948 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1949 return EXT2_ET_CORRUPT_SUPERBLOCK;
1950
1951 return 0;
1952}
1953
1954static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1955 int reset, int drop)
1956{
1957 journal_superblock_t *jsb;
1958
1959 if (drop)
1960 mark_buffer_clean(journal->j_sb_buffer);
1961 else if (!(ctx->options & E2F_OPT_READONLY)) {
1962 jsb = journal->j_superblock;
1963 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1964 if (reset)
1965 jsb->s_start = 0; /* this marks the journal as empty */
1966 mark_buffer_dirty(journal->j_sb_buffer);
1967 }
1968 brelse(journal->j_sb_buffer);
1969
1970 if (ctx->journal_io) {
1971 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1972 io_channel_close(ctx->journal_io);
1973 ctx->journal_io = 0;
1974 }
1975
1976#ifndef USE_INODE_IO
1977 ext2fs_free_mem(&journal->j_inode);
1978#endif
1979 ext2fs_free_mem(&journal->j_fs_dev);
1980 ext2fs_free_mem(&journal);
1981}
1982
1983/*
1984 * This function makes sure that the superblock fields regarding the
1985 * journal are consistent.
1986 */
1987static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1988{
1989 struct ext2_super_block *sb = ctx->fs->super;
1990 journal_t *journal;
1991 int recover = ctx->fs->super->s_feature_incompat &
1992 EXT3_FEATURE_INCOMPAT_RECOVER;
1993 struct problem_context pctx;
1994 problem_t problem;
1995 int reset = 0, force_fsck = 0;
1996 int retval;
1997
1998 /* If we don't have any journal features, don't do anything more */
1999 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2000 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2001 uuid_is_null(sb->s_journal_uuid))
2002 return 0;
2003
2004 clear_problem_context(&pctx);
2005 pctx.num = sb->s_journal_inum;
2006
2007 retval = e2fsck_get_journal(ctx, &journal);
2008 if (retval) {
2009 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2010 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2011 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2012 (retval == EXT2_ET_NO_JOURNAL))
2013 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2014 return retval;
2015 }
2016
2017 retval = e2fsck_journal_load(journal);
2018 if (retval) {
2019 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2020 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2021 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2022 &pctx))) ||
2023 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2024 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2025 &pctx))) ||
2026 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2027 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2028 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2029 &pctx);
2030 e2fsck_journal_release(ctx, journal, 0, 1);
2031 return retval;
2032 }
2033
2034 /*
2035 * We want to make the flags consistent here. We will not leave with
2036 * needs_recovery set but has_journal clear. We can't get in a loop
2037 * with -y, -n, or -p, only if a user isn't making up their mind.
2038 */
2039no_has_journal:
2040 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2041 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2042 pctx.str = "inode";
2043 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2044 if (recover &&
2045 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2046 goto no_has_journal;
2047 /*
2048 * Need a full fsck if we are releasing a
2049 * journal stored on a reserved inode.
2050 */
2051 force_fsck = recover ||
2052 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2053 /* Clear all of the journal fields */
2054 sb->s_journal_inum = 0;
2055 sb->s_journal_dev = 0;
2056 memset(sb->s_journal_uuid, 0,
2057 sizeof(sb->s_journal_uuid));
2058 e2fsck_clear_recover(ctx, force_fsck);
2059 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2060 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2061 ext2fs_mark_super_dirty(ctx->fs);
2062 }
2063 }
2064
2065 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2066 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2067 journal->j_superblock->s_start != 0) {
2068 /* Print status information */
2069 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2070 if (ctx->superblock)
2071 problem = PR_0_JOURNAL_RUN_DEFAULT;
2072 else
2073 problem = PR_0_JOURNAL_RUN;
2074 if (fix_problem(ctx, problem, &pctx)) {
2075 ctx->options |= E2F_OPT_FORCE;
2076 sb->s_feature_incompat |=
2077 EXT3_FEATURE_INCOMPAT_RECOVER;
2078 ext2fs_mark_super_dirty(ctx->fs);
2079 } else if (fix_problem(ctx,
2080 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2081 reset = 1;
2082 sb->s_state &= ~EXT2_VALID_FS;
2083 ext2fs_mark_super_dirty(ctx->fs);
2084 }
2085 /*
2086 * If the user answers no to the above question, we
2087 * ignore the fact that journal apparently has data;
2088 * accidentally replaying over valid data would be far
2089 * worse than skipping a questionable recovery.
2090 *
2091 * XXX should we abort with a fatal error here? What
2092 * will the ext3 kernel code do if a filesystem with
2093 * !NEEDS_RECOVERY but with a non-zero
2094 * journal->j_superblock->s_start is mounted?
2095 */
2096 }
2097
2098 e2fsck_journal_release(ctx, journal, reset, 0);
2099 return retval;
2100}
2101
2102static errcode_t recover_ext3_journal(e2fsck_t ctx)
2103{
2104 journal_t *journal;
2105 int retval;
2106
2107 journal_init_revoke_caches();
2108 retval = e2fsck_get_journal(ctx, &journal);
2109 if (retval)
2110 return retval;
2111
2112 retval = e2fsck_journal_load(journal);
2113 if (retval)
2114 goto errout;
2115
2116 retval = journal_init_revoke(journal, 1024);
2117 if (retval)
2118 goto errout;
2119
2120 retval = -journal_recover(journal);
2121 if (retval)
2122 goto errout;
2123
2124 if (journal->j_superblock->s_errno) {
2125 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2126 ext2fs_mark_super_dirty(ctx->fs);
2127 journal->j_superblock->s_errno = 0;
2128 mark_buffer_dirty(journal->j_sb_buffer);
2129 }
2130
2131errout:
2132 journal_destroy_revoke(journal);
2133 journal_destroy_revoke_caches();
2134 e2fsck_journal_release(ctx, journal, 1, 0);
2135 return retval;
2136}
2137
2138static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2139{
2140 io_manager io_ptr = ctx->fs->io->manager;
2141 int blocksize = ctx->fs->blocksize;
2142 errcode_t retval, recover_retval;
2143
2144 printf(_("%s: recovering journal\n"), ctx->device_name);
2145 if (ctx->options & E2F_OPT_READONLY) {
2146 printf(_("%s: won't do journal recovery while read-only\n"),
2147 ctx->device_name);
2148 return EXT2_ET_FILE_RO;
2149 }
2150
2151 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2152 ext2fs_flush(ctx->fs); /* Force out any modifications */
2153
2154 recover_retval = recover_ext3_journal(ctx);
2155
2156 /*
2157 * Reload the filesystem context to get up-to-date data from disk
2158 * because journal recovery will change the filesystem under us.
2159 */
2160 ext2fs_close(ctx->fs);
2161 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2162 ctx->superblock, blocksize, io_ptr,
2163 &ctx->fs);
2164
2165 if (retval) {
2166 bb_error_msg(_("while trying to re-open %s"),
2167 ctx->device_name);
2168 bb_error_msg_and_die(0);
2169 }
2170 ctx->fs->priv_data = ctx;
2171
2172 /* Set the superblock flags */
2173 e2fsck_clear_recover(ctx, recover_retval);
2174 return recover_retval;
2175}
2176
2177/*
2178 * This function will move the journal inode from a visible file in
2179 * the filesystem directory hierarchy to the reserved inode if necessary.
2180 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002181static const char *const journal_names[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002182 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2183
2184static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2185{
2186 struct ext2_super_block *sb = ctx->fs->super;
2187 struct problem_context pctx;
2188 struct ext2_inode inode;
2189 ext2_filsys fs = ctx->fs;
2190 ext2_ino_t ino;
2191 errcode_t retval;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002192 const char *const * cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002193 int group, mount_flags;
2194
2195 clear_problem_context(&pctx);
2196
2197 /*
2198 * If the filesystem is opened read-only, or there is no
2199 * journal, then do nothing.
2200 */
2201 if ((ctx->options & E2F_OPT_READONLY) ||
2202 (sb->s_journal_inum == 0) ||
2203 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2204 return;
2205
2206 /*
2207 * Read in the journal inode
2208 */
2209 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2210 return;
2211
2212 /*
2213 * If it's necessary to backup the journal inode, do so.
2214 */
2215 if ((sb->s_jnl_backup_type == 0) ||
2216 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2217 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2218 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2219 memcpy(sb->s_jnl_blocks, inode.i_block,
2220 EXT2_N_BLOCKS*4);
2221 sb->s_jnl_blocks[16] = inode.i_size;
2222 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2223 ext2fs_mark_super_dirty(fs);
2224 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2225 }
2226 }
2227
2228 /*
2229 * If the journal is already the hidden inode, then do nothing
2230 */
2231 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2232 return;
2233
2234 /*
2235 * The journal inode had better have only one link and not be readable.
2236 */
2237 if (inode.i_links_count != 1)
2238 return;
2239
2240 /*
2241 * If the filesystem is mounted, or we can't tell whether
2242 * or not it's mounted, do nothing.
2243 */
2244 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2245 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2246 return;
2247
2248 /*
2249 * If we can't find the name of the journal inode, then do
2250 * nothing.
2251 */
2252 for (cpp = journal_names; *cpp; cpp++) {
2253 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2254 strlen(*cpp), 0, &ino);
2255 if ((retval == 0) && (ino == sb->s_journal_inum))
2256 break;
2257 }
2258 if (*cpp == 0)
2259 return;
2260
2261 /* We need the inode bitmap to be loaded */
2262 retval = ext2fs_read_bitmaps(fs);
2263 if (retval)
2264 return;
2265
2266 pctx.str = *cpp;
2267 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2268 return;
2269
2270 /*
2271 * OK, we've done all the checks, let's actually move the
2272 * journal inode. Errors at this point mean we need to force
2273 * an ext2 filesystem check.
2274 */
2275 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2276 goto err_out;
2277 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2278 goto err_out;
2279 sb->s_journal_inum = EXT2_JOURNAL_INO;
2280 ext2fs_mark_super_dirty(fs);
2281 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2282 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00002283 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002284 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2285 goto err_out;
2286
2287 group = ext2fs_group_of_ino(fs, ino);
2288 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2289 ext2fs_mark_ib_dirty(fs);
2290 fs->group_desc[group].bg_free_inodes_count++;
2291 fs->super->s_free_inodes_count++;
2292 return;
2293
2294err_out:
2295 pctx.errcode = retval;
2296 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2297 fs->super->s_state &= ~EXT2_VALID_FS;
2298 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002299}
2300
2301/*
2302 * message.c --- print e2fsck messages (with compression)
2303 *
2304 * print_e2fsck_message() prints a message to the user, using
2305 * compression techniques and expansions of abbreviations.
2306 *
2307 * The following % expansions are supported:
2308 *
2309 * %b <blk> block number
2310 * %B <blkcount> integer
2311 * %c <blk2> block number
2312 * %Di <dirent>->ino inode number
2313 * %Dn <dirent>->name string
2314 * %Dr <dirent>->rec_len
2315 * %Dl <dirent>->name_len
2316 * %Dt <dirent>->filetype
2317 * %d <dir> inode number
2318 * %g <group> integer
2319 * %i <ino> inode number
2320 * %Is <inode> -> i_size
2321 * %IS <inode> -> i_extra_isize
2322 * %Ib <inode> -> i_blocks
2323 * %Il <inode> -> i_links_count
2324 * %Im <inode> -> i_mode
2325 * %IM <inode> -> i_mtime
2326 * %IF <inode> -> i_faddr
2327 * %If <inode> -> i_file_acl
2328 * %Id <inode> -> i_dir_acl
2329 * %Iu <inode> -> i_uid
2330 * %Ig <inode> -> i_gid
2331 * %j <ino2> inode number
2332 * %m <com_err error message>
2333 * %N <num>
2334 * %p ext2fs_get_pathname of directory <ino>
2335 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2336 * the containing directory. (If dirent is NULL
2337 * then return the pathname of directory <ino2>)
2338 * %q ext2fs_get_pathname of directory <dir>
2339 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2340 * the containing directory.
2341 * %s <str> miscellaneous string
2342 * %S backup superblock
2343 * %X <num> hexadecimal format
2344 *
2345 * The following '@' expansions are supported:
2346 *
2347 * @a extended attribute
2348 * @A error allocating
2349 * @b block
2350 * @B bitmap
2351 * @c compress
2352 * @C conflicts with some other fs block
2353 * @D deleted
2354 * @d directory
2355 * @e entry
2356 * @E Entry '%Dn' in %p (%i)
2357 * @f filesystem
2358 * @F for @i %i (%Q) is
2359 * @g group
2360 * @h HTREE directory inode
2361 * @i inode
2362 * @I illegal
2363 * @j journal
2364 * @l lost+found
2365 * @L is a link
2366 * @m multiply-claimed
2367 * @n invalid
2368 * @o orphaned
2369 * @p problem in
2370 * @r root inode
2371 * @s should be
2372 * @S superblock
2373 * @u unattached
2374 * @v device
2375 * @z zero-length
2376 */
2377
2378
2379/*
2380 * This structure defines the abbreviations used by the text strings
2381 * below. The first character in the string is the index letter. An
2382 * abbreviation of the form '@<i>' is expanded by looking up the index
2383 * letter <i> in the table below.
2384 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002385static const char *const abbrevs[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002386 N_("aextended attribute"),
2387 N_("Aerror allocating"),
2388 N_("bblock"),
2389 N_("Bbitmap"),
2390 N_("ccompress"),
2391 N_("Cconflicts with some other fs @b"),
2392 N_("iinode"),
2393 N_("Iillegal"),
2394 N_("jjournal"),
2395 N_("Ddeleted"),
2396 N_("ddirectory"),
2397 N_("eentry"),
2398 N_("E@e '%Dn' in %p (%i)"),
2399 N_("ffilesystem"),
2400 N_("Ffor @i %i (%Q) is"),
2401 N_("ggroup"),
2402 N_("hHTREE @d @i"),
2403 N_("llost+found"),
2404 N_("Lis a link"),
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002405 N_("mmultiply-claimed"),
2406 N_("ninvalid"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002407 N_("oorphaned"),
2408 N_("pproblem in"),
2409 N_("rroot @i"),
2410 N_("sshould be"),
2411 N_("Ssuper@b"),
2412 N_("uunattached"),
2413 N_("vdevice"),
2414 N_("zzero-length"),
2415 "@@",
2416 0
2417 };
2418
2419/*
2420 * Give more user friendly names to the "special" inodes.
2421 */
2422#define num_special_inodes 11
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002423static const char *const special_inode_name[] =
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002424{
2425 N_("<The NULL inode>"), /* 0 */
2426 N_("<The bad blocks inode>"), /* 1 */
2427 "/", /* 2 */
2428 N_("<The ACL index inode>"), /* 3 */
2429 N_("<The ACL data inode>"), /* 4 */
2430 N_("<The boot loader inode>"), /* 5 */
2431 N_("<The undelete directory inode>"), /* 6 */
2432 N_("<The group descriptor inode>"), /* 7 */
2433 N_("<The journal inode>"), /* 8 */
2434 N_("<Reserved inode 9>"), /* 9 */
2435 N_("<Reserved inode 10>"), /* 10 */
2436};
2437
2438/*
2439 * This function does "safe" printing. It will convert non-printable
2440 * ASCII characters using '^' and M- notation.
2441 */
2442static void safe_print(const char *cp, int len)
2443{
2444 unsigned char ch;
2445
2446 if (len < 0)
2447 len = strlen(cp);
2448
2449 while (len--) {
2450 ch = *cp++;
2451 if (ch > 128) {
2452 fputs("M-", stdout);
2453 ch -= 128;
2454 }
2455 if ((ch < 32) || (ch == 0x7f)) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002456 bb_putchar('^');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002457 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2458 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00002459 bb_putchar(ch);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002460 }
2461}
2462
2463
2464/*
2465 * This function prints a pathname, using the ext2fs_get_pathname
2466 * function
2467 */
2468static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2469{
2470 errcode_t retval;
2471 char *path;
2472
2473 if (!dir && (ino < num_special_inodes)) {
2474 fputs(_(special_inode_name[ino]), stdout);
2475 return;
2476 }
2477
2478 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2479 if (retval)
2480 fputs("???", stdout);
2481 else {
2482 safe_print(path, -1);
2483 ext2fs_free_mem(&path);
2484 }
2485}
2486
2487static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2488 struct problem_context *pctx, int first);
2489/*
2490 * This function handles the '@' expansion. We allow recursive
2491 * expansion; an @ expression can contain further '@' and '%'
2492 * expressions.
2493 */
2494static void expand_at_expression(e2fsck_t ctx, char ch,
2495 struct problem_context *pctx,
2496 int *first)
2497{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002498 const char *const *cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002499 const char *str;
2500
2501 /* Search for the abbreviation */
2502 for (cpp = abbrevs; *cpp; cpp++) {
2503 if (ch == *cpp[0])
2504 break;
2505 }
2506 if (*cpp) {
2507 str = _(*cpp) + 1;
2508 if (*first && islower(*str)) {
2509 *first = 0;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002510 bb_putchar(toupper(*str++));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002511 }
2512 print_e2fsck_message(ctx, str, pctx, *first);
2513 } else
2514 printf("@%c", ch);
2515}
2516
2517/*
2518 * This function expands '%IX' expressions
2519 */
2520static void expand_inode_expression(char ch,
2521 struct problem_context *ctx)
2522{
2523 struct ext2_inode *inode;
2524 struct ext2_inode_large *large_inode;
2525 char * time_str;
2526 time_t t;
2527 int do_gmt = -1;
2528
2529 if (!ctx || !ctx->inode)
2530 goto no_inode;
2531
2532 inode = ctx->inode;
2533 large_inode = (struct ext2_inode_large *) inode;
2534
2535 switch (ch) {
2536 case 's':
2537 if (LINUX_S_ISDIR(inode->i_mode))
2538 printf("%u", inode->i_size);
2539 else {
2540 printf("%"PRIu64, (inode->i_size |
2541 ((uint64_t) inode->i_size_high << 32)));
2542 }
2543 break;
2544 case 'S':
2545 printf("%u", large_inode->i_extra_isize);
2546 break;
2547 case 'b':
2548 printf("%u", inode->i_blocks);
2549 break;
2550 case 'l':
2551 printf("%d", inode->i_links_count);
2552 break;
2553 case 'm':
2554 printf("0%o", inode->i_mode);
2555 break;
2556 case 'M':
2557 /* The diet libc doesn't respect the TZ environemnt variable */
2558 if (do_gmt == -1) {
2559 time_str = getenv("TZ");
2560 if (!time_str)
2561 time_str = "";
2562 do_gmt = !strcmp(time_str, "GMT");
2563 }
2564 t = inode->i_mtime;
2565 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2566 printf("%.24s", time_str);
2567 break;
2568 case 'F':
2569 printf("%u", inode->i_faddr);
2570 break;
2571 case 'f':
2572 printf("%u", inode->i_file_acl);
2573 break;
2574 case 'd':
2575 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2576 inode->i_dir_acl : 0));
2577 break;
2578 case 'u':
2579 printf("%d", (inode->i_uid |
2580 (inode->osd2.linux2.l_i_uid_high << 16)));
2581 break;
2582 case 'g':
2583 printf("%d", (inode->i_gid |
2584 (inode->osd2.linux2.l_i_gid_high << 16)));
2585 break;
2586 default:
2587 no_inode:
2588 printf("%%I%c", ch);
2589 break;
2590 }
2591}
2592
2593/*
2594 * This function expands '%dX' expressions
2595 */
2596static void expand_dirent_expression(char ch,
2597 struct problem_context *ctx)
2598{
2599 struct ext2_dir_entry *dirent;
2600 int len;
2601
2602 if (!ctx || !ctx->dirent)
2603 goto no_dirent;
2604
2605 dirent = ctx->dirent;
2606
2607 switch (ch) {
2608 case 'i':
2609 printf("%u", dirent->inode);
2610 break;
2611 case 'n':
2612 len = dirent->name_len & 0xFF;
2613 if (len > EXT2_NAME_LEN)
2614 len = EXT2_NAME_LEN;
2615 if (len > dirent->rec_len)
2616 len = dirent->rec_len;
2617 safe_print(dirent->name, len);
2618 break;
2619 case 'r':
2620 printf("%u", dirent->rec_len);
2621 break;
2622 case 'l':
2623 printf("%u", dirent->name_len & 0xFF);
2624 break;
2625 case 't':
2626 printf("%u", dirent->name_len >> 8);
2627 break;
2628 default:
2629 no_dirent:
2630 printf("%%D%c", ch);
2631 break;
2632 }
2633}
2634
2635static void expand_percent_expression(ext2_filsys fs, char ch,
2636 struct problem_context *ctx)
2637{
2638 if (!ctx)
2639 goto no_context;
2640
2641 switch (ch) {
2642 case '%':
Denis Vlasenko4daad902007-09-27 10:20:47 +00002643 bb_putchar('%');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002644 break;
2645 case 'b':
2646 printf("%u", ctx->blk);
2647 break;
2648 case 'B':
2649 printf("%"PRIi64, ctx->blkcount);
2650 break;
2651 case 'c':
2652 printf("%u", ctx->blk2);
2653 break;
2654 case 'd':
2655 printf("%u", ctx->dir);
2656 break;
2657 case 'g':
2658 printf("%d", ctx->group);
2659 break;
2660 case 'i':
2661 printf("%u", ctx->ino);
2662 break;
2663 case 'j':
2664 printf("%u", ctx->ino2);
2665 break;
2666 case 'm':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002667 fputs(error_message(ctx->errcode), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002668 break;
2669 case 'N':
2670 printf("%"PRIi64, ctx->num);
2671 break;
2672 case 'p':
2673 print_pathname(fs, ctx->ino, 0);
2674 break;
2675 case 'P':
2676 print_pathname(fs, ctx->ino2,
2677 ctx->dirent ? ctx->dirent->inode : 0);
2678 break;
2679 case 'q':
2680 print_pathname(fs, ctx->dir, 0);
2681 break;
2682 case 'Q':
2683 print_pathname(fs, ctx->dir, ctx->ino);
2684 break;
2685 case 'S':
2686 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2687 break;
2688 case 's':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002689 fputs((ctx->str ? ctx->str : "NULL"), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002690 break;
2691 case 'X':
2692 printf("0x%"PRIi64, ctx->num);
2693 break;
2694 default:
2695 no_context:
2696 printf("%%%c", ch);
2697 break;
2698 }
2699}
2700
2701
2702static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2703 struct problem_context *pctx, int first)
2704{
2705 ext2_filsys fs = ctx->fs;
2706 const char * cp;
2707 int i;
2708
2709 e2fsck_clear_progbar(ctx);
2710 for (cp = msg; *cp; cp++) {
2711 if (cp[0] == '@') {
2712 cp++;
2713 expand_at_expression(ctx, *cp, pctx, &first);
2714 } else if (cp[0] == '%' && cp[1] == 'I') {
2715 cp += 2;
2716 expand_inode_expression(*cp, pctx);
2717 } else if (cp[0] == '%' && cp[1] == 'D') {
2718 cp += 2;
2719 expand_dirent_expression(*cp, pctx);
2720 } else if ((cp[0] == '%')) {
2721 cp++;
2722 expand_percent_expression(fs, *cp, pctx);
2723 } else {
2724 for (i=0; cp[i]; i++)
2725 if ((cp[i] == '@') || cp[i] == '%')
2726 break;
2727 printf("%.*s", i, cp);
2728 cp += i-1;
2729 }
2730 first = 0;
2731 }
2732}
2733
2734
2735/*
2736 * region.c --- code which manages allocations within a region.
2737 */
2738
2739struct region_el {
2740 region_addr_t start;
2741 region_addr_t end;
2742 struct region_el *next;
2743};
2744
2745struct region_struct {
2746 region_addr_t min;
2747 region_addr_t max;
2748 struct region_el *allocated;
2749};
2750
2751static region_t region_create(region_addr_t min, region_addr_t max)
2752{
2753 region_t region;
2754
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002755 region = xzalloc(sizeof(struct region_struct));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002756 region->min = min;
2757 region->max = max;
2758 return region;
2759}
2760
2761static void region_free(region_t region)
2762{
2763 struct region_el *r, *next;
2764
2765 for (r = region->allocated; r; r = next) {
2766 next = r->next;
2767 free(r);
2768 }
2769 memset(region, 0, sizeof(struct region_struct));
2770 free(region);
2771}
2772
2773static int region_allocate(region_t region, region_addr_t start, int n)
2774{
2775 struct region_el *r, *new_region, *prev, *next;
2776 region_addr_t end;
2777
2778 end = start+n;
2779 if ((start < region->min) || (end > region->max))
2780 return -1;
2781 if (n == 0)
2782 return 1;
2783
2784 /*
2785 * Search through the linked list. If we find that it
2786 * conflicts witih something that's already allocated, return
2787 * 1; if we can find an existing region which we can grow, do
2788 * so. Otherwise, stop when we find the appropriate place
2789 * insert a new region element into the linked list.
2790 */
2791 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2792 if (((start >= r->start) && (start < r->end)) ||
2793 ((end > r->start) && (end <= r->end)) ||
2794 ((start <= r->start) && (end >= r->end)))
2795 return 1;
2796 if (end == r->start) {
2797 r->start = start;
2798 return 0;
2799 }
2800 if (start == r->end) {
2801 if ((next = r->next)) {
2802 if (end > next->start)
2803 return 1;
2804 if (end == next->start) {
2805 r->end = next->end;
2806 r->next = next->next;
2807 free(next);
2808 return 0;
2809 }
2810 }
2811 r->end = end;
2812 return 0;
2813 }
2814 if (start < r->start)
2815 break;
2816 }
2817 /*
2818 * Insert a new region element structure into the linked list
2819 */
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002820 new_region = xmalloc(sizeof(struct region_el));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002821 new_region->start = start;
2822 new_region->end = start + n;
2823 new_region->next = r;
2824 if (prev)
2825 prev->next = new_region;
2826 else
2827 region->allocated = new_region;
2828 return 0;
2829}
2830
2831/*
2832 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2833 *
2834 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2835 * and applies the following tests to each inode:
2836 *
2837 * - The mode field of the inode must be legal.
2838 * - The size and block count fields of the inode are correct.
2839 * - A data block must not be used by another inode
2840 *
2841 * Pass 1 also gathers the collects the following information:
2842 *
2843 * - A bitmap of which inodes are in use. (inode_used_map)
2844 * - A bitmap of which inodes are directories. (inode_dir_map)
2845 * - A bitmap of which inodes are regular files. (inode_reg_map)
2846 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2847 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2848 * - A bitmap of which blocks are in use. (block_found_map)
2849 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2850 * - The data blocks of the directory inodes. (dir_map)
2851 *
2852 * Pass 1 is designed to stash away enough information so that the
2853 * other passes should not need to read in the inode information
2854 * during the normal course of a filesystem check. (Althogh if an
2855 * inconsistency is detected, other passes may need to read in an
2856 * inode to fix it.)
2857 *
2858 * Note that pass 1B will be invoked if there are any duplicate blocks
2859 * found.
2860 */
2861
2862
2863static int process_block(ext2_filsys fs, blk_t *blocknr,
2864 e2_blkcnt_t blockcnt, blk_t ref_blk,
2865 int ref_offset, void *priv_data);
2866static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2867 e2_blkcnt_t blockcnt, blk_t ref_blk,
2868 int ref_offset, void *priv_data);
2869static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2870 char *block_buf);
2871static void mark_table_blocks(e2fsck_t ctx);
2872static void alloc_imagic_map(e2fsck_t ctx);
2873static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2874static void handle_fs_bad_blocks(e2fsck_t ctx);
2875static void process_inodes(e2fsck_t ctx, char *block_buf);
2876static int process_inode_cmp(const void *a, const void *b);
2877static errcode_t scan_callback(ext2_filsys fs,
2878 dgrp_t group, void * priv_data);
2879static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2880 char *block_buf, int adjust_sign);
2881/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2882
2883static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2884 struct ext2_inode * inode, int bufsize,
2885 const char *proc);
2886
2887struct process_block_struct_1 {
2888 ext2_ino_t ino;
2889 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2890 fragmented:1, compressed:1, bbcheck:1;
2891 blk_t num_blocks;
2892 blk_t max_blocks;
2893 e2_blkcnt_t last_block;
2894 int num_illegal_blocks;
2895 blk_t previous_block;
2896 struct ext2_inode *inode;
2897 struct problem_context *pctx;
2898 ext2fs_block_bitmap fs_meta_blocks;
2899 e2fsck_t ctx;
2900};
2901
2902struct process_inode_block {
2903 ext2_ino_t ino;
2904 struct ext2_inode inode;
2905};
2906
2907struct scan_callback_struct {
2908 e2fsck_t ctx;
2909 char *block_buf;
2910};
2911
2912/*
2913 * For the inodes to process list.
2914 */
2915static struct process_inode_block *inodes_to_process;
2916static int process_inode_count;
2917
2918static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2919 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2920
2921/*
2922 * Free all memory allocated by pass1 in preparation for restarting
2923 * things.
2924 */
2925static void unwind_pass1(void)
2926{
2927 ext2fs_free_mem(&inodes_to_process);
2928}
2929
2930/*
2931 * Check to make sure a device inode is real. Returns 1 if the device
2932 * checks out, 0 if not.
2933 *
2934 * Note: this routine is now also used to check FIFO's and Sockets,
2935 * since they have the same requirement; the i_block fields should be
2936 * zero.
2937 */
2938static int
2939e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2940{
2941 int i;
2942
2943 /*
2944 * If i_blocks is non-zero, or the index flag is set, then
2945 * this is a bogus device/fifo/socket
2946 */
2947 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2948 (inode->i_flags & EXT2_INDEX_FL))
2949 return 0;
2950
2951 /*
2952 * We should be able to do the test below all the time, but
2953 * because the kernel doesn't forcibly clear the device
2954 * inode's additional i_block fields, there are some rare
2955 * occasions when a legitimate device inode will have non-zero
2956 * additional i_block fields. So for now, we only complain
2957 * when the immutable flag is set, which should never happen
2958 * for devices. (And that's when the problem is caused, since
2959 * you can't set or clear immutable flags for devices.) Once
2960 * the kernel has been fixed we can change this...
2961 */
2962 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2963 for (i=4; i < EXT2_N_BLOCKS; i++)
2964 if (inode->i_block[i])
2965 return 0;
2966 }
2967 return 1;
2968}
2969
2970/*
2971 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2972 * checks out, 0 if not.
2973 */
2974static int
2975e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2976{
2977 unsigned int len;
2978 int i;
2979 blk_t blocks;
2980
2981 if ((inode->i_size_high || inode->i_size == 0) ||
2982 (inode->i_flags & EXT2_INDEX_FL))
2983 return 0;
2984
2985 blocks = ext2fs_inode_data_blocks(fs, inode);
2986 if (blocks) {
2987 if ((inode->i_size >= fs->blocksize) ||
2988 (blocks != fs->blocksize >> 9) ||
2989 (inode->i_block[0] < fs->super->s_first_data_block) ||
2990 (inode->i_block[0] >= fs->super->s_blocks_count))
2991 return 0;
2992
2993 for (i = 1; i < EXT2_N_BLOCKS; i++)
2994 if (inode->i_block[i])
2995 return 0;
2996
2997 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2998 return 0;
2999
3000 len = strnlen(buf, fs->blocksize);
3001 if (len == fs->blocksize)
3002 return 0;
3003 } else {
3004 if (inode->i_size >= sizeof(inode->i_block))
3005 return 0;
3006
3007 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3008 if (len == sizeof(inode->i_block))
3009 return 0;
3010 }
3011 if (len != inode->i_size)
3012 return 0;
3013 return 1;
3014}
3015
3016/*
3017 * If the immutable (or append-only) flag is set on the inode, offer
3018 * to clear it.
3019 */
3020#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3021static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3022{
3023 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3024 return;
3025
3026 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3027 return;
3028
3029 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3030 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3031}
3032
3033/*
3034 * If device, fifo or socket, check size is zero -- if not offer to
3035 * clear it
3036 */
3037static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3038{
3039 struct ext2_inode *inode = pctx->inode;
3040
3041 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3042 return;
3043
3044 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3045 return;
3046
3047 inode->i_size = 0;
3048 inode->i_size_high = 0;
3049 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3050}
3051
3052static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3053{
3054 struct ext2_super_block *sb = ctx->fs->super;
3055 struct ext2_inode_large *inode;
3056 struct ext2_ext_attr_entry *entry;
3057 char *start, *end;
3058 int storage_size, remain, offs;
3059 int problem = 0;
3060
3061 inode = (struct ext2_inode_large *) pctx->inode;
3062 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3063 inode->i_extra_isize;
3064 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3065 inode->i_extra_isize + sizeof(__u32);
3066 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3067 entry = (struct ext2_ext_attr_entry *) start;
3068
3069 /* scan all entry's headers first */
3070
3071 /* take finish entry 0UL into account */
3072 remain = storage_size - sizeof(__u32);
3073 offs = end - start;
3074
3075 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3076
3077 /* header eats this space */
3078 remain -= sizeof(struct ext2_ext_attr_entry);
3079
3080 /* is attribute name valid? */
3081 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3082 pctx->num = entry->e_name_len;
3083 problem = PR_1_ATTR_NAME_LEN;
3084 goto fix;
3085 }
3086
3087 /* attribute len eats this space */
3088 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3089
3090 /* check value size */
3091 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3092 pctx->num = entry->e_value_size;
3093 problem = PR_1_ATTR_VALUE_SIZE;
3094 goto fix;
3095 }
3096
3097 /* check value placement */
3098 if (entry->e_value_offs +
3099 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3100 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3101 pctx->num = entry->e_value_offs;
3102 problem = PR_1_ATTR_VALUE_OFFSET;
3103 goto fix;
3104 }
3105
3106 /* e_value_block must be 0 in inode's ea */
3107 if (entry->e_value_block != 0) {
3108 pctx->num = entry->e_value_block;
3109 problem = PR_1_ATTR_VALUE_BLOCK;
3110 goto fix;
3111 }
3112
3113 /* e_hash must be 0 in inode's ea */
3114 if (entry->e_hash != 0) {
3115 pctx->num = entry->e_hash;
3116 problem = PR_1_ATTR_HASH;
3117 goto fix;
3118 }
3119
3120 remain -= entry->e_value_size;
3121 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3122
3123 entry = EXT2_EXT_ATTR_NEXT(entry);
3124 }
3125fix:
3126 /*
3127 * it seems like a corruption. it's very unlikely we could repair
3128 * EA(s) in automatic fashion -bzzz
3129 */
3130 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3131 return;
3132
3133 /* simple remove all possible EA(s) */
3134 *((__u32 *)start) = 0UL;
3135 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3136 EXT2_INODE_SIZE(sb), "pass1");
3137}
3138
3139static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3140{
3141 struct ext2_super_block *sb = ctx->fs->super;
3142 struct ext2_inode_large *inode;
3143 __u32 *eamagic;
3144 int min, max;
3145
3146 inode = (struct ext2_inode_large *) pctx->inode;
3147 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3148 /* this isn't large inode. so, nothing to check */
3149 return;
3150 }
3151
3152 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3153 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3154 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3155 /*
3156 * For now we will allow i_extra_isize to be 0, but really
3157 * implementations should never allow i_extra_isize to be 0
3158 */
3159 if (inode->i_extra_isize &&
3160 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3161 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3162 return;
3163 inode->i_extra_isize = min;
3164 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3165 EXT2_INODE_SIZE(sb), "pass1");
3166 return;
3167 }
3168
3169 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3170 inode->i_extra_isize);
3171 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3172 /* it seems inode has an extended attribute(s) in body */
3173 check_ea_in_inode(ctx, pctx);
3174 }
3175}
3176
3177static void e2fsck_pass1(e2fsck_t ctx)
3178{
3179 int i;
3180 __u64 max_sizes;
3181 ext2_filsys fs = ctx->fs;
3182 ext2_ino_t ino;
3183 struct ext2_inode *inode;
3184 ext2_inode_scan scan;
3185 char *block_buf;
3186 unsigned char frag, fsize;
3187 struct problem_context pctx;
3188 struct scan_callback_struct scan_struct;
3189 struct ext2_super_block *sb = ctx->fs->super;
3190 int imagic_fs;
3191 int busted_fs_time = 0;
3192 int inode_size;
3193
3194 clear_problem_context(&pctx);
3195
3196 if (!(ctx->options & E2F_OPT_PREEN))
3197 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3198
3199 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3200 !(ctx->options & E2F_OPT_NO)) {
3201 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3202 ctx->dirs_to_hash = 0;
3203 }
3204
3205 /* Pass 1 */
3206
3207#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3208
3209 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3210 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3211 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3212 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3213 max_sizes = (max_sizes * (1UL << i)) - 1;
3214 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3215 }
3216#undef EXT2_BPP
3217
3218 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3219
3220 /*
3221 * Allocate bitmaps structures
3222 */
3223 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3224 &ctx->inode_used_map);
3225 if (pctx.errcode) {
3226 pctx.num = 1;
3227 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3228 ctx->flags |= E2F_FLAG_ABORT;
3229 return;
3230 }
3231 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3232 _("directory inode map"), &ctx->inode_dir_map);
3233 if (pctx.errcode) {
3234 pctx.num = 2;
3235 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3236 ctx->flags |= E2F_FLAG_ABORT;
3237 return;
3238 }
3239 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3240 _("regular file inode map"), &ctx->inode_reg_map);
3241 if (pctx.errcode) {
3242 pctx.num = 6;
3243 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3244 ctx->flags |= E2F_FLAG_ABORT;
3245 return;
3246 }
3247 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3248 &ctx->block_found_map);
3249 if (pctx.errcode) {
3250 pctx.num = 1;
3251 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3252 ctx->flags |= E2F_FLAG_ABORT;
3253 return;
3254 }
3255 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3256 &ctx->inode_link_info);
3257 if (pctx.errcode) {
3258 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3259 ctx->flags |= E2F_FLAG_ABORT;
3260 return;
3261 }
3262 inode_size = EXT2_INODE_SIZE(fs->super);
3263 inode = (struct ext2_inode *)
3264 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3265
3266 inodes_to_process = (struct process_inode_block *)
3267 e2fsck_allocate_memory(ctx,
3268 (ctx->process_inode_size *
3269 sizeof(struct process_inode_block)),
3270 "array of inodes to process");
3271 process_inode_count = 0;
3272
3273 pctx.errcode = ext2fs_init_dblist(fs, 0);
3274 if (pctx.errcode) {
3275 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3276 ctx->flags |= E2F_FLAG_ABORT;
3277 return;
3278 }
3279
3280 /*
3281 * If the last orphan field is set, clear it, since the pass1
3282 * processing will automatically find and clear the orphans.
3283 * In the future, we may want to try using the last_orphan
3284 * linked list ourselves, but for now, we clear it so that the
3285 * ext3 mount code won't get confused.
3286 */
3287 if (!(ctx->options & E2F_OPT_READONLY)) {
3288 if (fs->super->s_last_orphan) {
3289 fs->super->s_last_orphan = 0;
3290 ext2fs_mark_super_dirty(fs);
3291 }
3292 }
3293
3294 mark_table_blocks(ctx);
3295 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3296 "block interate buffer");
3297 e2fsck_use_inode_shortcuts(ctx, 1);
3298 ehandler_operation(_("doing inode scan"));
3299 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3300 &scan);
3301 if (pctx.errcode) {
3302 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3303 ctx->flags |= E2F_FLAG_ABORT;
3304 return;
3305 }
3306 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3307 ctx->stashed_inode = inode;
3308 scan_struct.ctx = ctx;
3309 scan_struct.block_buf = block_buf;
3310 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3311 if (ctx->progress)
3312 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3313 return;
3314 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3315 (fs->super->s_mtime < fs->super->s_inodes_count))
3316 busted_fs_time = 1;
3317
3318 while (1) {
3319 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3320 inode, inode_size);
3321 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3322 return;
3323 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3324 continue;
3325 }
3326 if (pctx.errcode) {
3327 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3328 ctx->flags |= E2F_FLAG_ABORT;
3329 return;
3330 }
3331 if (!ino)
3332 break;
3333 pctx.ino = ino;
3334 pctx.inode = inode;
3335 ctx->stashed_ino = ino;
3336 if (inode->i_links_count) {
3337 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3338 ino, inode->i_links_count);
3339 if (pctx.errcode) {
3340 pctx.num = inode->i_links_count;
3341 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3342 ctx->flags |= E2F_FLAG_ABORT;
3343 return;
3344 }
3345 }
3346 if (ino == EXT2_BAD_INO) {
3347 struct process_block_struct_1 pb;
3348
3349 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3350 &pb.fs_meta_blocks);
3351 if (pctx.errcode) {
3352 pctx.num = 4;
3353 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3354 ctx->flags |= E2F_FLAG_ABORT;
3355 return;
3356 }
3357 pb.ino = EXT2_BAD_INO;
3358 pb.num_blocks = pb.last_block = 0;
3359 pb.num_illegal_blocks = 0;
3360 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3361 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3362 pb.inode = inode;
3363 pb.pctx = &pctx;
3364 pb.ctx = ctx;
3365 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3366 block_buf, process_bad_block, &pb);
3367 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3368 if (pctx.errcode) {
3369 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3370 ctx->flags |= E2F_FLAG_ABORT;
3371 return;
3372 }
3373 if (pb.bbcheck)
3374 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3375 ctx->flags |= E2F_FLAG_ABORT;
3376 return;
3377 }
3378 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3379 clear_problem_context(&pctx);
3380 continue;
3381 } else if (ino == EXT2_ROOT_INO) {
3382 /*
3383 * Make sure the root inode is a directory; if
3384 * not, offer to clear it. It will be
3385 * regnerated in pass #3.
3386 */
3387 if (!LINUX_S_ISDIR(inode->i_mode)) {
3388 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003389 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003390 inode->i_links_count = 0;
3391 ext2fs_icount_store(ctx->inode_link_info,
3392 ino, 0);
3393 e2fsck_write_inode(ctx, ino, inode,
3394 "pass1");
3395 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003396 }
3397 /*
3398 * If dtime is set, offer to clear it. mke2fs
3399 * version 0.2b created filesystems with the
3400 * dtime field set for the root and lost+found
3401 * directories. We won't worry about
3402 * /lost+found, since that can be regenerated
3403 * easily. But we will fix the root directory
3404 * as a special case.
3405 */
3406 if (inode->i_dtime && inode->i_links_count) {
3407 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3408 inode->i_dtime = 0;
3409 e2fsck_write_inode(ctx, ino, inode,
3410 "pass1");
3411 }
3412 }
3413 } else if (ino == EXT2_JOURNAL_INO) {
3414 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3415 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3416 if (!LINUX_S_ISREG(inode->i_mode) &&
3417 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3418 &pctx)) {
3419 inode->i_mode = LINUX_S_IFREG;
3420 e2fsck_write_inode(ctx, ino, inode,
3421 "pass1");
3422 }
3423 check_blocks(ctx, &pctx, block_buf);
3424 continue;
3425 }
3426 if ((inode->i_links_count || inode->i_blocks ||
3427 inode->i_blocks || inode->i_block[0]) &&
3428 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3429 &pctx)) {
3430 memset(inode, 0, inode_size);
3431 ext2fs_icount_store(ctx->inode_link_info,
3432 ino, 0);
3433 e2fsck_write_inode_full(ctx, ino, inode,
3434 inode_size, "pass1");
3435 }
3436 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3437 int problem = 0;
3438
3439 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3440 if (ino == EXT2_BOOT_LOADER_INO) {
3441 if (LINUX_S_ISDIR(inode->i_mode))
3442 problem = PR_1_RESERVED_BAD_MODE;
3443 } else if (ino == EXT2_RESIZE_INO) {
3444 if (inode->i_mode &&
3445 !LINUX_S_ISREG(inode->i_mode))
3446 problem = PR_1_RESERVED_BAD_MODE;
3447 } else {
3448 if (inode->i_mode != 0)
3449 problem = PR_1_RESERVED_BAD_MODE;
3450 }
3451 if (problem) {
3452 if (fix_problem(ctx, problem, &pctx)) {
3453 inode->i_mode = 0;
3454 e2fsck_write_inode(ctx, ino, inode,
3455 "pass1");
3456 }
3457 }
3458 check_blocks(ctx, &pctx, block_buf);
3459 continue;
3460 }
3461 /*
3462 * Check for inodes who might have been part of the
3463 * orphaned list linked list. They should have gotten
3464 * dealt with by now, unless the list had somehow been
3465 * corrupted.
3466 *
3467 * FIXME: In the future, inodes which are still in use
3468 * (and which are therefore) pending truncation should
3469 * be handled specially. Right now we just clear the
3470 * dtime field, and the normal e2fsck handling of
3471 * inodes where i_size and the inode blocks are
3472 * inconsistent is to fix i_size, instead of releasing
3473 * the extra blocks. This won't catch the inodes that
3474 * was at the end of the orphan list, but it's better
3475 * than nothing. The right answer is that there
3476 * shouldn't be any bugs in the orphan list handling. :-)
3477 */
3478 if (inode->i_dtime && !busted_fs_time &&
3479 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3480 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3481 inode->i_dtime = inode->i_links_count ?
Denis Vlasenko04158e02009-02-02 10:48:06 +00003482 0 : time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003483 e2fsck_write_inode(ctx, ino, inode,
3484 "pass1");
3485 }
3486 }
3487
3488 /*
3489 * This code assumes that deleted inodes have
3490 * i_links_count set to 0.
3491 */
3492 if (!inode->i_links_count) {
3493 if (!inode->i_dtime && inode->i_mode) {
3494 if (fix_problem(ctx,
3495 PR_1_ZERO_DTIME, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003496 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003497 e2fsck_write_inode(ctx, ino, inode,
3498 "pass1");
3499 }
3500 }
3501 continue;
3502 }
3503 /*
3504 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3505 * deleted files. Oops.
3506 *
3507 * Since all new ext2 implementations get this right,
3508 * we now assume that the case of non-zero
3509 * i_links_count and non-zero dtime means that we
3510 * should keep the file, not delete it.
3511 *
3512 */
3513 if (inode->i_dtime) {
3514 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3515 inode->i_dtime = 0;
3516 e2fsck_write_inode(ctx, ino, inode, "pass1");
3517 }
3518 }
3519
3520 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3521 switch (fs->super->s_creator_os) {
3522 case EXT2_OS_LINUX:
3523 frag = inode->osd2.linux2.l_i_frag;
3524 fsize = inode->osd2.linux2.l_i_fsize;
3525 break;
3526 case EXT2_OS_HURD:
3527 frag = inode->osd2.hurd2.h_i_frag;
3528 fsize = inode->osd2.hurd2.h_i_fsize;
3529 break;
3530 case EXT2_OS_MASIX:
3531 frag = inode->osd2.masix2.m_i_frag;
3532 fsize = inode->osd2.masix2.m_i_fsize;
3533 break;
3534 default:
3535 frag = fsize = 0;
3536 }
3537
3538 if (inode->i_faddr || frag || fsize ||
3539 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3540 mark_inode_bad(ctx, ino);
3541 if (inode->i_flags & EXT2_IMAGIC_FL) {
3542 if (imagic_fs) {
3543 if (!ctx->inode_imagic_map)
3544 alloc_imagic_map(ctx);
3545 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3546 ino);
3547 } else {
3548 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3549 inode->i_flags &= ~EXT2_IMAGIC_FL;
3550 e2fsck_write_inode(ctx, ino,
3551 inode, "pass1");
3552 }
3553 }
3554 }
3555
3556 check_inode_extra_space(ctx, &pctx);
3557
3558 if (LINUX_S_ISDIR(inode->i_mode)) {
3559 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3560 e2fsck_add_dir_info(ctx, ino, 0);
3561 ctx->fs_directory_count++;
3562 } else if (LINUX_S_ISREG (inode->i_mode)) {
3563 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3564 ctx->fs_regular_count++;
3565 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3566 e2fsck_pass1_check_device_inode(fs, inode)) {
3567 check_immutable(ctx, &pctx);
3568 check_size(ctx, &pctx);
3569 ctx->fs_chardev_count++;
3570 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3571 e2fsck_pass1_check_device_inode(fs, inode)) {
3572 check_immutable(ctx, &pctx);
3573 check_size(ctx, &pctx);
3574 ctx->fs_blockdev_count++;
3575 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3576 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3577 check_immutable(ctx, &pctx);
3578 ctx->fs_symlinks_count++;
3579 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3580 ctx->fs_fast_symlinks_count++;
3581 check_blocks(ctx, &pctx, block_buf);
3582 continue;
3583 }
3584 }
3585 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3586 e2fsck_pass1_check_device_inode(fs, inode)) {
3587 check_immutable(ctx, &pctx);
3588 check_size(ctx, &pctx);
3589 ctx->fs_fifo_count++;
3590 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3591 e2fsck_pass1_check_device_inode(fs, inode)) {
3592 check_immutable(ctx, &pctx);
3593 check_size(ctx, &pctx);
3594 ctx->fs_sockets_count++;
3595 } else
3596 mark_inode_bad(ctx, ino);
3597 if (inode->i_block[EXT2_IND_BLOCK])
3598 ctx->fs_ind_count++;
3599 if (inode->i_block[EXT2_DIND_BLOCK])
3600 ctx->fs_dind_count++;
3601 if (inode->i_block[EXT2_TIND_BLOCK])
3602 ctx->fs_tind_count++;
3603 if (inode->i_block[EXT2_IND_BLOCK] ||
3604 inode->i_block[EXT2_DIND_BLOCK] ||
3605 inode->i_block[EXT2_TIND_BLOCK] ||
3606 inode->i_file_acl) {
3607 inodes_to_process[process_inode_count].ino = ino;
3608 inodes_to_process[process_inode_count].inode = *inode;
3609 process_inode_count++;
3610 } else
3611 check_blocks(ctx, &pctx, block_buf);
3612
3613 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3614 return;
3615
3616 if (process_inode_count >= ctx->process_inode_size) {
3617 process_inodes(ctx, block_buf);
3618
3619 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3620 return;
3621 }
3622 }
3623 process_inodes(ctx, block_buf);
3624 ext2fs_close_inode_scan(scan);
3625 ehandler_operation(0);
3626
3627 /*
3628 * If any extended attribute blocks' reference counts need to
3629 * be adjusted, either up (ctx->refcount_extra), or down
3630 * (ctx->refcount), then fix them.
3631 */
3632 if (ctx->refcount) {
3633 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3634 ea_refcount_free(ctx->refcount);
3635 ctx->refcount = 0;
3636 }
3637 if (ctx->refcount_extra) {
3638 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3639 block_buf, +1);
3640 ea_refcount_free(ctx->refcount_extra);
3641 ctx->refcount_extra = 0;
3642 }
3643
3644 if (ctx->invalid_bitmaps)
3645 handle_fs_bad_blocks(ctx);
3646
3647 /* We don't need the block_ea_map any more */
3648 ext2fs_free_block_bitmap(ctx->block_ea_map);
3649 ctx->block_ea_map = 0;
3650
3651 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3652 ext2fs_block_bitmap save_bmap;
3653
3654 save_bmap = fs->block_map;
3655 fs->block_map = ctx->block_found_map;
3656 clear_problem_context(&pctx);
3657 pctx.errcode = ext2fs_create_resize_inode(fs);
3658 if (pctx.errcode) {
3659 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3660 /* Should never get here */
3661 ctx->flags |= E2F_FLAG_ABORT;
3662 return;
3663 }
3664 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3665 "recreate inode");
Denis Vlasenko04158e02009-02-02 10:48:06 +00003666 inode->i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003667 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3668 "recreate inode");
3669 fs->block_map = save_bmap;
3670 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3671 }
3672
3673 if (ctx->flags & E2F_FLAG_RESTART) {
3674 /*
3675 * Only the master copy of the superblock and block
3676 * group descriptors are going to be written during a
3677 * restart, so set the superblock to be used to be the
3678 * master superblock.
3679 */
3680 ctx->use_superblock = 0;
3681 unwind_pass1();
3682 goto endit;
3683 }
3684
3685 if (ctx->block_dup_map) {
3686 if (ctx->options & E2F_OPT_PREEN) {
3687 clear_problem_context(&pctx);
3688 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3689 }
3690 e2fsck_pass1_dupblocks(ctx, block_buf);
3691 }
3692 ext2fs_free_mem(&inodes_to_process);
3693endit:
3694 e2fsck_use_inode_shortcuts(ctx, 0);
3695
3696 ext2fs_free_mem(&block_buf);
3697 ext2fs_free_mem(&inode);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003698}
3699
3700/*
3701 * When the inode_scan routines call this callback at the end of the
3702 * glock group, call process_inodes.
3703 */
3704static errcode_t scan_callback(ext2_filsys fs,
3705 dgrp_t group, void * priv_data)
3706{
3707 struct scan_callback_struct *scan_struct;
3708 e2fsck_t ctx;
3709
3710 scan_struct = (struct scan_callback_struct *) priv_data;
3711 ctx = scan_struct->ctx;
3712
3713 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3714
3715 if (ctx->progress)
3716 if ((ctx->progress)(ctx, 1, group+1,
3717 ctx->fs->group_desc_count))
3718 return EXT2_ET_CANCEL_REQUESTED;
3719
3720 return 0;
3721}
3722
3723/*
3724 * Process the inodes in the "inodes to process" list.
3725 */
3726static void process_inodes(e2fsck_t ctx, char *block_buf)
3727{
3728 int i;
3729 struct ext2_inode *old_stashed_inode;
3730 ext2_ino_t old_stashed_ino;
3731 const char *old_operation;
3732 char buf[80];
3733 struct problem_context pctx;
3734
3735 /* begin process_inodes */
3736 if (process_inode_count == 0)
3737 return;
3738 old_operation = ehandler_operation(0);
3739 old_stashed_inode = ctx->stashed_inode;
3740 old_stashed_ino = ctx->stashed_ino;
3741 qsort(inodes_to_process, process_inode_count,
3742 sizeof(struct process_inode_block), process_inode_cmp);
3743 clear_problem_context(&pctx);
3744 for (i=0; i < process_inode_count; i++) {
3745 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3746 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3747 sprintf(buf, _("reading indirect blocks of inode %u"),
3748 pctx.ino);
3749 ehandler_operation(buf);
3750 check_blocks(ctx, &pctx, block_buf);
3751 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3752 break;
3753 }
3754 ctx->stashed_inode = old_stashed_inode;
3755 ctx->stashed_ino = old_stashed_ino;
3756 process_inode_count = 0;
3757 /* end process inodes */
3758
3759 ehandler_operation(old_operation);
3760}
3761
3762static int process_inode_cmp(const void *a, const void *b)
3763{
3764 const struct process_inode_block *ib_a =
3765 (const struct process_inode_block *) a;
3766 const struct process_inode_block *ib_b =
3767 (const struct process_inode_block *) b;
3768 int ret;
3769
3770 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3771 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3772 if (ret == 0)
3773 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3774 return ret;
3775}
3776
3777/*
3778 * Mark an inode as being bad in some what
3779 */
3780static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3781{
3782 struct problem_context pctx;
3783
3784 if (!ctx->inode_bad_map) {
3785 clear_problem_context(&pctx);
3786
3787 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3788 _("bad inode map"), &ctx->inode_bad_map);
3789 if (pctx.errcode) {
3790 pctx.num = 3;
3791 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3792 /* Should never get here */
3793 ctx->flags |= E2F_FLAG_ABORT;
3794 return;
3795 }
3796 }
3797 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3798}
3799
3800
3801/*
3802 * This procedure will allocate the inode imagic table
3803 */
3804static void alloc_imagic_map(e2fsck_t ctx)
3805{
3806 struct problem_context pctx;
3807
3808 clear_problem_context(&pctx);
3809 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3810 _("imagic inode map"),
3811 &ctx->inode_imagic_map);
3812 if (pctx.errcode) {
3813 pctx.num = 5;
3814 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3815 /* Should never get here */
3816 ctx->flags |= E2F_FLAG_ABORT;
3817 return;
3818 }
3819}
3820
3821/*
3822 * Marks a block as in use, setting the dup_map if it's been set
3823 * already. Called by process_block and process_bad_block.
3824 *
3825 * WARNING: Assumes checks have already been done to make sure block
3826 * is valid. This is true in both process_block and process_bad_block.
3827 */
3828static void mark_block_used(e2fsck_t ctx, blk_t block)
3829{
3830 struct problem_context pctx;
3831
3832 clear_problem_context(&pctx);
3833
3834 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3835 if (!ctx->block_dup_map) {
3836 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3837 _("multiply claimed block map"),
3838 &ctx->block_dup_map);
3839 if (pctx.errcode) {
3840 pctx.num = 3;
3841 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3842 &pctx);
3843 /* Should never get here */
3844 ctx->flags |= E2F_FLAG_ABORT;
3845 return;
3846 }
3847 }
3848 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3849 } else {
3850 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3851 }
3852}
3853
3854/*
3855 * Adjust the extended attribute block's reference counts at the end
3856 * of pass 1, either by subtracting out references for EA blocks that
3857 * are still referenced in ctx->refcount, or by adding references for
3858 * EA blocks that had extra references as accounted for in
3859 * ctx->refcount_extra.
3860 */
3861static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3862 char *block_buf, int adjust_sign)
3863{
3864 struct ext2_ext_attr_header *header;
3865 struct problem_context pctx;
3866 ext2_filsys fs = ctx->fs;
3867 blk_t blk;
3868 __u32 should_be;
3869 int count;
3870
3871 clear_problem_context(&pctx);
3872
3873 ea_refcount_intr_begin(refcount);
3874 while (1) {
3875 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3876 break;
3877 pctx.blk = blk;
3878 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3879 if (pctx.errcode) {
3880 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3881 return;
3882 }
3883 header = (struct ext2_ext_attr_header *) block_buf;
3884 pctx.blkcount = header->h_refcount;
3885 should_be = header->h_refcount + adjust_sign * count;
3886 pctx.num = should_be;
3887 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3888 header->h_refcount = should_be;
3889 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3890 block_buf);
3891 if (pctx.errcode) {
3892 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3893 continue;
3894 }
3895 }
3896 }
3897}
3898
3899/*
3900 * Handle processing the extended attribute blocks
3901 */
3902static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3903 char *block_buf)
3904{
3905 ext2_filsys fs = ctx->fs;
3906 ext2_ino_t ino = pctx->ino;
3907 struct ext2_inode *inode = pctx->inode;
3908 blk_t blk;
3909 char * end;
3910 struct ext2_ext_attr_header *header;
3911 struct ext2_ext_attr_entry *entry;
3912 int count;
3913 region_t region;
3914
3915 blk = inode->i_file_acl;
3916 if (blk == 0)
3917 return 0;
3918
3919 /*
3920 * If the Extended attribute flag isn't set, then a non-zero
3921 * file acl means that the inode is corrupted.
3922 *
3923 * Or if the extended attribute block is an invalid block,
3924 * then the inode is also corrupted.
3925 */
3926 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3927 (blk < fs->super->s_first_data_block) ||
3928 (blk >= fs->super->s_blocks_count)) {
3929 mark_inode_bad(ctx, ino);
3930 return 0;
3931 }
3932
3933 /* If ea bitmap hasn't been allocated, create it */
3934 if (!ctx->block_ea_map) {
3935 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3936 _("ext attr block map"),
3937 &ctx->block_ea_map);
3938 if (pctx->errcode) {
3939 pctx->num = 2;
3940 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3941 ctx->flags |= E2F_FLAG_ABORT;
3942 return 0;
3943 }
3944 }
3945
3946 /* Create the EA refcount structure if necessary */
3947 if (!ctx->refcount) {
3948 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3949 if (pctx->errcode) {
3950 pctx->num = 1;
3951 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3952 ctx->flags |= E2F_FLAG_ABORT;
3953 return 0;
3954 }
3955 }
3956
3957 /* Have we seen this EA block before? */
3958 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3959 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3960 return 1;
3961 /* Ooops, this EA was referenced more than it stated */
3962 if (!ctx->refcount_extra) {
3963 pctx->errcode = ea_refcount_create(0,
3964 &ctx->refcount_extra);
3965 if (pctx->errcode) {
3966 pctx->num = 2;
3967 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3968 ctx->flags |= E2F_FLAG_ABORT;
3969 return 0;
3970 }
3971 }
3972 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3973 return 1;
3974 }
3975
3976 /*
3977 * OK, we haven't seen this EA block yet. So we need to
3978 * validate it
3979 */
3980 pctx->blk = blk;
3981 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3982 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3983 goto clear_extattr;
3984 header = (struct ext2_ext_attr_header *) block_buf;
3985 pctx->blk = inode->i_file_acl;
3986 if (((ctx->ext_attr_ver == 1) &&
3987 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3988 ((ctx->ext_attr_ver == 2) &&
3989 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3990 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3991 goto clear_extattr;
3992 }
3993
3994 if (header->h_blocks != 1) {
3995 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3996 goto clear_extattr;
3997 }
3998
3999 region = region_create(0, fs->blocksize);
4000 if (!region) {
4001 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4002 ctx->flags |= E2F_FLAG_ABORT;
4003 return 0;
4004 }
4005 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4006 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4007 goto clear_extattr;
4008 }
4009
4010 entry = (struct ext2_ext_attr_entry *)(header+1);
4011 end = block_buf + fs->blocksize;
4012 while ((char *)entry < end && *(__u32 *)entry) {
4013 if (region_allocate(region, (char *)entry - (char *)header,
4014 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4015 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4016 goto clear_extattr;
4017 }
4018 if ((ctx->ext_attr_ver == 1 &&
4019 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4020 (ctx->ext_attr_ver == 2 &&
4021 entry->e_name_index == 0)) {
4022 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4023 goto clear_extattr;
4024 }
4025 if (entry->e_value_block != 0) {
4026 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4027 goto clear_extattr;
4028 }
4029 if (entry->e_value_size &&
4030 region_allocate(region, entry->e_value_offs,
4031 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4032 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4033 goto clear_extattr;
4034 }
4035 entry = EXT2_EXT_ATTR_NEXT(entry);
4036 }
4037 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4038 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4039 goto clear_extattr;
4040 }
4041 region_free(region);
4042
4043 count = header->h_refcount - 1;
4044 if (count)
4045 ea_refcount_store(ctx->refcount, blk, count);
4046 mark_block_used(ctx, blk);
4047 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4048
4049 return 1;
4050
4051clear_extattr:
4052 inode->i_file_acl = 0;
4053 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4054 return 0;
4055}
4056
4057/* Returns 1 if bad htree, 0 if OK */
4058static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4059 ext2_ino_t ino FSCK_ATTR((unused)),
4060 struct ext2_inode *inode,
4061 char *block_buf)
4062{
4063 struct ext2_dx_root_info *root;
4064 ext2_filsys fs = ctx->fs;
4065 errcode_t retval;
4066 blk_t blk;
4067
4068 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4069 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4070 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4071 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4072 return 1;
4073
4074 blk = inode->i_block[0];
4075 if (((blk == 0) ||
4076 (blk < fs->super->s_first_data_block) ||
4077 (blk >= fs->super->s_blocks_count)) &&
4078 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4079 return 1;
4080
4081 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4082 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4083 return 1;
4084
4085 /* XXX should check that beginning matches a directory */
4086 root = (struct ext2_dx_root_info *) (block_buf + 24);
4087
4088 if ((root->reserved_zero || root->info_length < 8) &&
4089 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4090 return 1;
4091
4092 pctx->num = root->hash_version;
4093 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4094 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4095 (root->hash_version != EXT2_HASH_TEA) &&
4096 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4097 return 1;
4098
4099 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4100 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4101 return 1;
4102
4103 pctx->num = root->indirect_levels;
4104 if ((root->indirect_levels > 1) &&
4105 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4106 return 1;
4107
4108 return 0;
4109}
4110
4111/*
4112 * This subroutine is called on each inode to account for all of the
4113 * blocks used by that inode.
4114 */
4115static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4116 char *block_buf)
4117{
4118 ext2_filsys fs = ctx->fs;
4119 struct process_block_struct_1 pb;
4120 ext2_ino_t ino = pctx->ino;
4121 struct ext2_inode *inode = pctx->inode;
4122 int bad_size = 0;
4123 int dirty_inode = 0;
4124 __u64 size;
4125
4126 pb.ino = ino;
4127 pb.num_blocks = 0;
4128 pb.last_block = -1;
4129 pb.num_illegal_blocks = 0;
4130 pb.suppress = 0; pb.clear = 0;
4131 pb.fragmented = 0;
4132 pb.compressed = 0;
4133 pb.previous_block = 0;
4134 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4135 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4136 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4137 pb.inode = inode;
4138 pb.pctx = pctx;
4139 pb.ctx = ctx;
4140 pctx->ino = ino;
4141 pctx->errcode = 0;
4142
4143 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4144 if (fs->super->s_feature_incompat &
4145 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4146 pb.compressed = 1;
4147 else {
4148 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4149 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4150 dirty_inode++;
4151 }
4152 }
4153 }
4154
4155 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4156 pb.num_blocks++;
4157
4158 if (ext2fs_inode_has_valid_blocks(inode))
4159 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4160 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4161 block_buf, process_block, &pb);
4162 end_problem_latch(ctx, PR_LATCH_BLOCK);
4163 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4164 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4165 goto out;
4166 if (pctx->errcode)
4167 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4168
4169 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4170 ctx->fs_fragmented++;
4171
4172 if (pb.clear) {
4173 inode->i_links_count = 0;
4174 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004175 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004176 dirty_inode++;
4177 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4178 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4179 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4180 /*
4181 * The inode was probably partially accounted for
4182 * before processing was aborted, so we need to
4183 * restart the pass 1 scan.
4184 */
4185 ctx->flags |= E2F_FLAG_RESTART;
4186 goto out;
4187 }
4188
4189 if (inode->i_flags & EXT2_INDEX_FL) {
4190 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4191 inode->i_flags &= ~EXT2_INDEX_FL;
4192 dirty_inode++;
4193 } else {
4194#ifdef ENABLE_HTREE
4195 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4196#endif
4197 }
4198 }
4199 if (ctx->dirs_to_hash && pb.is_dir &&
4200 !(inode->i_flags & EXT2_INDEX_FL) &&
4201 ((inode->i_size / fs->blocksize) >= 3))
4202 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4203
4204 if (!pb.num_blocks && pb.is_dir) {
4205 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4206 inode->i_links_count = 0;
4207 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004208 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004209 dirty_inode++;
4210 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4211 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4212 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4213 ctx->fs_directory_count--;
4214 goto out;
4215 }
4216 }
4217
4218 pb.num_blocks *= (fs->blocksize / 512);
4219
4220 if (pb.is_dir) {
4221 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4222 if (nblock > (pb.last_block + 1))
4223 bad_size = 1;
4224 else if (nblock < (pb.last_block + 1)) {
4225 if (((pb.last_block + 1) - nblock) >
4226 fs->super->s_prealloc_dir_blocks)
4227 bad_size = 2;
4228 }
4229 } else {
4230 size = EXT2_I_SIZE(inode);
4231 if ((pb.last_block >= 0) &&
4232 (size < (__u64) pb.last_block * fs->blocksize))
4233 bad_size = 3;
4234 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4235 bad_size = 4;
4236 }
4237 /* i_size for symlinks is checked elsewhere */
4238 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4239 pctx->num = (pb.last_block+1) * fs->blocksize;
4240 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4241 inode->i_size = pctx->num;
4242 if (!LINUX_S_ISDIR(inode->i_mode))
4243 inode->i_size_high = pctx->num >> 32;
4244 dirty_inode++;
4245 }
4246 pctx->num = 0;
4247 }
4248 if (LINUX_S_ISREG(inode->i_mode) &&
4249 (inode->i_size_high || inode->i_size & 0x80000000UL))
4250 ctx->large_files++;
4251 if (pb.num_blocks != inode->i_blocks) {
4252 pctx->num = pb.num_blocks;
4253 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4254 inode->i_blocks = pb.num_blocks;
4255 dirty_inode++;
4256 }
4257 pctx->num = 0;
4258 }
4259out:
4260 if (dirty_inode)
4261 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4262}
4263
4264
4265/*
4266 * This is a helper function for check_blocks().
4267 */
4268static int process_block(ext2_filsys fs,
4269 blk_t *block_nr,
4270 e2_blkcnt_t blockcnt,
4271 blk_t ref_block FSCK_ATTR((unused)),
4272 int ref_offset FSCK_ATTR((unused)),
4273 void *priv_data)
4274{
4275 struct process_block_struct_1 *p;
4276 struct problem_context *pctx;
4277 blk_t blk = *block_nr;
4278 int ret_code = 0;
4279 int problem = 0;
4280 e2fsck_t ctx;
4281
4282 p = (struct process_block_struct_1 *) priv_data;
4283 pctx = p->pctx;
4284 ctx = p->ctx;
4285
4286 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4287 /* todo: Check that the comprblk_fl is high, that the
4288 blkaddr pattern looks right (all non-holes up to
4289 first EXT2FS_COMPRESSED_BLKADDR, then all
4290 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4291 that the feature_incompat bit is high, and that the
4292 inode is a regular file. If we're doing a "full
4293 check" (a concept introduced to e2fsck by e2compr,
4294 meaning that we look at data blocks as well as
4295 metadata) then call some library routine that
4296 checks the compressed data. I'll have to think
4297 about this, because one particularly important
4298 problem to be able to fix is to recalculate the
4299 cluster size if necessary. I think that perhaps
4300 we'd better do most/all e2compr-specific checks
4301 separately, after the non-e2compr checks. If not
4302 doing a full check, it may be useful to test that
4303 the personality is linux; e.g. if it isn't then
4304 perhaps this really is just an illegal block. */
4305 return 0;
4306 }
4307
4308 if (blk == 0) {
4309 if (p->is_dir == 0) {
4310 /*
4311 * Should never happen, since only directories
4312 * get called with BLOCK_FLAG_HOLE
4313 */
4314#ifdef DEBUG_E2FSCK
4315 printf("process_block() called with blk == 0, "
4316 "blockcnt=%d, inode %lu???\n",
4317 blockcnt, p->ino);
4318#endif
4319 return 0;
4320 }
4321 if (blockcnt < 0)
4322 return 0;
4323 if (blockcnt * fs->blocksize < p->inode->i_size) {
4324 goto mark_dir;
4325 }
4326 return 0;
4327 }
4328
4329 /*
4330 * Simplistic fragmentation check. We merely require that the
4331 * file be contiguous. (Which can never be true for really
4332 * big files that are greater than a block group.)
4333 */
4334 if (!HOLE_BLKADDR(p->previous_block)) {
4335 if (p->previous_block+1 != blk)
4336 p->fragmented = 1;
4337 }
4338 p->previous_block = blk;
4339
4340 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4341 problem = PR_1_TOOBIG_DIR;
4342 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4343 problem = PR_1_TOOBIG_REG;
4344 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4345 problem = PR_1_TOOBIG_SYMLINK;
4346
4347 if (blk < fs->super->s_first_data_block ||
4348 blk >= fs->super->s_blocks_count)
4349 problem = PR_1_ILLEGAL_BLOCK_NUM;
4350
4351 if (problem) {
4352 p->num_illegal_blocks++;
4353 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4354 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4355 p->clear = 1;
4356 return BLOCK_ABORT;
4357 }
4358 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4359 p->suppress = 1;
4360 set_latch_flags(PR_LATCH_BLOCK,
4361 PRL_SUPPRESS, 0);
4362 }
4363 }
4364 pctx->blk = blk;
4365 pctx->blkcount = blockcnt;
4366 if (fix_problem(ctx, problem, pctx)) {
4367 blk = *block_nr = 0;
4368 ret_code = BLOCK_CHANGED;
4369 goto mark_dir;
4370 } else
4371 return 0;
4372 }
4373
4374 if (p->ino == EXT2_RESIZE_INO) {
4375 /*
4376 * The resize inode has already be sanity checked
4377 * during pass #0 (the superblock checks). All we
4378 * have to do is mark the double indirect block as
4379 * being in use; all of the other blocks are handled
4380 * by mark_table_blocks()).
4381 */
4382 if (blockcnt == BLOCK_COUNT_DIND)
4383 mark_block_used(ctx, blk);
4384 } else
4385 mark_block_used(ctx, blk);
4386 p->num_blocks++;
4387 if (blockcnt >= 0)
4388 p->last_block = blockcnt;
4389mark_dir:
4390 if (p->is_dir && (blockcnt >= 0)) {
4391 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4392 blk, blockcnt);
4393 if (pctx->errcode) {
4394 pctx->blk = blk;
4395 pctx->num = blockcnt;
4396 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4397 /* Should never get here */
4398 ctx->flags |= E2F_FLAG_ABORT;
4399 return BLOCK_ABORT;
4400 }
4401 }
4402 return ret_code;
4403}
4404
4405static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4406 blk_t *block_nr,
4407 e2_blkcnt_t blockcnt,
4408 blk_t ref_block FSCK_ATTR((unused)),
4409 int ref_offset FSCK_ATTR((unused)),
4410 void *priv_data EXT2FS_ATTR((unused)))
4411{
4412 /*
4413 * Note: This function processes blocks for the bad blocks
4414 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4415 */
4416
4417 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4418 return BLOCK_ERROR;
4419}
4420
4421/*
4422 * This routine gets called at the end of pass 1 if bad blocks are
4423 * detected in the superblock, group descriptors, inode_bitmaps, or
4424 * block bitmaps. At this point, all of the blocks have been mapped
4425 * out, so we can try to allocate new block(s) to replace the bad
4426 * blocks.
4427 */
4428static void handle_fs_bad_blocks(e2fsck_t ctx)
4429{
4430 printf("Bad blocks detected on your filesystem\n"
4431 "You should get your data off as the device will soon die\n");
4432}
4433
4434/*
4435 * This routine marks all blocks which are used by the superblock,
4436 * group descriptors, inode bitmaps, and block bitmaps.
4437 */
4438static void mark_table_blocks(e2fsck_t ctx)
4439{
4440 ext2_filsys fs = ctx->fs;
4441 blk_t block, b;
4442 dgrp_t i;
4443 int j;
4444 struct problem_context pctx;
4445
4446 clear_problem_context(&pctx);
4447
4448 block = fs->super->s_first_data_block;
4449 for (i = 0; i < fs->group_desc_count; i++) {
4450 pctx.group = i;
4451
4452 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4453
4454 /*
4455 * Mark the blocks used for the inode table
4456 */
4457 if (fs->group_desc[i].bg_inode_table) {
4458 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4459 j < fs->inode_blocks_per_group;
4460 j++, b++) {
4461 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4462 b)) {
4463 pctx.blk = b;
4464 if (fix_problem(ctx,
4465 PR_1_ITABLE_CONFLICT, &pctx)) {
4466 ctx->invalid_inode_table_flag[i]++;
4467 ctx->invalid_bitmaps++;
4468 }
4469 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004470 ext2fs_mark_block_bitmap(ctx->block_found_map, b);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004471 }
4472 }
4473 }
4474
4475 /*
4476 * Mark block used for the block bitmap
4477 */
4478 if (fs->group_desc[i].bg_block_bitmap) {
4479 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4480 fs->group_desc[i].bg_block_bitmap)) {
4481 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4482 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4483 ctx->invalid_block_bitmap_flag[i]++;
4484 ctx->invalid_bitmaps++;
4485 }
4486 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004487 ext2fs_mark_block_bitmap(ctx->block_found_map,
4488 fs->group_desc[i].bg_block_bitmap);
4489 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004490 }
4491 /*
4492 * Mark block used for the inode bitmap
4493 */
4494 if (fs->group_desc[i].bg_inode_bitmap) {
4495 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4496 fs->group_desc[i].bg_inode_bitmap)) {
4497 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4498 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4499 ctx->invalid_inode_bitmap_flag[i]++;
4500 ctx->invalid_bitmaps++;
4501 }
4502 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004503 ext2fs_mark_block_bitmap(ctx->block_found_map,
4504 fs->group_desc[i].bg_inode_bitmap);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004505 }
4506 }
4507 block += fs->super->s_blocks_per_group;
4508 }
4509}
4510
4511/*
4512 * Thes subroutines short circuits ext2fs_get_blocks and
4513 * ext2fs_check_directory; we use them since we already have the inode
4514 * structure, so there's no point in letting the ext2fs library read
4515 * the inode again.
4516 */
4517static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4518 blk_t *blocks)
4519{
4520 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4521 int i;
4522
4523 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4524 return EXT2_ET_CALLBACK_NOTHANDLED;
4525
4526 for (i=0; i < EXT2_N_BLOCKS; i++)
4527 blocks[i] = ctx->stashed_inode->i_block[i];
4528 return 0;
4529}
4530
4531static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4532 struct ext2_inode *inode)
4533{
4534 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4535
4536 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4537 return EXT2_ET_CALLBACK_NOTHANDLED;
4538 *inode = *ctx->stashed_inode;
4539 return 0;
4540}
4541
4542static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4543 struct ext2_inode *inode)
4544{
4545 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4546
4547 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4548 *ctx->stashed_inode = *inode;
4549 return EXT2_ET_CALLBACK_NOTHANDLED;
4550}
4551
4552static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4553{
4554 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4555
4556 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4557 return EXT2_ET_CALLBACK_NOTHANDLED;
4558
4559 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4560 return EXT2_ET_NO_DIRECTORY;
4561 return 0;
4562}
4563
4564void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4565{
4566 ext2_filsys fs = ctx->fs;
4567
4568 if (bool) {
4569 fs->get_blocks = pass1_get_blocks;
4570 fs->check_directory = pass1_check_directory;
4571 fs->read_inode = pass1_read_inode;
4572 fs->write_inode = pass1_write_inode;
4573 ctx->stashed_ino = 0;
4574 } else {
4575 fs->get_blocks = 0;
4576 fs->check_directory = 0;
4577 fs->read_inode = 0;
4578 fs->write_inode = 0;
4579 }
4580}
4581
4582/*
4583 * pass1b.c --- Pass #1b of e2fsck
4584 *
4585 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4586 * only invoked if pass 1 discovered blocks which are in use by more
4587 * than one inode.
4588 *
4589 * Pass1B scans the data blocks of all the inodes again, generating a
4590 * complete list of duplicate blocks and which inodes have claimed
4591 * them.
4592 *
4593 * Pass1C does a tree-traversal of the filesystem, to determine the
4594 * parent directories of these inodes. This step is necessary so that
4595 * e2fsck can print out the pathnames of affected inodes.
4596 *
4597 * Pass1D is a reconciliation pass. For each inode with duplicate
4598 * blocks, the user is prompted if s/he would like to clone the file
4599 * (so that the file gets a fresh copy of the duplicated blocks) or
4600 * simply to delete the file.
4601 *
4602 */
4603
4604
4605/* Needed for architectures where sizeof(int) != sizeof(void *) */
4606#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4607#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4608
4609/* Define an extension to the ext2 library's block count information */
4610#define BLOCK_COUNT_EXTATTR (-5)
4611
4612struct block_el {
4613 blk_t block;
4614 struct block_el *next;
4615};
4616
4617struct inode_el {
4618 ext2_ino_t inode;
4619 struct inode_el *next;
4620};
4621
4622struct dup_block {
4623 int num_bad;
4624 struct inode_el *inode_list;
4625};
4626
4627/*
4628 * This structure stores information about a particular inode which
4629 * is sharing blocks with other inodes. This information is collected
4630 * to display to the user, so that the user knows what files he or she
4631 * is dealing with, when trying to decide how to resolve the conflict
4632 * of multiply-claimed blocks.
4633 */
4634struct dup_inode {
4635 ext2_ino_t dir;
4636 int num_dupblocks;
4637 struct ext2_inode inode;
4638 struct block_el *block_list;
4639};
4640
4641static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4642 e2_blkcnt_t blockcnt, blk_t ref_blk,
4643 int ref_offset, void *priv_data);
4644static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4645 struct dup_inode *dp, char *block_buf);
4646static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4647 struct dup_inode *dp, char* block_buf);
4648static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4649
4650static void pass1b(e2fsck_t ctx, char *block_buf);
4651static void pass1c(e2fsck_t ctx, char *block_buf);
4652static void pass1d(e2fsck_t ctx, char *block_buf);
4653
4654static int dup_inode_count = 0;
4655
4656static dict_t blk_dict, ino_dict;
4657
4658static ext2fs_inode_bitmap inode_dup_map;
4659
4660static int dict_int_cmp(const void *a, const void *b)
4661{
4662 intptr_t ia, ib;
4663
4664 ia = (intptr_t)a;
4665 ib = (intptr_t)b;
4666
4667 return (ia-ib);
4668}
4669
4670/*
4671 * Add a duplicate block record
4672 */
4673static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4674 struct ext2_inode *inode)
4675{
4676 dnode_t *n;
4677 struct dup_block *db;
4678 struct dup_inode *di;
4679 struct block_el *blk_el;
4680 struct inode_el *ino_el;
4681
4682 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4683 if (n)
4684 db = (struct dup_block *) dnode_get(n);
4685 else {
4686 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4687 sizeof(struct dup_block), "duplicate block header");
4688 db->num_bad = 0;
4689 db->inode_list = 0;
4690 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4691 }
4692 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4693 sizeof(struct inode_el), "inode element");
4694 ino_el->inode = ino;
4695 ino_el->next = db->inode_list;
4696 db->inode_list = ino_el;
4697 db->num_bad++;
4698
4699 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4700 if (n)
4701 di = (struct dup_inode *) dnode_get(n);
4702 else {
4703 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4704 sizeof(struct dup_inode), "duplicate inode header");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00004705 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004706 di->num_dupblocks = 0;
4707 di->block_list = 0;
4708 di->inode = *inode;
4709 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4710 }
4711 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4712 sizeof(struct block_el), "block element");
4713 blk_el->block = blk;
4714 blk_el->next = di->block_list;
4715 di->block_list = blk_el;
4716 di->num_dupblocks++;
4717}
4718
4719/*
4720 * Free a duplicate inode record
4721 */
4722static void inode_dnode_free(dnode_t *node)
4723{
4724 struct dup_inode *di;
4725 struct block_el *p, *next;
4726
4727 di = (struct dup_inode *) dnode_get(node);
4728 for (p = di->block_list; p; p = next) {
4729 next = p->next;
4730 free(p);
4731 }
4732 free(node);
4733}
4734
4735/*
4736 * Free a duplicate block record
4737 */
4738static void block_dnode_free(dnode_t *node)
4739{
4740 struct dup_block *db;
4741 struct inode_el *p, *next;
4742
4743 db = (struct dup_block *) dnode_get(node);
4744 for (p = db->inode_list; p; p = next) {
4745 next = p->next;
4746 free(p);
4747 }
4748 free(node);
4749}
4750
4751
4752/*
4753 * Main procedure for handling duplicate blocks
4754 */
4755void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4756{
4757 ext2_filsys fs = ctx->fs;
4758 struct problem_context pctx;
4759
4760 clear_problem_context(&pctx);
4761
4762 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4763 _("multiply claimed inode map"), &inode_dup_map);
4764 if (pctx.errcode) {
4765 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4766 ctx->flags |= E2F_FLAG_ABORT;
4767 return;
4768 }
4769
4770 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4771 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772 dict_set_allocator(&ino_dict, inode_dnode_free);
4773 dict_set_allocator(&blk_dict, block_dnode_free);
4774
4775 pass1b(ctx, block_buf);
4776 pass1c(ctx, block_buf);
4777 pass1d(ctx, block_buf);
4778
4779 /*
4780 * Time to free all of the accumulated data structures that we
4781 * don't need anymore.
4782 */
4783 dict_free_nodes(&ino_dict);
4784 dict_free_nodes(&blk_dict);
4785}
4786
4787/*
4788 * Scan the inodes looking for inodes that contain duplicate blocks.
4789 */
4790struct process_block_struct_1b {
4791 e2fsck_t ctx;
4792 ext2_ino_t ino;
4793 int dup_blocks;
4794 struct ext2_inode *inode;
4795 struct problem_context *pctx;
4796};
4797
4798static void pass1b(e2fsck_t ctx, char *block_buf)
4799{
4800 ext2_filsys fs = ctx->fs;
4801 ext2_ino_t ino;
4802 struct ext2_inode inode;
4803 ext2_inode_scan scan;
4804 struct process_block_struct_1b pb;
4805 struct problem_context pctx;
4806
4807 clear_problem_context(&pctx);
4808
4809 if (!(ctx->options & E2F_OPT_PREEN))
4810 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4811 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4812 &scan);
4813 if (pctx.errcode) {
4814 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4815 ctx->flags |= E2F_FLAG_ABORT;
4816 return;
4817 }
4818 ctx->stashed_inode = &inode;
4819 pb.ctx = ctx;
4820 pb.pctx = &pctx;
4821 pctx.str = "pass1b";
4822 while (1) {
4823 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4824 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4825 continue;
4826 if (pctx.errcode) {
4827 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4828 ctx->flags |= E2F_FLAG_ABORT;
4829 return;
4830 }
4831 if (!ino)
4832 break;
4833 pctx.ino = ctx->stashed_ino = ino;
4834 if ((ino != EXT2_BAD_INO) &&
4835 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4836 continue;
4837
4838 pb.ino = ino;
4839 pb.dup_blocks = 0;
4840 pb.inode = &inode;
4841
4842 if (ext2fs_inode_has_valid_blocks(&inode) ||
4843 (ino == EXT2_BAD_INO))
4844 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4845 0, block_buf, process_pass1b_block, &pb);
4846 if (inode.i_file_acl)
4847 process_pass1b_block(fs, &inode.i_file_acl,
4848 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4849 if (pb.dup_blocks) {
4850 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4851 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4852 ino == EXT2_ROOT_INO)
4853 dup_inode_count++;
4854 }
4855 if (pctx.errcode)
4856 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4857 }
4858 ext2fs_close_inode_scan(scan);
4859 e2fsck_use_inode_shortcuts(ctx, 0);
4860}
4861
4862static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4863 blk_t *block_nr,
4864 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4865 blk_t ref_blk FSCK_ATTR((unused)),
4866 int ref_offset FSCK_ATTR((unused)),
4867 void *priv_data)
4868{
4869 struct process_block_struct_1b *p;
4870 e2fsck_t ctx;
4871
4872 if (HOLE_BLKADDR(*block_nr))
4873 return 0;
4874 p = (struct process_block_struct_1b *) priv_data;
4875 ctx = p->ctx;
4876
4877 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4878 return 0;
4879
4880 /* OK, this is a duplicate block */
4881 if (p->ino != EXT2_BAD_INO) {
4882 p->pctx->blk = *block_nr;
4883 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4884 }
4885 p->dup_blocks++;
4886 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4887
4888 add_dupe(ctx, p->ino, *block_nr, p->inode);
4889
4890 return 0;
4891}
4892
4893/*
4894 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4895 * is used so that we can print pathnames when prompting the user for
4896 * what to do.
4897 */
4898struct search_dir_struct {
4899 int count;
4900 ext2_ino_t first_inode;
4901 ext2_ino_t max_inode;
4902};
4903
4904static int search_dirent_proc(ext2_ino_t dir, int entry,
4905 struct ext2_dir_entry *dirent,
4906 int offset FSCK_ATTR((unused)),
4907 int blocksize FSCK_ATTR((unused)),
4908 char *buf FSCK_ATTR((unused)),
4909 void *priv_data)
4910{
4911 struct search_dir_struct *sd;
4912 struct dup_inode *p;
4913 dnode_t *n;
4914
4915 sd = (struct search_dir_struct *) priv_data;
4916
4917 if (dirent->inode > sd->max_inode)
4918 /* Should abort this inode, but not everything */
4919 return 0;
4920
4921 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4922 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4923 return 0;
4924
4925 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4926 if (!n)
4927 return 0;
4928 p = (struct dup_inode *) dnode_get(n);
4929 p->dir = dir;
4930 sd->count--;
4931
4932 return sd->count ? 0 : DIRENT_ABORT;
4933}
4934
4935
4936static void pass1c(e2fsck_t ctx, char *block_buf)
4937{
4938 ext2_filsys fs = ctx->fs;
4939 struct search_dir_struct sd;
4940 struct problem_context pctx;
4941
4942 clear_problem_context(&pctx);
4943
4944 if (!(ctx->options & E2F_OPT_PREEN))
4945 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4946
4947 /*
4948 * Search through all directories to translate inodes to names
4949 * (by searching for the containing directory for that inode.)
4950 */
4951 sd.count = dup_inode_count;
4952 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4953 sd.max_inode = fs->super->s_inodes_count;
4954 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4955 search_dirent_proc, &sd);
4956}
4957
4958static void pass1d(e2fsck_t ctx, char *block_buf)
4959{
4960 ext2_filsys fs = ctx->fs;
4961 struct dup_inode *p, *t;
4962 struct dup_block *q;
4963 ext2_ino_t *shared, ino;
4964 int shared_len;
4965 int i;
4966 int file_ok;
4967 int meta_data = 0;
4968 struct problem_context pctx;
4969 dnode_t *n, *m;
4970 struct block_el *s;
4971 struct inode_el *r;
4972
4973 clear_problem_context(&pctx);
4974
4975 if (!(ctx->options & E2F_OPT_PREEN))
4976 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4977 e2fsck_read_bitmaps(ctx);
4978
4979 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4980 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4981 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4982 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4983 "Shared inode list");
4984 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4985 p = (struct dup_inode *) dnode_get(n);
4986 shared_len = 0;
4987 file_ok = 1;
4988 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4989 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4990 continue;
4991
4992 /*
4993 * Find all of the inodes which share blocks with this
4994 * one. First we find all of the duplicate blocks
4995 * belonging to this inode, and then search each block
4996 * get the list of inodes, and merge them together.
4997 */
4998 for (s = p->block_list; s; s = s->next) {
4999 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5000 if (!m)
5001 continue; /* Should never happen... */
5002 q = (struct dup_block *) dnode_get(m);
5003 if (q->num_bad > 1)
5004 file_ok = 0;
5005 if (check_if_fs_block(ctx, s->block)) {
5006 file_ok = 0;
5007 meta_data = 1;
5008 }
5009
5010 /*
5011 * Add all inodes used by this block to the
5012 * shared[] --- which is a unique list, so
5013 * if an inode is already in shared[], don't
5014 * add it again.
5015 */
5016 for (r = q->inode_list; r; r = r->next) {
5017 if (r->inode == ino)
5018 continue;
5019 for (i = 0; i < shared_len; i++)
5020 if (shared[i] == r->inode)
5021 break;
5022 if (i == shared_len) {
5023 shared[shared_len++] = r->inode;
5024 }
5025 }
5026 }
5027
5028 /*
5029 * Report the inode that we are working on
5030 */
5031 pctx.inode = &p->inode;
5032 pctx.ino = ino;
5033 pctx.dir = p->dir;
5034 pctx.blkcount = p->num_dupblocks;
5035 pctx.num = meta_data ? shared_len+1 : shared_len;
5036 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5037 pctx.blkcount = 0;
5038 pctx.num = 0;
5039
5040 if (meta_data)
5041 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5042
5043 for (i = 0; i < shared_len; i++) {
5044 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5045 if (!m)
5046 continue; /* should never happen */
5047 t = (struct dup_inode *) dnode_get(m);
5048 /*
5049 * Report the inode that we are sharing with
5050 */
5051 pctx.inode = &t->inode;
5052 pctx.ino = shared[i];
5053 pctx.dir = t->dir;
5054 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5055 }
5056 if (file_ok) {
5057 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5058 continue;
5059 }
5060 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5061 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5062 if (pctx.errcode)
5063 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5064 else
5065 continue;
5066 }
5067 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5068 delete_file(ctx, ino, p, block_buf);
5069 else
5070 ext2fs_unmark_valid(fs);
5071 }
5072 ext2fs_free_mem(&shared);
5073}
5074
5075/*
5076 * Drop the refcount on the dup_block structure, and clear the entry
5077 * in the block_dup_map if appropriate.
5078 */
5079static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5080{
5081 p->num_bad--;
5082 if (p->num_bad <= 0 ||
5083 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5084 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5085}
5086
5087static int delete_file_block(ext2_filsys fs,
5088 blk_t *block_nr,
5089 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5090 blk_t ref_block FSCK_ATTR((unused)),
5091 int ref_offset FSCK_ATTR((unused)),
5092 void *priv_data)
5093{
5094 struct process_block_struct_1b *pb;
5095 struct dup_block *p;
5096 dnode_t *n;
5097 e2fsck_t ctx;
5098
5099 pb = (struct process_block_struct_1b *) priv_data;
5100 ctx = pb->ctx;
5101
5102 if (HOLE_BLKADDR(*block_nr))
5103 return 0;
5104
5105 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5106 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5107 if (n) {
5108 p = (struct dup_block *) dnode_get(n);
5109 decrement_badcount(ctx, *block_nr, p);
5110 } else
5111 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5112 *block_nr);
5113 } else {
5114 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5115 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5116 }
5117
5118 return 0;
5119}
5120
5121static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5122 struct dup_inode *dp, char* block_buf)
5123{
5124 ext2_filsys fs = ctx->fs;
5125 struct process_block_struct_1b pb;
5126 struct ext2_inode inode;
5127 struct problem_context pctx;
5128 unsigned int count;
5129
5130 clear_problem_context(&pctx);
5131 pctx.ino = pb.ino = ino;
5132 pb.dup_blocks = dp->num_dupblocks;
5133 pb.ctx = ctx;
5134 pctx.str = "delete_file";
5135
5136 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5137 if (ext2fs_inode_has_valid_blocks(&inode))
5138 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5139 delete_file_block, &pb);
5140 if (pctx.errcode)
5141 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5142 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5143 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5144 if (ctx->inode_bad_map)
5145 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5146 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5147
5148 /* Inode may have changed by block_iterate, so reread it */
5149 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5150 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00005151 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005152 if (inode.i_file_acl &&
5153 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5154 count = 1;
5155 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5156 block_buf, -1, &count);
5157 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5158 pctx.errcode = 0;
5159 count = 1;
5160 }
5161 if (pctx.errcode) {
5162 pctx.blk = inode.i_file_acl;
5163 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5164 }
5165 /*
5166 * If the count is zero, then arrange to have the
5167 * block deleted. If the block is in the block_dup_map,
5168 * also call delete_file_block since it will take care
5169 * of keeping the accounting straight.
5170 */
5171 if ((count == 0) ||
5172 ext2fs_test_block_bitmap(ctx->block_dup_map,
5173 inode.i_file_acl))
5174 delete_file_block(fs, &inode.i_file_acl,
5175 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5176 }
5177 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5178}
5179
5180struct clone_struct {
5181 errcode_t errcode;
5182 ext2_ino_t dir;
5183 char *buf;
5184 e2fsck_t ctx;
5185};
5186
5187static int clone_file_block(ext2_filsys fs,
5188 blk_t *block_nr,
5189 e2_blkcnt_t blockcnt,
5190 blk_t ref_block FSCK_ATTR((unused)),
5191 int ref_offset FSCK_ATTR((unused)),
5192 void *priv_data)
5193{
5194 struct dup_block *p;
5195 blk_t new_block;
5196 errcode_t retval;
5197 struct clone_struct *cs = (struct clone_struct *) priv_data;
5198 dnode_t *n;
5199 e2fsck_t ctx;
5200
5201 ctx = cs->ctx;
5202
5203 if (HOLE_BLKADDR(*block_nr))
5204 return 0;
5205
5206 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5207 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5208 if (n) {
5209 p = (struct dup_block *) dnode_get(n);
5210 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5211 &new_block);
5212 if (retval) {
5213 cs->errcode = retval;
5214 return BLOCK_ABORT;
5215 }
5216 if (cs->dir && (blockcnt >= 0)) {
5217 retval = ext2fs_set_dir_block(fs->dblist,
5218 cs->dir, new_block, blockcnt);
5219 if (retval) {
5220 cs->errcode = retval;
5221 return BLOCK_ABORT;
5222 }
5223 }
5224
5225 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5226 cs->buf);
5227 if (retval) {
5228 cs->errcode = retval;
5229 return BLOCK_ABORT;
5230 }
5231 retval = io_channel_write_blk(fs->io, new_block, 1,
5232 cs->buf);
5233 if (retval) {
5234 cs->errcode = retval;
5235 return BLOCK_ABORT;
5236 }
5237 decrement_badcount(ctx, *block_nr, p);
5238 *block_nr = new_block;
5239 ext2fs_mark_block_bitmap(ctx->block_found_map,
5240 new_block);
5241 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5242 return BLOCK_CHANGED;
5243 } else
5244 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5245 *block_nr);
5246 }
5247 return 0;
5248}
5249
5250static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5251 struct dup_inode *dp, char* block_buf)
5252{
5253 ext2_filsys fs = ctx->fs;
5254 errcode_t retval;
5255 struct clone_struct cs;
5256 struct problem_context pctx;
5257 blk_t blk;
5258 dnode_t *n;
5259 struct inode_el *ino_el;
5260 struct dup_block *db;
5261 struct dup_inode *di;
5262
5263 clear_problem_context(&pctx);
5264 cs.errcode = 0;
5265 cs.dir = 0;
5266 cs.ctx = ctx;
5267 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5268 if (retval)
5269 return retval;
5270
5271 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5272 cs.dir = ino;
5273
5274 pctx.ino = ino;
5275 pctx.str = "clone_file";
5276 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5277 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5278 clone_file_block, &cs);
5279 ext2fs_mark_bb_dirty(fs);
5280 if (pctx.errcode) {
5281 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5282 retval = pctx.errcode;
5283 goto errout;
5284 }
5285 if (cs.errcode) {
5286 bb_error_msg(_("returned from clone_file_block"));
5287 retval = cs.errcode;
5288 goto errout;
5289 }
5290 /* The inode may have changed on disk, so we have to re-read it */
5291 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5292 blk = dp->inode.i_file_acl;
5293 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5294 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5295 BLOCK_CHANGED)) {
5296 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5297 /*
5298 * If we cloned the EA block, find all other inodes
5299 * which refered to that EA block, and modify
5300 * them to point to the new EA block.
5301 */
5302 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5303 db = (struct dup_block *) dnode_get(n);
5304 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5305 if (ino_el->inode == ino)
5306 continue;
5307 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5308 di = (struct dup_inode *) dnode_get(n);
5309 if (di->inode.i_file_acl == blk) {
5310 di->inode.i_file_acl = dp->inode.i_file_acl;
5311 e2fsck_write_inode(ctx, ino_el->inode,
5312 &di->inode, "clone file EA");
5313 decrement_badcount(ctx, blk, db);
5314 }
5315 }
5316 }
5317 retval = 0;
5318errout:
5319 ext2fs_free_mem(&cs.buf);
5320 return retval;
5321}
5322
5323/*
5324 * This routine returns 1 if a block overlaps with one of the superblocks,
5325 * group descriptors, inode bitmaps, or block bitmaps.
5326 */
5327static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5328{
5329 ext2_filsys fs = ctx->fs;
5330 blk_t block;
5331 dgrp_t i;
5332
5333 block = fs->super->s_first_data_block;
5334 for (i = 0; i < fs->group_desc_count; i++) {
5335
5336 /* Check superblocks/block group descriptros */
5337 if (ext2fs_bg_has_super(fs, i)) {
5338 if (test_block >= block &&
5339 (test_block <= block + fs->desc_blocks))
5340 return 1;
5341 }
5342
5343 /* Check the inode table */
5344 if ((fs->group_desc[i].bg_inode_table) &&
5345 (test_block >= fs->group_desc[i].bg_inode_table) &&
5346 (test_block < (fs->group_desc[i].bg_inode_table +
5347 fs->inode_blocks_per_group)))
5348 return 1;
5349
5350 /* Check the bitmap blocks */
5351 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5352 (test_block == fs->group_desc[i].bg_inode_bitmap))
5353 return 1;
5354
5355 block += fs->super->s_blocks_per_group;
5356 }
5357 return 0;
5358}
5359/*
5360 * pass2.c --- check directory structure
5361 *
5362 * Pass 2 of e2fsck iterates through all active directory inodes, and
5363 * applies to following tests to each directory entry in the directory
5364 * blocks in the inodes:
5365 *
5366 * - The length of the directory entry (rec_len) should be at
5367 * least 8 bytes, and no more than the remaining space
5368 * left in the directory block.
5369 * - The length of the name in the directory entry (name_len)
5370 * should be less than (rec_len - 8).
5371 * - The inode number in the directory entry should be within
5372 * legal bounds.
5373 * - The inode number should refer to a in-use inode.
5374 * - The first entry should be '.', and its inode should be
5375 * the inode of the directory.
5376 * - The second entry should be '..'.
5377 *
5378 * To minimize disk seek time, the directory blocks are processed in
5379 * sorted order of block numbers.
5380 *
5381 * Pass 2 also collects the following information:
5382 * - The inode numbers of the subdirectories for each directory.
5383 *
5384 * Pass 2 relies on the following information from previous passes:
5385 * - The directory information collected in pass 1.
5386 * - The inode_used_map bitmap
5387 * - The inode_bad_map bitmap
5388 * - The inode_dir_map bitmap
5389 *
5390 * Pass 2 frees the following data structures
5391 * - The inode_bad_map bitmap
5392 * - The inode_reg_map bitmap
5393 */
5394
5395/*
5396 * Keeps track of how many times an inode is referenced.
5397 */
5398static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5399static int check_dir_block(ext2_filsys fs,
5400 struct ext2_db_entry *dir_blocks_info,
5401 void *priv_data);
5402static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5403 struct problem_context *pctx);
5404static int update_dir_block(ext2_filsys fs,
5405 blk_t *block_nr,
5406 e2_blkcnt_t blockcnt,
5407 blk_t ref_block,
5408 int ref_offset,
5409 void *priv_data);
5410static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5411static int htree_depth(struct dx_dir_info *dx_dir,
5412 struct dx_dirblock_info *dx_db);
5413static int special_dir_block_cmp(const void *a, const void *b);
5414
5415struct check_dir_struct {
5416 char *buf;
5417 struct problem_context pctx;
5418 int count, max;
5419 e2fsck_t ctx;
5420};
5421
5422static void e2fsck_pass2(e2fsck_t ctx)
5423{
5424 struct ext2_super_block *sb = ctx->fs->super;
5425 struct problem_context pctx;
5426 ext2_filsys fs = ctx->fs;
5427 char *buf;
5428 struct dir_info *dir;
5429 struct check_dir_struct cd;
5430 struct dx_dir_info *dx_dir;
5431 struct dx_dirblock_info *dx_db, *dx_parent;
5432 int b;
5433 int i, depth;
5434 problem_t code;
5435 int bad_dir;
5436
5437 clear_problem_context(&cd.pctx);
5438
5439 /* Pass 2 */
5440
5441 if (!(ctx->options & E2F_OPT_PREEN))
5442 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5443
5444 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5445 0, ctx->inode_link_info,
5446 &ctx->inode_count);
5447 if (cd.pctx.errcode) {
5448 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5449 ctx->flags |= E2F_FLAG_ABORT;
5450 return;
5451 }
5452 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5453 "directory scan buffer");
5454
5455 /*
5456 * Set up the parent pointer for the root directory, if
5457 * present. (If the root directory is not present, we will
5458 * create it in pass 3.)
5459 */
5460 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5461 if (dir)
5462 dir->parent = EXT2_ROOT_INO;
5463
5464 cd.buf = buf;
5465 cd.ctx = ctx;
5466 cd.count = 1;
5467 cd.max = ext2fs_dblist_count(fs->dblist);
5468
5469 if (ctx->progress)
5470 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5471
5472 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5473 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5474
5475 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5476 &cd);
5477 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478 return;
5479 if (cd.pctx.errcode) {
5480 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5481 ctx->flags |= E2F_FLAG_ABORT;
5482 return;
5483 }
5484
5485#ifdef ENABLE_HTREE
5486 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5487 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5488 return;
5489 if (dx_dir->numblocks == 0)
5490 continue;
5491 clear_problem_context(&pctx);
5492 bad_dir = 0;
5493 pctx.dir = dx_dir->ino;
5494 dx_db = dx_dir->dx_block;
5495 if (dx_db->flags & DX_FLAG_REFERENCED)
5496 dx_db->flags |= DX_FLAG_DUP_REF;
5497 else
5498 dx_db->flags |= DX_FLAG_REFERENCED;
5499 /*
5500 * Find all of the first and last leaf blocks, and
5501 * update their parent's min and max hash values
5502 */
5503 for (b=0, dx_db = dx_dir->dx_block;
5504 b < dx_dir->numblocks;
5505 b++, dx_db++) {
5506 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5507 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5508 continue;
5509 dx_parent = &dx_dir->dx_block[dx_db->parent];
5510 /*
5511 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5512 */
5513 if (dx_db->flags & DX_FLAG_FIRST)
5514 dx_parent->min_hash = dx_db->min_hash;
5515 /*
5516 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5517 */
5518 if (dx_db->flags & DX_FLAG_LAST)
5519 dx_parent->max_hash = dx_db->max_hash;
5520 }
5521
5522 for (b=0, dx_db = dx_dir->dx_block;
5523 b < dx_dir->numblocks;
5524 b++, dx_db++) {
5525 pctx.blkcount = b;
5526 pctx.group = dx_db->parent;
5527 code = 0;
5528 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5529 (dx_db->min_hash < dx_db->node_min_hash)) {
5530 pctx.blk = dx_db->min_hash;
5531 pctx.blk2 = dx_db->node_min_hash;
5532 code = PR_2_HTREE_MIN_HASH;
5533 fix_problem(ctx, code, &pctx);
5534 bad_dir++;
5535 }
5536 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5537 depth = htree_depth(dx_dir, dx_db);
5538 if (depth != dx_dir->depth) {
5539 code = PR_2_HTREE_BAD_DEPTH;
5540 fix_problem(ctx, code, &pctx);
5541 bad_dir++;
5542 }
5543 }
5544 /*
5545 * This test doesn't apply for the root block
5546 * at block #0
5547 */
5548 if (b &&
5549 (dx_db->max_hash > dx_db->node_max_hash)) {
5550 pctx.blk = dx_db->max_hash;
5551 pctx.blk2 = dx_db->node_max_hash;
5552 code = PR_2_HTREE_MAX_HASH;
5553 fix_problem(ctx, code, &pctx);
5554 bad_dir++;
5555 }
5556 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5557 code = PR_2_HTREE_NOTREF;
5558 fix_problem(ctx, code, &pctx);
5559 bad_dir++;
5560 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5561 code = PR_2_HTREE_DUPREF;
5562 fix_problem(ctx, code, &pctx);
5563 bad_dir++;
5564 }
5565 if (code == 0)
5566 continue;
5567 }
5568 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5569 clear_htree(ctx, dx_dir->ino);
5570 dx_dir->numblocks = 0;
5571 }
5572 }
5573#endif
5574 ext2fs_free_mem(&buf);
5575 ext2fs_free_dblist(fs->dblist);
5576
5577 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5578 ctx->inode_bad_map = 0;
5579 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5580 ctx->inode_reg_map = 0;
5581
5582 clear_problem_context(&pctx);
5583 if (ctx->large_files) {
5584 if (!(sb->s_feature_ro_compat &
5585 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5586 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5587 sb->s_feature_ro_compat |=
5588 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5589 ext2fs_mark_super_dirty(fs);
5590 }
5591 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5592 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5593 ext2fs_update_dynamic_rev(fs);
5594 ext2fs_mark_super_dirty(fs);
5595 }
5596 } else if (!ctx->large_files &&
5597 (sb->s_feature_ro_compat &
5598 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5599 if (fs->flags & EXT2_FLAG_RW) {
5600 sb->s_feature_ro_compat &=
5601 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5602 ext2fs_mark_super_dirty(fs);
5603 }
5604 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005605}
5606
5607#define MAX_DEPTH 32000
5608static int htree_depth(struct dx_dir_info *dx_dir,
5609 struct dx_dirblock_info *dx_db)
5610{
5611 int depth = 0;
5612
5613 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5614 dx_db = &dx_dir->dx_block[dx_db->parent];
5615 depth++;
5616 }
5617 return depth;
5618}
5619
5620static int dict_de_cmp(const void *a, const void *b)
5621{
5622 const struct ext2_dir_entry *de_a, *de_b;
5623 int a_len, b_len;
5624
5625 de_a = (const struct ext2_dir_entry *) a;
5626 a_len = de_a->name_len & 0xFF;
5627 de_b = (const struct ext2_dir_entry *) b;
5628 b_len = de_b->name_len & 0xFF;
5629
5630 if (a_len != b_len)
5631 return (a_len - b_len);
5632
5633 return strncmp(de_a->name, de_b->name, a_len);
5634}
5635
5636/*
5637 * This is special sort function that makes sure that directory blocks
5638 * with a dirblock of zero are sorted to the beginning of the list.
5639 * This guarantees that the root node of the htree directories are
5640 * processed first, so we know what hash version to use.
5641 */
5642static int special_dir_block_cmp(const void *a, const void *b)
5643{
5644 const struct ext2_db_entry *db_a =
5645 (const struct ext2_db_entry *) a;
5646 const struct ext2_db_entry *db_b =
5647 (const struct ext2_db_entry *) b;
5648
5649 if (db_a->blockcnt && !db_b->blockcnt)
5650 return 1;
5651
5652 if (!db_a->blockcnt && db_b->blockcnt)
5653 return -1;
5654
5655 if (db_a->blk != db_b->blk)
5656 return (int) (db_a->blk - db_b->blk);
5657
5658 if (db_a->ino != db_b->ino)
5659 return (int) (db_a->ino - db_b->ino);
5660
5661 return (int) (db_a->blockcnt - db_b->blockcnt);
5662}
5663
5664
5665/*
5666 * Make sure the first entry in the directory is '.', and that the
5667 * directory entry is sane.
5668 */
5669static int check_dot(e2fsck_t ctx,
5670 struct ext2_dir_entry *dirent,
5671 ext2_ino_t ino, struct problem_context *pctx)
5672{
5673 struct ext2_dir_entry *nextdir;
5674 int status = 0;
5675 int created = 0;
5676 int new_len;
5677 int problem = 0;
5678
5679 if (!dirent->inode)
5680 problem = PR_2_MISSING_DOT;
5681 else if (((dirent->name_len & 0xFF) != 1) ||
5682 (dirent->name[0] != '.'))
5683 problem = PR_2_1ST_NOT_DOT;
5684 else if (dirent->name[1] != '\0')
5685 problem = PR_2_DOT_NULL_TERM;
5686
5687 if (problem) {
5688 if (fix_problem(ctx, problem, pctx)) {
5689 if (dirent->rec_len < 12)
5690 dirent->rec_len = 12;
5691 dirent->inode = ino;
5692 dirent->name_len = 1;
5693 dirent->name[0] = '.';
5694 dirent->name[1] = '\0';
5695 status = 1;
5696 created = 1;
5697 }
5698 }
5699 if (dirent->inode != ino) {
5700 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5701 dirent->inode = ino;
5702 status = 1;
5703 }
5704 }
5705 if (dirent->rec_len > 12) {
5706 new_len = dirent->rec_len - 12;
5707 if (new_len > 12) {
5708 if (created ||
5709 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5710 nextdir = (struct ext2_dir_entry *)
5711 ((char *) dirent + 12);
5712 dirent->rec_len = 12;
5713 nextdir->rec_len = new_len;
5714 nextdir->inode = 0;
5715 nextdir->name_len = 0;
5716 status = 1;
5717 }
5718 }
5719 }
5720 return status;
5721}
5722
5723/*
5724 * Make sure the second entry in the directory is '..', and that the
5725 * directory entry is sane. We do not check the inode number of '..'
5726 * here; this gets done in pass 3.
5727 */
5728static int check_dotdot(e2fsck_t ctx,
5729 struct ext2_dir_entry *dirent,
5730 struct dir_info *dir, struct problem_context *pctx)
5731{
5732 int problem = 0;
5733
5734 if (!dirent->inode)
5735 problem = PR_2_MISSING_DOT_DOT;
5736 else if (((dirent->name_len & 0xFF) != 2) ||
5737 (dirent->name[0] != '.') ||
5738 (dirent->name[1] != '.'))
5739 problem = PR_2_2ND_NOT_DOT_DOT;
5740 else if (dirent->name[2] != '\0')
5741 problem = PR_2_DOT_DOT_NULL_TERM;
5742
5743 if (problem) {
5744 if (fix_problem(ctx, problem, pctx)) {
5745 if (dirent->rec_len < 12)
5746 dirent->rec_len = 12;
5747 /*
5748 * Note: we don't have the parent inode just
5749 * yet, so we will fill it in with the root
5750 * inode. This will get fixed in pass 3.
5751 */
5752 dirent->inode = EXT2_ROOT_INO;
5753 dirent->name_len = 2;
5754 dirent->name[0] = '.';
5755 dirent->name[1] = '.';
5756 dirent->name[2] = '\0';
5757 return 1;
5758 }
5759 return 0;
5760 }
5761 dir->dotdot = dirent->inode;
5762 return 0;
5763}
5764
5765/*
5766 * Check to make sure a directory entry doesn't contain any illegal
5767 * characters.
5768 */
5769static int check_name(e2fsck_t ctx,
5770 struct ext2_dir_entry *dirent,
5771 struct problem_context *pctx)
5772{
5773 int i;
5774 int fixup = -1;
5775 int ret = 0;
5776
5777 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5778 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5779 if (fixup < 0) {
5780 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5781 }
5782 if (fixup) {
5783 dirent->name[i] = '.';
5784 ret = 1;
5785 }
5786 }
5787 }
5788 return ret;
5789}
5790
5791/*
5792 * Check the directory filetype (if present)
5793 */
5794
5795/*
5796 * Given a mode, return the ext2 file type
5797 */
5798static int ext2_file_type(unsigned int mode)
5799{
5800 if (LINUX_S_ISREG(mode))
5801 return EXT2_FT_REG_FILE;
5802
5803 if (LINUX_S_ISDIR(mode))
5804 return EXT2_FT_DIR;
5805
5806 if (LINUX_S_ISCHR(mode))
5807 return EXT2_FT_CHRDEV;
5808
5809 if (LINUX_S_ISBLK(mode))
5810 return EXT2_FT_BLKDEV;
5811
5812 if (LINUX_S_ISLNK(mode))
5813 return EXT2_FT_SYMLINK;
5814
5815 if (LINUX_S_ISFIFO(mode))
5816 return EXT2_FT_FIFO;
5817
5818 if (LINUX_S_ISSOCK(mode))
5819 return EXT2_FT_SOCK;
5820
5821 return 0;
5822}
5823
5824static int check_filetype(e2fsck_t ctx,
5825 struct ext2_dir_entry *dirent,
5826 struct problem_context *pctx)
5827{
5828 int filetype = dirent->name_len >> 8;
5829 int should_be = EXT2_FT_UNKNOWN;
5830 struct ext2_inode inode;
5831
5832 if (!(ctx->fs->super->s_feature_incompat &
5833 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5834 if (filetype == 0 ||
5835 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5836 return 0;
5837 dirent->name_len = dirent->name_len & 0xFF;
5838 return 1;
5839 }
5840
5841 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5842 should_be = EXT2_FT_DIR;
5843 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5844 dirent->inode)) {
5845 should_be = EXT2_FT_REG_FILE;
5846 } else if (ctx->inode_bad_map &&
5847 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5848 dirent->inode))
5849 should_be = 0;
5850 else {
5851 e2fsck_read_inode(ctx, dirent->inode, &inode,
5852 "check_filetype");
5853 should_be = ext2_file_type(inode.i_mode);
5854 }
5855 if (filetype == should_be)
5856 return 0;
5857 pctx->num = should_be;
5858
5859 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5860 pctx) == 0)
5861 return 0;
5862
5863 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5864 return 1;
5865}
5866
5867#ifdef ENABLE_HTREE
5868static void parse_int_node(ext2_filsys fs,
5869 struct ext2_db_entry *db,
5870 struct check_dir_struct *cd,
5871 struct dx_dir_info *dx_dir,
5872 char *block_buf)
5873{
5874 struct ext2_dx_root_info *root;
5875 struct ext2_dx_entry *ent;
5876 struct ext2_dx_countlimit *limit;
5877 struct dx_dirblock_info *dx_db;
5878 int i, expect_limit, count;
5879 blk_t blk;
5880 ext2_dirhash_t min_hash = 0xffffffff;
5881 ext2_dirhash_t max_hash = 0;
5882 ext2_dirhash_t hash = 0, prev_hash;
5883
5884 if (db->blockcnt == 0) {
5885 root = (struct ext2_dx_root_info *) (block_buf + 24);
5886 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5887 } else {
5888 ent = (struct ext2_dx_entry *) (block_buf+8);
5889 }
5890 limit = (struct ext2_dx_countlimit *) ent;
5891
5892 count = ext2fs_le16_to_cpu(limit->count);
5893 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5894 sizeof(struct ext2_dx_entry);
5895 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5896 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5897 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5898 goto clear_and_exit;
5899 }
5900 if (count > expect_limit) {
5901 cd->pctx.num = count;
5902 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5903 goto clear_and_exit;
5904 count = expect_limit;
5905 }
5906
5907 for (i=0; i < count; i++) {
5908 prev_hash = hash;
5909 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5910 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5911 /* Check to make sure the block is valid */
5912 if (blk > (blk_t) dx_dir->numblocks) {
5913 cd->pctx.blk = blk;
5914 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5915 &cd->pctx))
5916 goto clear_and_exit;
5917 }
5918 if (hash < prev_hash &&
5919 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5920 goto clear_and_exit;
5921 dx_db = &dx_dir->dx_block[blk];
5922 if (dx_db->flags & DX_FLAG_REFERENCED) {
5923 dx_db->flags |= DX_FLAG_DUP_REF;
5924 } else {
5925 dx_db->flags |= DX_FLAG_REFERENCED;
5926 dx_db->parent = db->blockcnt;
5927 }
5928 if (hash < min_hash)
5929 min_hash = hash;
5930 if (hash > max_hash)
5931 max_hash = hash;
5932 dx_db->node_min_hash = hash;
5933 if ((i+1) < count)
5934 dx_db->node_max_hash =
5935 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5936 else {
5937 dx_db->node_max_hash = 0xfffffffe;
5938 dx_db->flags |= DX_FLAG_LAST;
5939 }
5940 if (i == 0)
5941 dx_db->flags |= DX_FLAG_FIRST;
5942 }
5943 dx_db = &dx_dir->dx_block[db->blockcnt];
5944 dx_db->min_hash = min_hash;
5945 dx_db->max_hash = max_hash;
5946 return;
5947
5948clear_and_exit:
5949 clear_htree(cd->ctx, cd->pctx.ino);
5950 dx_dir->numblocks = 0;
5951}
5952#endif /* ENABLE_HTREE */
5953
5954/*
5955 * Given a busted directory, try to salvage it somehow.
5956 *
5957 */
5958static void salvage_directory(ext2_filsys fs,
5959 struct ext2_dir_entry *dirent,
5960 struct ext2_dir_entry *prev,
5961 unsigned int *offset)
5962{
5963 char *cp = (char *) dirent;
5964 int left = fs->blocksize - *offset - dirent->rec_len;
5965 int name_len = dirent->name_len & 0xFF;
5966
5967 /*
5968 * Special case of directory entry of size 8: copy what's left
5969 * of the directory block up to cover up the invalid hole.
5970 */
5971 if ((left >= 12) && (dirent->rec_len == 8)) {
5972 memmove(cp, cp+8, left);
5973 memset(cp + left, 0, 8);
5974 return;
5975 }
5976 /*
5977 * If the directory entry overruns the end of the directory
5978 * block, and the name is small enough to fit, then adjust the
5979 * record length.
5980 */
5981 if ((left < 0) &&
5982 (name_len + 8 <= dirent->rec_len + left) &&
5983 dirent->inode <= fs->super->s_inodes_count &&
5984 strnlen(dirent->name, name_len) == name_len) {
5985 dirent->rec_len += left;
5986 return;
5987 }
5988 /*
5989 * If the directory entry is a multiple of four, so it is
5990 * valid, let the previous directory entry absorb the invalid
5991 * one.
5992 */
5993 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5994 prev->rec_len += dirent->rec_len;
5995 *offset += dirent->rec_len;
5996 return;
5997 }
5998 /*
5999 * Default salvage method --- kill all of the directory
6000 * entries for the rest of the block. We will either try to
6001 * absorb it into the previous directory entry, or create a
6002 * new empty directory entry the rest of the directory block.
6003 */
6004 if (prev) {
6005 prev->rec_len += fs->blocksize - *offset;
6006 *offset = fs->blocksize;
6007 } else {
6008 dirent->rec_len = fs->blocksize - *offset;
6009 dirent->name_len = 0;
6010 dirent->inode = 0;
6011 }
6012}
6013
6014static int check_dir_block(ext2_filsys fs,
6015 struct ext2_db_entry *db,
6016 void *priv_data)
6017{
6018 struct dir_info *subdir, *dir;
6019 struct dx_dir_info *dx_dir;
6020#ifdef ENABLE_HTREE
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01006021 struct dx_dirblock_info *dx_db = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006022#endif /* ENABLE_HTREE */
6023 struct ext2_dir_entry *dirent, *prev;
6024 ext2_dirhash_t hash;
6025 unsigned int offset = 0;
6026 int dir_modified = 0;
6027 int dot_state;
6028 blk_t block_nr = db->blk;
6029 ext2_ino_t ino = db->ino;
6030 __u16 links;
6031 struct check_dir_struct *cd;
6032 char *buf;
6033 e2fsck_t ctx;
6034 int problem;
6035 struct ext2_dx_root_info *root;
6036 struct ext2_dx_countlimit *limit;
6037 static dict_t de_dict;
6038 struct problem_context pctx;
6039 int dups_found = 0;
6040
6041 cd = (struct check_dir_struct *) priv_data;
6042 buf = cd->buf;
6043 ctx = cd->ctx;
6044
6045 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6046 return DIRENT_ABORT;
6047
6048 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6049 return DIRENT_ABORT;
6050
6051 /*
6052 * Make sure the inode is still in use (could have been
6053 * deleted in the duplicate/bad blocks pass.
6054 */
6055 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6056 return 0;
6057
6058 cd->pctx.ino = ino;
6059 cd->pctx.blk = block_nr;
6060 cd->pctx.blkcount = db->blockcnt;
6061 cd->pctx.ino2 = 0;
6062 cd->pctx.dirent = 0;
6063 cd->pctx.num = 0;
6064
6065 if (db->blk == 0) {
6066 if (allocate_dir_block(ctx, db, &cd->pctx))
6067 return 0;
6068 block_nr = db->blk;
6069 }
6070
6071 if (db->blockcnt)
6072 dot_state = 2;
6073 else
6074 dot_state = 0;
6075
6076 if (ctx->dirs_to_hash &&
6077 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6078 dups_found++;
6079
6080 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6081 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6082 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6083 if (cd->pctx.errcode) {
6084 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6085 ctx->flags |= E2F_FLAG_ABORT;
6086 return DIRENT_ABORT;
6087 }
6088 memset(buf, 0, fs->blocksize);
6089 }
6090#ifdef ENABLE_HTREE
6091 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6092 if (dx_dir && dx_dir->numblocks) {
6093 if (db->blockcnt >= dx_dir->numblocks) {
6094 printf("XXX should never happen!!!\n");
6095 abort();
6096 }
6097 dx_db = &dx_dir->dx_block[db->blockcnt];
6098 dx_db->type = DX_DIRBLOCK_LEAF;
6099 dx_db->phys = block_nr;
6100 dx_db->min_hash = ~0;
6101 dx_db->max_hash = 0;
6102
6103 dirent = (struct ext2_dir_entry *) buf;
6104 limit = (struct ext2_dx_countlimit *) (buf+8);
6105 if (db->blockcnt == 0) {
6106 root = (struct ext2_dx_root_info *) (buf + 24);
6107 dx_db->type = DX_DIRBLOCK_ROOT;
6108 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6109 if ((root->reserved_zero ||
6110 root->info_length < 8 ||
6111 root->indirect_levels > 1) &&
6112 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6113 clear_htree(ctx, ino);
6114 dx_dir->numblocks = 0;
6115 dx_db = 0;
6116 }
6117 dx_dir->hashversion = root->hash_version;
6118 dx_dir->depth = root->indirect_levels + 1;
6119 } else if ((dirent->inode == 0) &&
6120 (dirent->rec_len == fs->blocksize) &&
6121 (dirent->name_len == 0) &&
6122 (ext2fs_le16_to_cpu(limit->limit) ==
6123 ((fs->blocksize-8) /
6124 sizeof(struct ext2_dx_entry))))
6125 dx_db->type = DX_DIRBLOCK_NODE;
6126 }
6127#endif /* ENABLE_HTREE */
6128
6129 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6130 prev = 0;
6131 do {
6132 problem = 0;
6133 dirent = (struct ext2_dir_entry *) (buf + offset);
6134 cd->pctx.dirent = dirent;
6135 cd->pctx.num = offset;
6136 if (((offset + dirent->rec_len) > fs->blocksize) ||
6137 (dirent->rec_len < 12) ||
6138 ((dirent->rec_len % 4) != 0) ||
6139 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6140 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6141 salvage_directory(fs, dirent, prev, &offset);
6142 dir_modified++;
6143 continue;
6144 } else
6145 goto abort_free_dict;
6146 }
6147 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6148 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6149 dirent->name_len = EXT2_NAME_LEN;
6150 dir_modified++;
6151 }
6152 }
6153
6154 if (dot_state == 0) {
6155 if (check_dot(ctx, dirent, ino, &cd->pctx))
6156 dir_modified++;
6157 } else if (dot_state == 1) {
6158 dir = e2fsck_get_dir_info(ctx, ino);
6159 if (!dir) {
6160 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6161 goto abort_free_dict;
6162 }
6163 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6164 dir_modified++;
6165 } else if (dirent->inode == ino) {
6166 problem = PR_2_LINK_DOT;
6167 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6168 dirent->inode = 0;
6169 dir_modified++;
6170 goto next;
6171 }
6172 }
6173 if (!dirent->inode)
6174 goto next;
6175
6176 /*
6177 * Make sure the inode listed is a legal one.
6178 */
6179 if (((dirent->inode != EXT2_ROOT_INO) &&
6180 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6181 (dirent->inode > fs->super->s_inodes_count)) {
6182 problem = PR_2_BAD_INO;
6183 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6184 dirent->inode))) {
6185 /*
6186 * If the inode is unused, offer to clear it.
6187 */
6188 problem = PR_2_UNUSED_INODE;
6189 } else if ((dot_state > 1) &&
6190 ((dirent->name_len & 0xFF) == 1) &&
6191 (dirent->name[0] == '.')) {
6192 /*
6193 * If there's a '.' entry in anything other
6194 * than the first directory entry, it's a
6195 * duplicate entry that should be removed.
6196 */
6197 problem = PR_2_DUP_DOT;
6198 } else if ((dot_state > 1) &&
6199 ((dirent->name_len & 0xFF) == 2) &&
6200 (dirent->name[0] == '.') &&
6201 (dirent->name[1] == '.')) {
6202 /*
6203 * If there's a '..' entry in anything other
6204 * than the second directory entry, it's a
6205 * duplicate entry that should be removed.
6206 */
6207 problem = PR_2_DUP_DOT_DOT;
6208 } else if ((dot_state > 1) &&
6209 (dirent->inode == EXT2_ROOT_INO)) {
6210 /*
6211 * Don't allow links to the root directory.
6212 * We check this specially to make sure we
6213 * catch this error case even if the root
6214 * directory hasn't been created yet.
6215 */
6216 problem = PR_2_LINK_ROOT;
6217 } else if ((dot_state > 1) &&
6218 (dirent->name_len & 0xFF) == 0) {
6219 /*
6220 * Don't allow zero-length directory names.
6221 */
6222 problem = PR_2_NULL_NAME;
6223 }
6224
6225 if (problem) {
6226 if (fix_problem(ctx, problem, &cd->pctx)) {
6227 dirent->inode = 0;
6228 dir_modified++;
6229 goto next;
6230 } else {
6231 ext2fs_unmark_valid(fs);
6232 if (problem == PR_2_BAD_INO)
6233 goto next;
6234 }
6235 }
6236
6237 /*
6238 * If the inode was marked as having bad fields in
6239 * pass1, process it and offer to fix/clear it.
6240 * (We wait until now so that we can display the
6241 * pathname to the user.)
6242 */
6243 if (ctx->inode_bad_map &&
6244 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6245 dirent->inode)) {
6246 if (e2fsck_process_bad_inode(ctx, ino,
6247 dirent->inode,
6248 buf + fs->blocksize)) {
6249 dirent->inode = 0;
6250 dir_modified++;
6251 goto next;
6252 }
6253 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6254 return DIRENT_ABORT;
6255 }
6256
6257 if (check_name(ctx, dirent, &cd->pctx))
6258 dir_modified++;
6259
6260 if (check_filetype(ctx, dirent, &cd->pctx))
6261 dir_modified++;
6262
6263#ifdef ENABLE_HTREE
6264 if (dx_db) {
6265 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6266 (dirent->name_len & 0xFF),
6267 fs->super->s_hash_seed, &hash, 0);
6268 if (hash < dx_db->min_hash)
6269 dx_db->min_hash = hash;
6270 if (hash > dx_db->max_hash)
6271 dx_db->max_hash = hash;
6272 }
6273#endif
6274
6275 /*
6276 * If this is a directory, then mark its parent in its
6277 * dir_info structure. If the parent field is already
6278 * filled in, then this directory has more than one
6279 * hard link. We assume the first link is correct,
6280 * and ask the user if he/she wants to clear this one.
6281 */
6282 if ((dot_state > 1) &&
6283 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6284 dirent->inode))) {
6285 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6286 if (!subdir) {
6287 cd->pctx.ino = dirent->inode;
6288 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6289 goto abort_free_dict;
6290 }
6291 if (subdir->parent) {
6292 cd->pctx.ino2 = subdir->parent;
6293 if (fix_problem(ctx, PR_2_LINK_DIR,
6294 &cd->pctx)) {
6295 dirent->inode = 0;
6296 dir_modified++;
6297 goto next;
6298 }
6299 cd->pctx.ino2 = 0;
6300 } else
6301 subdir->parent = ino;
6302 }
6303
6304 if (dups_found) {
6305 ;
6306 } else if (dict_lookup(&de_dict, dirent)) {
6307 clear_problem_context(&pctx);
6308 pctx.ino = ino;
6309 pctx.dirent = dirent;
6310 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6311 if (!ctx->dirs_to_hash)
6312 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6313 if (ctx->dirs_to_hash)
6314 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6315 dups_found++;
6316 } else
6317 dict_alloc_insert(&de_dict, dirent, dirent);
6318
6319 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6320 &links);
6321 if (links > 1)
6322 ctx->fs_links_count++;
6323 ctx->fs_total_count++;
6324 next:
6325 prev = dirent;
6326 offset += dirent->rec_len;
6327 dot_state++;
6328 } while (offset < fs->blocksize);
6329#ifdef ENABLE_HTREE
6330 if (dx_db) {
6331 cd->pctx.dir = cd->pctx.ino;
6332 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6333 (dx_db->type == DX_DIRBLOCK_NODE))
6334 parse_int_node(fs, db, cd, dx_dir, buf);
6335 }
6336#endif /* ENABLE_HTREE */
6337 if (offset != fs->blocksize) {
6338 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6339 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6340 dirent->rec_len = cd->pctx.num;
6341 dir_modified++;
6342 }
6343 }
6344 if (dir_modified) {
6345 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6346 if (cd->pctx.errcode) {
6347 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6348 &cd->pctx))
6349 goto abort_free_dict;
6350 }
6351 ext2fs_mark_changed(fs);
6352 }
6353 dict_free_nodes(&de_dict);
6354 return 0;
6355abort_free_dict:
6356 dict_free_nodes(&de_dict);
6357 ctx->flags |= E2F_FLAG_ABORT;
6358 return DIRENT_ABORT;
6359}
6360
6361/*
6362 * This function is called to deallocate a block, and is an interator
6363 * functioned called by deallocate inode via ext2fs_iterate_block().
6364 */
6365static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6366 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6367 blk_t ref_block FSCK_ATTR((unused)),
6368 int ref_offset FSCK_ATTR((unused)),
6369 void *priv_data)
6370{
6371 e2fsck_t ctx = (e2fsck_t) priv_data;
6372
6373 if (HOLE_BLKADDR(*block_nr))
6374 return 0;
6375 if ((*block_nr < fs->super->s_first_data_block) ||
6376 (*block_nr >= fs->super->s_blocks_count))
6377 return 0;
6378 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6379 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6380 return 0;
6381}
6382
6383/*
6384 * This fuction deallocates an inode
6385 */
6386static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6387{
6388 ext2_filsys fs = ctx->fs;
6389 struct ext2_inode inode;
6390 struct problem_context pctx;
6391 __u32 count;
6392
6393 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6394 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6395 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006396 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006397 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6398 clear_problem_context(&pctx);
6399 pctx.ino = ino;
6400
6401 /*
6402 * Fix up the bitmaps...
6403 */
6404 e2fsck_read_bitmaps(ctx);
6405 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6406 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6407 if (ctx->inode_bad_map)
6408 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6409 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6410
6411 if (inode.i_file_acl &&
6412 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6413 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6414 block_buf, -1, &count);
6415 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6416 pctx.errcode = 0;
6417 count = 1;
6418 }
6419 if (pctx.errcode) {
6420 pctx.blk = inode.i_file_acl;
6421 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6422 ctx->flags |= E2F_FLAG_ABORT;
6423 return;
6424 }
6425 if (count == 0) {
6426 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6427 inode.i_file_acl);
6428 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6429 }
6430 inode.i_file_acl = 0;
6431 }
6432
6433 if (!ext2fs_inode_has_valid_blocks(&inode))
6434 return;
6435
6436 if (LINUX_S_ISREG(inode.i_mode) &&
6437 (inode.i_size_high || inode.i_size & 0x80000000UL))
6438 ctx->large_files--;
6439
6440 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6441 deallocate_inode_block, ctx);
6442 if (pctx.errcode) {
6443 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6444 ctx->flags |= E2F_FLAG_ABORT;
6445 return;
6446 }
6447}
6448
6449/*
6450 * This fuction clears the htree flag on an inode
6451 */
6452static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6453{
6454 struct ext2_inode inode;
6455
6456 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6457 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6458 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6459 if (ctx->dirs_to_hash)
6460 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6461}
6462
6463
6464static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6465 ext2_ino_t ino, char *buf)
6466{
6467 ext2_filsys fs = ctx->fs;
6468 struct ext2_inode inode;
6469 int inode_modified = 0;
6470 int not_fixed = 0;
6471 unsigned char *frag, *fsize;
6472 struct problem_context pctx;
6473 int problem = 0;
6474
6475 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6476
6477 clear_problem_context(&pctx);
6478 pctx.ino = ino;
6479 pctx.dir = dir;
6480 pctx.inode = &inode;
6481
6482 if (inode.i_file_acl &&
6483 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6484 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6485 inode.i_file_acl = 0;
6486#if BB_BIG_ENDIAN
6487 /*
6488 * This is a special kludge to deal with long symlinks
6489 * on big endian systems. i_blocks had already been
6490 * decremented earlier in pass 1, but since i_file_acl
6491 * hadn't yet been cleared, ext2fs_read_inode()
6492 * assumed that the file was short symlink and would
6493 * not have byte swapped i_block[0]. Hence, we have
6494 * to byte-swap it here.
6495 */
6496 if (LINUX_S_ISLNK(inode.i_mode) &&
6497 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6498 (inode.i_blocks == fs->blocksize >> 9))
6499 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6500#endif
6501 inode_modified++;
6502 } else
6503 not_fixed++;
6504
6505 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6506 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6507 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6508 !(LINUX_S_ISSOCK(inode.i_mode)))
6509 problem = PR_2_BAD_MODE;
6510 else if (LINUX_S_ISCHR(inode.i_mode)
6511 && !e2fsck_pass1_check_device_inode(fs, &inode))
6512 problem = PR_2_BAD_CHAR_DEV;
6513 else if (LINUX_S_ISBLK(inode.i_mode)
6514 && !e2fsck_pass1_check_device_inode(fs, &inode))
6515 problem = PR_2_BAD_BLOCK_DEV;
6516 else if (LINUX_S_ISFIFO(inode.i_mode)
6517 && !e2fsck_pass1_check_device_inode(fs, &inode))
6518 problem = PR_2_BAD_FIFO;
6519 else if (LINUX_S_ISSOCK(inode.i_mode)
6520 && !e2fsck_pass1_check_device_inode(fs, &inode))
6521 problem = PR_2_BAD_SOCKET;
6522 else if (LINUX_S_ISLNK(inode.i_mode)
6523 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6524 problem = PR_2_INVALID_SYMLINK;
6525 }
6526
6527 if (problem) {
6528 if (fix_problem(ctx, problem, &pctx)) {
6529 deallocate_inode(ctx, ino, 0);
6530 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6531 return 0;
6532 return 1;
6533 } else
6534 not_fixed++;
6535 problem = 0;
6536 }
6537
6538 if (inode.i_faddr) {
6539 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6540 inode.i_faddr = 0;
6541 inode_modified++;
6542 } else
6543 not_fixed++;
6544 }
6545
6546 switch (fs->super->s_creator_os) {
6547 case EXT2_OS_LINUX:
6548 frag = &inode.osd2.linux2.l_i_frag;
6549 fsize = &inode.osd2.linux2.l_i_fsize;
6550 break;
6551 case EXT2_OS_HURD:
6552 frag = &inode.osd2.hurd2.h_i_frag;
6553 fsize = &inode.osd2.hurd2.h_i_fsize;
6554 break;
6555 case EXT2_OS_MASIX:
6556 frag = &inode.osd2.masix2.m_i_frag;
6557 fsize = &inode.osd2.masix2.m_i_fsize;
6558 break;
6559 default:
6560 frag = fsize = 0;
6561 }
6562 if (frag && *frag) {
6563 pctx.num = *frag;
6564 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6565 *frag = 0;
6566 inode_modified++;
6567 } else
6568 not_fixed++;
6569 pctx.num = 0;
6570 }
6571 if (fsize && *fsize) {
6572 pctx.num = *fsize;
6573 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6574 *fsize = 0;
6575 inode_modified++;
6576 } else
6577 not_fixed++;
6578 pctx.num = 0;
6579 }
6580
6581 if (inode.i_file_acl &&
6582 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6583 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6584 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6585 inode.i_file_acl = 0;
6586 inode_modified++;
6587 } else
6588 not_fixed++;
6589 }
6590 if (inode.i_dir_acl &&
6591 LINUX_S_ISDIR(inode.i_mode)) {
6592 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6593 inode.i_dir_acl = 0;
6594 inode_modified++;
6595 } else
6596 not_fixed++;
6597 }
6598
6599 if (inode_modified)
6600 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6601 if (!not_fixed)
6602 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6603 return 0;
6604}
6605
6606
6607/*
6608 * allocate_dir_block --- this function allocates a new directory
6609 * block for a particular inode; this is done if a directory has
6610 * a "hole" in it, or if a directory has a illegal block number
6611 * that was zeroed out and now needs to be replaced.
6612 */
6613static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6614 struct problem_context *pctx)
6615{
6616 ext2_filsys fs = ctx->fs;
6617 blk_t blk;
6618 char *block;
6619 struct ext2_inode inode;
6620
6621 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6622 return 1;
6623
6624 /*
6625 * Read the inode and block bitmaps in; we'll be messing with
6626 * them.
6627 */
6628 e2fsck_read_bitmaps(ctx);
6629
6630 /*
6631 * First, find a free block
6632 */
6633 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6634 if (pctx->errcode) {
6635 pctx->str = "ext2fs_new_block";
6636 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6637 return 1;
6638 }
6639 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6640 ext2fs_mark_block_bitmap(fs->block_map, blk);
6641 ext2fs_mark_bb_dirty(fs);
6642
6643 /*
6644 * Now let's create the actual data block for the inode
6645 */
6646 if (db->blockcnt)
6647 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6648 else
6649 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6650 EXT2_ROOT_INO, &block);
6651
6652 if (pctx->errcode) {
6653 pctx->str = "ext2fs_new_dir_block";
6654 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6655 return 1;
6656 }
6657
6658 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6659 ext2fs_free_mem(&block);
6660 if (pctx->errcode) {
6661 pctx->str = "ext2fs_write_dir_block";
6662 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6663 return 1;
6664 }
6665
6666 /*
6667 * Update the inode block count
6668 */
6669 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6670 inode.i_blocks += fs->blocksize / 512;
6671 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6672 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6673 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6674
6675 /*
6676 * Finally, update the block pointers for the inode
6677 */
6678 db->blk = blk;
6679 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6680 0, update_dir_block, db);
6681 if (pctx->errcode) {
6682 pctx->str = "ext2fs_block_iterate";
6683 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6684 return 1;
6685 }
6686
6687 return 0;
6688}
6689
6690/*
6691 * This is a helper function for allocate_dir_block().
6692 */
6693static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6694 blk_t *block_nr,
6695 e2_blkcnt_t blockcnt,
6696 blk_t ref_block FSCK_ATTR((unused)),
6697 int ref_offset FSCK_ATTR((unused)),
6698 void *priv_data)
6699{
6700 struct ext2_db_entry *db;
6701
6702 db = (struct ext2_db_entry *) priv_data;
6703 if (db->blockcnt == (int) blockcnt) {
6704 *block_nr = db->blk;
6705 return BLOCK_CHANGED;
6706 }
6707 return 0;
6708}
6709
6710/*
6711 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6712 *
6713 * Pass #3 assures that all directories are connected to the
6714 * filesystem tree, using the following algorithm:
6715 *
6716 * First, the root directory is checked to make sure it exists; if
6717 * not, e2fsck will offer to create a new one. It is then marked as
6718 * "done".
6719 *
6720 * Then, pass3 interates over all directory inodes; for each directory
6721 * it attempts to trace up the filesystem tree, using dirinfo.parent
6722 * until it reaches a directory which has been marked "done". If it
6723 * cannot do so, then the directory must be disconnected, and e2fsck
6724 * will offer to reconnect it to /lost+found. While it is chasing
6725 * parent pointers up the filesystem tree, if pass3 sees a directory
6726 * twice, then it has detected a filesystem loop, and it will again
6727 * offer to reconnect the directory to /lost+found in to break the
6728 * filesystem loop.
6729 *
6730 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6731 * reconnect inodes to /lost+found; this subroutine is also used by
6732 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6733 * is responsible for creating /lost+found if it does not exist.
6734 *
6735 * Pass 3 frees the following data structures:
6736 * - The dirinfo directory information cache.
6737 */
6738
6739static void check_root(e2fsck_t ctx);
6740static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6741 struct problem_context *pctx);
6742static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6743
6744static ext2fs_inode_bitmap inode_loop_detect;
6745static ext2fs_inode_bitmap inode_done_map;
6746
6747static void e2fsck_pass3(e2fsck_t ctx)
6748{
6749 ext2_filsys fs = ctx->fs;
6750 int i;
6751 struct problem_context pctx;
6752 struct dir_info *dir;
6753 unsigned long maxdirs, count;
6754
6755 clear_problem_context(&pctx);
6756
6757 /* Pass 3 */
6758
6759 if (!(ctx->options & E2F_OPT_PREEN))
6760 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6761
6762 /*
6763 * Allocate some bitmaps to do loop detection.
6764 */
6765 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6766 &inode_done_map);
6767 if (pctx.errcode) {
6768 pctx.num = 2;
6769 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6770 ctx->flags |= E2F_FLAG_ABORT;
6771 goto abort_exit;
6772 }
6773 check_root(ctx);
6774 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6775 goto abort_exit;
6776
6777 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6778
6779 maxdirs = e2fsck_get_num_dirinfo(ctx);
6780 count = 1;
6781
6782 if (ctx->progress)
6783 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6784 goto abort_exit;
6785
6786 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6787 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6788 goto abort_exit;
6789 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6790 goto abort_exit;
6791 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6792 if (check_directory(ctx, dir, &pctx))
6793 goto abort_exit;
6794 }
6795
6796 /*
6797 * Force the creation of /lost+found if not present
6798 */
6799 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6800 e2fsck_get_lost_and_found(ctx, 1);
6801
6802 /*
6803 * If there are any directories that need to be indexed or
6804 * optimized, do it here.
6805 */
6806 e2fsck_rehash_directories(ctx);
6807
6808abort_exit:
6809 e2fsck_free_dir_info(ctx);
6810 ext2fs_free_inode_bitmap(inode_loop_detect);
6811 inode_loop_detect = 0;
6812 ext2fs_free_inode_bitmap(inode_done_map);
6813 inode_done_map = 0;
6814}
6815
6816/*
6817 * This makes sure the root inode is present; if not, we ask if the
6818 * user wants us to create it. Not creating it is a fatal error.
6819 */
6820static void check_root(e2fsck_t ctx)
6821{
6822 ext2_filsys fs = ctx->fs;
6823 blk_t blk;
6824 struct ext2_inode inode;
6825 char * block;
6826 struct problem_context pctx;
6827
6828 clear_problem_context(&pctx);
6829
6830 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6831 /*
6832 * If the root inode is not a directory, die here. The
6833 * user must have answered 'no' in pass1 when we
6834 * offered to clear it.
6835 */
6836 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6837 EXT2_ROOT_INO))) {
6838 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6839 ctx->flags |= E2F_FLAG_ABORT;
6840 }
6841 return;
6842 }
6843
6844 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6845 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6846 ctx->flags |= E2F_FLAG_ABORT;
6847 return;
6848 }
6849
6850 e2fsck_read_bitmaps(ctx);
6851
6852 /*
6853 * First, find a free block
6854 */
6855 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6856 if (pctx.errcode) {
6857 pctx.str = "ext2fs_new_block";
6858 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6859 ctx->flags |= E2F_FLAG_ABORT;
6860 return;
6861 }
6862 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6863 ext2fs_mark_block_bitmap(fs->block_map, blk);
6864 ext2fs_mark_bb_dirty(fs);
6865
6866 /*
6867 * Now let's create the actual data block for the inode
6868 */
6869 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6870 &block);
6871 if (pctx.errcode) {
6872 pctx.str = "ext2fs_new_dir_block";
6873 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6874 ctx->flags |= E2F_FLAG_ABORT;
6875 return;
6876 }
6877
6878 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6879 if (pctx.errcode) {
6880 pctx.str = "ext2fs_write_dir_block";
6881 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6882 ctx->flags |= E2F_FLAG_ABORT;
6883 return;
6884 }
6885 ext2fs_free_mem(&block);
6886
6887 /*
6888 * Set up the inode structure
6889 */
6890 memset(&inode, 0, sizeof(inode));
6891 inode.i_mode = 040755;
6892 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006893 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006894 inode.i_links_count = 2;
6895 inode.i_blocks = fs->blocksize / 512;
6896 inode.i_block[0] = blk;
6897
6898 /*
6899 * Write out the inode.
6900 */
6901 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6902 if (pctx.errcode) {
6903 pctx.str = "ext2fs_write_inode";
6904 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6905 ctx->flags |= E2F_FLAG_ABORT;
6906 return;
6907 }
6908
6909 /*
6910 * Miscellaneous bookkeeping...
6911 */
6912 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6913 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6914 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6915
6916 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6917 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6918 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6919 ext2fs_mark_ib_dirty(fs);
6920}
6921
6922/*
6923 * This subroutine is responsible for making sure that a particular
6924 * directory is connected to the root; if it isn't we trace it up as
6925 * far as we can go, and then offer to connect the resulting parent to
6926 * the lost+found. We have to do loop detection; if we ever discover
6927 * a loop, we treat that as a disconnected directory and offer to
6928 * reparent it to lost+found.
6929 *
6930 * However, loop detection is expensive, because for very large
6931 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6932 * is non-trivial. Loops in filesystems are also a rare error case,
6933 * and we shouldn't optimize for error cases. So we try two passes of
6934 * the algorithm. The first time, we ignore loop detection and merely
6935 * increment a counter; if the counter exceeds some extreme threshold,
6936 * then we try again with the loop detection bitmap enabled.
6937 */
6938static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6939 struct problem_context *pctx)
6940{
6941 ext2_filsys fs = ctx->fs;
6942 struct dir_info *p = dir;
6943 int loop_pass = 0, parent_count = 0;
6944
6945 if (!p)
6946 return 0;
6947
6948 while (1) {
6949 /*
6950 * Mark this inode as being "done"; by the time we
6951 * return from this function, the inode we either be
6952 * verified as being connected to the directory tree,
6953 * or we will have offered to reconnect this to
6954 * lost+found.
6955 *
6956 * If it was marked done already, then we've reached a
6957 * parent we've already checked.
6958 */
6959 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6960 break;
6961
6962 /*
6963 * If this directory doesn't have a parent, or we've
6964 * seen the parent once already, then offer to
6965 * reparent it to lost+found
6966 */
6967 if (!p->parent ||
6968 (loop_pass &&
6969 (ext2fs_test_inode_bitmap(inode_loop_detect,
6970 p->parent)))) {
6971 pctx->ino = p->ino;
6972 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6973 if (e2fsck_reconnect_file(ctx, pctx->ino))
6974 ext2fs_unmark_valid(fs);
6975 else {
6976 p = e2fsck_get_dir_info(ctx, pctx->ino);
6977 p->parent = ctx->lost_and_found;
6978 fix_dotdot(ctx, p, ctx->lost_and_found);
6979 }
6980 }
6981 break;
6982 }
6983 p = e2fsck_get_dir_info(ctx, p->parent);
6984 if (!p) {
6985 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6986 return 0;
6987 }
6988 if (loop_pass) {
6989 ext2fs_mark_inode_bitmap(inode_loop_detect,
6990 p->ino);
6991 } else if (parent_count++ > 2048) {
6992 /*
6993 * If we've run into a path depth that's
6994 * greater than 2048, try again with the inode
6995 * loop bitmap turned on and start from the
6996 * top.
6997 */
6998 loop_pass = 1;
6999 if (inode_loop_detect)
7000 ext2fs_clear_inode_bitmap(inode_loop_detect);
7001 else {
7002 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7003 if (pctx->errcode) {
7004 pctx->num = 1;
7005 fix_problem(ctx,
7006 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7007 ctx->flags |= E2F_FLAG_ABORT;
7008 return -1;
7009 }
7010 }
7011 p = dir;
7012 }
7013 }
7014
7015 /*
7016 * Make sure that .. and the parent directory are the same;
7017 * offer to fix it if not.
7018 */
7019 if (dir->parent != dir->dotdot) {
7020 pctx->ino = dir->ino;
7021 pctx->ino2 = dir->dotdot;
7022 pctx->dir = dir->parent;
7023 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7024 fix_dotdot(ctx, dir, dir->parent);
7025 }
7026 return 0;
7027}
7028
7029/*
7030 * This routine gets the lost_and_found inode, making it a directory
7031 * if necessary
7032 */
7033ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7034{
7035 ext2_filsys fs = ctx->fs;
7036 ext2_ino_t ino;
7037 blk_t blk;
7038 errcode_t retval;
7039 struct ext2_inode inode;
7040 char * block;
7041 static const char name[] = "lost+found";
7042 struct problem_context pctx;
7043 struct dir_info *dirinfo;
7044
7045 if (ctx->lost_and_found)
7046 return ctx->lost_and_found;
7047
7048 clear_problem_context(&pctx);
7049
7050 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7051 sizeof(name)-1, 0, &ino);
7052 if (retval && !fix)
7053 return 0;
7054 if (!retval) {
7055 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7056 ctx->lost_and_found = ino;
7057 return ino;
7058 }
7059
7060 /* Lost+found isn't a directory! */
7061 if (!fix)
7062 return 0;
7063 pctx.ino = ino;
7064 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7065 return 0;
7066
7067 /* OK, unlink the old /lost+found file. */
7068 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7069 if (pctx.errcode) {
7070 pctx.str = "ext2fs_unlink";
7071 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7072 return 0;
7073 }
7074 dirinfo = e2fsck_get_dir_info(ctx, ino);
7075 if (dirinfo)
7076 dirinfo->parent = 0;
7077 e2fsck_adjust_inode_count(ctx, ino, -1);
7078 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7079 pctx.errcode = retval;
7080 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7081 }
7082 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7083 return 0;
7084
7085 /*
7086 * Read the inode and block bitmaps in; we'll be messing with
7087 * them.
7088 */
7089 e2fsck_read_bitmaps(ctx);
7090
7091 /*
7092 * First, find a free block
7093 */
7094 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7095 if (retval) {
7096 pctx.errcode = retval;
7097 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7098 return 0;
7099 }
7100 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7101 ext2fs_block_alloc_stats(fs, blk, +1);
7102
7103 /*
7104 * Next find a free inode.
7105 */
7106 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7107 ctx->inode_used_map, &ino);
7108 if (retval) {
7109 pctx.errcode = retval;
7110 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7111 return 0;
7112 }
7113 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7114 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7115 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7116
7117 /*
7118 * Now let's create the actual data block for the inode
7119 */
7120 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7121 if (retval) {
7122 pctx.errcode = retval;
7123 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7124 return 0;
7125 }
7126
7127 retval = ext2fs_write_dir_block(fs, blk, block);
7128 ext2fs_free_mem(&block);
7129 if (retval) {
7130 pctx.errcode = retval;
7131 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7132 return 0;
7133 }
7134
7135 /*
7136 * Set up the inode structure
7137 */
7138 memset(&inode, 0, sizeof(inode));
7139 inode.i_mode = 040700;
7140 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007141 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007142 inode.i_links_count = 2;
7143 inode.i_blocks = fs->blocksize / 512;
7144 inode.i_block[0] = blk;
7145
7146 /*
7147 * Next, write out the inode.
7148 */
7149 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7150 if (pctx.errcode) {
7151 pctx.str = "ext2fs_write_inode";
7152 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153 return 0;
7154 }
7155 /*
7156 * Finally, create the directory link
7157 */
7158 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7159 if (pctx.errcode) {
7160 pctx.str = "ext2fs_link";
7161 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7162 return 0;
7163 }
7164
7165 /*
7166 * Miscellaneous bookkeeping that needs to be kept straight.
7167 */
7168 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7169 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7170 ext2fs_icount_store(ctx->inode_count, ino, 2);
7171 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7172 ctx->lost_and_found = ino;
7173 return ino;
7174}
7175
7176/*
7177 * This routine will connect a file to lost+found
7178 */
7179int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7180{
7181 ext2_filsys fs = ctx->fs;
7182 errcode_t retval;
7183 char name[80];
7184 struct problem_context pctx;
7185 struct ext2_inode inode;
7186 int file_type = 0;
7187
7188 clear_problem_context(&pctx);
7189 pctx.ino = ino;
7190
7191 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7192 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7193 ctx->bad_lost_and_found++;
7194 }
7195 if (ctx->bad_lost_and_found) {
7196 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7197 return 1;
7198 }
7199
7200 sprintf(name, "#%u", ino);
7201 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7202 file_type = ext2_file_type(inode.i_mode);
7203 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7204 if (retval == EXT2_ET_DIR_NO_SPACE) {
7205 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7206 return 1;
7207 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7208 1, 0);
7209 if (retval) {
7210 pctx.errcode = retval;
7211 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7212 return 1;
7213 }
7214 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7215 ino, file_type);
7216 }
7217 if (retval) {
7218 pctx.errcode = retval;
7219 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7220 return 1;
7221 }
7222 e2fsck_adjust_inode_count(ctx, ino, 1);
7223
7224 return 0;
7225}
7226
7227/*
7228 * Utility routine to adjust the inode counts on an inode.
7229 */
7230errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7231{
7232 ext2_filsys fs = ctx->fs;
7233 errcode_t retval;
7234 struct ext2_inode inode;
7235
7236 if (!ino)
7237 return 0;
7238
7239 retval = ext2fs_read_inode(fs, ino, &inode);
7240 if (retval)
7241 return retval;
7242
7243 if (adj == 1) {
7244 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7245 if (inode.i_links_count == (__u16) ~0)
7246 return 0;
7247 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7248 inode.i_links_count++;
7249 } else if (adj == -1) {
7250 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7251 if (inode.i_links_count == 0)
7252 return 0;
7253 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7254 inode.i_links_count--;
7255 }
7256
7257 retval = ext2fs_write_inode(fs, ino, &inode);
7258 if (retval)
7259 return retval;
7260
7261 return 0;
7262}
7263
7264/*
7265 * Fix parent --- this routine fixes up the parent of a directory.
7266 */
7267struct fix_dotdot_struct {
7268 ext2_filsys fs;
7269 ext2_ino_t parent;
7270 int done;
7271 e2fsck_t ctx;
7272};
7273
7274static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7275 int offset FSCK_ATTR((unused)),
7276 int blocksize FSCK_ATTR((unused)),
7277 char *buf FSCK_ATTR((unused)),
7278 void *priv_data)
7279{
7280 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7281 errcode_t retval;
7282 struct problem_context pctx;
7283
7284 if ((dirent->name_len & 0xFF) != 2)
7285 return 0;
7286 if (strncmp(dirent->name, "..", 2))
7287 return 0;
7288
7289 clear_problem_context(&pctx);
7290
7291 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7292 if (retval) {
7293 pctx.errcode = retval;
7294 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7295 }
7296 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7297 if (retval) {
7298 pctx.errcode = retval;
7299 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7300 }
7301 dirent->inode = fp->parent;
7302
7303 fp->done++;
7304 return DIRENT_ABORT | DIRENT_CHANGED;
7305}
7306
7307static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7308{
7309 ext2_filsys fs = ctx->fs;
7310 errcode_t retval;
7311 struct fix_dotdot_struct fp;
7312 struct problem_context pctx;
7313
7314 fp.fs = fs;
7315 fp.parent = parent;
7316 fp.done = 0;
7317 fp.ctx = ctx;
7318
7319 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7320 0, fix_dotdot_proc, &fp);
7321 if (retval || !fp.done) {
7322 clear_problem_context(&pctx);
7323 pctx.ino = dir->ino;
7324 pctx.errcode = retval;
7325 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7326 PR_3_FIX_PARENT_NOFIND, &pctx);
7327 ext2fs_unmark_valid(fs);
7328 }
7329 dir->dotdot = parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007330}
7331
7332/*
7333 * These routines are responsible for expanding a /lost+found if it is
7334 * too small.
7335 */
7336
7337struct expand_dir_struct {
7338 int num;
7339 int guaranteed_size;
7340 int newblocks;
7341 int last_block;
7342 errcode_t err;
7343 e2fsck_t ctx;
7344};
7345
7346static int expand_dir_proc(ext2_filsys fs,
7347 blk_t *blocknr,
7348 e2_blkcnt_t blockcnt,
7349 blk_t ref_block FSCK_ATTR((unused)),
7350 int ref_offset FSCK_ATTR((unused)),
7351 void *priv_data)
7352{
7353 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7354 blk_t new_blk;
7355 static blk_t last_blk = 0;
7356 char *block;
7357 errcode_t retval;
7358 e2fsck_t ctx;
7359
7360 ctx = es->ctx;
7361
7362 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7363 return BLOCK_ABORT;
7364
7365 if (blockcnt > 0)
7366 es->last_block = blockcnt;
7367 if (*blocknr) {
7368 last_blk = *blocknr;
7369 return 0;
7370 }
7371 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7372 &new_blk);
7373 if (retval) {
7374 es->err = retval;
7375 return BLOCK_ABORT;
7376 }
7377 if (blockcnt > 0) {
7378 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7379 if (retval) {
7380 es->err = retval;
7381 return BLOCK_ABORT;
7382 }
7383 es->num--;
7384 retval = ext2fs_write_dir_block(fs, new_blk, block);
7385 } else {
7386 retval = ext2fs_get_mem(fs->blocksize, &block);
7387 if (retval) {
7388 es->err = retval;
7389 return BLOCK_ABORT;
7390 }
7391 memset(block, 0, fs->blocksize);
7392 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7393 }
7394 if (retval) {
7395 es->err = retval;
7396 return BLOCK_ABORT;
7397 }
7398 ext2fs_free_mem(&block);
7399 *blocknr = new_blk;
7400 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7401 ext2fs_block_alloc_stats(fs, new_blk, +1);
7402 es->newblocks++;
7403
7404 if (es->num == 0)
7405 return (BLOCK_CHANGED | BLOCK_ABORT);
7406 else
7407 return BLOCK_CHANGED;
7408}
7409
7410errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7411 int num, int guaranteed_size)
7412{
7413 ext2_filsys fs = ctx->fs;
7414 errcode_t retval;
7415 struct expand_dir_struct es;
7416 struct ext2_inode inode;
7417
7418 if (!(fs->flags & EXT2_FLAG_RW))
7419 return EXT2_ET_RO_FILSYS;
7420
7421 /*
7422 * Read the inode and block bitmaps in; we'll be messing with
7423 * them.
7424 */
7425 e2fsck_read_bitmaps(ctx);
7426
7427 retval = ext2fs_check_directory(fs, dir);
7428 if (retval)
7429 return retval;
7430
7431 es.num = num;
7432 es.guaranteed_size = guaranteed_size;
7433 es.last_block = 0;
7434 es.err = 0;
7435 es.newblocks = 0;
7436 es.ctx = ctx;
7437
7438 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7439 0, expand_dir_proc, &es);
7440
7441 if (es.err)
7442 return es.err;
7443
7444 /*
7445 * Update the size and block count fields in the inode.
7446 */
7447 retval = ext2fs_read_inode(fs, dir, &inode);
7448 if (retval)
7449 return retval;
7450
7451 inode.i_size = (es.last_block + 1) * fs->blocksize;
7452 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7453
7454 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7455
7456 return 0;
7457}
7458
7459/*
7460 * pass4.c -- pass #4 of e2fsck: Check reference counts
7461 *
7462 * Pass 4 frees the following data structures:
7463 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7464 */
7465
7466/*
7467 * This routine is called when an inode is not connected to the
7468 * directory tree.
7469 *
7470 * This subroutine returns 1 then the caller shouldn't bother with the
7471 * rest of the pass 4 tests.
7472 */
7473static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7474{
7475 ext2_filsys fs = ctx->fs;
7476 struct ext2_inode inode;
7477 struct problem_context pctx;
7478
7479 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7480 clear_problem_context(&pctx);
7481 pctx.ino = i;
7482 pctx.inode = &inode;
7483
7484 /*
7485 * Offer to delete any zero-length files that does not have
7486 * blocks. If there is an EA block, it might have useful
7487 * information, so we won't prompt to delete it, but let it be
7488 * reconnected to lost+found.
7489 */
7490 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7491 LINUX_S_ISDIR(inode.i_mode))) {
7492 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7493 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7494 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007495 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007496 e2fsck_write_inode(ctx, i, &inode,
7497 "disconnect_inode");
7498 /*
7499 * Fix up the bitmaps...
7500 */
7501 e2fsck_read_bitmaps(ctx);
7502 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7503 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7504 ext2fs_inode_alloc_stats2(fs, i, -1,
7505 LINUX_S_ISDIR(inode.i_mode));
7506 return 0;
7507 }
7508 }
7509
7510 /*
7511 * Prompt to reconnect.
7512 */
7513 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7514 if (e2fsck_reconnect_file(ctx, i))
7515 ext2fs_unmark_valid(fs);
7516 } else {
7517 /*
7518 * If we don't attach the inode, then skip the
7519 * i_links_test since there's no point in trying to
7520 * force i_links_count to zero.
7521 */
7522 ext2fs_unmark_valid(fs);
7523 return 1;
7524 }
7525 return 0;
7526}
7527
7528
7529static void e2fsck_pass4(e2fsck_t ctx)
7530{
7531 ext2_filsys fs = ctx->fs;
7532 ext2_ino_t i;
7533 struct ext2_inode inode;
7534 struct problem_context pctx;
7535 __u16 link_count, link_counted;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01007536 char *buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007537 int group, maxgroup;
7538
7539 /* Pass 4 */
7540
7541 clear_problem_context(&pctx);
7542
7543 if (!(ctx->options & E2F_OPT_PREEN))
7544 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7545
7546 group = 0;
7547 maxgroup = fs->group_desc_count;
7548 if (ctx->progress)
7549 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7550 return;
7551
7552 for (i=1; i <= fs->super->s_inodes_count; i++) {
7553 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7554 return;
7555 if ((i % fs->super->s_inodes_per_group) == 0) {
7556 group++;
7557 if (ctx->progress)
7558 if ((ctx->progress)(ctx, 4, group, maxgroup))
7559 return;
7560 }
7561 if (i == EXT2_BAD_INO ||
7562 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7563 continue;
7564 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7565 (ctx->inode_imagic_map &&
7566 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7567 continue;
7568 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7569 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7570 if (link_counted == 0) {
7571 if (!buf)
7572 buf = e2fsck_allocate_memory(ctx,
7573 fs->blocksize, "bad_inode buffer");
7574 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7575 continue;
7576 if (disconnect_inode(ctx, i))
7577 continue;
7578 ext2fs_icount_fetch(ctx->inode_link_info, i,
7579 &link_count);
7580 ext2fs_icount_fetch(ctx->inode_count, i,
7581 &link_counted);
7582 }
7583 if (link_counted != link_count) {
7584 e2fsck_read_inode(ctx, i, &inode, "pass4");
7585 pctx.ino = i;
7586 pctx.inode = &inode;
7587 if (link_count != inode.i_links_count) {
7588 pctx.num = link_count;
7589 fix_problem(ctx,
7590 PR_4_INCONSISTENT_COUNT, &pctx);
7591 }
7592 pctx.num = link_counted;
7593 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7594 inode.i_links_count = link_counted;
7595 e2fsck_write_inode(ctx, i, &inode, "pass4");
7596 }
7597 }
7598 }
7599 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7600 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7601 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7602 ctx->inode_imagic_map = 0;
7603 ext2fs_free_mem(&buf);
7604}
7605
7606/*
7607 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7608 */
7609
7610#define NO_BLK ((blk_t) -1)
7611
7612static void print_bitmap_problem(e2fsck_t ctx, int problem,
7613 struct problem_context *pctx)
7614{
7615 switch (problem) {
7616 case PR_5_BLOCK_UNUSED:
7617 if (pctx->blk == pctx->blk2)
7618 pctx->blk2 = 0;
7619 else
7620 problem = PR_5_BLOCK_RANGE_UNUSED;
7621 break;
7622 case PR_5_BLOCK_USED:
7623 if (pctx->blk == pctx->blk2)
7624 pctx->blk2 = 0;
7625 else
7626 problem = PR_5_BLOCK_RANGE_USED;
7627 break;
7628 case PR_5_INODE_UNUSED:
7629 if (pctx->ino == pctx->ino2)
7630 pctx->ino2 = 0;
7631 else
7632 problem = PR_5_INODE_RANGE_UNUSED;
7633 break;
7634 case PR_5_INODE_USED:
7635 if (pctx->ino == pctx->ino2)
7636 pctx->ino2 = 0;
7637 else
7638 problem = PR_5_INODE_RANGE_USED;
7639 break;
7640 }
7641 fix_problem(ctx, problem, pctx);
7642 pctx->blk = pctx->blk2 = NO_BLK;
7643 pctx->ino = pctx->ino2 = 0;
7644}
7645
7646static void check_block_bitmaps(e2fsck_t ctx)
7647{
7648 ext2_filsys fs = ctx->fs;
7649 blk_t i;
7650 int *free_array;
7651 int group = 0;
7652 unsigned int blocks = 0;
7653 unsigned int free_blocks = 0;
7654 int group_free = 0;
7655 int actual, bitmap;
7656 struct problem_context pctx;
7657 int problem, save_problem, fixit, had_problem;
7658 errcode_t retval;
7659
7660 clear_problem_context(&pctx);
7661 free_array = (int *) e2fsck_allocate_memory(ctx,
7662 fs->group_desc_count * sizeof(int), "free block count array");
7663
7664 if ((fs->super->s_first_data_block <
7665 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7666 (fs->super->s_blocks_count-1 >
7667 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7668 pctx.num = 1;
7669 pctx.blk = fs->super->s_first_data_block;
7670 pctx.blk2 = fs->super->s_blocks_count -1;
7671 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7672 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7673 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7674
7675 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7676 return;
7677 }
7678
7679 if ((fs->super->s_first_data_block <
7680 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7681 (fs->super->s_blocks_count-1 >
7682 ext2fs_get_block_bitmap_end(fs->block_map))) {
7683 pctx.num = 2;
7684 pctx.blk = fs->super->s_first_data_block;
7685 pctx.blk2 = fs->super->s_blocks_count -1;
7686 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7687 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7688 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7689
7690 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7691 return;
7692 }
7693
7694redo_counts:
7695 had_problem = 0;
7696 save_problem = 0;
7697 pctx.blk = pctx.blk2 = NO_BLK;
7698 for (i = fs->super->s_first_data_block;
7699 i < fs->super->s_blocks_count;
7700 i++) {
7701 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7702 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7703
7704 if (actual == bitmap)
7705 goto do_counts;
7706
7707 if (!actual && bitmap) {
7708 /*
7709 * Block not used, but marked in use in the bitmap.
7710 */
7711 problem = PR_5_BLOCK_UNUSED;
7712 } else {
7713 /*
7714 * Block used, but not marked in use in the bitmap.
7715 */
7716 problem = PR_5_BLOCK_USED;
7717 }
7718 if (pctx.blk == NO_BLK) {
7719 pctx.blk = pctx.blk2 = i;
7720 save_problem = problem;
7721 } else {
7722 if ((problem == save_problem) &&
7723 (pctx.blk2 == i-1))
7724 pctx.blk2++;
7725 else {
7726 print_bitmap_problem(ctx, save_problem, &pctx);
7727 pctx.blk = pctx.blk2 = i;
7728 save_problem = problem;
7729 }
7730 }
7731 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7732 had_problem++;
7733
7734 do_counts:
7735 if (!bitmap) {
7736 group_free++;
7737 free_blocks++;
7738 }
7739 blocks ++;
7740 if ((blocks == fs->super->s_blocks_per_group) ||
7741 (i == fs->super->s_blocks_count-1)) {
7742 free_array[group] = group_free;
7743 group ++;
7744 blocks = 0;
7745 group_free = 0;
7746 if (ctx->progress)
7747 if ((ctx->progress)(ctx, 5, group,
7748 fs->group_desc_count*2))
7749 return;
7750 }
7751 }
7752 if (pctx.blk != NO_BLK)
7753 print_bitmap_problem(ctx, save_problem, &pctx);
7754 if (had_problem)
7755 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7756 else
7757 fixit = -1;
7758 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7759
7760 if (fixit == 1) {
7761 ext2fs_free_block_bitmap(fs->block_map);
7762 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7763 &fs->block_map);
7764 if (retval) {
7765 clear_problem_context(&pctx);
7766 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7767 ctx->flags |= E2F_FLAG_ABORT;
7768 return;
7769 }
7770 ext2fs_set_bitmap_padding(fs->block_map);
7771 ext2fs_mark_bb_dirty(fs);
7772
7773 /* Redo the counts */
7774 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7775 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7776 goto redo_counts;
7777 } else if (fixit == 0)
7778 ext2fs_unmark_valid(fs);
7779
7780 for (i = 0; i < fs->group_desc_count; i++) {
7781 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7782 pctx.group = i;
7783 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7784 pctx.blk2 = free_array[i];
7785
7786 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7787 &pctx)) {
7788 fs->group_desc[i].bg_free_blocks_count =
7789 free_array[i];
7790 ext2fs_mark_super_dirty(fs);
7791 } else
7792 ext2fs_unmark_valid(fs);
7793 }
7794 }
7795 if (free_blocks != fs->super->s_free_blocks_count) {
7796 pctx.group = 0;
7797 pctx.blk = fs->super->s_free_blocks_count;
7798 pctx.blk2 = free_blocks;
7799
7800 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7801 fs->super->s_free_blocks_count = free_blocks;
7802 ext2fs_mark_super_dirty(fs);
7803 } else
7804 ext2fs_unmark_valid(fs);
7805 }
7806 ext2fs_free_mem(&free_array);
7807}
7808
7809static void check_inode_bitmaps(e2fsck_t ctx)
7810{
7811 ext2_filsys fs = ctx->fs;
7812 ext2_ino_t i;
7813 unsigned int free_inodes = 0;
7814 int group_free = 0;
7815 int dirs_count = 0;
7816 int group = 0;
7817 unsigned int inodes = 0;
7818 int *free_array;
7819 int *dir_array;
7820 int actual, bitmap;
7821 errcode_t retval;
7822 struct problem_context pctx;
7823 int problem, save_problem, fixit, had_problem;
7824
7825 clear_problem_context(&pctx);
7826 free_array = (int *) e2fsck_allocate_memory(ctx,
7827 fs->group_desc_count * sizeof(int), "free inode count array");
7828
7829 dir_array = (int *) e2fsck_allocate_memory(ctx,
7830 fs->group_desc_count * sizeof(int), "directory count array");
7831
7832 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7833 (fs->super->s_inodes_count >
7834 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7835 pctx.num = 3;
7836 pctx.blk = 1;
7837 pctx.blk2 = fs->super->s_inodes_count;
7838 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7839 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7840 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7841
7842 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7843 return;
7844 }
7845 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7846 (fs->super->s_inodes_count >
7847 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7848 pctx.num = 4;
7849 pctx.blk = 1;
7850 pctx.blk2 = fs->super->s_inodes_count;
7851 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7852 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7853 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7854
7855 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7856 return;
7857 }
7858
7859redo_counts:
7860 had_problem = 0;
7861 save_problem = 0;
7862 pctx.ino = pctx.ino2 = 0;
7863 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7864 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7865 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7866
7867 if (actual == bitmap)
7868 goto do_counts;
7869
7870 if (!actual && bitmap) {
7871 /*
7872 * Inode wasn't used, but marked in bitmap
7873 */
7874 problem = PR_5_INODE_UNUSED;
7875 } else /* if (actual && !bitmap) */ {
7876 /*
7877 * Inode used, but not in bitmap
7878 */
7879 problem = PR_5_INODE_USED;
7880 }
7881 if (pctx.ino == 0) {
7882 pctx.ino = pctx.ino2 = i;
7883 save_problem = problem;
7884 } else {
7885 if ((problem == save_problem) &&
7886 (pctx.ino2 == i-1))
7887 pctx.ino2++;
7888 else {
7889 print_bitmap_problem(ctx, save_problem, &pctx);
7890 pctx.ino = pctx.ino2 = i;
7891 save_problem = problem;
7892 }
7893 }
7894 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7895 had_problem++;
7896
7897do_counts:
7898 if (!bitmap) {
7899 group_free++;
7900 free_inodes++;
7901 } else {
7902 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7903 dirs_count++;
7904 }
7905 inodes++;
7906 if ((inodes == fs->super->s_inodes_per_group) ||
7907 (i == fs->super->s_inodes_count)) {
7908 free_array[group] = group_free;
7909 dir_array[group] = dirs_count;
7910 group ++;
7911 inodes = 0;
7912 group_free = 0;
7913 dirs_count = 0;
7914 if (ctx->progress)
7915 if ((ctx->progress)(ctx, 5,
7916 group + fs->group_desc_count,
7917 fs->group_desc_count*2))
7918 return;
7919 }
7920 }
7921 if (pctx.ino)
7922 print_bitmap_problem(ctx, save_problem, &pctx);
7923
7924 if (had_problem)
7925 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7926 else
7927 fixit = -1;
7928 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7929
7930 if (fixit == 1) {
7931 ext2fs_free_inode_bitmap(fs->inode_map);
7932 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7933 &fs->inode_map);
7934 if (retval) {
7935 clear_problem_context(&pctx);
7936 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7937 ctx->flags |= E2F_FLAG_ABORT;
7938 return;
7939 }
7940 ext2fs_set_bitmap_padding(fs->inode_map);
7941 ext2fs_mark_ib_dirty(fs);
7942
7943 /* redo counts */
7944 inodes = 0; free_inodes = 0; group_free = 0;
7945 dirs_count = 0; group = 0;
7946 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7947 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7948 goto redo_counts;
7949 } else if (fixit == 0)
7950 ext2fs_unmark_valid(fs);
7951
7952 for (i = 0; i < fs->group_desc_count; i++) {
7953 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7954 pctx.group = i;
7955 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7956 pctx.ino2 = free_array[i];
7957 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7958 &pctx)) {
7959 fs->group_desc[i].bg_free_inodes_count =
7960 free_array[i];
7961 ext2fs_mark_super_dirty(fs);
7962 } else
7963 ext2fs_unmark_valid(fs);
7964 }
7965 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7966 pctx.group = i;
7967 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7968 pctx.ino2 = dir_array[i];
7969
7970 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7971 &pctx)) {
7972 fs->group_desc[i].bg_used_dirs_count =
7973 dir_array[i];
7974 ext2fs_mark_super_dirty(fs);
7975 } else
7976 ext2fs_unmark_valid(fs);
7977 }
7978 }
7979 if (free_inodes != fs->super->s_free_inodes_count) {
7980 pctx.group = -1;
7981 pctx.ino = fs->super->s_free_inodes_count;
7982 pctx.ino2 = free_inodes;
7983
7984 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7985 fs->super->s_free_inodes_count = free_inodes;
7986 ext2fs_mark_super_dirty(fs);
7987 } else
7988 ext2fs_unmark_valid(fs);
7989 }
7990 ext2fs_free_mem(&free_array);
7991 ext2fs_free_mem(&dir_array);
7992}
7993
7994static void check_inode_end(e2fsck_t ctx)
7995{
7996 ext2_filsys fs = ctx->fs;
7997 ext2_ino_t end, save_inodes_count, i;
7998 struct problem_context pctx;
7999
8000 clear_problem_context(&pctx);
8001
8002 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8003 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8004 &save_inodes_count);
8005 if (pctx.errcode) {
8006 pctx.num = 1;
8007 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8008 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8009 return;
8010 }
8011 if (save_inodes_count == end)
8012 return;
8013
8014 for (i = save_inodes_count + 1; i <= end; i++) {
8015 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8016 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8017 for (i = save_inodes_count + 1; i <= end; i++)
8018 ext2fs_mark_inode_bitmap(fs->inode_map,
8019 i);
8020 ext2fs_mark_ib_dirty(fs);
8021 } else
8022 ext2fs_unmark_valid(fs);
8023 break;
8024 }
8025 }
8026
8027 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8028 save_inodes_count, 0);
8029 if (pctx.errcode) {
8030 pctx.num = 2;
8031 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8032 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8033 return;
8034 }
8035}
8036
8037static void check_block_end(e2fsck_t ctx)
8038{
8039 ext2_filsys fs = ctx->fs;
8040 blk_t end, save_blocks_count, i;
8041 struct problem_context pctx;
8042
8043 clear_problem_context(&pctx);
8044
8045 end = fs->block_map->start +
8046 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8047 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8048 &save_blocks_count);
8049 if (pctx.errcode) {
8050 pctx.num = 3;
8051 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8052 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8053 return;
8054 }
8055 if (save_blocks_count == end)
8056 return;
8057
8058 for (i = save_blocks_count + 1; i <= end; i++) {
8059 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8060 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8061 for (i = save_blocks_count + 1; i <= end; i++)
8062 ext2fs_mark_block_bitmap(fs->block_map,
8063 i);
8064 ext2fs_mark_bb_dirty(fs);
8065 } else
8066 ext2fs_unmark_valid(fs);
8067 break;
8068 }
8069 }
8070
8071 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8072 save_blocks_count, 0);
8073 if (pctx.errcode) {
8074 pctx.num = 4;
8075 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8076 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8077 return;
8078 }
8079}
8080
8081static void e2fsck_pass5(e2fsck_t ctx)
8082{
8083 struct problem_context pctx;
8084
8085 /* Pass 5 */
8086
8087 clear_problem_context(&pctx);
8088
8089 if (!(ctx->options & E2F_OPT_PREEN))
8090 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8091
8092 if (ctx->progress)
8093 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8094 return;
8095
8096 e2fsck_read_bitmaps(ctx);
8097
8098 check_block_bitmaps(ctx);
8099 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100 return;
8101 check_inode_bitmaps(ctx);
8102 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8103 return;
8104 check_inode_end(ctx);
8105 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8106 return;
8107 check_block_end(ctx);
8108 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8109 return;
8110
8111 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8112 ctx->inode_used_map = 0;
8113 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8114 ctx->inode_dir_map = 0;
8115 ext2fs_free_block_bitmap(ctx->block_found_map);
8116 ctx->block_found_map = 0;
8117}
8118
8119/*
8120 * problem.c --- report filesystem problems to the user
8121 */
8122
8123#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8124#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8125#define PR_NO_DEFAULT 0x000004 /* Default to no */
8126#define PR_MSG_ONLY 0x000008 /* Print message only */
8127
8128/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8129
8130#define PR_FATAL 0x001000 /* Fatal error */
8131#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8132 /* ask another */
8133#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8134#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8135#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8136#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8137#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8138
8139
8140#define PROMPT_NONE 0
8141#define PROMPT_FIX 1
8142#define PROMPT_CLEAR 2
8143#define PROMPT_RELOCATE 3
8144#define PROMPT_ALLOCATE 4
8145#define PROMPT_EXPAND 5
8146#define PROMPT_CONNECT 6
8147#define PROMPT_CREATE 7
8148#define PROMPT_SALVAGE 8
8149#define PROMPT_TRUNCATE 9
8150#define PROMPT_CLEAR_INODE 10
8151#define PROMPT_ABORT 11
8152#define PROMPT_SPLIT 12
8153#define PROMPT_CONTINUE 13
8154#define PROMPT_CLONE 14
8155#define PROMPT_DELETE 15
8156#define PROMPT_SUPPRESS 16
8157#define PROMPT_UNLINK 17
8158#define PROMPT_CLEAR_HTREE 18
8159#define PROMPT_RECREATE 19
8160#define PROMPT_NULL 20
8161
8162struct e2fsck_problem {
8163 problem_t e2p_code;
8164 const char * e2p_description;
8165 char prompt;
8166 int flags;
8167 problem_t second_code;
8168};
8169
8170struct latch_descr {
8171 int latch_code;
8172 problem_t question;
8173 problem_t end_message;
8174 int flags;
8175};
8176
8177/*
8178 * These are the prompts which are used to ask the user if they want
8179 * to fix a problem.
8180 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008181static const char *const prompt[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008182 N_("(no prompt)"), /* 0 */
8183 N_("Fix"), /* 1 */
8184 N_("Clear"), /* 2 */
8185 N_("Relocate"), /* 3 */
8186 N_("Allocate"), /* 4 */
8187 N_("Expand"), /* 5 */
8188 N_("Connect to /lost+found"), /* 6 */
8189 N_("Create"), /* 7 */
8190 N_("Salvage"), /* 8 */
8191 N_("Truncate"), /* 9 */
8192 N_("Clear inode"), /* 10 */
8193 N_("Abort"), /* 11 */
8194 N_("Split"), /* 12 */
8195 N_("Continue"), /* 13 */
8196 N_("Clone multiply-claimed blocks"), /* 14 */
8197 N_("Delete file"), /* 15 */
8198 N_("Suppress messages"),/* 16 */
8199 N_("Unlink"), /* 17 */
8200 N_("Clear HTree index"),/* 18 */
8201 N_("Recreate"), /* 19 */
8202 "", /* 20 */
8203};
8204
8205/*
8206 * These messages are printed when we are preen mode and we will be
8207 * automatically fixing the problem.
8208 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008209static const char *const preen_msg[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008210 N_("(NONE)"), /* 0 */
8211 N_("FIXED"), /* 1 */
8212 N_("CLEARED"), /* 2 */
8213 N_("RELOCATED"), /* 3 */
8214 N_("ALLOCATED"), /* 4 */
8215 N_("EXPANDED"), /* 5 */
8216 N_("RECONNECTED"), /* 6 */
8217 N_("CREATED"), /* 7 */
8218 N_("SALVAGED"), /* 8 */
8219 N_("TRUNCATED"), /* 9 */
8220 N_("INODE CLEARED"), /* 10 */
8221 N_("ABORTED"), /* 11 */
8222 N_("SPLIT"), /* 12 */
8223 N_("CONTINUING"), /* 13 */
8224 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8225 N_("FILE DELETED"), /* 15 */
8226 N_("SUPPRESSED"), /* 16 */
8227 N_("UNLINKED"), /* 17 */
8228 N_("HTREE INDEX CLEARED"),/* 18 */
8229 N_("WILL RECREATE"), /* 19 */
8230 "", /* 20 */
8231};
8232
8233static const struct e2fsck_problem problem_table[] = {
8234
8235 /* Pre-Pass 1 errors */
8236
8237 /* Block bitmap not in group */
8238 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8239 PROMPT_RELOCATE, PR_LATCH_RELOC },
8240
8241 /* Inode bitmap not in group */
8242 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8243 PROMPT_RELOCATE, PR_LATCH_RELOC },
8244
8245 /* Inode table not in group */
8246 { PR_0_ITABLE_NOT_GROUP,
8247 N_("@i table for @g %g is not in @g. (@b %b)\n"
8248 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8249 PROMPT_RELOCATE, PR_LATCH_RELOC },
8250
8251 /* Superblock corrupt */
8252 { PR_0_SB_CORRUPT,
8253 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8254 "@f. If the @v is valid and it really contains an ext2\n"
8255 "@f (and not swap or ufs or something else), then the @S\n"
8256 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8257 " e2fsck -b %S <@v>\n\n"),
8258 PROMPT_NONE, PR_FATAL },
8259
8260 /* Filesystem size is wrong */
8261 { PR_0_FS_SIZE_WRONG,
8262 N_("The @f size (according to the @S) is %b @bs\n"
8263 "The physical size of the @v is %c @bs\n"
8264 "Either the @S or the partition table is likely to be corrupt!\n"),
8265 PROMPT_ABORT, 0 },
8266
8267 /* Fragments not supported */
8268 { PR_0_NO_FRAGMENTS,
8269 N_("@S @b_size = %b, fragsize = %c.\n"
8270 "This version of e2fsck does not support fragment sizes different\n"
8271 "from the @b size.\n"),
8272 PROMPT_NONE, PR_FATAL },
8273
8274 /* Bad blocks_per_group */
8275 { PR_0_BLOCKS_PER_GROUP,
8276 N_("@S @bs_per_group = %b, should have been %c\n"),
8277 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8278
8279 /* Bad first_data_block */
8280 { PR_0_FIRST_DATA_BLOCK,
8281 N_("@S first_data_@b = %b, should have been %c\n"),
8282 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8283
8284 /* Adding UUID to filesystem */
8285 { PR_0_ADD_UUID,
8286 N_("@f did not have a UUID; generating one.\n\n"),
8287 PROMPT_NONE, 0 },
8288
8289 /* Relocate hint */
8290 { PR_0_RELOCATE_HINT,
8291 N_("Note: if several inode or block bitmap blocks or part\n"
8292 "of the inode table require relocation, you may wish to try\n"
8293 "running e2fsck with the '-b %S' option first. The problem\n"
8294 "may lie only with the primary block group descriptors, and\n"
8295 "the backup block group descriptors may be OK.\n\n"),
8296 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8297
8298 /* Miscellaneous superblock corruption */
8299 { PR_0_MISC_CORRUPT_SUPER,
8300 N_("Corruption found in @S. (%s = %N).\n"),
8301 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8302
8303 /* Error determing physical device size of filesystem */
8304 { PR_0_GETSIZE_ERROR,
8305 N_("Error determining size of the physical @v: %m\n"),
8306 PROMPT_NONE, PR_FATAL },
8307
8308 /* Inode count in superblock is incorrect */
8309 { PR_0_INODE_COUNT_WRONG,
8310 N_("@i count in @S is %i, @s %j.\n"),
8311 PROMPT_FIX, 0 },
8312
8313 { PR_0_HURD_CLEAR_FILETYPE,
8314 N_("The Hurd does not support the filetype feature.\n"),
8315 PROMPT_CLEAR, 0 },
8316
8317 /* Journal inode is invalid */
8318 { PR_0_JOURNAL_BAD_INODE,
8319 N_("@S has an @n ext3 @j (@i %i).\n"),
8320 PROMPT_CLEAR, PR_PREEN_OK },
8321
8322 /* The external journal has (unsupported) multiple filesystems */
8323 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8324 N_("External @j has multiple @f users (unsupported).\n"),
8325 PROMPT_NONE, PR_FATAL },
8326
8327 /* Can't find external journal */
8328 { PR_0_CANT_FIND_JOURNAL,
8329 N_("Can't find external @j\n"),
8330 PROMPT_NONE, PR_FATAL },
8331
8332 /* External journal has bad superblock */
8333 { PR_0_EXT_JOURNAL_BAD_SUPER,
8334 N_("External @j has bad @S\n"),
8335 PROMPT_NONE, PR_FATAL },
8336
8337 /* Superblock has a bad journal UUID */
8338 { PR_0_JOURNAL_BAD_UUID,
8339 N_("External @j does not support this @f\n"),
8340 PROMPT_NONE, PR_FATAL },
8341
8342 /* Journal has an unknown superblock type */
8343 { PR_0_JOURNAL_UNSUPP_SUPER,
8344 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8345 "It is likely that your copy of e2fsck is old and/or doesn't "
8346 "support this @j format.\n"
8347 "It is also possible the @j @S is corrupt.\n"),
8348 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8349
8350 /* Journal superblock is corrupt */
8351 { PR_0_JOURNAL_BAD_SUPER,
8352 N_("Ext3 @j @S is corrupt.\n"),
8353 PROMPT_FIX, PR_PREEN_OK },
8354
8355 /* Superblock flag should be cleared */
8356 { PR_0_JOURNAL_HAS_JOURNAL,
8357 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8358 PROMPT_CLEAR, PR_PREEN_OK },
8359
8360 /* Superblock flag is incorrect */
8361 { PR_0_JOURNAL_RECOVER_SET,
8362 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8363 PROMPT_CLEAR, PR_PREEN_OK },
8364
8365 /* Journal has data, but recovery flag is clear */
8366 { PR_0_JOURNAL_RECOVERY_CLEAR,
8367 N_("ext3 recovery flag is clear, but @j has data.\n"),
8368 PROMPT_NONE, 0 },
8369
8370 /* Ask if we should clear the journal */
8371 { PR_0_JOURNAL_RESET_JOURNAL,
8372 N_("Clear @j"),
8373 PROMPT_NULL, PR_PREEN_NOMSG },
8374
8375 /* Ask if we should run the journal anyway */
8376 { PR_0_JOURNAL_RUN,
8377 N_("Run @j anyway"),
8378 PROMPT_NULL, 0 },
8379
8380 /* Run the journal by default */
8381 { PR_0_JOURNAL_RUN_DEFAULT,
8382 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8383 PROMPT_NONE, 0 },
8384
8385 /* Clearing orphan inode */
8386 { PR_0_ORPHAN_CLEAR_INODE,
8387 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8388 PROMPT_NONE, 0 },
8389
8390 /* Illegal block found in orphaned inode */
8391 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8392 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8393 PROMPT_NONE, 0 },
8394
8395 /* Already cleared block found in orphaned inode */
8396 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8397 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8398 PROMPT_NONE, 0 },
8399
8400 /* Illegal orphan inode in superblock */
8401 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8402 N_("@I @o @i %i in @S.\n"),
8403 PROMPT_NONE, 0 },
8404
8405 /* Illegal inode in orphaned inode list */
8406 { PR_0_ORPHAN_ILLEGAL_INODE,
8407 N_("@I @i %i in @o @i list.\n"),
8408 PROMPT_NONE, 0 },
8409
8410 /* Filesystem revision is 0, but feature flags are set */
8411 { PR_0_FS_REV_LEVEL,
8412 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8413 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8414
8415 /* Journal superblock has an unknown read-only feature flag set */
8416 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8417 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8418 PROMPT_ABORT, 0 },
8419
8420 /* Journal superblock has an unknown incompatible feature flag set */
8421 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8422 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8423 PROMPT_ABORT, 0 },
8424
8425 /* Journal has unsupported version number */
8426 { PR_0_JOURNAL_UNSUPP_VERSION,
8427 N_("@j version not supported by this e2fsck.\n"),
8428 PROMPT_ABORT, 0 },
8429
8430 /* Moving journal to hidden file */
8431 { PR_0_MOVE_JOURNAL,
8432 N_("Moving @j from /%s to hidden @i.\n\n"),
8433 PROMPT_NONE, 0 },
8434
8435 /* Error moving journal to hidden file */
8436 { PR_0_ERR_MOVE_JOURNAL,
8437 N_("Error moving @j: %m\n\n"),
8438 PROMPT_NONE, 0 },
8439
8440 /* Clearing V2 journal superblock */
8441 { PR_0_CLEAR_V2_JOURNAL,
8442 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8443 "Clearing fields beyond the V1 @j @S...\n\n"),
8444 PROMPT_NONE, 0 },
8445
8446 /* Backup journal inode blocks */
8447 { PR_0_BACKUP_JNL,
8448 N_("Backing up @j @i @b information.\n\n"),
8449 PROMPT_NONE, 0 },
8450
8451 /* Reserved blocks w/o resize_inode */
8452 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8453 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8454 "is %N; @s zero. "),
8455 PROMPT_FIX, 0 },
8456
8457 /* Resize_inode not enabled, but resize inode is non-zero */
8458 { PR_0_CLEAR_RESIZE_INODE,
8459 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8460 PROMPT_CLEAR, 0 },
8461
8462 /* Resize inode invalid */
8463 { PR_0_RESIZE_INODE_INVALID,
8464 N_("Resize @i not valid. "),
8465 PROMPT_RECREATE, 0 },
8466
8467 /* Pass 1 errors */
8468
8469 /* Pass 1: Checking inodes, blocks, and sizes */
8470 { PR_1_PASS_HEADER,
8471 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8472 PROMPT_NONE, 0 },
8473
8474 /* Root directory is not an inode */
8475 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8476 PROMPT_CLEAR, 0 },
8477
8478 /* Root directory has dtime set */
8479 { PR_1_ROOT_DTIME,
8480 N_("@r has dtime set (probably due to old mke2fs). "),
8481 PROMPT_FIX, PR_PREEN_OK },
8482
8483 /* Reserved inode has bad mode */
8484 { PR_1_RESERVED_BAD_MODE,
8485 N_("Reserved @i %i (%Q) has @n mode. "),
8486 PROMPT_CLEAR, PR_PREEN_OK },
8487
8488 /* Deleted inode has zero dtime */
8489 { PR_1_ZERO_DTIME,
8490 N_("@D @i %i has zero dtime. "),
8491 PROMPT_FIX, PR_PREEN_OK },
8492
8493 /* Inode in use, but dtime set */
8494 { PR_1_SET_DTIME,
8495 N_("@i %i is in use, but has dtime set. "),
8496 PROMPT_FIX, PR_PREEN_OK },
8497
8498 /* Zero-length directory */
8499 { PR_1_ZERO_LENGTH_DIR,
8500 N_("@i %i is a @z @d. "),
8501 PROMPT_CLEAR, PR_PREEN_OK },
8502
8503 /* Block bitmap conflicts with some other fs block */
8504 { PR_1_BB_CONFLICT,
8505 N_("@g %g's @b @B at %b @C.\n"),
8506 PROMPT_RELOCATE, 0 },
8507
8508 /* Inode bitmap conflicts with some other fs block */
8509 { PR_1_IB_CONFLICT,
8510 N_("@g %g's @i @B at %b @C.\n"),
8511 PROMPT_RELOCATE, 0 },
8512
8513 /* Inode table conflicts with some other fs block */
8514 { PR_1_ITABLE_CONFLICT,
8515 N_("@g %g's @i table at %b @C.\n"),
8516 PROMPT_RELOCATE, 0 },
8517
8518 /* Block bitmap is on a bad block */
8519 { PR_1_BB_BAD_BLOCK,
8520 N_("@g %g's @b @B (%b) is bad. "),
8521 PROMPT_RELOCATE, 0 },
8522
8523 /* Inode bitmap is on a bad block */
8524 { PR_1_IB_BAD_BLOCK,
8525 N_("@g %g's @i @B (%b) is bad. "),
8526 PROMPT_RELOCATE, 0 },
8527
8528 /* Inode has incorrect i_size */
8529 { PR_1_BAD_I_SIZE,
8530 N_("@i %i, i_size is %Is, @s %N. "),
8531 PROMPT_FIX, PR_PREEN_OK },
8532
8533 /* Inode has incorrect i_blocks */
8534 { PR_1_BAD_I_BLOCKS,
8535 N_("@i %i, i_@bs is %Ib, @s %N. "),
8536 PROMPT_FIX, PR_PREEN_OK },
8537
8538 /* Illegal blocknumber in inode */
8539 { PR_1_ILLEGAL_BLOCK_NUM,
8540 N_("@I @b #%B (%b) in @i %i. "),
8541 PROMPT_CLEAR, PR_LATCH_BLOCK },
8542
8543 /* Block number overlaps fs metadata */
8544 { PR_1_BLOCK_OVERLAPS_METADATA,
8545 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8546 PROMPT_CLEAR, PR_LATCH_BLOCK },
8547
8548 /* Inode has illegal blocks (latch question) */
8549 { PR_1_INODE_BLOCK_LATCH,
8550 N_("@i %i has illegal @b(s). "),
8551 PROMPT_CLEAR, 0 },
8552
8553 /* Too many bad blocks in inode */
8554 { PR_1_TOO_MANY_BAD_BLOCKS,
8555 N_("Too many illegal @bs in @i %i.\n"),
8556 PROMPT_CLEAR_INODE, PR_NO_OK },
8557
8558 /* Illegal block number in bad block inode */
8559 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8560 N_("@I @b #%B (%b) in bad @b @i. "),
8561 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8562
8563 /* Bad block inode has illegal blocks (latch question) */
8564 { PR_1_INODE_BBLOCK_LATCH,
8565 N_("Bad @b @i has illegal @b(s). "),
8566 PROMPT_CLEAR, 0 },
8567
8568 /* Duplicate or bad blocks in use! */
8569 { PR_1_DUP_BLOCKS_PREENSTOP,
8570 N_("Duplicate or bad @b in use!\n"),
8571 PROMPT_NONE, 0 },
8572
8573 /* Bad block used as bad block indirect block */
8574 { PR_1_BBINODE_BAD_METABLOCK,
8575 N_("Bad @b %b used as bad @b @i indirect @b. "),
8576 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8577
8578 /* Inconsistency can't be fixed prompt */
8579 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8580 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8581 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8582 "in the @f.\n"),
8583 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8584
8585 /* Bad primary block */
8586 { PR_1_BAD_PRIMARY_BLOCK,
8587 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8588 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8589
8590 /* Bad primary block prompt */
8591 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8592 N_("You can remove this @b from the bad @b list and hope\n"
8593 "that the @b is really OK. But there are no guarantees.\n\n"),
8594 PROMPT_CLEAR, PR_PREEN_NOMSG },
8595
8596 /* Bad primary superblock */
8597 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8598 N_("The primary @S (%b) is on the bad @b list.\n"),
8599 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8600
8601 /* Bad primary block group descriptors */
8602 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8603 N_("Block %b in the primary @g descriptors "
8604 "is on the bad @b list\n"),
8605 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8606
8607 /* Bad superblock in group */
8608 { PR_1_BAD_SUPERBLOCK,
8609 N_("Warning: Group %g's @S (%b) is bad.\n"),
8610 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8611
8612 /* Bad block group descriptors in group */
8613 { PR_1_BAD_GROUP_DESCRIPTORS,
8614 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8615 "@b (%b).\n"),
8616 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8617
8618 /* Block claimed for no reason */
8619 { PR_1_PROGERR_CLAIMED_BLOCK,
8620 N_("Programming error? @b #%b claimed for no reason in "
8621 "process_bad_@b.\n"),
8622 PROMPT_NONE, PR_PREEN_OK },
8623
8624 /* Error allocating blocks for relocating metadata */
8625 { PR_1_RELOC_BLOCK_ALLOCATE,
8626 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8627 PROMPT_NONE, PR_PREEN_OK },
8628
8629 /* Error allocating block buffer during relocation process */
8630 { PR_1_RELOC_MEMORY_ALLOCATE,
8631 N_("@A @b buffer for relocating %s\n"),
8632 PROMPT_NONE, PR_PREEN_OK },
8633
8634 /* Relocating metadata group information from X to Y */
8635 { PR_1_RELOC_FROM_TO,
8636 N_("Relocating @g %g's %s from %b to %c...\n"),
8637 PROMPT_NONE, PR_PREEN_OK },
8638
8639 /* Relocating metatdata group information to X */
8640 { PR_1_RELOC_TO,
8641 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8642 PROMPT_NONE, PR_PREEN_OK },
8643
8644 /* Block read error during relocation process */
8645 { PR_1_RELOC_READ_ERR,
8646 N_("Warning: could not read @b %b of %s: %m\n"),
8647 PROMPT_NONE, PR_PREEN_OK },
8648
8649 /* Block write error during relocation process */
8650 { PR_1_RELOC_WRITE_ERR,
8651 N_("Warning: could not write @b %b for %s: %m\n"),
8652 PROMPT_NONE, PR_PREEN_OK },
8653
8654 /* Error allocating inode bitmap */
8655 { PR_1_ALLOCATE_IBITMAP_ERROR,
8656 N_("@A @i @B (%N): %m\n"),
8657 PROMPT_NONE, PR_FATAL },
8658
8659 /* Error allocating block bitmap */
8660 { PR_1_ALLOCATE_BBITMAP_ERROR,
8661 N_("@A @b @B (%N): %m\n"),
8662 PROMPT_NONE, PR_FATAL },
8663
8664 /* Error allocating icount structure */
8665 { PR_1_ALLOCATE_ICOUNT,
8666 N_("@A icount link information: %m\n"),
8667 PROMPT_NONE, PR_FATAL },
8668
8669 /* Error allocating dbcount */
8670 { PR_1_ALLOCATE_DBCOUNT,
8671 N_("@A @d @b array: %m\n"),
8672 PROMPT_NONE, PR_FATAL },
8673
8674 /* Error while scanning inodes */
8675 { PR_1_ISCAN_ERROR,
8676 N_("Error while scanning @is (%i): %m\n"),
8677 PROMPT_NONE, PR_FATAL },
8678
8679 /* Error while iterating over blocks */
8680 { PR_1_BLOCK_ITERATE,
8681 N_("Error while iterating over @bs in @i %i: %m\n"),
8682 PROMPT_NONE, PR_FATAL },
8683
8684 /* Error while storing inode count information */
8685 { PR_1_ICOUNT_STORE,
8686 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8687 PROMPT_NONE, PR_FATAL },
8688
8689 /* Error while storing directory block information */
8690 { PR_1_ADD_DBLOCK,
8691 N_("Error storing @d @b information "
8692 "(@i=%i, @b=%b, num=%N): %m\n"),
8693 PROMPT_NONE, PR_FATAL },
8694
8695 /* Error while reading inode (for clearing) */
8696 { PR_1_READ_INODE,
8697 N_("Error reading @i %i: %m\n"),
8698 PROMPT_NONE, PR_FATAL },
8699
8700 /* Suppress messages prompt */
8701 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8702
8703 /* Imagic flag set on an inode when filesystem doesn't support it */
8704 { PR_1_SET_IMAGIC,
8705 N_("@i %i has imagic flag set. "),
8706 PROMPT_CLEAR, 0 },
8707
8708 /* Immutable flag set on a device or socket inode */
8709 { PR_1_SET_IMMUTABLE,
8710 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8711 "or append-only flag set. "),
8712 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8713
8714 /* Compression flag set on an inode when filesystem doesn't support it */
8715 { PR_1_COMPR_SET,
8716 N_("@i %i has @cion flag set on @f without @cion support. "),
8717 PROMPT_CLEAR, 0 },
8718
8719 /* Non-zero size for device, fifo or socket inode */
8720 { PR_1_SET_NONZSIZE,
8721 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8722 PROMPT_FIX, PR_PREEN_OK },
8723
8724 /* Filesystem revision is 0, but feature flags are set */
8725 { PR_1_FS_REV_LEVEL,
8726 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8727 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8728
8729 /* Journal inode is not in use, but contains data */
8730 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8731 N_("@j @i is not in use, but contains data. "),
8732 PROMPT_CLEAR, PR_PREEN_OK },
8733
8734 /* Journal has bad mode */
8735 { PR_1_JOURNAL_BAD_MODE,
8736 N_("@j is not regular file. "),
8737 PROMPT_FIX, PR_PREEN_OK },
8738
8739 /* Deal with inodes that were part of orphan linked list */
8740 { PR_1_LOW_DTIME,
8741 N_("@i %i was part of the @o @i list. "),
8742 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8743
8744 /* Deal with inodes that were part of corrupted orphan linked
8745 list (latch question) */
8746 { PR_1_ORPHAN_LIST_REFUGEES,
8747 N_("@is that were part of a corrupted orphan linked list found. "),
8748 PROMPT_FIX, 0 },
8749
8750 /* Error allocating refcount structure */
8751 { PR_1_ALLOCATE_REFCOUNT,
8752 N_("@A refcount structure (%N): %m\n"),
8753 PROMPT_NONE, PR_FATAL },
8754
8755 /* Error reading extended attribute block */
8756 { PR_1_READ_EA_BLOCK,
8757 N_("Error reading @a @b %b for @i %i. "),
8758 PROMPT_CLEAR, 0 },
8759
8760 /* Invalid extended attribute block */
8761 { PR_1_BAD_EA_BLOCK,
8762 N_("@i %i has a bad @a @b %b. "),
8763 PROMPT_CLEAR, 0 },
8764
8765 /* Error reading Extended Attribute block while fixing refcount */
8766 { PR_1_EXTATTR_READ_ABORT,
8767 N_("Error reading @a @b %b (%m). "),
8768 PROMPT_ABORT, 0 },
8769
8770 /* Extended attribute reference count incorrect */
8771 { PR_1_EXTATTR_REFCOUNT,
8772 N_("@a @b %b has reference count %B, @s %N. "),
8773 PROMPT_FIX, 0 },
8774
8775 /* Error writing Extended Attribute block while fixing refcount */
8776 { PR_1_EXTATTR_WRITE,
8777 N_("Error writing @a @b %b (%m). "),
8778 PROMPT_ABORT, 0 },
8779
8780 /* Multiple EA blocks not supported */
8781 { PR_1_EA_MULTI_BLOCK,
8782 N_("@a @b %b has h_@bs > 1. "),
8783 PROMPT_CLEAR, 0},
8784
8785 /* Error allocating EA region allocation structure */
8786 { PR_1_EA_ALLOC_REGION,
8787 N_("@A @a @b %b. "),
8788 PROMPT_ABORT, 0},
8789
8790 /* Error EA allocation collision */
8791 { PR_1_EA_ALLOC_COLLISION,
8792 N_("@a @b %b is corrupt (allocation collision). "),
8793 PROMPT_CLEAR, 0},
8794
8795 /* Bad extended attribute name */
8796 { PR_1_EA_BAD_NAME,
8797 N_("@a @b %b is corrupt (@n name). "),
8798 PROMPT_CLEAR, 0},
8799
8800 /* Bad extended attribute value */
8801 { PR_1_EA_BAD_VALUE,
8802 N_("@a @b %b is corrupt (@n value). "),
8803 PROMPT_CLEAR, 0},
8804
8805 /* Inode too big (latch question) */
8806 { PR_1_INODE_TOOBIG,
8807 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8808
8809 /* Directory too big */
8810 { PR_1_TOOBIG_DIR,
8811 N_("@b #%B (%b) causes @d to be too big. "),
8812 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8813
8814 /* Regular file too big */
8815 { PR_1_TOOBIG_REG,
8816 N_("@b #%B (%b) causes file to be too big. "),
8817 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8818
8819 /* Symlink too big */
8820 { PR_1_TOOBIG_SYMLINK,
8821 N_("@b #%B (%b) causes symlink to be too big. "),
8822 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8823
8824 /* INDEX_FL flag set on a non-HTREE filesystem */
8825 { PR_1_HTREE_SET,
8826 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8827 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8828
8829 /* INDEX_FL flag set on a non-directory */
8830 { PR_1_HTREE_NODIR,
8831 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8832 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8833
8834 /* Invalid root node in HTREE directory */
8835 { PR_1_HTREE_BADROOT,
8836 N_("@h %i has an @n root node.\n"),
8837 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8838
8839 /* Unsupported hash version in HTREE directory */
8840 { PR_1_HTREE_HASHV,
8841 N_("@h %i has an unsupported hash version (%N)\n"),
8842 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8843
8844 /* Incompatible flag in HTREE root node */
8845 { PR_1_HTREE_INCOMPAT,
8846 N_("@h %i uses an incompatible htree root node flag.\n"),
8847 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8848
8849 /* HTREE too deep */
8850 { PR_1_HTREE_DEPTH,
8851 N_("@h %i has a tree depth (%N) which is too big\n"),
8852 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8853
8854 /* Bad block has indirect block that conflicts with filesystem block */
8855 { PR_1_BB_FS_BLOCK,
8856 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8857 "@f metadata. "),
8858 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8859
8860 /* Resize inode failed */
8861 { PR_1_RESIZE_INODE_CREATE,
8862 N_("Resize @i (re)creation failed: %m."),
8863 PROMPT_ABORT, 0 },
8864
8865 /* invalid inode->i_extra_isize */
8866 { PR_1_EXTRA_ISIZE,
8867 N_("@i %i has a extra size (%IS) which is @n\n"),
8868 PROMPT_FIX, PR_PREEN_OK },
8869
8870 /* invalid ea entry->e_name_len */
8871 { PR_1_ATTR_NAME_LEN,
8872 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8873 PROMPT_CLEAR, PR_PREEN_OK },
8874
8875 /* invalid ea entry->e_value_size */
8876 { PR_1_ATTR_VALUE_SIZE,
8877 N_("@a in @i %i has a value size (%N) which is @n\n"),
8878 PROMPT_CLEAR, PR_PREEN_OK },
8879
8880 /* invalid ea entry->e_value_offs */
8881 { PR_1_ATTR_VALUE_OFFSET,
8882 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8883 PROMPT_CLEAR, PR_PREEN_OK },
8884
8885 /* invalid ea entry->e_value_block */
8886 { PR_1_ATTR_VALUE_BLOCK,
8887 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8888 PROMPT_CLEAR, PR_PREEN_OK },
8889
8890 /* invalid ea entry->e_hash */
8891 { PR_1_ATTR_HASH,
8892 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8893 PROMPT_CLEAR, PR_PREEN_OK },
8894
8895 /* Pass 1b errors */
8896
8897 /* Pass 1B: Rescan for duplicate/bad blocks */
8898 { PR_1B_PASS_HEADER,
8899 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8900 "Pass 1B: Rescanning for @m @bs\n"),
8901 PROMPT_NONE, 0 },
8902
8903 /* Duplicate/bad block(s) header */
8904 { PR_1B_DUP_BLOCK_HEADER,
8905 N_("@m @b(s) in @i %i:"),
8906 PROMPT_NONE, 0 },
8907
8908 /* Duplicate/bad block(s) in inode */
8909 { PR_1B_DUP_BLOCK,
8910 " %b",
8911 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8912
8913 /* Duplicate/bad block(s) end */
8914 { PR_1B_DUP_BLOCK_END,
8915 "\n",
8916 PROMPT_NONE, PR_PREEN_NOHDR },
8917
8918 /* Error while scanning inodes */
8919 { PR_1B_ISCAN_ERROR,
8920 N_("Error while scanning inodes (%i): %m\n"),
8921 PROMPT_NONE, PR_FATAL },
8922
8923 /* Error allocating inode bitmap */
8924 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8925 N_("@A @i @B (@i_dup_map): %m\n"),
8926 PROMPT_NONE, PR_FATAL },
8927
8928 /* Error while iterating over blocks */
8929 { PR_1B_BLOCK_ITERATE,
8930 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8931 PROMPT_NONE, 0 },
8932
8933 /* Error adjusting EA refcount */
8934 { PR_1B_ADJ_EA_REFCOUNT,
8935 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8936 PROMPT_NONE, 0 },
8937
8938
8939 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8940 { PR_1C_PASS_HEADER,
8941 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8942 PROMPT_NONE, 0 },
8943
8944
8945 /* Pass 1D: Reconciling multiply-claimed blocks */
8946 { PR_1D_PASS_HEADER,
8947 N_("Pass 1D: Reconciling @m @bs\n"),
8948 PROMPT_NONE, 0 },
8949
8950 /* File has duplicate blocks */
8951 { PR_1D_DUP_FILE,
8952 N_("File %Q (@i #%i, mod time %IM)\n"
8953 " has %B @m @b(s), shared with %N file(s):\n"),
8954 PROMPT_NONE, 0 },
8955
8956 /* List of files sharing duplicate blocks */
8957 { PR_1D_DUP_FILE_LIST,
8958 N_("\t%Q (@i #%i, mod time %IM)\n"),
8959 PROMPT_NONE, 0 },
8960
8961 /* File sharing blocks with filesystem metadata */
8962 { PR_1D_SHARE_METADATA,
8963 N_("\t<@f metadata>\n"),
8964 PROMPT_NONE, 0 },
8965
8966 /* Report of how many duplicate/bad inodes */
8967 { PR_1D_NUM_DUP_INODES,
8968 N_("(There are %N @is containing @m @bs.)\n\n"),
8969 PROMPT_NONE, 0 },
8970
8971 /* Duplicated blocks already reassigned or cloned. */
8972 { PR_1D_DUP_BLOCKS_DEALT,
8973 N_("@m @bs already reassigned or cloned.\n\n"),
8974 PROMPT_NONE, 0 },
8975
8976 /* Clone duplicate/bad blocks? */
8977 { PR_1D_CLONE_QUESTION,
8978 "", PROMPT_CLONE, PR_NO_OK },
8979
8980 /* Delete file? */
8981 { PR_1D_DELETE_QUESTION,
8982 "", PROMPT_DELETE, 0 },
8983
8984 /* Couldn't clone file (error) */
8985 { PR_1D_CLONE_ERROR,
8986 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8987
8988 /* Pass 2 errors */
8989
8990 /* Pass 2: Checking directory structure */
8991 { PR_2_PASS_HEADER,
8992 N_("Pass 2: Checking @d structure\n"),
8993 PROMPT_NONE, 0 },
8994
8995 /* Bad inode number for '.' */
8996 { PR_2_BAD_INODE_DOT,
8997 N_("@n @i number for '.' in @d @i %i.\n"),
8998 PROMPT_FIX, 0 },
8999
9000 /* Directory entry has bad inode number */
9001 { PR_2_BAD_INO,
9002 N_("@E has @n @i #: %Di.\n"),
9003 PROMPT_CLEAR, 0 },
9004
9005 /* Directory entry has deleted or unused inode */
9006 { PR_2_UNUSED_INODE,
9007 N_("@E has @D/unused @i %Di. "),
9008 PROMPT_CLEAR, PR_PREEN_OK },
9009
9010 /* Directry entry is link to '.' */
9011 { PR_2_LINK_DOT,
9012 N_("@E @L to '.' "),
9013 PROMPT_CLEAR, 0 },
9014
9015 /* Directory entry points to inode now located in a bad block */
9016 { PR_2_BB_INODE,
9017 N_("@E points to @i (%Di) located in a bad @b.\n"),
9018 PROMPT_CLEAR, 0 },
9019
9020 /* Directory entry contains a link to a directory */
9021 { PR_2_LINK_DIR,
9022 N_("@E @L to @d %P (%Di).\n"),
9023 PROMPT_CLEAR, 0 },
9024
9025 /* Directory entry contains a link to the root directry */
9026 { PR_2_LINK_ROOT,
9027 N_("@E @L to the @r.\n"),
9028 PROMPT_CLEAR, 0 },
9029
9030 /* Directory entry has illegal characters in its name */
9031 { PR_2_BAD_NAME,
9032 N_("@E has illegal characters in its name.\n"),
9033 PROMPT_FIX, 0 },
9034
9035 /* Missing '.' in directory inode */
9036 { PR_2_MISSING_DOT,
9037 N_("Missing '.' in @d @i %i.\n"),
9038 PROMPT_FIX, 0 },
9039
9040 /* Missing '..' in directory inode */
9041 { PR_2_MISSING_DOT_DOT,
9042 N_("Missing '..' in @d @i %i.\n"),
9043 PROMPT_FIX, 0 },
9044
9045 /* First entry in directory inode doesn't contain '.' */
9046 { PR_2_1ST_NOT_DOT,
9047 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9048 PROMPT_FIX, 0 },
9049
9050 /* Second entry in directory inode doesn't contain '..' */
9051 { PR_2_2ND_NOT_DOT_DOT,
9052 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9053 PROMPT_FIX, 0 },
9054
9055 /* i_faddr should be zero */
9056 { PR_2_FADDR_ZERO,
9057 N_("i_faddr @F %IF, @s zero.\n"),
9058 PROMPT_CLEAR, 0 },
9059
9060 /* i_file_acl should be zero */
9061 { PR_2_FILE_ACL_ZERO,
9062 N_("i_file_acl @F %If, @s zero.\n"),
9063 PROMPT_CLEAR, 0 },
9064
9065 /* i_dir_acl should be zero */
9066 { PR_2_DIR_ACL_ZERO,
9067 N_("i_dir_acl @F %Id, @s zero.\n"),
9068 PROMPT_CLEAR, 0 },
9069
9070 /* i_frag should be zero */
9071 { PR_2_FRAG_ZERO,
9072 N_("i_frag @F %N, @s zero.\n"),
9073 PROMPT_CLEAR, 0 },
9074
9075 /* i_fsize should be zero */
9076 { PR_2_FSIZE_ZERO,
9077 N_("i_fsize @F %N, @s zero.\n"),
9078 PROMPT_CLEAR, 0 },
9079
9080 /* inode has bad mode */
9081 { PR_2_BAD_MODE,
9082 N_("@i %i (%Q) has @n mode (%Im).\n"),
9083 PROMPT_CLEAR, 0 },
9084
9085 /* directory corrupted */
9086 { PR_2_DIR_CORRUPTED,
9087 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9088 PROMPT_SALVAGE, 0 },
9089
9090 /* filename too long */
9091 { PR_2_FILENAME_LONG,
9092 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9093 PROMPT_TRUNCATE, 0 },
9094
9095 /* Directory inode has a missing block (hole) */
9096 { PR_2_DIRECTORY_HOLE,
9097 N_("@d @i %i has an unallocated @b #%B. "),
9098 PROMPT_ALLOCATE, 0 },
9099
9100 /* '.' is not NULL terminated */
9101 { PR_2_DOT_NULL_TERM,
9102 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9103 PROMPT_FIX, 0 },
9104
9105 /* '..' is not NULL terminated */
9106 { PR_2_DOT_DOT_NULL_TERM,
9107 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9108 PROMPT_FIX, 0 },
9109
9110 /* Illegal character device inode */
9111 { PR_2_BAD_CHAR_DEV,
9112 N_("@i %i (%Q) is an @I character @v.\n"),
9113 PROMPT_CLEAR, 0 },
9114
9115 /* Illegal block device inode */
9116 { PR_2_BAD_BLOCK_DEV,
9117 N_("@i %i (%Q) is an @I @b @v.\n"),
9118 PROMPT_CLEAR, 0 },
9119
9120 /* Duplicate '.' entry */
9121 { PR_2_DUP_DOT,
9122 N_("@E is duplicate '.' @e.\n"),
9123 PROMPT_FIX, 0 },
9124
9125 /* Duplicate '..' entry */
9126 { PR_2_DUP_DOT_DOT,
9127 N_("@E is duplicate '..' @e.\n"),
9128 PROMPT_FIX, 0 },
9129
9130 /* Internal error: couldn't find dir_info */
9131 { PR_2_NO_DIRINFO,
9132 N_("Internal error: cannot find dir_info for %i.\n"),
9133 PROMPT_NONE, PR_FATAL },
9134
9135 /* Final rec_len is wrong */
9136 { PR_2_FINAL_RECLEN,
9137 N_("@E has rec_len of %Dr, @s %N.\n"),
9138 PROMPT_FIX, 0 },
9139
9140 /* Error allocating icount structure */
9141 { PR_2_ALLOCATE_ICOUNT,
9142 N_("@A icount structure: %m\n"),
9143 PROMPT_NONE, PR_FATAL },
9144
9145 /* Error iterating over directory blocks */
9146 { PR_2_DBLIST_ITERATE,
9147 N_("Error iterating over @d @bs: %m\n"),
9148 PROMPT_NONE, PR_FATAL },
9149
9150 /* Error reading directory block */
9151 { PR_2_READ_DIRBLOCK,
9152 N_("Error reading @d @b %b (@i %i): %m\n"),
9153 PROMPT_CONTINUE, 0 },
9154
9155 /* Error writing directory block */
9156 { PR_2_WRITE_DIRBLOCK,
9157 N_("Error writing @d @b %b (@i %i): %m\n"),
9158 PROMPT_CONTINUE, 0 },
9159
9160 /* Error allocating new directory block */
9161 { PR_2_ALLOC_DIRBOCK,
9162 N_("@A new @d @b for @i %i (%s): %m\n"),
9163 PROMPT_NONE, 0 },
9164
9165 /* Error deallocating inode */
9166 { PR_2_DEALLOC_INODE,
9167 N_("Error deallocating @i %i: %m\n"),
9168 PROMPT_NONE, PR_FATAL },
9169
9170 /* Directory entry for '.' is big. Split? */
9171 { PR_2_SPLIT_DOT,
9172 N_("@d @e for '.' is big. "),
9173 PROMPT_SPLIT, PR_NO_OK },
9174
9175 /* Illegal FIFO inode */
9176 { PR_2_BAD_FIFO,
9177 N_("@i %i (%Q) is an @I FIFO.\n"),
9178 PROMPT_CLEAR, 0 },
9179
9180 /* Illegal socket inode */
9181 { PR_2_BAD_SOCKET,
9182 N_("@i %i (%Q) is an @I socket.\n"),
9183 PROMPT_CLEAR, 0 },
9184
9185 /* Directory filetype not set */
9186 { PR_2_SET_FILETYPE,
9187 N_("Setting filetype for @E to %N.\n"),
9188 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9189
9190 /* Directory filetype incorrect */
9191 { PR_2_BAD_FILETYPE,
9192 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9193 PROMPT_FIX, 0 },
9194
9195 /* Directory filetype set on filesystem */
9196 { PR_2_CLEAR_FILETYPE,
9197 N_("@E has filetype set.\n"),
9198 PROMPT_CLEAR, PR_PREEN_OK },
9199
9200 /* Directory filename is null */
9201 { PR_2_NULL_NAME,
9202 N_("@E has a @z name.\n"),
9203 PROMPT_CLEAR, 0 },
9204
9205 /* Invalid symlink */
9206 { PR_2_INVALID_SYMLINK,
9207 N_("Symlink %Q (@i #%i) is @n.\n"),
9208 PROMPT_CLEAR, 0 },
9209
9210 /* i_file_acl (extended attribute block) is bad */
9211 { PR_2_FILE_ACL_BAD,
9212 N_("@a @b @F @n (%If).\n"),
9213 PROMPT_CLEAR, 0 },
9214
9215 /* Filesystem contains large files, but has no such flag in sb */
9216 { PR_2_FEATURE_LARGE_FILES,
9217 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9218 PROMPT_FIX, 0 },
9219
9220 /* Node in HTREE directory not referenced */
9221 { PR_2_HTREE_NOTREF,
9222 N_("@p @h %d: node (%B) not referenced\n"),
9223 PROMPT_NONE, 0 },
9224
9225 /* Node in HTREE directory referenced twice */
9226 { PR_2_HTREE_DUPREF,
9227 N_("@p @h %d: node (%B) referenced twice\n"),
9228 PROMPT_NONE, 0 },
9229
9230 /* Node in HTREE directory has bad min hash */
9231 { PR_2_HTREE_MIN_HASH,
9232 N_("@p @h %d: node (%B) has bad min hash\n"),
9233 PROMPT_NONE, 0 },
9234
9235 /* Node in HTREE directory has bad max hash */
9236 { PR_2_HTREE_MAX_HASH,
9237 N_("@p @h %d: node (%B) has bad max hash\n"),
9238 PROMPT_NONE, 0 },
9239
9240 /* Clear invalid HTREE directory */
9241 { PR_2_HTREE_CLEAR,
9242 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9243
9244 /* Bad block in htree interior node */
9245 { PR_2_HTREE_BADBLK,
9246 N_("@p @h %d (%q): bad @b number %b.\n"),
9247 PROMPT_CLEAR_HTREE, 0 },
9248
9249 /* Error adjusting EA refcount */
9250 { PR_2_ADJ_EA_REFCOUNT,
9251 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9252 PROMPT_NONE, PR_FATAL },
9253
9254 /* Invalid HTREE root node */
9255 { PR_2_HTREE_BAD_ROOT,
9256 N_("@p @h %d: root node is @n\n"),
9257 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9258
9259 /* Invalid HTREE limit */
9260 { PR_2_HTREE_BAD_LIMIT,
9261 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9262 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9263
9264 /* Invalid HTREE count */
9265 { PR_2_HTREE_BAD_COUNT,
9266 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9267 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9268
9269 /* HTREE interior node has out-of-order hashes in table */
9270 { PR_2_HTREE_HASH_ORDER,
9271 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9272 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9273
9274 /* Node in HTREE directory has invalid depth */
9275 { PR_2_HTREE_BAD_DEPTH,
9276 N_("@p @h %d: node (%B) has @n depth\n"),
9277 PROMPT_NONE, 0 },
9278
9279 /* Duplicate directory entry found */
9280 { PR_2_DUPLICATE_DIRENT,
9281 N_("Duplicate @E found. "),
9282 PROMPT_CLEAR, 0 },
9283
9284 /* Non-unique filename found */
9285 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9286 N_("@E has a non-unique filename.\nRename to %s"),
9287 PROMPT_NULL, 0 },
9288
9289 /* Duplicate directory entry found */
9290 { PR_2_REPORT_DUP_DIRENT,
9291 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9292 PROMPT_NONE, 0 },
9293
9294 /* Pass 3 errors */
9295
9296 /* Pass 3: Checking directory connectivity */
9297 { PR_3_PASS_HEADER,
9298 N_("Pass 3: Checking @d connectivity\n"),
9299 PROMPT_NONE, 0 },
9300
9301 /* Root inode not allocated */
9302 { PR_3_NO_ROOT_INODE,
9303 N_("@r not allocated. "),
9304 PROMPT_ALLOCATE, 0 },
9305
9306 /* No room in lost+found */
9307 { PR_3_EXPAND_LF_DIR,
9308 N_("No room in @l @d. "),
9309 PROMPT_EXPAND, 0 },
9310
9311 /* Unconnected directory inode */
9312 { PR_3_UNCONNECTED_DIR,
9313 N_("Unconnected @d @i %i (%p)\n"),
9314 PROMPT_CONNECT, 0 },
9315
9316 /* /lost+found not found */
9317 { PR_3_NO_LF_DIR,
9318 N_("/@l not found. "),
9319 PROMPT_CREATE, PR_PREEN_OK },
9320
9321 /* .. entry is incorrect */
9322 { PR_3_BAD_DOT_DOT,
9323 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9324 PROMPT_FIX, 0 },
9325
9326 /* Bad or non-existent /lost+found. Cannot reconnect */
9327 { PR_3_NO_LPF,
9328 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9329 PROMPT_NONE, 0 },
9330
9331 /* Could not expand /lost+found */
9332 { PR_3_CANT_EXPAND_LPF,
9333 N_("Could not expand /@l: %m\n"),
9334 PROMPT_NONE, 0 },
9335
9336 /* Could not reconnect inode */
9337 { PR_3_CANT_RECONNECT,
9338 N_("Could not reconnect %i: %m\n"),
9339 PROMPT_NONE, 0 },
9340
9341 /* Error while trying to find /lost+found */
9342 { PR_3_ERR_FIND_LPF,
9343 N_("Error while trying to find /@l: %m\n"),
9344 PROMPT_NONE, 0 },
9345
9346 /* Error in ext2fs_new_block while creating /lost+found */
9347 { PR_3_ERR_LPF_NEW_BLOCK,
9348 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9349 PROMPT_NONE, 0 },
9350
9351 /* Error in ext2fs_new_inode while creating /lost+found */
9352 { PR_3_ERR_LPF_NEW_INODE,
9353 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9354 PROMPT_NONE, 0 },
9355
9356 /* Error in ext2fs_new_dir_block while creating /lost+found */
9357 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9358 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9359 PROMPT_NONE, 0 },
9360
9361 /* Error while writing directory block for /lost+found */
9362 { PR_3_ERR_LPF_WRITE_BLOCK,
9363 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9364 PROMPT_NONE, 0 },
9365
9366 /* Error while adjusting inode count */
9367 { PR_3_ADJUST_INODE,
9368 N_("Error while adjusting @i count on @i %i\n"),
9369 PROMPT_NONE, 0 },
9370
9371 /* Couldn't fix parent directory -- error */
9372 { PR_3_FIX_PARENT_ERR,
9373 N_("Couldn't fix parent of @i %i: %m\n\n"),
9374 PROMPT_NONE, 0 },
9375
9376 /* Couldn't fix parent directory -- couldn't find it */
9377 { PR_3_FIX_PARENT_NOFIND,
9378 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9379 PROMPT_NONE, 0 },
9380
9381 /* Error allocating inode bitmap */
9382 { PR_3_ALLOCATE_IBITMAP_ERROR,
9383 N_("@A @i @B (%N): %m\n"),
9384 PROMPT_NONE, PR_FATAL },
9385
9386 /* Error creating root directory */
9387 { PR_3_CREATE_ROOT_ERROR,
9388 N_("Error creating root @d (%s): %m\n"),
9389 PROMPT_NONE, PR_FATAL },
9390
9391 /* Error creating lost and found directory */
9392 { PR_3_CREATE_LPF_ERROR,
9393 N_("Error creating /@l @d (%s): %m\n"),
9394 PROMPT_NONE, PR_FATAL },
9395
9396 /* Root inode is not directory; aborting */
9397 { PR_3_ROOT_NOT_DIR_ABORT,
9398 N_("@r is not a @d; aborting.\n"),
9399 PROMPT_NONE, PR_FATAL },
9400
9401 /* Cannot proceed without a root inode. */
9402 { PR_3_NO_ROOT_INODE_ABORT,
Denys Vlasenko6331cf02009-11-13 09:08:27 +01009403 N_("can't proceed without a @r.\n"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009404 PROMPT_NONE, PR_FATAL },
9405
9406 /* Internal error: couldn't find dir_info */
9407 { PR_3_NO_DIRINFO,
9408 N_("Internal error: cannot find dir_info for %i.\n"),
9409 PROMPT_NONE, PR_FATAL },
9410
9411 /* Lost+found not a directory */
9412 { PR_3_LPF_NOTDIR,
9413 N_("/@l is not a @d (ino=%i)\n"),
9414 PROMPT_UNLINK, 0 },
9415
9416 /* Pass 3A Directory Optimization */
9417
9418 /* Pass 3A: Optimizing directories */
9419 { PR_3A_PASS_HEADER,
9420 N_("Pass 3A: Optimizing directories\n"),
9421 PROMPT_NONE, PR_PREEN_NOMSG },
9422
9423 /* Error iterating over directories */
9424 { PR_3A_OPTIMIZE_ITER,
9425 N_("Failed to create dirs_to_hash iterator: %m"),
9426 PROMPT_NONE, 0 },
9427
9428 /* Error rehash directory */
9429 { PR_3A_OPTIMIZE_DIR_ERR,
9430 N_("Failed to optimize directory %q (%d): %m"),
9431 PROMPT_NONE, 0 },
9432
9433 /* Rehashing dir header */
9434 { PR_3A_OPTIMIZE_DIR_HEADER,
9435 N_("Optimizing directories: "),
9436 PROMPT_NONE, PR_MSG_ONLY },
9437
9438 /* Rehashing directory %d */
9439 { PR_3A_OPTIMIZE_DIR,
9440 " %d",
9441 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9442
9443 /* Rehashing dir end */
9444 { PR_3A_OPTIMIZE_DIR_END,
9445 "\n",
9446 PROMPT_NONE, PR_PREEN_NOHDR },
9447
9448 /* Pass 4 errors */
9449
9450 /* Pass 4: Checking reference counts */
9451 { PR_4_PASS_HEADER,
9452 N_("Pass 4: Checking reference counts\n"),
9453 PROMPT_NONE, 0 },
9454
9455 /* Unattached zero-length inode */
9456 { PR_4_ZERO_LEN_INODE,
9457 N_("@u @z @i %i. "),
9458 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9459
9460 /* Unattached inode */
9461 { PR_4_UNATTACHED_INODE,
9462 N_("@u @i %i\n"),
9463 PROMPT_CONNECT, 0 },
9464
9465 /* Inode ref count wrong */
9466 { PR_4_BAD_REF_COUNT,
9467 N_("@i %i ref count is %Il, @s %N. "),
9468 PROMPT_FIX, PR_PREEN_OK },
9469
9470 { PR_4_INCONSISTENT_COUNT,
9471 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9472 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9473 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9474 "They @s the same!\n"),
9475 PROMPT_NONE, 0 },
9476
9477 /* Pass 5 errors */
9478
9479 /* Pass 5: Checking group summary information */
9480 { PR_5_PASS_HEADER,
9481 N_("Pass 5: Checking @g summary information\n"),
9482 PROMPT_NONE, 0 },
9483
9484 /* Padding at end of inode bitmap is not set. */
9485 { PR_5_INODE_BMAP_PADDING,
9486 N_("Padding at end of @i @B is not set. "),
9487 PROMPT_FIX, PR_PREEN_OK },
9488
9489 /* Padding at end of block bitmap is not set. */
9490 { PR_5_BLOCK_BMAP_PADDING,
9491 N_("Padding at end of @b @B is not set. "),
9492 PROMPT_FIX, PR_PREEN_OK },
9493
9494 /* Block bitmap differences header */
9495 { PR_5_BLOCK_BITMAP_HEADER,
9496 N_("@b @B differences: "),
9497 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9498
9499 /* Block not used, but marked in bitmap */
9500 { PR_5_BLOCK_UNUSED,
9501 " -%b",
9502 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9503
9504 /* Block used, but not marked used in bitmap */
9505 { PR_5_BLOCK_USED,
9506 " +%b",
9507 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9508
9509 /* Block bitmap differences end */
9510 { PR_5_BLOCK_BITMAP_END,
9511 "\n",
9512 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9513
9514 /* Inode bitmap differences header */
9515 { PR_5_INODE_BITMAP_HEADER,
9516 N_("@i @B differences: "),
9517 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9518
9519 /* Inode not used, but marked in bitmap */
9520 { PR_5_INODE_UNUSED,
9521 " -%i",
9522 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9523
9524 /* Inode used, but not marked used in bitmap */
9525 { PR_5_INODE_USED,
9526 " +%i",
9527 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9528
9529 /* Inode bitmap differences end */
9530 { PR_5_INODE_BITMAP_END,
9531 "\n",
9532 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9533
9534 /* Free inodes count for group wrong */
9535 { PR_5_FREE_INODE_COUNT_GROUP,
9536 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9537 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9538
9539 /* Directories count for group wrong */
9540 { PR_5_FREE_DIR_COUNT_GROUP,
9541 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9542 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9543
9544 /* Free inodes count wrong */
9545 { PR_5_FREE_INODE_COUNT,
9546 N_("Free @is count wrong (%i, counted=%j).\n"),
9547 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9548
9549 /* Free blocks count for group wrong */
9550 { PR_5_FREE_BLOCK_COUNT_GROUP,
9551 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9552 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9553
9554 /* Free blocks count wrong */
9555 { PR_5_FREE_BLOCK_COUNT,
9556 N_("Free @bs count wrong (%b, counted=%c).\n"),
9557 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9558
9559 /* Programming error: bitmap endpoints don't match */
9560 { PR_5_BMAP_ENDPOINTS,
9561 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9562 "match calculated @B endpoints (%i, %j)\n"),
9563 PROMPT_NONE, PR_FATAL },
9564
9565 /* Internal error: fudging end of bitmap */
9566 { PR_5_FUDGE_BITMAP_ERROR,
9567 N_("Internal error: fudging end of bitmap (%N)\n"),
9568 PROMPT_NONE, PR_FATAL },
9569
9570 /* Error copying in replacement inode bitmap */
9571 { PR_5_COPY_IBITMAP_ERROR,
9572 N_("Error copying in replacement @i @B: %m\n"),
9573 PROMPT_NONE, PR_FATAL },
9574
9575 /* Error copying in replacement block bitmap */
9576 { PR_5_COPY_BBITMAP_ERROR,
9577 N_("Error copying in replacement @b @B: %m\n"),
9578 PROMPT_NONE, PR_FATAL },
9579
9580 /* Block range not used, but marked in bitmap */
9581 { PR_5_BLOCK_RANGE_UNUSED,
9582 " -(%b--%c)",
9583 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9584
9585 /* Block range used, but not marked used in bitmap */
9586 { PR_5_BLOCK_RANGE_USED,
9587 " +(%b--%c)",
9588 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9589
9590 /* Inode range not used, but marked in bitmap */
9591 { PR_5_INODE_RANGE_UNUSED,
9592 " -(%i--%j)",
9593 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9594
9595 /* Inode range used, but not marked used in bitmap */
9596 { PR_5_INODE_RANGE_USED,
9597 " +(%i--%j)",
9598 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9599
9600 { 0 }
9601};
9602
9603/*
9604 * This is the latch flags register. It allows several problems to be
9605 * "latched" together. This means that the user has to answer but one
9606 * question for the set of problems, and all of the associated
9607 * problems will be either fixed or not fixed.
9608 */
9609static struct latch_descr pr_latch_info[] = {
9610 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9611 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9612 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9613 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9614 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9615 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9616 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9617 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9618 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9619 { -1, 0, 0 },
9620};
9621
9622static const struct e2fsck_problem *find_problem(problem_t code)
9623{
9624 int i;
9625
9626 for (i=0; problem_table[i].e2p_code; i++) {
9627 if (problem_table[i].e2p_code == code)
9628 return &problem_table[i];
9629 }
9630 return 0;
9631}
9632
9633static struct latch_descr *find_latch(int code)
9634{
9635 int i;
9636
9637 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9638 if (pr_latch_info[i].latch_code == code)
9639 return &pr_latch_info[i];
9640 }
9641 return 0;
9642}
9643
9644int end_problem_latch(e2fsck_t ctx, int mask)
9645{
9646 struct latch_descr *ldesc;
9647 struct problem_context pctx;
9648 int answer = -1;
9649
9650 ldesc = find_latch(mask);
9651 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9652 clear_problem_context(&pctx);
9653 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9654 }
9655 ldesc->flags &= ~(PRL_VARIABLE);
9656 return answer;
9657}
9658
9659int set_latch_flags(int mask, int setflags, int clearflags)
9660{
9661 struct latch_descr *ldesc;
9662
9663 ldesc = find_latch(mask);
9664 if (!ldesc)
9665 return -1;
9666 ldesc->flags |= setflags;
9667 ldesc->flags &= ~clearflags;
9668 return 0;
9669}
9670
9671void clear_problem_context(struct problem_context *ctx)
9672{
9673 memset(ctx, 0, sizeof(struct problem_context));
9674 ctx->blkcount = -1;
9675 ctx->group = -1;
9676}
9677
9678int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9679{
9680 ext2_filsys fs = ctx->fs;
9681 const struct e2fsck_problem *ptr;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01009682 struct latch_descr *ldesc = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009683 const char *message;
9684 int def_yn, answer, ans;
9685 int print_answer = 0;
9686 int suppress = 0;
9687
9688 ptr = find_problem(code);
9689 if (!ptr) {
9690 printf(_("Unhandled error code (0x%x)!\n"), code);
9691 return 0;
9692 }
9693 def_yn = 1;
9694 if ((ptr->flags & PR_NO_DEFAULT) ||
9695 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9696 (ctx->options & E2F_OPT_NO))
9697 def_yn= 0;
9698
9699 /*
9700 * Do special latch processing. This is where we ask the
9701 * latch question, if it exists
9702 */
9703 if (ptr->flags & PR_LATCH_MASK) {
9704 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9705 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9706 ans = fix_problem(ctx, ldesc->question, pctx);
9707 if (ans == 1)
9708 ldesc->flags |= PRL_YES;
9709 if (ans == 0)
9710 ldesc->flags |= PRL_NO;
9711 ldesc->flags |= PRL_LATCHED;
9712 }
9713 if (ldesc->flags & PRL_SUPPRESS)
9714 suppress++;
9715 }
9716 if ((ptr->flags & PR_PREEN_NOMSG) &&
9717 (ctx->options & E2F_OPT_PREEN))
9718 suppress++;
9719 if ((ptr->flags & PR_NO_NOMSG) &&
9720 (ctx->options & E2F_OPT_NO))
9721 suppress++;
9722 if (!suppress) {
9723 message = ptr->e2p_description;
9724 if ((ctx->options & E2F_OPT_PREEN) &&
9725 !(ptr->flags & PR_PREEN_NOHDR)) {
9726 printf("%s: ", ctx->device_name ?
9727 ctx->device_name : ctx->filesystem_name);
9728 }
9729 if (*message)
9730 print_e2fsck_message(ctx, _(message), pctx, 1);
9731 }
9732 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9733 preenhalt(ctx);
9734
9735 if (ptr->flags & PR_FATAL)
9736 bb_error_msg_and_die(0);
9737
9738 if (ptr->prompt == PROMPT_NONE) {
9739 if (ptr->flags & PR_NOCOLLATE)
9740 answer = -1;
9741 else
9742 answer = def_yn;
9743 } else {
9744 if (ctx->options & E2F_OPT_PREEN) {
9745 answer = def_yn;
9746 if (!(ptr->flags & PR_PREEN_NOMSG))
9747 print_answer = 1;
9748 } else if ((ptr->flags & PR_LATCH_MASK) &&
9749 (ldesc->flags & (PRL_YES | PRL_NO))) {
9750 if (!suppress)
9751 print_answer = 1;
9752 if (ldesc->flags & PRL_YES)
9753 answer = 1;
9754 else
9755 answer = 0;
9756 } else
9757 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9758 if (!answer && !(ptr->flags & PR_NO_OK))
9759 ext2fs_unmark_valid(fs);
9760
9761 if (print_answer)
9762 printf("%s.\n", answer ?
9763 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009764 }
9765
9766 if ((ptr->prompt == PROMPT_ABORT) && answer)
9767 bb_error_msg_and_die(0);
9768
9769 if (ptr->flags & PR_AFTER_CODE)
9770 answer = fix_problem(ctx, ptr->second_code, pctx);
9771
9772 return answer;
9773}
9774
9775/*
9776 * linux/fs/recovery.c
9777 *
9778 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9779 */
9780
9781/*
9782 * Maintain information about the progress of the recovery job, so that
9783 * the different passes can carry information between them.
9784 */
9785struct recovery_info
9786{
9787 tid_t start_transaction;
9788 tid_t end_transaction;
9789
9790 int nr_replays;
9791 int nr_revokes;
9792 int nr_revoke_hits;
9793};
9794
9795enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9796static int do_one_pass(journal_t *journal,
9797 struct recovery_info *info, enum passtype pass);
9798static int scan_revoke_records(journal_t *, struct buffer_head *,
9799 tid_t, struct recovery_info *);
9800
9801/*
9802 * Read a block from the journal
9803 */
9804
9805static int jread(struct buffer_head **bhp, journal_t *journal,
9806 unsigned int offset)
9807{
9808 int err;
9809 unsigned long blocknr;
9810 struct buffer_head *bh;
9811
9812 *bhp = NULL;
9813
9814 err = journal_bmap(journal, offset, &blocknr);
9815
9816 if (err) {
9817 printf("JBD: bad block at offset %u\n", offset);
9818 return err;
9819 }
9820
9821 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9822 if (!bh)
9823 return -ENOMEM;
9824
9825 if (!buffer_uptodate(bh)) {
9826 /* If this is a brand new buffer, start readahead.
9827 Otherwise, we assume we are already reading it. */
9828 if (!buffer_req(bh))
9829 do_readahead(journal, offset);
9830 wait_on_buffer(bh);
9831 }
9832
9833 if (!buffer_uptodate(bh)) {
9834 printf("JBD: Failed to read block at offset %u\n", offset);
9835 brelse(bh);
9836 return -EIO;
9837 }
9838
9839 *bhp = bh;
9840 return 0;
9841}
9842
9843
9844/*
9845 * Count the number of in-use tags in a journal descriptor block.
9846 */
9847
9848static int count_tags(struct buffer_head *bh, int size)
9849{
9850 char * tagp;
9851 journal_block_tag_t * tag;
9852 int nr = 0;
9853
9854 tagp = &bh->b_data[sizeof(journal_header_t)];
9855
9856 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9857 tag = (journal_block_tag_t *) tagp;
9858
9859 nr++;
9860 tagp += sizeof(journal_block_tag_t);
9861 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9862 tagp += 16;
9863
9864 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9865 break;
9866 }
9867
9868 return nr;
9869}
9870
9871
9872/* Make sure we wrap around the log correctly! */
9873#define wrap(journal, var) \
9874do { \
9875 if (var >= (journal)->j_last) \
9876 var -= ((journal)->j_last - (journal)->j_first); \
9877} while (0)
9878
9879/**
9880 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9881 * @journal: the journal to recover
9882 *
9883 * The primary function for recovering the log contents when mounting a
9884 * journaled device.
9885 *
9886 * Recovery is done in three passes. In the first pass, we look for the
9887 * end of the log. In the second, we assemble the list of revoke
9888 * blocks. In the third and final pass, we replay any un-revoked blocks
9889 * in the log.
9890 */
9891int journal_recover(journal_t *journal)
9892{
9893 int err;
9894 journal_superblock_t * sb;
9895
9896 struct recovery_info info;
9897
9898 memset(&info, 0, sizeof(info));
9899 sb = journal->j_superblock;
9900
9901 /*
9902 * The journal superblock's s_start field (the current log head)
9903 * is always zero if, and only if, the journal was cleanly
9904 * unmounted.
9905 */
9906
9907 if (!sb->s_start) {
9908 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9909 return 0;
9910 }
9911
9912 err = do_one_pass(journal, &info, PASS_SCAN);
9913 if (!err)
9914 err = do_one_pass(journal, &info, PASS_REVOKE);
9915 if (!err)
9916 err = do_one_pass(journal, &info, PASS_REPLAY);
9917
9918 /* Restart the log at the next transaction ID, thus invalidating
9919 * any existing commit records in the log. */
9920 journal->j_transaction_sequence = ++info.end_transaction;
9921
9922 journal_clear_revoke(journal);
9923 sync_blockdev(journal->j_fs_dev);
9924 return err;
9925}
9926
9927static int do_one_pass(journal_t *journal,
9928 struct recovery_info *info, enum passtype pass)
9929{
9930 unsigned int first_commit_ID, next_commit_ID;
9931 unsigned long next_log_block;
9932 int err, success = 0;
9933 journal_superblock_t * sb;
9934 journal_header_t * tmp;
9935 struct buffer_head * bh;
9936 unsigned int sequence;
9937 int blocktype;
9938
9939 /* Precompute the maximum metadata descriptors in a descriptor block */
9940 int MAX_BLOCKS_PER_DESC;
9941 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9942 / sizeof(journal_block_tag_t));
9943
9944 /*
9945 * First thing is to establish what we expect to find in the log
9946 * (in terms of transaction IDs), and where (in terms of log
9947 * block offsets): query the superblock.
9948 */
9949
9950 sb = journal->j_superblock;
9951 next_commit_ID = ntohl(sb->s_sequence);
9952 next_log_block = ntohl(sb->s_start);
9953
9954 first_commit_ID = next_commit_ID;
9955 if (pass == PASS_SCAN)
9956 info->start_transaction = first_commit_ID;
9957
9958 /*
9959 * Now we walk through the log, transaction by transaction,
9960 * making sure that each transaction has a commit block in the
9961 * expected place. Each complete transaction gets replayed back
9962 * into the main filesystem.
9963 */
9964
9965 while (1) {
9966 int flags;
9967 char * tagp;
9968 journal_block_tag_t * tag;
9969 struct buffer_head * obh;
9970 struct buffer_head * nbh;
9971
9972 /* If we already know where to stop the log traversal,
9973 * check right now that we haven't gone past the end of
9974 * the log. */
9975
9976 if (pass != PASS_SCAN)
9977 if (tid_geq(next_commit_ID, info->end_transaction))
9978 break;
9979
9980 /* Skip over each chunk of the transaction looking
9981 * either the next descriptor block or the final commit
9982 * record. */
9983
9984 err = jread(&bh, journal, next_log_block);
9985 if (err)
9986 goto failed;
9987
9988 next_log_block++;
9989 wrap(journal, next_log_block);
9990
9991 /* What kind of buffer is it?
9992 *
9993 * If it is a descriptor block, check that it has the
9994 * expected sequence number. Otherwise, we're all done
9995 * here. */
9996
9997 tmp = (journal_header_t *)bh->b_data;
9998
9999 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10000 brelse(bh);
10001 break;
10002 }
10003
10004 blocktype = ntohl(tmp->h_blocktype);
10005 sequence = ntohl(tmp->h_sequence);
10006
10007 if (sequence != next_commit_ID) {
10008 brelse(bh);
10009 break;
10010 }
10011
10012 /* OK, we have a valid descriptor block which matches
10013 * all of the sequence number checks. What are we going
10014 * to do with it? That depends on the pass... */
10015
Denis Vlasenkobb045062008-09-27 14:06:06 +000010016 switch (blocktype) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010017 case JFS_DESCRIPTOR_BLOCK:
10018 /* If it is a valid descriptor block, replay it
10019 * in pass REPLAY; otherwise, just skip over the
10020 * blocks it describes. */
10021 if (pass != PASS_REPLAY) {
10022 next_log_block +=
10023 count_tags(bh, journal->j_blocksize);
10024 wrap(journal, next_log_block);
10025 brelse(bh);
10026 continue;
10027 }
10028
10029 /* A descriptor block: we can now write all of
10030 * the data blocks. Yay, useful work is finally
10031 * getting done here! */
10032
10033 tagp = &bh->b_data[sizeof(journal_header_t)];
10034 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10035 <= journal->j_blocksize) {
10036 unsigned long io_block;
10037
10038 tag = (journal_block_tag_t *) tagp;
10039 flags = ntohl(tag->t_flags);
10040
10041 io_block = next_log_block++;
10042 wrap(journal, next_log_block);
10043 err = jread(&obh, journal, io_block);
10044 if (err) {
10045 /* Recover what we can, but
10046 * report failure at the end. */
10047 success = err;
10048 printf("JBD: IO error %d recovering "
10049 "block %ld in log\n",
10050 err, io_block);
10051 } else {
10052 unsigned long blocknr;
10053
10054 blocknr = ntohl(tag->t_blocknr);
10055
10056 /* If the block has been
10057 * revoked, then we're all done
10058 * here. */
10059 if (journal_test_revoke
10060 (journal, blocknr,
10061 next_commit_ID)) {
10062 brelse(obh);
10063 ++info->nr_revoke_hits;
10064 goto skip_write;
10065 }
10066
10067 /* Find a buffer for the new
10068 * data being restored */
10069 nbh = getblk(journal->j_fs_dev,
10070 blocknr,
10071 journal->j_blocksize);
10072 if (nbh == NULL) {
10073 printf("JBD: Out of memory "
10074 "during recovery.\n");
10075 err = -ENOMEM;
10076 brelse(bh);
10077 brelse(obh);
10078 goto failed;
10079 }
10080
10081 lock_buffer(nbh);
10082 memcpy(nbh->b_data, obh->b_data,
10083 journal->j_blocksize);
10084 if (flags & JFS_FLAG_ESCAPE) {
10085 *((unsigned int *)bh->b_data) =
10086 htonl(JFS_MAGIC_NUMBER);
10087 }
10088
10089 mark_buffer_uptodate(nbh, 1);
10090 mark_buffer_dirty(nbh);
10091 ++info->nr_replays;
10092 /* ll_rw_block(WRITE, 1, &nbh); */
10093 unlock_buffer(nbh);
10094 brelse(obh);
10095 brelse(nbh);
10096 }
10097
10098 skip_write:
10099 tagp += sizeof(journal_block_tag_t);
10100 if (!(flags & JFS_FLAG_SAME_UUID))
10101 tagp += 16;
10102
10103 if (flags & JFS_FLAG_LAST_TAG)
10104 break;
10105 }
10106
10107 brelse(bh);
10108 continue;
10109
10110 case JFS_COMMIT_BLOCK:
10111 /* Found an expected commit block: not much to
10112 * do other than move on to the next sequence
10113 * number. */
10114 brelse(bh);
10115 next_commit_ID++;
10116 continue;
10117
10118 case JFS_REVOKE_BLOCK:
10119 /* If we aren't in the REVOKE pass, then we can
10120 * just skip over this block. */
10121 if (pass != PASS_REVOKE) {
10122 brelse(bh);
10123 continue;
10124 }
10125
10126 err = scan_revoke_records(journal, bh,
10127 next_commit_ID, info);
10128 brelse(bh);
10129 if (err)
10130 goto failed;
10131 continue;
10132
10133 default:
10134 goto done;
10135 }
10136 }
10137
10138 done:
10139 /*
10140 * We broke out of the log scan loop: either we came to the
10141 * known end of the log or we found an unexpected block in the
10142 * log. If the latter happened, then we know that the "current"
10143 * transaction marks the end of the valid log.
10144 */
10145
10146 if (pass == PASS_SCAN)
10147 info->end_transaction = next_commit_ID;
10148 else {
10149 /* It's really bad news if different passes end up at
10150 * different places (but possible due to IO errors). */
10151 if (info->end_transaction != next_commit_ID) {
10152 printf("JBD: recovery pass %d ended at "
10153 "transaction %u, expected %u\n",
10154 pass, next_commit_ID, info->end_transaction);
10155 if (!success)
10156 success = -EIO;
10157 }
10158 }
10159
10160 return success;
10161
10162 failed:
10163 return err;
10164}
10165
10166
10167/* Scan a revoke record, marking all blocks mentioned as revoked. */
10168
10169static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10170 tid_t sequence, struct recovery_info *info)
10171{
10172 journal_revoke_header_t *header;
10173 int offset, max;
10174
10175 header = (journal_revoke_header_t *) bh->b_data;
10176 offset = sizeof(journal_revoke_header_t);
10177 max = ntohl(header->r_count);
10178
10179 while (offset < max) {
10180 unsigned long blocknr;
10181 int err;
10182
10183 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10184 offset += 4;
10185 err = journal_set_revoke(journal, blocknr, sequence);
10186 if (err)
10187 return err;
10188 ++info->nr_revokes;
10189 }
10190 return 0;
10191}
10192
10193
10194/*
10195 * rehash.c --- rebuild hash tree directories
10196 *
10197 * This algorithm is designed for simplicity of implementation and to
10198 * pack the directory as much as possible. It however requires twice
10199 * as much memory as the size of the directory. The maximum size
10200 * directory supported using a 4k blocksize is roughly a gigabyte, and
10201 * so there may very well be problems with machines that don't have
10202 * virtual memory, and obscenely large directories.
10203 *
10204 * An alternate algorithm which is much more disk intensive could be
10205 * written, and probably will need to be written in the future. The
10206 * design goals of such an algorithm are: (a) use (roughly) constant
10207 * amounts of memory, no matter how large the directory, (b) the
10208 * directory must be safe at all times, even if e2fsck is interrupted
10209 * in the middle, (c) we must use minimal amounts of extra disk
10210 * blocks. This pretty much requires an incremental approach, where
10211 * we are reading from one part of the directory, and inserting into
10212 * the front half. So the algorithm will have to keep track of a
10213 * moving block boundary between the new tree and the old tree, and
10214 * files will need to be moved from the old directory and inserted
10215 * into the new tree. If the new directory requires space which isn't
10216 * yet available, blocks from the beginning part of the old directory
10217 * may need to be moved to the end of the directory to make room for
10218 * the new tree:
10219 *
10220 * --------------------------------------------------------
10221 * | new tree | | old tree |
10222 * --------------------------------------------------------
10223 * ^ ptr ^ptr
10224 * tail new head old
10225 *
10226 * This is going to be a pain in the tuckus to implement, and will
10227 * require a lot more disk accesses. So I'm going to skip it for now;
10228 * it's only really going to be an issue for really, really big
10229 * filesystems (when we reach the level of tens of millions of files
10230 * in a single directory). It will probably be easier to simply
10231 * require that e2fsck use VM first.
10232 */
10233
10234struct fill_dir_struct {
10235 char *buf;
10236 struct ext2_inode *inode;
10237 int err;
10238 e2fsck_t ctx;
10239 struct hash_entry *harray;
10240 int max_array, num_array;
10241 int dir_size;
10242 int compress;
10243 ino_t parent;
10244};
10245
10246struct hash_entry {
10247 ext2_dirhash_t hash;
10248 ext2_dirhash_t minor_hash;
10249 struct ext2_dir_entry *dir;
10250};
10251
10252struct out_dir {
10253 int num;
10254 int max;
10255 char *buf;
10256 ext2_dirhash_t *hashes;
10257};
10258
10259static int fill_dir_block(ext2_filsys fs,
10260 blk_t *block_nr,
10261 e2_blkcnt_t blockcnt,
10262 blk_t ref_block FSCK_ATTR((unused)),
10263 int ref_offset FSCK_ATTR((unused)),
10264 void *priv_data)
10265{
10266 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10267 struct hash_entry *new_array, *ent;
10268 struct ext2_dir_entry *dirent;
10269 char *dir;
10270 unsigned int offset, dir_offset;
10271
10272 if (blockcnt < 0)
10273 return 0;
10274
10275 offset = blockcnt * fs->blocksize;
10276 if (offset + fs->blocksize > fd->inode->i_size) {
10277 fd->err = EXT2_ET_DIR_CORRUPTED;
10278 return BLOCK_ABORT;
10279 }
10280 dir = (fd->buf+offset);
10281 if (HOLE_BLKADDR(*block_nr)) {
10282 memset(dir, 0, fs->blocksize);
10283 dirent = (struct ext2_dir_entry *) dir;
10284 dirent->rec_len = fs->blocksize;
10285 } else {
10286 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10287 if (fd->err)
10288 return BLOCK_ABORT;
10289 }
10290 /* While the directory block is "hot", index it. */
10291 dir_offset = 0;
10292 while (dir_offset < fs->blocksize) {
10293 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10294 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10295 (dirent->rec_len < 8) ||
10296 ((dirent->rec_len % 4) != 0) ||
10297 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10298 fd->err = EXT2_ET_DIR_CORRUPTED;
10299 return BLOCK_ABORT;
10300 }
10301 dir_offset += dirent->rec_len;
10302 if (dirent->inode == 0)
10303 continue;
10304 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10305 (dirent->name[0] == '.'))
10306 continue;
10307 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10308 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10309 fd->parent = dirent->inode;
10310 continue;
10311 }
10312 if (fd->num_array >= fd->max_array) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010313 new_array = xrealloc(fd->harray,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010314 sizeof(struct hash_entry) * (fd->max_array+500));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010315 fd->harray = new_array;
10316 fd->max_array += 500;
10317 }
10318 ent = fd->harray + fd->num_array++;
10319 ent->dir = dirent;
10320 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10321 if (fd->compress)
10322 ent->hash = ent->minor_hash = 0;
10323 else {
10324 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10325 dirent->name,
10326 dirent->name_len & 0xFF,
10327 fs->super->s_hash_seed,
10328 &ent->hash, &ent->minor_hash);
10329 if (fd->err)
10330 return BLOCK_ABORT;
10331 }
10332 }
10333
10334 return 0;
10335}
10336
10337/* Used for sorting the hash entry */
10338static int name_cmp(const void *a, const void *b)
10339{
10340 const struct hash_entry *he_a = (const struct hash_entry *) a;
10341 const struct hash_entry *he_b = (const struct hash_entry *) b;
10342 int ret;
10343 int min_len;
10344
10345 min_len = he_a->dir->name_len;
10346 if (min_len > he_b->dir->name_len)
10347 min_len = he_b->dir->name_len;
10348
10349 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10350 if (ret == 0) {
10351 if (he_a->dir->name_len > he_b->dir->name_len)
10352 ret = 1;
10353 else if (he_a->dir->name_len < he_b->dir->name_len)
10354 ret = -1;
10355 else
10356 ret = he_b->dir->inode - he_a->dir->inode;
10357 }
10358 return ret;
10359}
10360
10361/* Used for sorting the hash entry */
10362static int hash_cmp(const void *a, const void *b)
10363{
10364 const struct hash_entry *he_a = (const struct hash_entry *) a;
10365 const struct hash_entry *he_b = (const struct hash_entry *) b;
10366 int ret;
10367
10368 if (he_a->hash > he_b->hash)
10369 ret = 1;
10370 else if (he_a->hash < he_b->hash)
10371 ret = -1;
10372 else {
10373 if (he_a->minor_hash > he_b->minor_hash)
10374 ret = 1;
10375 else if (he_a->minor_hash < he_b->minor_hash)
10376 ret = -1;
10377 else
10378 ret = name_cmp(a, b);
10379 }
10380 return ret;
10381}
10382
10383static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10384 int blocks)
10385{
10386 void *new_mem;
10387
10388 if (outdir->max) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010389 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010390 outdir->buf = new_mem;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010391 new_mem = xrealloc(outdir->hashes,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010392 blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010393 outdir->hashes = new_mem;
10394 } else {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010395 outdir->buf = xmalloc(blocks * fs->blocksize);
10396 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010397 outdir->num = 0;
10398 }
10399 outdir->max = blocks;
10400 return 0;
10401}
10402
10403static void free_out_dir(struct out_dir *outdir)
10404{
10405 free(outdir->buf);
10406 free(outdir->hashes);
10407 outdir->max = 0;
10408 outdir->num =0;
10409}
10410
10411static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10412 char ** ret)
10413{
10414 errcode_t retval;
10415
10416 if (outdir->num >= outdir->max) {
10417 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10418 if (retval)
10419 return retval;
10420 }
10421 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10422 memset(*ret, 0, fs->blocksize);
10423 return 0;
10424}
10425
10426/*
10427 * This function is used to make a unique filename. We do this by
10428 * appending ~0, and then incrementing the number. However, we cannot
10429 * expand the length of the filename beyond the padding available in
10430 * the directory entry.
10431 */
10432static void mutate_name(char *str, __u16 *len)
10433{
10434 int i;
10435 __u16 l = *len & 0xFF, h = *len & 0xff00;
10436
10437 /*
10438 * First check to see if it looks the name has been mutated
10439 * already
10440 */
10441 for (i = l-1; i > 0; i--) {
10442 if (!isdigit(str[i]))
10443 break;
10444 }
10445 if ((i == l-1) || (str[i] != '~')) {
10446 if (((l-1) & 3) < 2)
10447 l += 2;
10448 else
10449 l = (l+3) & ~3;
10450 str[l-2] = '~';
10451 str[l-1] = '0';
10452 *len = l | h;
10453 return;
10454 }
10455 for (i = l-1; i >= 0; i--) {
10456 if (isdigit(str[i])) {
10457 if (str[i] == '9')
10458 str[i] = '0';
10459 else {
10460 str[i]++;
10461 return;
10462 }
10463 continue;
10464 }
10465 if (i == 1) {
10466 if (str[0] == 'z')
10467 str[0] = 'A';
10468 else if (str[0] == 'Z') {
10469 str[0] = '~';
10470 str[1] = '0';
10471 } else
10472 str[0]++;
10473 } else if (i > 0) {
10474 str[i] = '1';
10475 str[i-1] = '~';
10476 } else {
10477 if (str[0] == '~')
10478 str[0] = 'a';
10479 else
10480 str[0]++;
10481 }
10482 break;
10483 }
10484}
10485
10486static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10487 ext2_ino_t ino,
10488 struct fill_dir_struct *fd)
10489{
10490 struct problem_context pctx;
10491 struct hash_entry *ent, *prev;
10492 int i, j;
10493 int fixed = 0;
10494 char new_name[256];
10495 __u16 new_len;
10496
10497 clear_problem_context(&pctx);
10498 pctx.ino = ino;
10499
10500 for (i=1; i < fd->num_array; i++) {
10501 ent = fd->harray + i;
10502 prev = ent - 1;
10503 if (!ent->dir->inode ||
10504 ((ent->dir->name_len & 0xFF) !=
10505 (prev->dir->name_len & 0xFF)) ||
10506 (strncmp(ent->dir->name, prev->dir->name,
10507 ent->dir->name_len & 0xFF)))
10508 continue;
10509 pctx.dirent = ent->dir;
10510 if ((ent->dir->inode == prev->dir->inode) &&
10511 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10512 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10513 ent->dir->inode = 0;
10514 fixed++;
10515 continue;
10516 }
10517 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10518 new_len = ent->dir->name_len;
10519 mutate_name(new_name, &new_len);
10520 for (j=0; j < fd->num_array; j++) {
10521 if ((i==j) ||
10522 ((ent->dir->name_len & 0xFF) !=
10523 (fd->harray[j].dir->name_len & 0xFF)) ||
10524 (strncmp(new_name, fd->harray[j].dir->name,
10525 new_len & 0xFF)))
10526 continue;
10527 mutate_name(new_name, &new_len);
10528
10529 j = -1;
10530 }
10531 new_name[new_len & 0xFF] = 0;
10532 pctx.str = new_name;
10533 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10534 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10535 ent->dir->name_len = new_len;
10536 ext2fs_dirhash(fs->super->s_def_hash_version,
10537 ent->dir->name,
10538 ent->dir->name_len & 0xFF,
10539 fs->super->s_hash_seed,
10540 &ent->hash, &ent->minor_hash);
10541 fixed++;
10542 }
10543 }
10544 return fixed;
10545}
10546
10547
10548static errcode_t copy_dir_entries(ext2_filsys fs,
10549 struct fill_dir_struct *fd,
10550 struct out_dir *outdir)
10551{
10552 errcode_t retval;
10553 char *block_start;
10554 struct hash_entry *ent;
10555 struct ext2_dir_entry *dirent;
10556 int i, rec_len, left;
10557 ext2_dirhash_t prev_hash;
10558 int offset;
10559
10560 outdir->max = 0;
10561 retval = alloc_size_dir(fs, outdir,
10562 (fd->dir_size / fs->blocksize) + 2);
10563 if (retval)
10564 return retval;
10565 outdir->num = fd->compress ? 0 : 1;
10566 offset = 0;
10567 outdir->hashes[0] = 0;
10568 prev_hash = 1;
10569 if ((retval = get_next_block(fs, outdir, &block_start)))
10570 return retval;
10571 dirent = (struct ext2_dir_entry *) block_start;
10572 left = fs->blocksize;
10573 for (i=0; i < fd->num_array; i++) {
10574 ent = fd->harray + i;
10575 if (ent->dir->inode == 0)
10576 continue;
10577 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10578 if (rec_len > left) {
10579 if (left)
10580 dirent->rec_len += left;
10581 if ((retval = get_next_block(fs, outdir,
10582 &block_start)))
10583 return retval;
10584 offset = 0;
10585 }
10586 left = fs->blocksize - offset;
10587 dirent = (struct ext2_dir_entry *) (block_start + offset);
10588 if (offset == 0) {
10589 if (ent->hash == prev_hash)
10590 outdir->hashes[outdir->num-1] = ent->hash | 1;
10591 else
10592 outdir->hashes[outdir->num-1] = ent->hash;
10593 }
10594 dirent->inode = ent->dir->inode;
10595 dirent->name_len = ent->dir->name_len;
10596 dirent->rec_len = rec_len;
10597 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10598 offset += rec_len;
10599 left -= rec_len;
10600 if (left < 12) {
10601 dirent->rec_len += left;
10602 offset += left;
10603 left = 0;
10604 }
10605 prev_hash = ent->hash;
10606 }
10607 if (left)
10608 dirent->rec_len += left;
10609
10610 return 0;
10611}
10612
10613
10614static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10615 ext2_ino_t ino, ext2_ino_t parent)
10616{
10617 struct ext2_dir_entry *dir;
10618 struct ext2_dx_root_info *root;
10619 struct ext2_dx_countlimit *limits;
10620 int filetype = 0;
10621
10622 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10623 filetype = EXT2_FT_DIR << 8;
10624
10625 memset(buf, 0, fs->blocksize);
10626 dir = (struct ext2_dir_entry *) buf;
10627 dir->inode = ino;
10628 dir->name[0] = '.';
10629 dir->name_len = 1 | filetype;
10630 dir->rec_len = 12;
10631 dir = (struct ext2_dir_entry *) (buf + 12);
10632 dir->inode = parent;
10633 dir->name[0] = '.';
10634 dir->name[1] = '.';
10635 dir->name_len = 2 | filetype;
10636 dir->rec_len = fs->blocksize - 12;
10637
10638 root = (struct ext2_dx_root_info *) (buf+24);
10639 root->reserved_zero = 0;
10640 root->hash_version = fs->super->s_def_hash_version;
10641 root->info_length = 8;
10642 root->indirect_levels = 0;
10643 root->unused_flags = 0;
10644
10645 limits = (struct ext2_dx_countlimit *) (buf+32);
10646 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10647 limits->count = 0;
10648
10649 return root;
10650}
10651
10652
10653static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10654{
10655 struct ext2_dir_entry *dir;
10656 struct ext2_dx_countlimit *limits;
10657
10658 memset(buf, 0, fs->blocksize);
10659 dir = (struct ext2_dir_entry *) buf;
10660 dir->inode = 0;
10661 dir->rec_len = fs->blocksize;
10662
10663 limits = (struct ext2_dx_countlimit *) (buf+8);
10664 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10665 limits->count = 0;
10666
10667 return (struct ext2_dx_entry *) limits;
10668}
10669
10670/*
10671 * This function takes the leaf nodes which have been written in
10672 * outdir, and populates the root node and any necessary interior nodes.
10673 */
10674static errcode_t calculate_tree(ext2_filsys fs,
10675 struct out_dir *outdir,
10676 ext2_ino_t ino,
10677 ext2_ino_t parent)
10678{
10679 struct ext2_dx_root_info *root_info;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010680 struct ext2_dx_entry *root, *dx_ent = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010681 struct ext2_dx_countlimit *root_limit, *limit;
10682 errcode_t retval;
10683 char * block_start;
10684 int i, c1, c2, nblks;
10685 int limit_offset, root_offset;
10686
10687 root_info = set_root_node(fs, outdir->buf, ino, parent);
10688 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10689 root_info->info_length;
10690 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10691 c1 = root_limit->limit;
10692 nblks = outdir->num;
10693
10694 /* Write out the pointer blocks */
10695 if (nblks-1 <= c1) {
10696 /* Just write out the root block, and we're done */
10697 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10698 for (i=1; i < nblks; i++) {
10699 root->block = ext2fs_cpu_to_le32(i);
10700 if (i != 1)
10701 root->hash =
10702 ext2fs_cpu_to_le32(outdir->hashes[i]);
10703 root++;
10704 c1--;
10705 }
10706 } else {
10707 c2 = 0;
10708 limit = 0;
10709 root_info->indirect_levels = 1;
10710 for (i=1; i < nblks; i++) {
10711 if (c1 == 0)
10712 return ENOSPC;
10713 if (c2 == 0) {
10714 if (limit)
10715 limit->limit = limit->count =
10716 ext2fs_cpu_to_le16(limit->limit);
10717 root = (struct ext2_dx_entry *)
10718 (outdir->buf + root_offset);
10719 root->block = ext2fs_cpu_to_le32(outdir->num);
10720 if (i != 1)
10721 root->hash =
10722 ext2fs_cpu_to_le32(outdir->hashes[i]);
10723 if ((retval = get_next_block(fs, outdir,
10724 &block_start)))
10725 return retval;
10726 dx_ent = set_int_node(fs, block_start);
10727 limit = (struct ext2_dx_countlimit *) dx_ent;
10728 c2 = limit->limit;
10729 root_offset += sizeof(struct ext2_dx_entry);
10730 c1--;
10731 }
10732 dx_ent->block = ext2fs_cpu_to_le32(i);
10733 if (c2 != limit->limit)
10734 dx_ent->hash =
10735 ext2fs_cpu_to_le32(outdir->hashes[i]);
10736 dx_ent++;
10737 c2--;
10738 }
10739 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10740 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10741 }
10742 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10743 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10744 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10745
10746 return 0;
10747}
10748
10749struct write_dir_struct {
10750 struct out_dir *outdir;
10751 errcode_t err;
10752 e2fsck_t ctx;
10753 int cleared;
10754};
10755
10756/*
10757 * Helper function which writes out a directory block.
10758 */
10759static int write_dir_block(ext2_filsys fs,
10760 blk_t *block_nr,
10761 e2_blkcnt_t blockcnt,
10762 blk_t ref_block FSCK_ATTR((unused)),
10763 int ref_offset FSCK_ATTR((unused)),
10764 void *priv_data)
10765{
10766 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10767 blk_t blk;
10768 char *dir;
10769
10770 if (*block_nr == 0)
10771 return 0;
10772 if (blockcnt >= wd->outdir->num) {
10773 e2fsck_read_bitmaps(wd->ctx);
10774 blk = *block_nr;
10775 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10776 ext2fs_block_alloc_stats(fs, blk, -1);
10777 *block_nr = 0;
10778 wd->cleared++;
10779 return BLOCK_CHANGED;
10780 }
10781 if (blockcnt < 0)
10782 return 0;
10783
10784 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10785 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10786 if (wd->err)
10787 return BLOCK_ABORT;
10788 return 0;
10789}
10790
10791static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10792 struct out_dir *outdir,
10793 ext2_ino_t ino, int compress)
10794{
10795 struct write_dir_struct wd;
10796 errcode_t retval;
10797 struct ext2_inode inode;
10798
10799 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10800 if (retval)
10801 return retval;
10802
10803 wd.outdir = outdir;
10804 wd.err = 0;
10805 wd.ctx = ctx;
10806 wd.cleared = 0;
10807
10808 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10809 write_dir_block, &wd);
10810 if (retval)
10811 return retval;
10812 if (wd.err)
10813 return wd.err;
10814
10815 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10816 if (compress)
10817 inode.i_flags &= ~EXT2_INDEX_FL;
10818 else
10819 inode.i_flags |= EXT2_INDEX_FL;
10820 inode.i_size = outdir->num * fs->blocksize;
10821 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10822 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10823
10824 return 0;
10825}
10826
10827static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10828{
10829 ext2_filsys fs = ctx->fs;
10830 errcode_t retval;
10831 struct ext2_inode inode;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010832 char *dir_buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010833 struct fill_dir_struct fd;
10834 struct out_dir outdir;
10835
10836 outdir.max = outdir.num = 0;
10837 outdir.buf = 0;
10838 outdir.hashes = 0;
10839 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10840
10841 retval = ENOMEM;
10842 fd.harray = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010843 dir_buf = xmalloc(inode.i_size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010844
10845 fd.max_array = inode.i_size / 32;
10846 fd.num_array = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010847 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010848
10849 fd.ctx = ctx;
10850 fd.buf = dir_buf;
10851 fd.inode = &inode;
10852 fd.err = 0;
10853 fd.dir_size = 0;
10854 fd.compress = 0;
10855 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10856 (inode.i_size / fs->blocksize) < 2)
10857 fd.compress = 1;
10858 fd.parent = 0;
10859
10860 /* Read in the entire directory into memory */
10861 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10862 fill_dir_block, &fd);
10863 if (fd.err) {
10864 retval = fd.err;
10865 goto errout;
10866 }
10867
10868 /* Sort the list */
10869resort:
10870 if (fd.compress)
10871 qsort(fd.harray+2, fd.num_array-2,
10872 sizeof(struct hash_entry), name_cmp);
10873 else
10874 qsort(fd.harray, fd.num_array,
10875 sizeof(struct hash_entry), hash_cmp);
10876
10877 /*
10878 * Look for duplicates
10879 */
10880 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10881 goto resort;
10882
10883 if (ctx->options & E2F_OPT_NO) {
10884 retval = 0;
10885 goto errout;
10886 }
10887
10888 /*
10889 * Copy the directory entries. In a htree directory these
10890 * will become the leaf nodes.
10891 */
10892 retval = copy_dir_entries(fs, &fd, &outdir);
10893 if (retval)
10894 goto errout;
10895
10896 free(dir_buf); dir_buf = 0;
10897
10898 if (!fd.compress) {
10899 /* Calculate the interior nodes */
10900 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10901 if (retval)
10902 goto errout;
10903 }
10904
10905 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10906
10907errout:
10908 free(dir_buf);
10909 free(fd.harray);
10910
10911 free_out_dir(&outdir);
10912 return retval;
10913}
10914
10915void e2fsck_rehash_directories(e2fsck_t ctx)
10916{
10917 struct problem_context pctx;
10918 struct dir_info *dir;
10919 ext2_u32_iterate iter;
10920 ext2_ino_t ino;
10921 errcode_t retval;
10922 int i, cur, max, all_dirs, dir_index, first = 1;
10923
10924 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10925
10926 if (!ctx->dirs_to_hash && !all_dirs)
10927 return;
10928
10929 e2fsck_get_lost_and_found(ctx, 0);
10930
10931 clear_problem_context(&pctx);
10932
10933 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10934 cur = 0;
10935 if (all_dirs) {
10936 i = 0;
10937 max = e2fsck_get_num_dirinfo(ctx);
10938 } else {
10939 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10940 &iter);
10941 if (retval) {
10942 pctx.errcode = retval;
10943 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10944 return;
10945 }
10946 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10947 }
10948 while (1) {
10949 if (all_dirs) {
10950 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10951 break;
10952 ino = dir->ino;
10953 } else {
10954 if (!ext2fs_u32_list_iterate(iter, &ino))
10955 break;
10956 }
10957 if (ino == ctx->lost_and_found)
10958 continue;
10959 pctx.dir = ino;
10960 if (first) {
10961 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10962 first = 0;
10963 }
10964 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10965 if (pctx.errcode) {
10966 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10967 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10968 }
10969 if (ctx->progress && !ctx->progress_fd)
10970 e2fsck_simple_progress(ctx, "Rebuilding directory",
10971 100.0 * (float) (++cur) / (float) max, ino);
10972 }
10973 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10974 if (!all_dirs)
10975 ext2fs_u32_list_iterate_end(iter);
10976
10977 ext2fs_u32_list_free(ctx->dirs_to_hash);
10978 ctx->dirs_to_hash = 0;
10979}
10980
10981/*
10982 * linux/fs/revoke.c
10983 *
10984 * Journal revoke routines for the generic filesystem journaling code;
10985 * part of the ext2fs journaling system.
10986 *
10987 * Revoke is the mechanism used to prevent old log records for deleted
10988 * metadata from being replayed on top of newer data using the same
10989 * blocks. The revoke mechanism is used in two separate places:
10990 *
10991 * + Commit: during commit we write the entire list of the current
10992 * transaction's revoked blocks to the journal
10993 *
10994 * + Recovery: during recovery we record the transaction ID of all
10995 * revoked blocks. If there are multiple revoke records in the log
10996 * for a single block, only the last one counts, and if there is a log
10997 * entry for a block beyond the last revoke, then that log entry still
10998 * gets replayed.
10999 *
11000 * We can get interactions between revokes and new log data within a
11001 * single transaction:
11002 *
11003 * Block is revoked and then journaled:
11004 * The desired end result is the journaling of the new block, so we
11005 * cancel the revoke before the transaction commits.
11006 *
11007 * Block is journaled and then revoked:
11008 * The revoke must take precedence over the write of the block, so we
11009 * need either to cancel the journal entry or to write the revoke
11010 * later in the log than the log block. In this case, we choose the
11011 * latter: journaling a block cancels any revoke record for that block
11012 * in the current transaction, so any revoke for that block in the
11013 * transaction must have happened after the block was journaled and so
11014 * the revoke must take precedence.
11015 *
11016 * Block is revoked and then written as data:
11017 * The data write is allowed to succeed, but the revoke is _not_
11018 * cancelled. We still need to prevent old log records from
11019 * overwriting the new data. We don't even need to clear the revoke
11020 * bit here.
11021 *
11022 * Revoke information on buffers is a tri-state value:
11023 *
11024 * RevokeValid clear: no cached revoke status, need to look it up
11025 * RevokeValid set, Revoked clear:
11026 * buffer has not been revoked, and cancel_revoke
11027 * need do nothing.
11028 * RevokeValid set, Revoked set:
11029 * buffer has been revoked.
11030 */
11031
11032static kmem_cache_t *revoke_record_cache;
11033static kmem_cache_t *revoke_table_cache;
11034
11035/* Each revoke record represents one single revoked block. During
11036 journal replay, this involves recording the transaction ID of the
11037 last transaction to revoke this block. */
11038
11039struct jbd_revoke_record_s
11040{
11041 struct list_head hash;
11042 tid_t sequence; /* Used for recovery only */
11043 unsigned long blocknr;
11044};
11045
11046
11047/* The revoke table is just a simple hash table of revoke records. */
11048struct jbd_revoke_table_s
11049{
11050 /* It is conceivable that we might want a larger hash table
11051 * for recovery. Must be a power of two. */
11052 int hash_size;
11053 int hash_shift;
11054 struct list_head *hash_table;
11055};
11056
11057
11058/* Utility functions to maintain the revoke table */
11059
11060/* Borrowed from buffer.c: this is a tried and tested block hash function */
11061static int hash(journal_t *journal, unsigned long block)
11062{
11063 struct jbd_revoke_table_s *table = journal->j_revoke;
11064 int hash_shift = table->hash_shift;
11065
11066 return ((block << (hash_shift - 6)) ^
11067 (block >> 13) ^
11068 (block << (hash_shift - 12))) & (table->hash_size - 1);
11069}
11070
11071static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11072 tid_t seq)
11073{
11074 struct list_head *hash_list;
11075 struct jbd_revoke_record_s *record;
11076
11077 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11078 if (!record)
11079 goto oom;
11080
11081 record->sequence = seq;
11082 record->blocknr = blocknr;
11083 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11084 list_add(&record->hash, hash_list);
11085 return 0;
11086
11087oom:
11088 return -ENOMEM;
11089}
11090
11091/* Find a revoke record in the journal's hash table. */
11092
11093static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11094 unsigned long blocknr)
11095{
11096 struct list_head *hash_list;
11097 struct jbd_revoke_record_s *record;
11098
11099 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11100
11101 record = (struct jbd_revoke_record_s *) hash_list->next;
11102 while (&(record->hash) != hash_list) {
11103 if (record->blocknr == blocknr)
11104 return record;
11105 record = (struct jbd_revoke_record_s *) record->hash.next;
11106 }
11107 return NULL;
11108}
11109
11110int journal_init_revoke_caches(void)
11111{
11112 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11113 if (revoke_record_cache == 0)
11114 return -ENOMEM;
11115
11116 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11117 if (revoke_table_cache == 0) {
11118 do_cache_destroy(revoke_record_cache);
11119 revoke_record_cache = NULL;
11120 return -ENOMEM;
11121 }
11122 return 0;
11123}
11124
11125void journal_destroy_revoke_caches(void)
11126{
11127 do_cache_destroy(revoke_record_cache);
11128 revoke_record_cache = 0;
11129 do_cache_destroy(revoke_table_cache);
11130 revoke_table_cache = 0;
11131}
11132
11133/* Initialise the revoke table for a given journal to a given size. */
11134
11135int journal_init_revoke(journal_t *journal, int hash_size)
11136{
11137 int shift, tmp;
11138
11139 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11140 if (!journal->j_revoke)
11141 return -ENOMEM;
11142
11143 /* Check that the hash_size is a power of two */
11144 journal->j_revoke->hash_size = hash_size;
11145
11146 shift = 0;
11147 tmp = hash_size;
Denis Vlasenkobb045062008-09-27 14:06:06 +000011148 while ((tmp >>= 1UL) != 0UL)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011149 shift++;
11150 journal->j_revoke->hash_shift = shift;
11151
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010011152 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011153
11154 for (tmp = 0; tmp < hash_size; tmp++)
11155 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11156
11157 return 0;
11158}
11159
11160/* Destoy a journal's revoke table. The table must already be empty! */
11161
11162void journal_destroy_revoke(journal_t *journal)
11163{
11164 struct jbd_revoke_table_s *table;
11165 struct list_head *hash_list;
11166 int i;
11167
11168 table = journal->j_revoke;
11169 if (!table)
11170 return;
11171
11172 for (i=0; i<table->hash_size; i++) {
11173 hash_list = &table->hash_table[i];
11174 }
11175
11176 free(table->hash_table);
11177 free(table);
11178 journal->j_revoke = NULL;
11179}
11180
11181/*
11182 * Revoke support for recovery.
11183 *
11184 * Recovery needs to be able to:
11185 *
11186 * record all revoke records, including the tid of the latest instance
11187 * of each revoke in the journal
11188 *
11189 * check whether a given block in a given transaction should be replayed
11190 * (ie. has not been revoked by a revoke record in that or a subsequent
11191 * transaction)
11192 *
11193 * empty the revoke table after recovery.
11194 */
11195
11196/*
11197 * First, setting revoke records. We create a new revoke record for
11198 * every block ever revoked in the log as we scan it for recovery, and
11199 * we update the existing records if we find multiple revokes for a
11200 * single block.
11201 */
11202
11203int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11204 tid_t sequence)
11205{
11206 struct jbd_revoke_record_s *record;
11207
11208 record = find_revoke_record(journal, blocknr);
11209 if (record) {
11210 /* If we have multiple occurences, only record the
11211 * latest sequence number in the hashed record */
11212 if (tid_gt(sequence, record->sequence))
11213 record->sequence = sequence;
11214 return 0;
11215 }
11216 return insert_revoke_hash(journal, blocknr, sequence);
11217}
11218
11219/*
11220 * Test revoke records. For a given block referenced in the log, has
11221 * that block been revoked? A revoke record with a given transaction
11222 * sequence number revokes all blocks in that transaction and earlier
11223 * ones, but later transactions still need replayed.
11224 */
11225
11226int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11227 tid_t sequence)
11228{
11229 struct jbd_revoke_record_s *record;
11230
11231 record = find_revoke_record(journal, blocknr);
11232 if (!record)
11233 return 0;
11234 if (tid_gt(sequence, record->sequence))
11235 return 0;
11236 return 1;
11237}
11238
11239/*
11240 * Finally, once recovery is over, we need to clear the revoke table so
11241 * that it can be reused by the running filesystem.
11242 */
11243
11244void journal_clear_revoke(journal_t *journal)
11245{
11246 int i;
11247 struct list_head *hash_list;
11248 struct jbd_revoke_record_s *record;
11249 struct jbd_revoke_table_s *revoke_var;
11250
11251 revoke_var = journal->j_revoke;
11252
11253 for (i = 0; i < revoke_var->hash_size; i++) {
11254 hash_list = &revoke_var->hash_table[i];
11255 while (!list_empty(hash_list)) {
11256 record = (struct jbd_revoke_record_s*) hash_list->next;
11257 list_del(&record->hash);
11258 free(record);
11259 }
11260 }
11261}
11262
11263/*
11264 * e2fsck.c - superblock checks
11265 */
11266
11267#define MIN_CHECK 1
11268#define MAX_CHECK 2
11269
11270static void check_super_value(e2fsck_t ctx, const char *descr,
11271 unsigned long value, int flags,
11272 unsigned long min_val, unsigned long max_val)
11273{
11274 struct problem_context pctx;
11275
11276 if (((flags & MIN_CHECK) && (value < min_val)) ||
11277 ((flags & MAX_CHECK) && (value > max_val))) {
11278 clear_problem_context(&pctx);
11279 pctx.num = value;
11280 pctx.str = descr;
11281 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11282 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11283 }
11284}
11285
11286/*
11287 * This routine may get stubbed out in special compilations of the
11288 * e2fsck code..
11289 */
11290#ifndef EXT2_SPECIAL_DEVICE_SIZE
11291static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11292{
11293 return (ext2fs_get_device_size(ctx->filesystem_name,
11294 EXT2_BLOCK_SIZE(ctx->fs->super),
11295 &ctx->num_blocks));
11296}
11297#endif
11298
11299/*
11300 * helper function to release an inode
11301 */
11302struct process_block_struct {
11303 e2fsck_t ctx;
11304 char *buf;
11305 struct problem_context *pctx;
11306 int truncating;
11307 int truncate_offset;
11308 e2_blkcnt_t truncate_block;
11309 int truncated_blocks;
11310 int abort;
11311 errcode_t errcode;
11312};
11313
11314static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11315 e2_blkcnt_t blockcnt,
11316 blk_t ref_blk FSCK_ATTR((unused)),
11317 int ref_offset FSCK_ATTR((unused)),
11318 void *priv_data)
11319{
11320 struct process_block_struct *pb;
11321 e2fsck_t ctx;
11322 struct problem_context *pctx;
11323 blk_t blk = *block_nr;
11324 int retval = 0;
11325
11326 pb = (struct process_block_struct *) priv_data;
11327 ctx = pb->ctx;
11328 pctx = pb->pctx;
11329
11330 pctx->blk = blk;
11331 pctx->blkcount = blockcnt;
11332
11333 if (HOLE_BLKADDR(blk))
11334 return 0;
11335
11336 if ((blk < fs->super->s_first_data_block) ||
11337 (blk >= fs->super->s_blocks_count)) {
11338 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011339 return_abort:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011340 pb->abort = 1;
11341 return BLOCK_ABORT;
11342 }
11343
11344 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11345 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11346 goto return_abort;
11347 }
11348
11349 /*
11350 * If we are deleting an orphan, then we leave the fields alone.
11351 * If we are truncating an orphan, then update the inode fields
11352 * and clean up any partial block data.
11353 */
11354 if (pb->truncating) {
11355 /*
11356 * We only remove indirect blocks if they are
11357 * completely empty.
11358 */
11359 if (blockcnt < 0) {
11360 int i, limit;
11361 blk_t *bp;
11362
11363 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11364 pb->buf);
11365 if (pb->errcode)
11366 goto return_abort;
11367
11368 limit = fs->blocksize >> 2;
11369 for (i = 0, bp = (blk_t *) pb->buf;
11370 i < limit; i++, bp++)
11371 if (*bp)
11372 return 0;
11373 }
11374 /*
11375 * We don't remove direct blocks until we've reached
11376 * the truncation block.
11377 */
11378 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11379 return 0;
11380 /*
11381 * If part of the last block needs truncating, we do
11382 * it here.
11383 */
11384 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11385 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11386 pb->buf);
11387 if (pb->errcode)
11388 goto return_abort;
11389 memset(pb->buf + pb->truncate_offset, 0,
11390 fs->blocksize - pb->truncate_offset);
11391 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11392 pb->buf);
11393 if (pb->errcode)
11394 goto return_abort;
11395 }
11396 pb->truncated_blocks++;
11397 *block_nr = 0;
11398 retval |= BLOCK_CHANGED;
11399 }
11400
11401 ext2fs_block_alloc_stats(fs, blk, -1);
11402 return retval;
11403}
11404
11405/*
11406 * This function releases an inode. Returns 1 if an inconsistency was
11407 * found. If the inode has a link count, then it is being truncated and
11408 * not deleted.
11409 */
11410static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11411 struct ext2_inode *inode, char *block_buf,
11412 struct problem_context *pctx)
11413{
11414 struct process_block_struct pb;
11415 ext2_filsys fs = ctx->fs;
11416 errcode_t retval;
11417 __u32 count;
11418
11419 if (!ext2fs_inode_has_valid_blocks(inode))
11420 return 0;
11421
11422 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11423 pb.ctx = ctx;
11424 pb.abort = 0;
11425 pb.errcode = 0;
11426 pb.pctx = pctx;
11427 if (inode->i_links_count) {
11428 pb.truncating = 1;
11429 pb.truncate_block = (e2_blkcnt_t)
11430 ((((long long)inode->i_size_high << 32) +
11431 inode->i_size + fs->blocksize - 1) /
11432 fs->blocksize);
11433 pb.truncate_offset = inode->i_size % fs->blocksize;
11434 } else {
11435 pb.truncating = 0;
11436 pb.truncate_block = 0;
11437 pb.truncate_offset = 0;
11438 }
11439 pb.truncated_blocks = 0;
11440 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11441 block_buf, release_inode_block, &pb);
11442 if (retval) {
11443 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11444 ino);
11445 return 1;
11446 }
11447 if (pb.abort)
11448 return 1;
11449
11450 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11451 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11452
11453 if (pb.truncated_blocks)
11454 inode->i_blocks -= pb.truncated_blocks *
11455 (fs->blocksize / 512);
11456
11457 if (inode->i_file_acl) {
11458 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11459 block_buf, -1, &count);
11460 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11461 retval = 0;
11462 count = 1;
11463 }
11464 if (retval) {
11465 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11466 ino);
11467 return 1;
11468 }
11469 if (count == 0)
11470 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11471 inode->i_file_acl = 0;
11472 }
11473 return 0;
11474}
11475
11476/*
11477 * This function releases all of the orphan inodes. It returns 1 if
11478 * it hit some error, and 0 on success.
11479 */
11480static int release_orphan_inodes(e2fsck_t ctx)
11481{
11482 ext2_filsys fs = ctx->fs;
11483 ext2_ino_t ino, next_ino;
11484 struct ext2_inode inode;
11485 struct problem_context pctx;
11486 char *block_buf;
11487
11488 if ((ino = fs->super->s_last_orphan) == 0)
11489 return 0;
11490
11491 /*
11492 * Win or lose, we won't be using the head of the orphan inode
11493 * list again.
11494 */
11495 fs->super->s_last_orphan = 0;
11496 ext2fs_mark_super_dirty(fs);
11497
11498 /*
11499 * If the filesystem contains errors, don't run the orphan
11500 * list, since the orphan list can't be trusted; and we're
11501 * going to be running a full e2fsck run anyway...
11502 */
11503 if (fs->super->s_state & EXT2_ERROR_FS)
11504 return 0;
11505
11506 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11507 (ino > fs->super->s_inodes_count)) {
11508 clear_problem_context(&pctx);
11509 pctx.ino = ino;
11510 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11511 return 1;
11512 }
11513
11514 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11515 "block iterate buffer");
11516 e2fsck_read_bitmaps(ctx);
11517
11518 while (ino) {
11519 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11520 clear_problem_context(&pctx);
11521 pctx.ino = ino;
11522 pctx.inode = &inode;
11523 pctx.str = inode.i_links_count ? _("Truncating") :
11524 _("Clearing");
11525
11526 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11527
11528 next_ino = inode.i_dtime;
11529 if (next_ino &&
11530 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11531 (next_ino > fs->super->s_inodes_count))) {
11532 pctx.ino = next_ino;
11533 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11534 goto return_abort;
11535 }
11536
11537 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11538 goto return_abort;
11539
11540 if (!inode.i_links_count) {
11541 ext2fs_inode_alloc_stats2(fs, ino, -1,
11542 LINUX_S_ISDIR(inode.i_mode));
Denis Vlasenko04158e02009-02-02 10:48:06 +000011543 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011544 } else {
11545 inode.i_dtime = 0;
11546 }
11547 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11548 ino = next_ino;
11549 }
11550 ext2fs_free_mem(&block_buf);
11551 return 0;
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011552 return_abort:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011553 ext2fs_free_mem(&block_buf);
11554 return 1;
11555}
11556
11557/*
11558 * Check the resize inode to make sure it is sane. We check both for
11559 * the case where on-line resizing is not enabled (in which case the
11560 * resize inode should be cleared) as well as the case where on-line
11561 * resizing is enabled.
11562 */
11563static void check_resize_inode(e2fsck_t ctx)
11564{
11565 ext2_filsys fs = ctx->fs;
11566 struct ext2_inode inode;
11567 struct problem_context pctx;
11568 int i, j, gdt_off, ind_off;
11569 blk_t blk, pblk, expect;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010011570 __u32 *dind_buf = NULL, *ind_buf;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011571 errcode_t retval;
11572
11573 clear_problem_context(&pctx);
11574
11575 /*
11576 * If the resize inode feature isn't set, then
11577 * s_reserved_gdt_blocks must be zero.
11578 */
11579 if (!(fs->super->s_feature_compat &
Denys Vlasenko176bc342012-04-17 15:06:55 +020011580 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011581 if (fs->super->s_reserved_gdt_blocks) {
11582 pctx.num = fs->super->s_reserved_gdt_blocks;
11583 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11584 &pctx)) {
11585 fs->super->s_reserved_gdt_blocks = 0;
11586 ext2fs_mark_super_dirty(fs);
11587 }
11588 }
11589 }
11590
11591 /* Read the resize inode */
11592 pctx.ino = EXT2_RESIZE_INO;
11593 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11594 if (retval) {
11595 if (fs->super->s_feature_compat &
Denys Vlasenko176bc342012-04-17 15:06:55 +020011596 EXT2_FEATURE_COMPAT_RESIZE_INO)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011597 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11598 return;
11599 }
11600
11601 /*
11602 * If the resize inode feature isn't set, check to make sure
11603 * the resize inode is cleared; then we're done.
11604 */
11605 if (!(fs->super->s_feature_compat &
Denys Vlasenko176bc342012-04-17 15:06:55 +020011606 EXT2_FEATURE_COMPAT_RESIZE_INO)) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011607 for (i=0; i < EXT2_N_BLOCKS; i++) {
11608 if (inode.i_block[i])
11609 break;
11610 }
11611 if ((i < EXT2_N_BLOCKS) &&
11612 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11613 memset(&inode, 0, sizeof(inode));
11614 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11615 "clear_resize");
11616 }
11617 return;
11618 }
11619
11620 /*
11621 * The resize inode feature is enabled; check to make sure the
11622 * only block in use is the double indirect block
11623 */
11624 blk = inode.i_block[EXT2_DIND_BLOCK];
11625 for (i=0; i < EXT2_N_BLOCKS; i++) {
11626 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11627 break;
11628 }
11629 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11630 !(inode.i_mode & LINUX_S_IFREG) ||
11631 (blk < fs->super->s_first_data_block ||
11632 blk >= fs->super->s_blocks_count)) {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011633 resize_inode_invalid:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011634 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11635 memset(&inode, 0, sizeof(inode));
11636 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11637 "clear_resize");
11638 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11639 }
11640 if (!(ctx->options & E2F_OPT_READONLY)) {
11641 fs->super->s_state &= ~EXT2_VALID_FS;
11642 ext2fs_mark_super_dirty(fs);
11643 }
11644 goto cleanup;
11645 }
11646 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11647 "resize dind buffer");
11648 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11649
11650 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11651 if (retval)
11652 goto resize_inode_invalid;
11653
11654 gdt_off = fs->desc_blocks;
11655 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11656 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11657 i++, gdt_off++, pblk++) {
11658 gdt_off %= fs->blocksize/4;
11659 if (dind_buf[gdt_off] != pblk)
11660 goto resize_inode_invalid;
11661 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11662 if (retval)
11663 goto resize_inode_invalid;
11664 ind_off = 0;
11665 for (j = 1; j < fs->group_desc_count; j++) {
11666 if (!ext2fs_bg_has_super(fs, j))
11667 continue;
11668 expect = pblk + (j * fs->super->s_blocks_per_group);
11669 if (ind_buf[ind_off] != expect)
11670 goto resize_inode_invalid;
11671 ind_off++;
11672 }
11673 }
11674
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011675 cleanup:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011676 ext2fs_free_mem(&dind_buf);
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011677}
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011678
11679static void check_super_block(e2fsck_t ctx)
11680{
11681 ext2_filsys fs = ctx->fs;
11682 blk_t first_block, last_block;
11683 struct ext2_super_block *sb = fs->super;
11684 struct ext2_group_desc *gd;
11685 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11686 blk_t bpg_max;
11687 int inodes_per_block;
11688 int ipg_max;
11689 int inode_size;
11690 dgrp_t i;
11691 blk_t should_be;
11692 struct problem_context pctx;
11693 __u32 free_blocks = 0, free_inodes = 0;
11694
11695 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11696 ipg_max = inodes_per_block * (blocks_per_group - 4);
11697 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11698 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11699 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11700 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11701 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11702
11703 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11704 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11705 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11706 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11707 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11708 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11709
11710 clear_problem_context(&pctx);
11711
11712 /*
11713 * Verify the super block constants...
11714 */
11715 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11716 MIN_CHECK, 1, 0);
11717 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11718 MIN_CHECK, 1, 0);
11719 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11720 MAX_CHECK, 0, sb->s_blocks_count);
11721 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11722 MIN_CHECK | MAX_CHECK, 0,
11723 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11724 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11725 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11726 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11727 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11728 bpg_max);
11729 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11730 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11731 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11732 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11733 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11734 MAX_CHECK, 0, sb->s_blocks_count / 2);
11735 check_super_value(ctx, "reserved_gdt_blocks",
11736 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11737 fs->blocksize/4);
11738 inode_size = EXT2_INODE_SIZE(sb);
11739 check_super_value(ctx, "inode_size",
11740 inode_size, MIN_CHECK | MAX_CHECK,
11741 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11742 if (inode_size & (inode_size - 1)) {
11743 pctx.num = inode_size;
11744 pctx.str = "inode_size";
11745 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11746 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11747 return;
11748 }
11749
11750 if (!ctx->num_blocks) {
11751 pctx.errcode = e2fsck_get_device_size(ctx);
11752 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11753 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11754 ctx->flags |= E2F_FLAG_ABORT;
11755 return;
11756 }
11757 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11758 (ctx->num_blocks < sb->s_blocks_count)) {
11759 pctx.blk = sb->s_blocks_count;
11760 pctx.blk2 = ctx->num_blocks;
11761 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11762 ctx->flags |= E2F_FLAG_ABORT;
11763 return;
11764 }
11765 }
11766 }
11767
11768 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11769 pctx.blk = EXT2_BLOCK_SIZE(sb);
11770 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11771 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11772 ctx->flags |= E2F_FLAG_ABORT;
11773 return;
11774 }
11775
11776 should_be = sb->s_frags_per_group >>
11777 (sb->s_log_block_size - sb->s_log_frag_size);
11778 if (sb->s_blocks_per_group != should_be) {
11779 pctx.blk = sb->s_blocks_per_group;
11780 pctx.blk2 = should_be;
11781 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11782 ctx->flags |= E2F_FLAG_ABORT;
11783 return;
11784 }
11785
11786 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11787 if (sb->s_first_data_block != should_be) {
11788 pctx.blk = sb->s_first_data_block;
11789 pctx.blk2 = should_be;
11790 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11791 ctx->flags |= E2F_FLAG_ABORT;
11792 return;
11793 }
11794
11795 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11796 if (sb->s_inodes_count != should_be) {
11797 pctx.ino = sb->s_inodes_count;
11798 pctx.ino2 = should_be;
11799 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11800 sb->s_inodes_count = should_be;
11801 ext2fs_mark_super_dirty(fs);
11802 }
11803 }
11804
11805 /*
11806 * Verify the group descriptors....
11807 */
11808 first_block = sb->s_first_data_block;
11809 last_block = first_block + blocks_per_group;
11810
11811 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11812 pctx.group = i;
11813
11814 if (i == fs->group_desc_count - 1)
11815 last_block = sb->s_blocks_count;
11816 if ((gd->bg_block_bitmap < first_block) ||
11817 (gd->bg_block_bitmap >= last_block)) {
11818 pctx.blk = gd->bg_block_bitmap;
11819 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11820 gd->bg_block_bitmap = 0;
11821 }
11822 if (gd->bg_block_bitmap == 0) {
11823 ctx->invalid_block_bitmap_flag[i]++;
11824 ctx->invalid_bitmaps++;
11825 }
11826 if ((gd->bg_inode_bitmap < first_block) ||
11827 (gd->bg_inode_bitmap >= last_block)) {
11828 pctx.blk = gd->bg_inode_bitmap;
11829 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11830 gd->bg_inode_bitmap = 0;
11831 }
11832 if (gd->bg_inode_bitmap == 0) {
11833 ctx->invalid_inode_bitmap_flag[i]++;
11834 ctx->invalid_bitmaps++;
11835 }
11836 if ((gd->bg_inode_table < first_block) ||
11837 ((gd->bg_inode_table +
11838 fs->inode_blocks_per_group - 1) >= last_block)) {
11839 pctx.blk = gd->bg_inode_table;
11840 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11841 gd->bg_inode_table = 0;
11842 }
11843 if (gd->bg_inode_table == 0) {
11844 ctx->invalid_inode_table_flag[i]++;
11845 ctx->invalid_bitmaps++;
11846 }
11847 free_blocks += gd->bg_free_blocks_count;
11848 free_inodes += gd->bg_free_inodes_count;
11849 first_block += sb->s_blocks_per_group;
11850 last_block += sb->s_blocks_per_group;
11851
11852 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11853 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11854 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11855 ext2fs_unmark_valid(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011856 }
11857
11858 /*
11859 * Update the global counts from the block group counts. This
11860 * is needed for an experimental patch which eliminates
11861 * locking the entire filesystem when allocating blocks or
11862 * inodes; if the filesystem is not unmounted cleanly, the
11863 * global counts may not be accurate.
11864 */
11865 if ((free_blocks != sb->s_free_blocks_count) ||
11866 (free_inodes != sb->s_free_inodes_count)) {
11867 if (ctx->options & E2F_OPT_READONLY)
11868 ext2fs_unmark_valid(fs);
11869 else {
11870 sb->s_free_blocks_count = free_blocks;
11871 sb->s_free_inodes_count = free_inodes;
11872 ext2fs_mark_super_dirty(fs);
11873 }
11874 }
11875
11876 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11877 (sb->s_free_inodes_count > sb->s_inodes_count))
11878 ext2fs_unmark_valid(fs);
11879
11880
11881 /*
11882 * If we have invalid bitmaps, set the error state of the
11883 * filesystem.
11884 */
11885 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11886 sb->s_state &= ~EXT2_VALID_FS;
11887 ext2fs_mark_super_dirty(fs);
11888 }
11889
11890 clear_problem_context(&pctx);
11891
11892 /*
11893 * If the UUID field isn't assigned, assign it.
11894 */
11895 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11896 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11897 uuid_generate(sb->s_uuid);
11898 ext2fs_mark_super_dirty(fs);
11899 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11900 }
11901 }
11902
11903 /* FIXME - HURD support?
11904 * For the Hurd, check to see if the filetype option is set,
11905 * since it doesn't support it.
11906 */
11907 if (!(ctx->options & E2F_OPT_READONLY) &&
11908 fs->super->s_creator_os == EXT2_OS_HURD &&
11909 (fs->super->s_feature_incompat &
11910 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11911 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11912 fs->super->s_feature_incompat &=
11913 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11914 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011915 }
11916 }
11917
11918 /*
11919 * If we have any of the compatibility flags set, we need to have a
11920 * revision 1 filesystem. Most kernels will not check the flags on
11921 * a rev 0 filesystem and we may have corruption issues because of
11922 * the incompatible changes to the filesystem.
11923 */
11924 if (!(ctx->options & E2F_OPT_READONLY) &&
11925 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11926 (fs->super->s_feature_compat ||
11927 fs->super->s_feature_ro_compat ||
11928 fs->super->s_feature_incompat) &&
11929 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11930 ext2fs_update_dynamic_rev(fs);
11931 ext2fs_mark_super_dirty(fs);
11932 }
11933
11934 check_resize_inode(ctx);
11935
11936 /*
11937 * Clean up any orphan inodes, if present.
11938 */
11939 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11940 fs->super->s_state &= ~EXT2_VALID_FS;
11941 ext2fs_mark_super_dirty(fs);
11942 }
11943
11944 /*
11945 * Move the ext3 journal file, if necessary.
11946 */
11947 e2fsck_move_ext3_journal(ctx);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011948}
11949
11950/*
11951 * swapfs.c --- byte-swap an ext2 filesystem
11952 */
11953
11954#ifdef ENABLE_SWAPFS
11955
11956struct swap_block_struct {
11957 ext2_ino_t ino;
11958 int isdir;
11959 errcode_t errcode;
11960 char *dir_buf;
11961 struct ext2_inode *inode;
11962};
11963
11964/*
11965 * This is a helper function for block_iterate. We mark all of the
11966 * indirect and direct blocks as changed, so that block_iterate will
11967 * write them out.
11968 */
11969static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11970 void *priv_data)
11971{
11972 errcode_t retval;
11973
11974 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11975
11976 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11977 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11978 if (retval) {
11979 sb->errcode = retval;
11980 return BLOCK_ABORT;
11981 }
11982 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11983 if (retval) {
11984 sb->errcode = retval;
11985 return BLOCK_ABORT;
11986 }
11987 }
11988 if (blockcnt >= 0) {
11989 if (blockcnt < EXT2_NDIR_BLOCKS)
11990 return 0;
11991 return BLOCK_CHANGED;
11992 }
11993 if (blockcnt == BLOCK_COUNT_IND) {
11994 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11995 return 0;
11996 return BLOCK_CHANGED;
11997 }
11998 if (blockcnt == BLOCK_COUNT_DIND) {
11999 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12000 return 0;
12001 return BLOCK_CHANGED;
12002 }
12003 if (blockcnt == BLOCK_COUNT_TIND) {
12004 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12005 return 0;
12006 return BLOCK_CHANGED;
12007 }
12008 return BLOCK_CHANGED;
12009}
12010
12011/*
12012 * This function is responsible for byte-swapping all of the indirect,
12013 * block pointers. It is also responsible for byte-swapping directories.
12014 */
12015static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12016 struct ext2_inode *inode)
12017{
12018 errcode_t retval;
12019 struct swap_block_struct sb;
12020
12021 sb.ino = ino;
12022 sb.inode = inode;
12023 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12024 sb.errcode = 0;
12025 sb.isdir = 0;
12026 if (LINUX_S_ISDIR(inode->i_mode))
12027 sb.isdir = 1;
12028
12029 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12030 swap_block, &sb);
12031 if (retval) {
12032 bb_error_msg(_("while calling ext2fs_block_iterate"));
12033 ctx->flags |= E2F_FLAG_ABORT;
12034 return;
12035 }
12036 if (sb.errcode) {
12037 bb_error_msg(_("while calling iterator function"));
12038 ctx->flags |= E2F_FLAG_ABORT;
12039 return;
12040 }
12041}
12042
12043static void swap_inodes(e2fsck_t ctx)
12044{
12045 ext2_filsys fs = ctx->fs;
12046 dgrp_t group;
12047 unsigned int i;
12048 ext2_ino_t ino = 1;
12049 char *buf, *block_buf;
12050 errcode_t retval;
12051 struct ext2_inode * inode;
12052
12053 e2fsck_use_inode_shortcuts(ctx, 1);
12054
12055 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12056 &buf);
12057 if (retval) {
12058 bb_error_msg(_("while allocating inode buffer"));
12059 ctx->flags |= E2F_FLAG_ABORT;
12060 return;
12061 }
12062 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12063 "block interate buffer");
12064 for (group = 0; group < fs->group_desc_count; group++) {
12065 retval = io_channel_read_blk(fs->io,
12066 fs->group_desc[group].bg_inode_table,
12067 fs->inode_blocks_per_group, buf);
12068 if (retval) {
12069 bb_error_msg(_("while reading inode table (group %d)"),
12070 group);
12071 ctx->flags |= E2F_FLAG_ABORT;
12072 return;
12073 }
12074 inode = (struct ext2_inode *) buf;
12075 for (i=0; i < fs->super->s_inodes_per_group;
12076 i++, ino++, inode++) {
12077 ctx->stashed_ino = ino;
12078 ctx->stashed_inode = inode;
12079
12080 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12081 ext2fs_swap_inode(fs, inode, inode, 0);
12082
12083 /*
12084 * Skip deleted files.
12085 */
12086 if (inode->i_links_count == 0)
12087 continue;
12088
12089 if (LINUX_S_ISDIR(inode->i_mode) ||
12090 ((inode->i_block[EXT2_IND_BLOCK] ||
12091 inode->i_block[EXT2_DIND_BLOCK] ||
12092 inode->i_block[EXT2_TIND_BLOCK]) &&
12093 ext2fs_inode_has_valid_blocks(inode)))
12094 swap_inode_blocks(ctx, ino, block_buf, inode);
12095
12096 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12097 return;
12098
12099 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12100 ext2fs_swap_inode(fs, inode, inode, 1);
12101 }
12102 retval = io_channel_write_blk(fs->io,
12103 fs->group_desc[group].bg_inode_table,
12104 fs->inode_blocks_per_group, buf);
12105 if (retval) {
12106 bb_error_msg(_("while writing inode table (group %d)"),
12107 group);
12108 ctx->flags |= E2F_FLAG_ABORT;
12109 return;
12110 }
12111 }
12112 ext2fs_free_mem(&buf);
12113 ext2fs_free_mem(&block_buf);
12114 e2fsck_use_inode_shortcuts(ctx, 0);
12115 ext2fs_flush_icache(fs);
12116}
12117
12118#if defined(__powerpc__) && BB_BIG_ENDIAN
12119/*
12120 * On the PowerPC, the big-endian variant of the ext2 filesystem
12121 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12122 * of each word. Thus a bitmap with only bit 0 set would be, as
12123 * a string of bytes, 00 00 00 01 00 ...
12124 * To cope with this, we byte-reverse each word of a bitmap if
12125 * we have a big-endian filesystem, that is, if we are *not*
12126 * byte-swapping other word-sized numbers.
12127 */
12128#define EXT2_BIG_ENDIAN_BITMAPS
12129#endif
12130
12131#ifdef EXT2_BIG_ENDIAN_BITMAPS
12132static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12133{
12134 __u32 *p = (__u32 *) bmap->bitmap;
12135 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12136
12137 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12138 *p = ext2fs_swab32(*p);
12139}
12140#endif
12141
12142
12143#ifdef ENABLE_SWAPFS
12144static void swap_filesys(e2fsck_t ctx)
12145{
12146 ext2_filsys fs = ctx->fs;
12147 if (!(ctx->options & E2F_OPT_PREEN))
12148 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12149
12150 /* Byte swap */
12151
12152 if (fs->super->s_mnt_count) {
12153 fprintf(stderr, _("%s: the filesystem must be freshly "
12154 "checked using fsck\n"
12155 "and not mounted before trying to "
12156 "byte-swap it.\n"), ctx->device_name);
12157 ctx->flags |= E2F_FLAG_ABORT;
12158 return;
12159 }
12160 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12161 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12162 EXT2_FLAG_SWAP_BYTES_WRITE);
12163 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12164 } else {
12165 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12166 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12167 }
12168 swap_inodes(ctx);
12169 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12170 return;
12171 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12172 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12173 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12174 EXT2_FLAG_SWAP_BYTES_WRITE);
12175
12176#ifdef EXT2_BIG_ENDIAN_BITMAPS
12177 e2fsck_read_bitmaps(ctx);
12178 ext2fs_swap_bitmap(fs->inode_map);
12179 ext2fs_swap_bitmap(fs->block_map);
12180 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12181#endif
12182 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12183 ext2fs_flush(fs);
12184 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12185}
12186#endif /* ENABLE_SWAPFS */
12187
12188#endif
12189
12190/*
12191 * util.c --- miscellaneous utilities
12192 */
12193
12194
12195void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12196 const char *description)
12197{
12198 void *ret;
12199 char buf[256];
12200
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012201 ret = xzalloc(size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012202 return ret;
12203}
12204
12205static char *string_copy(const char *str, int len)
12206{
12207 char *ret;
12208
12209 if (!str)
12210 return NULL;
12211 if (!len)
12212 len = strlen(str);
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012213 ret = xmalloc(len+1);
12214 strncpy(ret, str, len);
12215 ret[len] = 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012216 return ret;
12217}
12218
12219#ifndef HAVE_CONIO_H
12220static int read_a_char(void)
12221{
12222 char c;
12223 int r;
12224 int fail = 0;
12225
Denis Vlasenkobb045062008-09-27 14:06:06 +000012226 while (1) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012227 if (e2fsck_global_ctx &&
12228 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12229 return 3;
12230 }
12231 r = read(0, &c, 1);
12232 if (r == 1)
12233 return c;
12234 if (fail++ > 100)
12235 break;
12236 }
12237 return EOF;
12238}
12239#endif
12240
12241static int ask_yn(const char * string, int def)
12242{
12243 int c;
12244 const char *defstr;
12245 static const char short_yes[] = "yY";
12246 static const char short_no[] = "nN";
12247
12248#ifdef HAVE_TERMIOS_H
12249 struct termios termios, tmp;
12250
12251 tcgetattr (0, &termios);
12252 tmp = termios;
12253 tmp.c_lflag &= ~(ICANON | ECHO);
12254 tmp.c_cc[VMIN] = 1;
12255 tmp.c_cc[VTIME] = 0;
Denis Vlasenko202ac502008-11-05 13:20:58 +000012256 tcsetattr_stdin_TCSANOW(&tmp);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012257#endif
12258
12259 if (def == 1)
12260 defstr = "<y>";
12261 else if (def == 0)
12262 defstr = "<n>";
12263 else
12264 defstr = " (y/n)";
12265 printf("%s%s? ", string, defstr);
12266 while (1) {
12267 fflush (stdout);
12268 if ((c = read_a_char()) == EOF)
12269 break;
12270 if (c == 3) {
12271#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012272 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012273#endif
12274 if (e2fsck_global_ctx &&
12275 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12276 puts("\n");
12277 longjmp(e2fsck_global_ctx->abort_loc, 1);
12278 }
12279 puts(_("cancelled!\n"));
12280 return 0;
12281 }
12282 if (strchr(short_yes, (char) c)) {
12283 def = 1;
12284 break;
12285 }
12286 else if (strchr(short_no, (char) c)) {
12287 def = 0;
12288 break;
12289 }
12290 else if ((c == ' ' || c == '\n') && (def != -1))
12291 break;
12292 }
12293 if (def)
12294 puts("yes\n");
12295 else
12296 puts ("no\n");
12297#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012298 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012299#endif
12300 return def;
12301}
12302
12303int ask (e2fsck_t ctx, const char * string, int def)
12304{
12305 if (ctx->options & E2F_OPT_NO) {
12306 printf(_("%s? no\n\n"), string);
12307 return 0;
12308 }
12309 if (ctx->options & E2F_OPT_YES) {
12310 printf(_("%s? yes\n\n"), string);
12311 return 1;
12312 }
12313 if (ctx->options & E2F_OPT_PREEN) {
12314 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12315 return def;
12316 }
12317 return ask_yn(string, def);
12318}
12319
12320void e2fsck_read_bitmaps(e2fsck_t ctx)
12321{
12322 ext2_filsys fs = ctx->fs;
12323 errcode_t retval;
12324
12325 if (ctx->invalid_bitmaps) {
12326 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12327 ctx->device_name);
12328 bb_error_msg_and_die(0);
12329 }
12330
12331 ehandler_operation(_("reading inode and block bitmaps"));
12332 retval = ext2fs_read_bitmaps(fs);
12333 ehandler_operation(0);
12334 if (retval) {
12335 bb_error_msg(_("while retrying to read bitmaps for %s"),
12336 ctx->device_name);
12337 bb_error_msg_and_die(0);
12338 }
12339}
12340
12341static void e2fsck_write_bitmaps(e2fsck_t ctx)
12342{
12343 ext2_filsys fs = ctx->fs;
12344 errcode_t retval;
12345
12346 if (ext2fs_test_bb_dirty(fs)) {
12347 ehandler_operation(_("writing block bitmaps"));
12348 retval = ext2fs_write_block_bitmap(fs);
12349 ehandler_operation(0);
12350 if (retval) {
12351 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12352 ctx->device_name);
12353 bb_error_msg_and_die(0);
12354 }
12355 }
12356
12357 if (ext2fs_test_ib_dirty(fs)) {
12358 ehandler_operation(_("writing inode bitmaps"));
12359 retval = ext2fs_write_inode_bitmap(fs);
12360 ehandler_operation(0);
12361 if (retval) {
12362 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12363 ctx->device_name);
12364 bb_error_msg_and_die(0);
12365 }
12366 }
12367}
12368
12369void preenhalt(e2fsck_t ctx)
12370{
12371 ext2_filsys fs = ctx->fs;
12372
12373 if (!(ctx->options & E2F_OPT_PREEN))
12374 return;
12375 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12376 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12377 ctx->device_name);
12378 if (fs != NULL) {
12379 fs->super->s_state |= EXT2_ERROR_FS;
12380 ext2fs_mark_super_dirty(fs);
12381 ext2fs_close(fs);
12382 }
12383 exit(EXIT_UNCORRECTED);
12384}
12385
12386void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12387 struct ext2_inode * inode, const char *proc)
12388{
12389 int retval;
12390
12391 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12392 if (retval) {
12393 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12394 bb_error_msg_and_die(0);
12395 }
12396}
12397
12398extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12399 struct ext2_inode * inode, int bufsize,
12400 const char *proc)
12401{
12402 int retval;
12403
12404 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12405 if (retval) {
12406 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12407 bb_error_msg_and_die(0);
12408 }
12409}
12410
12411extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12412 struct ext2_inode * inode, const char *proc)
12413{
12414 int retval;
12415
12416 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12417 if (retval) {
12418 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12419 bb_error_msg_and_die(0);
12420 }
12421}
12422
12423blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12424 io_manager manager)
12425{
12426 struct ext2_super_block *sb;
12427 io_channel io = NULL;
12428 void *buf = NULL;
12429 int blocksize;
12430 blk_t superblock, ret_sb = 8193;
12431
12432 if (fs && fs->super) {
12433 ret_sb = (fs->super->s_blocks_per_group +
12434 fs->super->s_first_data_block);
12435 if (ctx) {
12436 ctx->superblock = ret_sb;
12437 ctx->blocksize = fs->blocksize;
12438 }
12439 return ret_sb;
12440 }
12441
12442 if (ctx) {
12443 if (ctx->blocksize) {
12444 ret_sb = ctx->blocksize * 8;
12445 if (ctx->blocksize == 1024)
12446 ret_sb++;
12447 ctx->superblock = ret_sb;
12448 return ret_sb;
12449 }
12450 ctx->superblock = ret_sb;
12451 ctx->blocksize = 1024;
12452 }
12453
12454 if (!name || !manager)
12455 goto cleanup;
12456
12457 if (manager->open(name, 0, &io) != 0)
12458 goto cleanup;
12459
12460 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12461 goto cleanup;
12462 sb = (struct ext2_super_block *) buf;
12463
12464 for (blocksize = EXT2_MIN_BLOCK_SIZE;
Denis Vlasenkob71c6682007-07-21 15:08:09 +000012465 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012466 superblock = blocksize*8;
12467 if (blocksize == 1024)
12468 superblock++;
12469 io_channel_set_blksize(io, blocksize);
12470 if (io_channel_read_blk(io, superblock,
12471 -SUPERBLOCK_SIZE, buf))
12472 continue;
12473#if BB_BIG_ENDIAN
12474 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12475 ext2fs_swap_super(sb);
12476#endif
12477 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12478 ret_sb = superblock;
12479 if (ctx) {
12480 ctx->superblock = superblock;
12481 ctx->blocksize = blocksize;
12482 }
12483 break;
12484 }
12485 }
12486
12487cleanup:
12488 if (io)
12489 io_channel_close(io);
12490 ext2fs_free_mem(&buf);
12491 return ret_sb;
12492}
12493
12494
12495/*
12496 * This function runs through the e2fsck passes and calls them all,
12497 * returning restart, abort, or cancel as necessary...
12498 */
12499typedef void (*pass_t)(e2fsck_t ctx);
12500
12501static const pass_t e2fsck_passes[] = {
12502 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12503 e2fsck_pass5, 0 };
12504
12505#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12506
12507static int e2fsck_run(e2fsck_t ctx)
12508{
12509 int i;
12510 pass_t e2fsck_pass;
12511
12512 if (setjmp(ctx->abort_loc)) {
12513 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12514 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12515 }
12516 ctx->flags |= E2F_FLAG_SETJMP_OK;
12517
12518 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12519 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12520 break;
12521 e2fsck_pass(ctx);
12522 if (ctx->progress)
12523 (void) (ctx->progress)(ctx, 0, 0, 0);
12524 }
12525 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12526
12527 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12528 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12529 return 0;
12530}
12531
12532
12533/*
12534 * unix.c - The unix-specific code for e2fsck
12535 */
12536
12537
12538/* Command line options */
12539static int swapfs;
12540#ifdef ENABLE_SWAPFS
12541static int normalize_swapfs;
12542#endif
12543static int cflag; /* check disk */
12544static int show_version_only;
12545static int verbose;
12546
12547#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12548
12549static void show_stats(e2fsck_t ctx)
12550{
12551 ext2_filsys fs = ctx->fs;
12552 int inodes, inodes_used, blocks, blocks_used;
12553 int dir_links;
12554 int num_files, num_links;
12555 int frag_percent;
12556
12557 dir_links = 2 * ctx->fs_directory_count - 1;
12558 num_files = ctx->fs_total_count - dir_links;
12559 num_links = ctx->fs_links_count - dir_links;
12560 inodes = fs->super->s_inodes_count;
12561 inodes_used = (fs->super->s_inodes_count -
12562 fs->super->s_free_inodes_count);
12563 blocks = fs->super->s_blocks_count;
12564 blocks_used = (fs->super->s_blocks_count -
12565 fs->super->s_free_blocks_count);
12566
12567 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12568 frag_percent = (frag_percent + 5) / 10;
12569
12570 if (!verbose) {
12571 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12572 ctx->device_name, inodes_used, inodes,
12573 frag_percent / 10, frag_percent % 10,
12574 blocks_used, blocks);
12575 return;
12576 }
12577 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12578 100 * inodes_used / inodes);
12579 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12580 P_E2("", "s", ctx->fs_fragmented),
12581 frag_percent / 10, frag_percent % 10);
12582 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12583 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12584 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12585 (int) ((long long) 100 * blocks_used / blocks));
12586 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12587 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12588 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12589 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12590 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12591 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12592 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12593 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12594 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12595 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12596 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12597}
12598
12599static void check_mount(e2fsck_t ctx)
12600{
12601 errcode_t retval;
12602 int cont;
12603
12604 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12605 &ctx->mount_flags);
12606 if (retval) {
Denis Vlasenko54d10052008-12-24 03:11:43 +000012607 bb_error_msg(_("while determining whether %s is mounted"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012608 ctx->filesystem_name);
12609 return;
12610 }
12611
12612 /*
12613 * If the filesystem isn't mounted, or it's the root filesystem
12614 * and it's mounted read-only, then everything's fine.
12615 */
12616 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12617 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12618 (ctx->mount_flags & EXT2_MF_READONLY)))
12619 return;
12620
12621 if (ctx->options & E2F_OPT_READONLY) {
12622 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12623 return;
12624 }
12625
12626 printf(_("%s is mounted. "), ctx->filesystem_name);
12627 if (!ctx->interactive)
Denys Vlasenko6331cf02009-11-13 09:08:27 +010012628 bb_error_msg_and_die(_("can't continue, aborting"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012629 printf(_("\n\n\007\007\007\007WARNING!!! "
12630 "Running e2fsck on a mounted filesystem may cause\n"
12631 "SEVERE filesystem damage.\007\007\007\n\n"));
12632 cont = ask_yn(_("Do you really want to continue"), -1);
12633 if (!cont) {
12634 printf(_("check aborted.\n"));
Denis Vlasenko6398cf42007-04-11 17:04:29 +000012635 exit(0);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012636 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012637}
12638
12639static int is_on_batt(void)
12640{
12641 FILE *f;
12642 DIR *d;
12643 char tmp[80], tmp2[80], fname[80];
12644 unsigned int acflag;
12645 struct dirent* de;
12646
Denis Vlasenko5415c852008-07-21 23:05:26 +000012647 f = fopen_for_read("/proc/apm");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012648 if (f) {
12649 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12650 acflag = 1;
12651 fclose(f);
12652 return (acflag != 1);
12653 }
12654 d = opendir("/proc/acpi/ac_adapter");
12655 if (d) {
12656 while ((de=readdir(d)) != NULL) {
12657 if (!strncmp(".", de->d_name, 1))
12658 continue;
12659 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12660 de->d_name);
Denis Vlasenko5415c852008-07-21 23:05:26 +000012661 f = fopen_for_read(fname);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012662 if (!f)
12663 continue;
12664 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12665 tmp[0] = 0;
12666 fclose(f);
12667 if (strncmp(tmp, "off-line", 8) == 0) {
12668 closedir(d);
12669 return 1;
12670 }
12671 }
12672 closedir(d);
12673 }
12674 return 0;
12675}
12676
12677/*
12678 * This routine checks to see if a filesystem can be skipped; if so,
12679 * it will exit with EXIT_OK. Under some conditions it will print a
12680 * message explaining why a check is being forced.
12681 */
12682static void check_if_skip(e2fsck_t ctx)
12683{
12684 ext2_filsys fs = ctx->fs;
12685 const char *reason = NULL;
12686 unsigned int reason_arg = 0;
12687 long next_check;
12688 int batt = is_on_batt();
Denis Vlasenko04158e02009-02-02 10:48:06 +000012689 time_t now = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012690
12691 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12692 return;
12693
12694 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12695 !ext2fs_test_valid(fs))
12696 reason = _(" contains a file system with errors");
12697 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12698 reason = _(" was not cleanly unmounted");
12699 else if ((fs->super->s_max_mnt_count > 0) &&
12700 (fs->super->s_mnt_count >=
12701 (unsigned) fs->super->s_max_mnt_count)) {
12702 reason = _(" has been mounted %u times without being checked");
12703 reason_arg = fs->super->s_mnt_count;
12704 if (batt && (fs->super->s_mnt_count <
12705 (unsigned) fs->super->s_max_mnt_count*2))
12706 reason = 0;
12707 } else if (fs->super->s_checkinterval &&
12708 ((now - fs->super->s_lastcheck) >=
12709 fs->super->s_checkinterval)) {
12710 reason = _(" has gone %u days without being checked");
12711 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12712 if (batt && ((now - fs->super->s_lastcheck) <
12713 fs->super->s_checkinterval*2))
12714 reason = 0;
12715 }
12716 if (reason) {
12717 fputs(ctx->device_name, stdout);
12718 printf(reason, reason_arg);
12719 fputs(_(", check forced.\n"), stdout);
12720 return;
12721 }
12722 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12723 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12724 fs->super->s_inodes_count,
12725 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12726 fs->super->s_blocks_count);
12727 next_check = 100000;
12728 if (fs->super->s_max_mnt_count > 0) {
12729 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12730 if (next_check <= 0)
12731 next_check = 1;
12732 }
12733 if (fs->super->s_checkinterval &&
12734 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12735 next_check = 1;
12736 if (next_check <= 5) {
12737 if (next_check == 1)
12738 fputs(_(" (check after next mount)"), stdout);
12739 else
12740 printf(_(" (check in %ld mounts)"), next_check);
12741 }
Denis Vlasenko4daad902007-09-27 10:20:47 +000012742 bb_putchar('\n');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012743 ext2fs_close(fs);
12744 ctx->fs = NULL;
12745 e2fsck_free_context(ctx);
12746 exit(EXIT_OK);
12747}
12748
12749/*
12750 * For completion notice
12751 */
12752struct percent_tbl {
12753 int max_pass;
12754 int table[32];
12755};
12756static const struct percent_tbl e2fsck_tbl = {
12757 5, { 0, 70, 90, 92, 95, 100 }
12758};
12759
12760static char bar[128], spaces[128];
12761
12762static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12763 int max)
12764{
12765 float percent;
12766
12767 if (pass <= 0)
12768 return 0.0;
12769 if (pass > tbl->max_pass || max == 0)
12770 return 100.0;
12771 percent = ((float) curr) / ((float) max);
12772 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12773 + tbl->table[pass-1]);
12774}
12775
12776void e2fsck_clear_progbar(e2fsck_t ctx)
12777{
12778 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12779 return;
12780
12781 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12782 ctx->stop_meta);
12783 fflush(stdout);
12784 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12785}
12786
12787int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12788 unsigned int dpynum)
12789{
12790 static const char spinner[] = "\\|/-";
12791 int i;
12792 unsigned int tick;
12793 struct timeval tv;
12794 int dpywidth;
12795 int fixed_percent;
12796
12797 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12798 return 0;
12799
12800 /*
12801 * Calculate the new progress position. If the
12802 * percentage hasn't changed, then we skip out right
12803 * away.
12804 */
12805 fixed_percent = (int) ((10 * percent) + 0.5);
12806 if (ctx->progress_last_percent == fixed_percent)
12807 return 0;
12808 ctx->progress_last_percent = fixed_percent;
12809
12810 /*
12811 * If we've already updated the spinner once within
12812 * the last 1/8th of a second, no point doing it
12813 * again.
12814 */
12815 gettimeofday(&tv, NULL);
12816 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12817 if ((tick == ctx->progress_last_time) &&
12818 (fixed_percent != 0) && (fixed_percent != 1000))
12819 return 0;
12820 ctx->progress_last_time = tick;
12821
12822 /*
12823 * Advance the spinner, and note that the progress bar
12824 * will be on the screen
12825 */
12826 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12827 ctx->flags |= E2F_FLAG_PROG_BAR;
12828
12829 dpywidth = 66 - strlen(label);
12830 dpywidth = 8 * (dpywidth / 8);
12831 if (dpynum)
12832 dpywidth -= 8;
12833
12834 i = ((percent * dpywidth) + 50) / 100;
12835 printf("%s%s: |%s%s", ctx->start_meta, label,
12836 bar + (sizeof(bar) - (i+1)),
12837 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12838 if (fixed_percent == 1000)
Denis Vlasenko4daad902007-09-27 10:20:47 +000012839 bb_putchar('|');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012840 else
Denis Vlasenko4daad902007-09-27 10:20:47 +000012841 bb_putchar(spinner[ctx->progress_pos & 3]);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012842 printf(" %4.1f%% ", percent);
12843 if (dpynum)
12844 printf("%u\r", dpynum);
12845 else
12846 fputs(" \r", stdout);
12847 fputs(ctx->stop_meta, stdout);
12848
12849 if (fixed_percent == 1000)
12850 e2fsck_clear_progbar(ctx);
12851 fflush(stdout);
12852
12853 return 0;
12854}
12855
12856static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12857 unsigned long cur, unsigned long max)
12858{
12859 char buf[80];
12860 float percent;
12861
12862 if (pass == 0)
12863 return 0;
12864
12865 if (ctx->progress_fd) {
12866 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
Denis Vlasenko73c571a2009-03-09 00:12:37 +000012867 xwrite_str(ctx->progress_fd, buf);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012868 } else {
12869 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12870 e2fsck_simple_progress(ctx, ctx->device_name,
12871 percent, 0);
12872 }
12873 return 0;
12874}
12875
12876static void reserve_stdio_fds(void)
12877{
12878 int fd;
12879
12880 while (1) {
12881 fd = open(bb_dev_null, O_RDWR);
12882 if (fd > 2)
12883 break;
12884 if (fd < 0) {
12885 fprintf(stderr, _("ERROR: Cannot open "
12886 "/dev/null (%s)\n"),
12887 strerror(errno));
12888 break;
12889 }
12890 }
12891 close(fd);
12892}
12893
12894static void signal_progress_on(int sig FSCK_ATTR((unused)))
12895{
12896 e2fsck_t ctx = e2fsck_global_ctx;
12897
12898 if (!ctx)
12899 return;
12900
12901 ctx->progress = e2fsck_update_progress;
12902 ctx->progress_fd = 0;
12903}
12904
12905static void signal_progress_off(int sig FSCK_ATTR((unused)))
12906{
12907 e2fsck_t ctx = e2fsck_global_ctx;
12908
12909 if (!ctx)
12910 return;
12911
12912 e2fsck_clear_progbar(ctx);
12913 ctx->progress = 0;
12914}
12915
12916static void signal_cancel(int sig FSCK_ATTR((unused)))
12917{
12918 e2fsck_t ctx = e2fsck_global_ctx;
12919
12920 if (!ctx)
12921 exit(FSCK_CANCELED);
12922
12923 ctx->flags |= E2F_FLAG_CANCEL;
12924}
12925
12926static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12927{
12928 char *buf, *token, *next, *p, *arg;
12929 int ea_ver;
12930 int extended_usage = 0;
12931
12932 buf = string_copy(opts, 0);
12933 for (token = buf; token && *token; token = next) {
12934 p = strchr(token, ',');
12935 next = 0;
12936 if (p) {
12937 *p = 0;
12938 next = p+1;
12939 }
12940 arg = strchr(token, '=');
12941 if (arg) {
12942 *arg = 0;
12943 arg++;
12944 }
12945 if (strcmp(token, "ea_ver") == 0) {
12946 if (!arg) {
12947 extended_usage++;
12948 continue;
12949 }
12950 ea_ver = strtoul(arg, &p, 0);
12951 if (*p ||
12952 ((ea_ver != 1) && (ea_ver != 2))) {
12953 fprintf(stderr,
12954 _("Invalid EA version.\n"));
12955 extended_usage++;
12956 continue;
12957 }
12958 ctx->ext_attr_ver = ea_ver;
12959 } else {
12960 fprintf(stderr, _("Unknown extended option: %s\n"),
12961 token);
12962 extended_usage++;
12963 }
12964 }
12965 if (extended_usage) {
12966 bb_error_msg_and_die(
12967 "Extended options are separated by commas, "
12968 "and may take an argument which\n"
12969 "is set off by an equals ('=') sign. "
12970 "Valid extended options are:\n"
12971 "\tea_ver=<ea_version (1 or 2)>\n\n");
12972 }
12973}
12974
12975
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000012976static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012977{
12978 int flush = 0;
12979 int c, fd;
12980 e2fsck_t ctx;
12981 errcode_t retval;
12982 struct sigaction sa;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010012983 char *extended_opts = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012984
12985 retval = e2fsck_allocate_context(&ctx);
12986 if (retval)
12987 return retval;
12988
12989 *ret_ctx = ctx;
12990
12991 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12992 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12993 if (isatty(0) && isatty(1)) {
12994 ctx->interactive = 1;
12995 } else {
12996 ctx->start_meta[0] = '\001';
12997 ctx->stop_meta[0] = '\002';
12998 }
12999 memset(bar, '=', sizeof(bar)-1);
13000 memset(spaces, ' ', sizeof(spaces)-1);
13001 blkid_get_cache(&ctx->blkid, NULL);
13002
13003 if (argc && *argv)
13004 ctx->program_name = *argv;
13005 else
13006 ctx->program_name = "e2fsck";
13007 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13008 switch (c) {
13009 case 'C':
13010 ctx->progress = e2fsck_update_progress;
13011 ctx->progress_fd = atoi(optarg);
13012 if (!ctx->progress_fd)
13013 break;
13014 /* Validate the file descriptor to avoid disasters */
13015 fd = dup(ctx->progress_fd);
13016 if (fd < 0) {
13017 fprintf(stderr,
13018 _("Error validating file descriptor %d: %s\n"),
13019 ctx->progress_fd,
13020 error_message(errno));
13021 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13022 } else
13023 close(fd);
13024 break;
13025 case 'D':
13026 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13027 break;
13028 case 'E':
13029 extended_opts = optarg;
13030 break;
13031 case 'p':
13032 case 'a':
13033 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13034 conflict_opt:
Denis Vlasenko54d10052008-12-24 03:11:43 +000013035 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013036 }
13037 ctx->options |= E2F_OPT_PREEN;
13038 break;
13039 case 'n':
13040 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13041 goto conflict_opt;
13042 ctx->options |= E2F_OPT_NO;
13043 break;
13044 case 'y':
13045 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13046 goto conflict_opt;
13047 ctx->options |= E2F_OPT_YES;
13048 break;
13049 case 't':
13050 /* FIXME - This needs to go away in a future path - will change binary */
13051 fprintf(stderr, _("The -t option is not "
13052 "supported on this version of e2fsck.\n"));
13053 break;
13054 case 'c':
13055 if (cflag++)
13056 ctx->options |= E2F_OPT_WRITECHECK;
13057 ctx->options |= E2F_OPT_CHECKBLOCKS;
13058 break;
13059 case 'r':
13060 /* What we do by default, anyway! */
13061 break;
13062 case 'b':
13063 ctx->use_superblock = atoi(optarg);
13064 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13065 break;
13066 case 'B':
13067 ctx->blocksize = atoi(optarg);
13068 break;
13069 case 'I':
13070 ctx->inode_buffer_blocks = atoi(optarg);
13071 break;
13072 case 'j':
13073 ctx->journal_name = string_copy(optarg, 0);
13074 break;
13075 case 'P':
13076 ctx->process_inode_size = atoi(optarg);
13077 break;
13078 case 'd':
13079 ctx->options |= E2F_OPT_DEBUG;
13080 break;
13081 case 'f':
13082 ctx->options |= E2F_OPT_FORCE;
13083 break;
13084 case 'F':
13085 flush = 1;
13086 break;
13087 case 'v':
13088 verbose = 1;
13089 break;
13090 case 'V':
13091 show_version_only = 1;
13092 break;
13093 case 'N':
13094 ctx->device_name = optarg;
13095 break;
13096#ifdef ENABLE_SWAPFS
13097 case 's':
13098 normalize_swapfs = 1;
13099 case 'S':
13100 swapfs = 1;
13101 break;
13102#else
13103 case 's':
13104 case 'S':
13105 fprintf(stderr, _("Byte-swapping filesystems "
13106 "not compiled in this version "
13107 "of e2fsck\n"));
13108 exit(1);
13109#endif
13110 default:
13111 bb_show_usage();
13112 }
13113 if (show_version_only)
13114 return 0;
13115 if (optind != argc - 1)
13116 bb_show_usage();
13117 if ((ctx->options & E2F_OPT_NO) &&
13118 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13119 ctx->options |= E2F_OPT_READONLY;
13120 ctx->io_options = strchr(argv[optind], '?');
13121 if (ctx->io_options)
13122 *ctx->io_options++ = 0;
13123 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13124 if (!ctx->filesystem_name) {
13125 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13126 bb_error_msg_and_die(0);
13127 }
13128 if (extended_opts)
13129 parse_extended_opts(ctx, extended_opts);
13130
13131 if (flush) {
13132 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13133 if (fd < 0) {
13134 bb_error_msg(_("while opening %s for flushing"),
13135 ctx->filesystem_name);
13136 bb_error_msg_and_die(0);
13137 }
13138 if ((retval = ext2fs_sync_device(fd, 1))) {
13139 bb_error_msg(_("while trying to flush %s"),
13140 ctx->filesystem_name);
13141 bb_error_msg_and_die(0);
13142 }
13143 close(fd);
13144 }
13145#ifdef ENABLE_SWAPFS
13146 if (swapfs && cflag) {
13147 fprintf(stderr, _("Incompatible options not "
13148 "allowed when byte-swapping.\n"));
13149 exit(EXIT_USAGE);
13150 }
13151#endif
13152 /*
13153 * Set up signal action
13154 */
13155 memset(&sa, 0, sizeof(struct sigaction));
13156 sa.sa_handler = signal_cancel;
13157 sigaction(SIGINT, &sa, 0);
13158 sigaction(SIGTERM, &sa, 0);
13159#ifdef SA_RESTART
13160 sa.sa_flags = SA_RESTART;
13161#endif
13162 e2fsck_global_ctx = ctx;
13163 sa.sa_handler = signal_progress_on;
13164 sigaction(SIGUSR1, &sa, 0);
13165 sa.sa_handler = signal_progress_off;
13166 sigaction(SIGUSR2, &sa, 0);
13167
13168 /* Update our PATH to include /sbin if we need to run badblocks */
13169 if (cflag)
13170 e2fs_set_sbin_path();
13171 return 0;
13172}
13173
13174static const char my_ver_string[] = E2FSPROGS_VERSION;
13175static const char my_ver_date[] = E2FSPROGS_DATE;
13176
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013177int e2fsck_main (int argc, char **argv);
13178int e2fsck_main (int argc, char **argv)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013179{
13180 errcode_t retval;
13181 int exit_value = EXIT_OK;
13182 ext2_filsys fs = 0;
13183 io_manager io_ptr;
13184 struct ext2_super_block *sb;
13185 const char *lib_ver_date;
13186 int my_ver, lib_ver;
13187 e2fsck_t ctx;
13188 struct problem_context pctx;
13189 int flags, run_result;
13190
13191 clear_problem_context(&pctx);
13192
13193 my_ver = ext2fs_parse_version_string(my_ver_string);
13194 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13195 if (my_ver > lib_ver) {
13196 fprintf( stderr, _("Error: ext2fs library version "
13197 "out of date!\n"));
13198 show_version_only++;
13199 }
13200
13201 retval = PRS(argc, argv, &ctx);
13202 if (retval) {
13203 bb_error_msg(_("while trying to initialize program"));
13204 exit(EXIT_ERROR);
13205 }
13206 reserve_stdio_fds();
13207
13208 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13209 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13210 my_ver_date);
13211
13212 if (show_version_only) {
13213 fprintf(stderr, _("\tUsing %s, %s\n"),
13214 error_message(EXT2_ET_BASE), lib_ver_date);
13215 exit(EXIT_OK);
13216 }
13217
13218 check_mount(ctx);
13219
13220 if (!(ctx->options & E2F_OPT_PREEN) &&
13221 !(ctx->options & E2F_OPT_NO) &&
13222 !(ctx->options & E2F_OPT_YES)) {
13223 if (!ctx->interactive)
13224 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13225 }
13226 ctx->superblock = ctx->use_superblock;
13227restart:
13228#ifdef CONFIG_TESTIO_DEBUG
13229 io_ptr = test_io_manager;
13230 test_io_backing_manager = unix_io_manager;
13231#else
13232 io_ptr = unix_io_manager;
13233#endif
13234 flags = 0;
13235 if ((ctx->options & E2F_OPT_READONLY) == 0)
13236 flags |= EXT2_FLAG_RW;
13237
13238 if (ctx->superblock && ctx->blocksize) {
13239 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13240 flags, ctx->superblock, ctx->blocksize,
13241 io_ptr, &fs);
13242 } else if (ctx->superblock) {
13243 int blocksize;
13244 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13245 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13246 retval = ext2fs_open2(ctx->filesystem_name,
13247 ctx->io_options, flags,
13248 ctx->superblock, blocksize,
13249 io_ptr, &fs);
13250 if (!retval)
13251 break;
13252 }
13253 } else
13254 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13255 flags, 0, 0, io_ptr, &fs);
13256 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13257 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13258 ((retval == EXT2_ET_BAD_MAGIC) ||
13259 ((retval == 0) && ext2fs_check_desc(fs)))) {
13260 if (!fs || (fs->group_desc_count > 1)) {
13261 printf(_("%s trying backup blocks...\n"),
13262 retval ? _("Couldn't find ext2 superblock,") :
13263 _("Group descriptors look bad..."));
13264 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13265 if (fs)
13266 ext2fs_close(fs);
13267 goto restart;
13268 }
13269 }
13270 if (retval) {
13271 bb_error_msg(_("while trying to open %s"),
13272 ctx->filesystem_name);
13273 if (retval == EXT2_ET_REV_TOO_HIGH) {
13274 printf(_("The filesystem revision is apparently "
13275 "too high for this version of e2fsck.\n"
13276 "(Or the filesystem superblock "
13277 "is corrupt)\n\n"));
13278 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13279 } else if (retval == EXT2_ET_SHORT_READ)
13280 printf(_("Could this be a zero-length partition?\n"));
13281 else if ((retval == EPERM) || (retval == EACCES))
13282 printf(_("You must have %s access to the "
13283 "filesystem or be root\n"),
13284 (ctx->options & E2F_OPT_READONLY) ?
13285 "r/o" : "r/w");
13286 else if (retval == ENXIO)
13287 printf(_("Possibly non-existent or swap device?\n"));
13288#ifdef EROFS
13289 else if (retval == EROFS)
13290 printf(_("Disk write-protected; use the -n option "
13291 "to do a read-only\n"
13292 "check of the device.\n"));
13293#endif
13294 else
13295 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13296 bb_error_msg_and_die(0);
13297 }
13298 ctx->fs = fs;
13299 fs->priv_data = ctx;
13300 sb = fs->super;
13301 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13302 bb_error_msg(_("while trying to open %s"),
13303 ctx->filesystem_name);
13304 get_newer:
13305 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13306 }
13307
13308 /*
13309 * Set the device name, which is used whenever we print error
13310 * or informational messages to the user.
13311 */
13312 if (ctx->device_name == 0 &&
13313 (sb->s_volume_name[0] != 0)) {
13314 ctx->device_name = string_copy(sb->s_volume_name,
13315 sizeof(sb->s_volume_name));
13316 }
13317 if (ctx->device_name == 0)
13318 ctx->device_name = ctx->filesystem_name;
13319
13320 /*
13321 * Make sure the ext3 superblock fields are consistent.
13322 */
13323 retval = e2fsck_check_ext3_journal(ctx);
13324 if (retval) {
13325 bb_error_msg(_("while checking ext3 journal for %s"),
13326 ctx->device_name);
13327 bb_error_msg_and_die(0);
13328 }
13329
13330 /*
13331 * Check to see if we need to do ext3-style recovery. If so,
13332 * do it, and then restart the fsck.
13333 */
13334 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13335 if (ctx->options & E2F_OPT_READONLY) {
13336 printf(_("Warning: skipping journal recovery "
13337 "because doing a read-only filesystem "
13338 "check.\n"));
13339 io_channel_flush(ctx->fs->io);
13340 } else {
13341 if (ctx->flags & E2F_FLAG_RESTARTED) {
13342 /*
13343 * Whoops, we attempted to run the
13344 * journal twice. This should never
13345 * happen, unless the hardware or
13346 * device driver is being bogus.
13347 */
Denys Vlasenko6331cf02009-11-13 09:08:27 +010013348 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013349 bb_error_msg_and_die(0);
13350 }
13351 retval = e2fsck_run_ext3_journal(ctx);
13352 if (retval) {
13353 bb_error_msg(_("while recovering ext3 journal of %s"),
13354 ctx->device_name);
13355 bb_error_msg_and_die(0);
13356 }
13357 ext2fs_close(ctx->fs);
13358 ctx->fs = 0;
13359 ctx->flags |= E2F_FLAG_RESTARTED;
13360 goto restart;
13361 }
13362 }
13363
13364 /*
13365 * Check for compatibility with the feature sets. We need to
13366 * be more stringent than ext2fs_open().
13367 */
13368 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13369 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13370 bb_error_msg("(%s)", ctx->device_name);
13371 goto get_newer;
13372 }
13373 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13374 bb_error_msg("(%s)", ctx->device_name);
13375 goto get_newer;
13376 }
13377#ifdef ENABLE_COMPRESSION
13378 /* FIXME - do we support this at all? */
13379 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
Denis Vlasenko54d10052008-12-24 03:11:43 +000013380 bb_error_msg(_("warning: compression support is experimental"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013381#endif
13382#ifndef ENABLE_HTREE
13383 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13384 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13385 "but filesystem %s has HTREE directories."),
13386 ctx->device_name);
13387 goto get_newer;
13388 }
13389#endif
13390
13391 /*
13392 * If the user specified a specific superblock, presumably the
13393 * master superblock has been trashed. So we mark the
13394 * superblock as dirty, so it can be written out.
13395 */
13396 if (ctx->superblock &&
13397 !(ctx->options & E2F_OPT_READONLY))
13398 ext2fs_mark_super_dirty(fs);
13399
13400 /*
13401 * We only update the master superblock because (a) paranoia;
13402 * we don't want to corrupt the backup superblocks, and (b) we
13403 * don't need to update the mount count and last checked
13404 * fields in the backup superblock (the kernel doesn't
13405 * update the backup superblocks anyway).
13406 */
13407 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13408
13409 ehandler_init(fs->io);
13410
13411 if (ctx->superblock)
13412 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13413 ext2fs_mark_valid(fs);
13414 check_super_block(ctx);
13415 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13416 bb_error_msg_and_die(0);
13417 check_if_skip(ctx);
13418 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13419 bb_error_msg_and_die(0);
13420#ifdef ENABLE_SWAPFS
13421
13422#ifdef WORDS_BIGENDIAN
13423#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13424#else
13425#define NATIVE_FLAG 0
13426#endif
13427
13428
13429 if (normalize_swapfs) {
13430 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13431 fprintf(stderr, _("%s: Filesystem byte order "
13432 "already normalized.\n"), ctx->device_name);
13433 bb_error_msg_and_die(0);
13434 }
13435 }
13436 if (swapfs) {
13437 swap_filesys(ctx);
13438 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13439 bb_error_msg_and_die(0);
13440 }
13441#endif
13442
13443 /*
13444 * Mark the system as valid, 'til proven otherwise
13445 */
13446 ext2fs_mark_valid(fs);
13447
13448 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13449 if (retval) {
13450 bb_error_msg(_("while reading bad blocks inode"));
13451 preenhalt(ctx);
13452 printf(_("This doesn't bode well,"
13453 " but we'll try to go on...\n"));
13454 }
13455
13456 run_result = e2fsck_run(ctx);
13457 e2fsck_clear_progbar(ctx);
13458 if (run_result == E2F_FLAG_RESTART) {
13459 printf(_("Restarting e2fsck from the beginning...\n"));
13460 retval = e2fsck_reset_context(ctx);
13461 if (retval) {
13462 bb_error_msg(_("while resetting context"));
13463 bb_error_msg_and_die(0);
13464 }
13465 ext2fs_close(fs);
13466 goto restart;
13467 }
13468 if (run_result & E2F_FLAG_CANCEL) {
13469 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13470 ctx->device_name : ctx->filesystem_name);
13471 exit_value |= FSCK_CANCELED;
13472 }
13473 if (run_result & E2F_FLAG_ABORT)
13474 bb_error_msg_and_die(_("aborted"));
13475
13476 /* Cleanup */
13477 if (ext2fs_test_changed(fs)) {
13478 exit_value |= EXIT_NONDESTRUCT;
13479 if (!(ctx->options & E2F_OPT_PREEN))
13480 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13481 ctx->device_name);
13482 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13483 printf(_("%s: ***** REBOOT LINUX *****\n"),
13484 ctx->device_name);
13485 exit_value |= EXIT_DESTRUCT;
13486 }
13487 }
13488 if (!ext2fs_test_valid(fs)) {
13489 printf(_("\n%s: ********** WARNING: Filesystem still has "
13490 "errors **********\n\n"), ctx->device_name);
13491 exit_value |= EXIT_UNCORRECTED;
13492 exit_value &= ~EXIT_NONDESTRUCT;
13493 }
13494 if (exit_value & FSCK_CANCELED)
13495 exit_value &= ~EXIT_NONDESTRUCT;
13496 else {
13497 show_stats(ctx);
13498 if (!(ctx->options & E2F_OPT_READONLY)) {
13499 if (ext2fs_test_valid(fs)) {
13500 if (!(sb->s_state & EXT2_VALID_FS))
13501 exit_value |= EXIT_NONDESTRUCT;
13502 sb->s_state = EXT2_VALID_FS;
13503 } else
13504 sb->s_state &= ~EXT2_VALID_FS;
13505 sb->s_mnt_count = 0;
13506 sb->s_lastcheck = time(NULL);
13507 ext2fs_mark_super_dirty(fs);
13508 }
13509 }
13510
13511 e2fsck_write_bitmaps(ctx);
13512
13513 ext2fs_close(fs);
13514 ctx->fs = NULL;
13515 free(ctx->filesystem_name);
13516 free(ctx->journal_name);
13517 e2fsck_free_context(ctx);
13518
13519 return exit_value;
13520}