blob: ad4ff348bc6ac61a0681afaccfec4d6b822f9b13 [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"
40//usage: "\nOptions:"
41//usage: "\n -p Automatic repair (no questions)"
42//usage: "\n -n Make no changes to the filesystem"
43//usage: "\n -y Assume 'yes' to all questions"
44//usage: "\n -c Check for bad blocks and add them to the badblock list"
45//usage: "\n -f Force checking even if filesystem is marked clean"
46//usage: "\n -v Verbose"
47//usage: "\n -b superblock Use alternative superblock"
48//usage: "\n -B blocksize Force blocksize when looking for superblock"
49//usage: "\n -j journal Set location of the external journal"
50//usage: "\n -l file Add to badblocks list"
51//usage: "\n -L file Set badblocks list"
52*/
53
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000054#include "e2fsck.h" /*Put all of our defines here to clean things up*/
55
56#define _(x) x
57#define N_(x) x
58
59/*
60 * Procedure declarations
61 */
62
63static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
64
65/* pass1.c */
66static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
67
68/* pass2.c */
69static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
70 ext2_ino_t ino, char *buf);
71
72/* pass3.c */
73static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
74static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
75 int num, int gauranteed_size);
76static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
77static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
78 int adj);
79
80/* rehash.c */
81static void e2fsck_rehash_directories(e2fsck_t ctx);
82
83/* util.c */
84static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
85 const char *description);
86static int ask(e2fsck_t ctx, const char * string, int def);
87static void e2fsck_read_bitmaps(e2fsck_t ctx);
88static void preenhalt(e2fsck_t ctx);
89static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
90 struct ext2_inode * inode, const char * proc);
91static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
92 struct ext2_inode * inode, const char * proc);
93static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
94 const char *name, io_manager manager);
95
96/* unix.c */
97static void e2fsck_clear_progbar(e2fsck_t ctx);
98static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
99 float percent, unsigned int dpynum);
100
101
102/*
103 * problem.h --- e2fsck problem error codes
104 */
105
106typedef __u32 problem_t;
107
108struct problem_context {
109 errcode_t errcode;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100110 ext2_ino_t ino, ino2, dir;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000111 struct ext2_inode *inode;
112 struct ext2_dir_entry *dirent;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100113 blk_t blk, blk2;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000114 e2_blkcnt_t blkcount;
115 int group;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100116 __u64 num;
117 const char *str;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000118};
119
120
121/*
122 * Function declarations
123 */
124static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
125static int end_problem_latch(e2fsck_t ctx, int mask);
126static int set_latch_flags(int mask, int setflags, int clearflags);
127static void clear_problem_context(struct problem_context *ctx);
128
129/*
130 * Dictionary Abstract Data Type
131 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
132 *
133 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
134 * kazlib_1_20
135 */
136
137#ifndef DICT_H
138#define DICT_H
139
140/*
141 * Blurb for inclusion into C++ translation units
142 */
143
144typedef unsigned long dictcount_t;
145#define DICTCOUNT_T_MAX ULONG_MAX
146
147/*
148 * The dictionary is implemented as a red-black tree
149 */
150
151typedef enum { dnode_red, dnode_black } dnode_color_t;
152
153typedef struct dnode_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100154 struct dnode_t *dict_left;
155 struct dnode_t *dict_right;
156 struct dnode_t *dict_parent;
157 dnode_color_t dict_color;
158 const void *dict_key;
159 void *dict_data;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000160} dnode_t;
161
162typedef int (*dict_comp_t)(const void *, const void *);
163typedef void (*dnode_free_t)(dnode_t *);
164
165typedef struct dict_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100166 dnode_t dict_nilnode;
167 dictcount_t dict_nodecount;
168 dictcount_t dict_maxcount;
169 dict_comp_t dict_compare;
170 dnode_free_t dict_freenode;
171 int dict_dupes;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000172} dict_t;
173
174typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
175
176typedef struct dict_load_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100177 dict_t *dict_dictptr;
178 dnode_t dict_nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000179} dict_load_t;
180
181#define dict_count(D) ((D)->dict_nodecount)
182#define dnode_get(N) ((N)->dict_data)
183#define dnode_getkey(N) ((N)->dict_key)
184
185#endif
186
187/*
188 * Compatibility header file for e2fsck which should be included
189 * instead of linux/jfs.h
190 *
191 * Copyright (C) 2000 Stephen C. Tweedie
192 */
193
194/*
195 * Pull in the definition of the e2fsck context structure
196 */
197
198struct buffer_head {
199 char b_data[8192];
200 e2fsck_t b_ctx;
201 io_channel b_io;
202 int b_size;
203 blk_t b_blocknr;
204 int b_dirty;
205 int b_uptodate;
206 int b_err;
207};
208
209
210#define K_DEV_FS 1
211#define K_DEV_JOURNAL 2
212
Denis Vlasenkobb045062008-09-27 14:06:06 +0000213#define lock_buffer(bh) do {} while (0)
214#define unlock_buffer(bh) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000215#define buffer_req(bh) 1
Denis Vlasenkobb045062008-09-27 14:06:06 +0000216#define do_readahead(journal, start) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000217
218static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
219
220typedef struct {
221 int object_length;
222} kmem_cache_t;
223
224#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
225
226/*
227 * We use the standard libext2fs portability tricks for inline
228 * functions.
229 */
230
231static kmem_cache_t * do_cache_create(int len)
232{
233 kmem_cache_t *new_cache;
234
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100235 new_cache = xmalloc(sizeof(*new_cache));
236 new_cache->object_length = len;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000237 return new_cache;
238}
239
240static void do_cache_destroy(kmem_cache_t *cache)
241{
242 free(cache);
243}
244
245
246/*
247 * Dictionary Abstract Data Type
248 */
249
250
251/*
252 * These macros provide short convenient names for structure members,
253 * which are embellished with dict_ prefixes so that they are
254 * properly confined to the documented namespace. It's legal for a
255 * program which uses dict to define, for instance, a macro called ``parent''.
256 * Such a macro would interfere with the dnode_t struct definition.
257 * In general, highly portable and reusable C modules which expose their
258 * structures need to confine structure member names to well-defined spaces.
259 * The resulting identifiers aren't necessarily convenient to use, nor
260 * readable, in the implementation, however!
261 */
262
263#define left dict_left
264#define right dict_right
265#define parent dict_parent
266#define color dict_color
267#define key dict_key
268#define data dict_data
269
270#define nilnode dict_nilnode
271#define maxcount dict_maxcount
272#define compare dict_compare
273#define dupes dict_dupes
274
275#define dict_root(D) ((D)->nilnode.left)
276#define dict_nil(D) (&(D)->nilnode)
277
278static void dnode_free(dnode_t *node);
279
280/*
281 * Perform a ``left rotation'' adjustment on the tree. The given node P and
282 * its right child C are rearranged so that the P instead becomes the left
283 * child of C. The left subtree of C is inherited as the new right subtree
284 * for P. The ordering of the keys within the tree is thus preserved.
285 */
286
287static void rotate_left(dnode_t *upper)
288{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100289 dnode_t *lower, *lowleft, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000290
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100291 lower = upper->right;
292 upper->right = lowleft = lower->left;
293 lowleft->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000294
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100295 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000296
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100297 /* don't need to check for root node here because root->parent is
298 the sentinel nil node, and root->parent->left points back to root */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000299
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100300 if (upper == upparent->left) {
301 upparent->left = lower;
302 } else {
303 assert (upper == upparent->right);
304 upparent->right = lower;
305 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000306
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100307 lower->left = upper;
308 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000309}
310
311/*
312 * This operation is the ``mirror'' image of rotate_left. It is
313 * the same procedure, but with left and right interchanged.
314 */
315
316static void rotate_right(dnode_t *upper)
317{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100318 dnode_t *lower, *lowright, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000319
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100320 lower = upper->left;
321 upper->left = lowright = lower->right;
322 lowright->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000323
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100324 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000325
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100326 if (upper == upparent->right) {
327 upparent->right = lower;
328 } else {
329 assert (upper == upparent->left);
330 upparent->left = lower;
331 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000332
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100333 lower->right = upper;
334 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000335}
336
337/*
338 * Do a postorder traversal of the tree rooted at the specified
339 * node and free everything under it. Used by dict_free().
340 */
341
342static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
343{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100344 if (node == nil)
345 return;
346 free_nodes(dict, node->left, nil);
347 free_nodes(dict, node->right, nil);
348 dict->dict_freenode(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000349}
350
351/*
352 * Verify that the tree contains the given node. This is done by
353 * traversing all of the nodes and comparing their pointers to the
354 * given pointer. Returns 1 if the node is found, otherwise
355 * returns zero. It is intended for debugging purposes.
356 */
357
358static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
359{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100360 if (root != nil) {
361 return root == node
362 || verify_dict_has_node(nil, root->left, node)
363 || verify_dict_has_node(nil, root->right, node);
364 }
365 return 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000366}
367
368
369/*
370 * Select a different set of node allocator routines.
371 */
372
373static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
374{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100375 assert(dict_count(dict) == 0);
376 dict->dict_freenode = fr;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000377}
378
379/*
380 * Free all the nodes in the dictionary by using the dictionary's
381 * installed free routine. The dictionary is emptied.
382 */
383
384static void dict_free_nodes(dict_t *dict)
385{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100386 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
387 free_nodes(dict, root, nil);
388 dict->dict_nodecount = 0;
389 dict->nilnode.left = &dict->nilnode;
390 dict->nilnode.right = &dict->nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000391}
392
393/*
394 * Initialize a user-supplied dictionary object.
395 */
396
397static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
398{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100399 dict->compare = comp;
400 dict->dict_freenode = dnode_free;
401 dict->dict_nodecount = 0;
402 dict->maxcount = maxcount;
403 dict->nilnode.left = &dict->nilnode;
404 dict->nilnode.right = &dict->nilnode;
405 dict->nilnode.parent = &dict->nilnode;
406 dict->nilnode.color = dnode_black;
407 dict->dupes = 0;
408 return dict;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000409}
410
411/*
412 * Locate a node in the dictionary having the given key.
413 * If the node is not found, a null a pointer is returned (rather than
414 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
415 * located node is returned.
416 */
417
418static dnode_t *dict_lookup(dict_t *dict, const void *key)
419{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100420 dnode_t *root = dict_root(dict);
421 dnode_t *nil = dict_nil(dict);
422 dnode_t *saved;
423 int result;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000424
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100425 /* simple binary search adapted for trees that contain duplicate keys */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000426
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100427 while (root != nil) {
428 result = dict->compare(key, root->key);
429 if (result < 0)
430 root = root->left;
431 else if (result > 0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000432 root = root->right;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100433 else {
434 if (!dict->dupes) { /* no duplicates, return match */
435 return root;
436 } else { /* could be dupes, find leftmost one */
437 do {
438 saved = root;
439 root = root->left;
440 while (root != nil && dict->compare(key, root->key))
441 root = root->right;
442 } while (root != nil);
443 return saved;
444 }
445 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000446 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000447
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100448 return NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000449}
450
451/*
452 * Insert a node into the dictionary. The node should have been
453 * initialized with a data field. All other fields are ignored.
454 * The behavior is undefined if the user attempts to insert into
455 * a dictionary that is already full (for which the dict_isfull()
456 * function returns true).
457 */
458
459static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
460{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100461 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
462 dnode_t *parent = nil, *uncle, *grandpa;
463 int result = -1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000464
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100465 node->key = key;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000466
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100467 /* basic binary tree insert */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000468
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100469 while (where != nil) {
470 parent = where;
471 result = dict->compare(key, where->key);
472 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
473 assert(dict->dupes || result != 0);
474 if (result < 0)
475 where = where->left;
476 else
477 where = where->right;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000478 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000479
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100480 assert(where == nil);
481
482 if (result < 0)
483 parent->left = node;
484 else
485 parent->right = node;
486
487 node->parent = parent;
488 node->left = nil;
489 node->right = nil;
490
491 dict->dict_nodecount++;
492
493 /* red black adjustments */
494
495 node->color = dnode_red;
496
497 while (parent->color == dnode_red) {
498 grandpa = parent->parent;
499 if (parent == grandpa->left) {
500 uncle = grandpa->right;
501 if (uncle->color == dnode_red) { /* red parent, red uncle */
502 parent->color = dnode_black;
503 uncle->color = dnode_black;
504 grandpa->color = dnode_red;
505 node = grandpa;
506 parent = grandpa->parent;
507 } else { /* red parent, black uncle */
508 if (node == parent->right) {
509 rotate_left(parent);
510 parent = node;
511 assert (grandpa == parent->parent);
512 /* rotation between parent and child preserves grandpa */
513 }
514 parent->color = dnode_black;
515 grandpa->color = dnode_red;
516 rotate_right(grandpa);
517 break;
518 }
519 } else { /* symmetric cases: parent == parent->parent->right */
520 uncle = grandpa->left;
521 if (uncle->color == dnode_red) {
522 parent->color = dnode_black;
523 uncle->color = dnode_black;
524 grandpa->color = dnode_red;
525 node = grandpa;
526 parent = grandpa->parent;
527 } else {
528 if (node == parent->left) {
529 rotate_right(parent);
530 parent = node;
531 assert (grandpa == parent->parent);
532 }
533 parent->color = dnode_black;
534 grandpa->color = dnode_red;
535 rotate_left(grandpa);
536 break;
537 }
538 }
539 }
540
541 dict_root(dict)->color = dnode_black;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000542}
543
544/*
545 * Allocate a node using the dictionary's allocator routine, give it
546 * the data item.
547 */
548
549static dnode_t *dnode_init(dnode_t *dnode, void *data)
550{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100551 dnode->data = data;
552 dnode->parent = NULL;
553 dnode->left = NULL;
554 dnode->right = NULL;
555 return dnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000556}
557
558static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
559{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100560 dnode_t *node = xmalloc(sizeof(dnode_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000561
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000562 dnode_init(node, data);
563 dict_insert(dict, node, key);
564 return 1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000565}
566
567/*
568 * Return the node with the lowest (leftmost) key. If the dictionary is empty
569 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
570 */
571
572static dnode_t *dict_first(dict_t *dict)
573{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100574 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000575
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100576 if (root != nil)
577 while ((left = root->left) != nil)
578 root = left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000579
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100580 return (root == nil) ? NULL : root;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000581}
582
583/*
584 * Return the given node's successor node---the node which has the
Marek Polacekb0b88842011-04-16 17:33:43 +0200585 * next key in the left to right ordering. If the node has
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000586 * no successor, a null pointer is returned rather than a pointer to
587 * the nil node.
588 */
589
590static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
591{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100592 dnode_t *nil = dict_nil(dict), *parent, *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000593
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100594 if (curr->right != nil) {
595 curr = curr->right;
596 while ((left = curr->left) != nil)
597 curr = left;
598 return curr;
599 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000600
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000601 parent = curr->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000602
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100603 while (parent != nil && curr == parent->right) {
604 curr = parent;
605 parent = curr->parent;
606 }
607
608 return (parent == nil) ? NULL : parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000609}
610
611
612static void dnode_free(dnode_t *node)
613{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100614 free(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000615}
616
617
618#undef left
619#undef right
620#undef parent
621#undef color
622#undef key
623#undef data
624
625#undef nilnode
626#undef maxcount
627#undef compare
628#undef dupes
629
630
631/*
632 * dirinfo.c --- maintains the directory information table for e2fsck.
633 */
634
635/*
636 * This subroutine is called during pass1 to create a directory info
637 * entry. During pass1, the passed-in parent is 0; it will get filled
638 * in during pass2.
639 */
640static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
641{
642 struct dir_info *dir;
643 int i, j;
644 ext2_ino_t num_dirs;
645 errcode_t retval;
646 unsigned long old_size;
647
648 if (!ctx->dir_info) {
649 ctx->dir_info_count = 0;
650 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
651 if (retval)
652 num_dirs = 1024; /* Guess */
653 ctx->dir_info_size = num_dirs + 10;
654 ctx->dir_info = (struct dir_info *)
655 e2fsck_allocate_memory(ctx, ctx->dir_info_size
656 * sizeof (struct dir_info),
657 "directory map");
658 }
659
660 if (ctx->dir_info_count >= ctx->dir_info_size) {
661 old_size = ctx->dir_info_size * sizeof(struct dir_info);
662 ctx->dir_info_size += 10;
663 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
664 sizeof(struct dir_info),
665 &ctx->dir_info);
666 if (retval) {
667 ctx->dir_info_size -= 10;
668 return;
669 }
670 }
671
672 /*
673 * Normally, add_dir_info is called with each inode in
674 * sequential order; but once in a while (like when pass 3
675 * needs to recreate the root directory or lost+found
676 * directory) it is called out of order. In those cases, we
677 * need to move the dir_info entries down to make room, since
678 * the dir_info array needs to be sorted by inode number for
679 * get_dir_info()'s sake.
680 */
681 if (ctx->dir_info_count &&
682 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
683 for (i = ctx->dir_info_count-1; i > 0; i--)
684 if (ctx->dir_info[i-1].ino < ino)
685 break;
686 dir = &ctx->dir_info[i];
687 if (dir->ino != ino)
688 for (j = ctx->dir_info_count++; j > i; j--)
689 ctx->dir_info[j] = ctx->dir_info[j-1];
690 } else
691 dir = &ctx->dir_info[ctx->dir_info_count++];
692
693 dir->ino = ino;
694 dir->dotdot = parent;
695 dir->parent = parent;
696}
697
698/*
699 * get_dir_info() --- given an inode number, try to find the directory
700 * information entry for it.
701 */
702static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
703{
704 int low, high, mid;
705
706 low = 0;
707 high = ctx->dir_info_count-1;
708 if (!ctx->dir_info)
709 return 0;
710 if (ino == ctx->dir_info[low].ino)
711 return &ctx->dir_info[low];
712 if (ino == ctx->dir_info[high].ino)
713 return &ctx->dir_info[high];
714
715 while (low < high) {
716 mid = (low+high)/2;
717 if (mid == low || mid == high)
718 break;
719 if (ino == ctx->dir_info[mid].ino)
720 return &ctx->dir_info[mid];
721 if (ino < ctx->dir_info[mid].ino)
722 high = mid;
723 else
724 low = mid;
725 }
726 return 0;
727}
728
729/*
730 * Free the dir_info structure when it isn't needed any more.
731 */
732static void e2fsck_free_dir_info(e2fsck_t ctx)
733{
734 ext2fs_free_mem(&ctx->dir_info);
735 ctx->dir_info_size = 0;
736 ctx->dir_info_count = 0;
737}
738
739/*
740 * Return the count of number of directories in the dir_info structure
741 */
742static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
743{
744 return ctx->dir_info_count;
745}
746
747/*
748 * A simple interator function
749 */
750static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
751{
752 if (*control >= ctx->dir_info_count)
753 return 0;
754
755 return ctx->dir_info + (*control)++;
756}
757
758/*
759 * dirinfo.c --- maintains the directory information table for e2fsck.
760 *
761 */
762
763#ifdef ENABLE_HTREE
764
765/*
766 * This subroutine is called during pass1 to create a directory info
767 * entry. During pass1, the passed-in parent is 0; it will get filled
768 * in during pass2.
769 */
770static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
771{
772 struct dx_dir_info *dir;
773 int i, j;
774 errcode_t retval;
775 unsigned long old_size;
776
777 if (!ctx->dx_dir_info) {
778 ctx->dx_dir_info_count = 0;
779 ctx->dx_dir_info_size = 100; /* Guess */
780 ctx->dx_dir_info = (struct dx_dir_info *)
781 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
782 * sizeof (struct dx_dir_info),
783 "directory map");
784 }
785
786 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
787 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
788 ctx->dx_dir_info_size += 10;
789 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
790 sizeof(struct dx_dir_info),
791 &ctx->dx_dir_info);
792 if (retval) {
793 ctx->dx_dir_info_size -= 10;
794 return;
795 }
796 }
797
798 /*
799 * Normally, add_dx_dir_info is called with each inode in
800 * sequential order; but once in a while (like when pass 3
801 * needs to recreate the root directory or lost+found
802 * directory) it is called out of order. In those cases, we
803 * need to move the dx_dir_info entries down to make room, since
804 * the dx_dir_info array needs to be sorted by inode number for
805 * get_dx_dir_info()'s sake.
806 */
807 if (ctx->dx_dir_info_count &&
808 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
809 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
810 if (ctx->dx_dir_info[i-1].ino < ino)
811 break;
812 dir = &ctx->dx_dir_info[i];
813 if (dir->ino != ino)
814 for (j = ctx->dx_dir_info_count++; j > i; j--)
815 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
816 } else
817 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
818
819 dir->ino = ino;
820 dir->numblocks = num_blocks;
821 dir->hashversion = 0;
822 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
823 * sizeof (struct dx_dirblock_info),
824 "dx_block info array");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000825}
826
827/*
828 * get_dx_dir_info() --- given an inode number, try to find the directory
829 * information entry for it.
830 */
831static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
832{
833 int low, high, mid;
834
835 low = 0;
836 high = ctx->dx_dir_info_count-1;
837 if (!ctx->dx_dir_info)
838 return 0;
839 if (ino == ctx->dx_dir_info[low].ino)
840 return &ctx->dx_dir_info[low];
841 if (ino == ctx->dx_dir_info[high].ino)
842 return &ctx->dx_dir_info[high];
843
844 while (low < high) {
845 mid = (low+high)/2;
846 if (mid == low || mid == high)
847 break;
848 if (ino == ctx->dx_dir_info[mid].ino)
849 return &ctx->dx_dir_info[mid];
850 if (ino < ctx->dx_dir_info[mid].ino)
851 high = mid;
852 else
853 low = mid;
854 }
855 return 0;
856}
857
858/*
859 * Free the dx_dir_info structure when it isn't needed any more.
860 */
861static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
862{
863 int i;
864 struct dx_dir_info *dir;
865
866 if (ctx->dx_dir_info) {
867 dir = ctx->dx_dir_info;
868 for (i=0; i < ctx->dx_dir_info_count; i++) {
869 ext2fs_free_mem(&dir->dx_block);
870 }
871 ext2fs_free_mem(&ctx->dx_dir_info);
872 }
873 ctx->dx_dir_info_size = 0;
874 ctx->dx_dir_info_count = 0;
875}
876
877/*
878 * A simple interator function
879 */
880static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
881{
882 if (*control >= ctx->dx_dir_info_count)
883 return 0;
884
885 return ctx->dx_dir_info + (*control)++;
886}
887
888#endif /* ENABLE_HTREE */
889/*
890 * e2fsck.c - a consistency checker for the new extended file system.
891 *
892 */
893
894/*
895 * This function allocates an e2fsck context
896 */
897static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
898{
899 e2fsck_t context;
900 errcode_t retval;
901
902 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
903 if (retval)
904 return retval;
905
906 memset(context, 0, sizeof(struct e2fsck_struct));
907
908 context->process_inode_size = 256;
909 context->ext_attr_ver = 2;
910
911 *ret = context;
912 return 0;
913}
914
915struct ea_refcount_el {
916 blk_t ea_blk;
917 int ea_count;
918};
919
920struct ea_refcount {
921 blk_t count;
922 blk_t size;
923 blk_t cursor;
924 struct ea_refcount_el *list;
925};
926
927static void ea_refcount_free(ext2_refcount_t refcount)
928{
929 if (!refcount)
930 return;
931
932 ext2fs_free_mem(&refcount->list);
933 ext2fs_free_mem(&refcount);
934}
935
936/*
937 * This function resets an e2fsck context; it is called when e2fsck
938 * needs to be restarted.
939 */
940static errcode_t e2fsck_reset_context(e2fsck_t ctx)
941{
942 ctx->flags = 0;
943 ctx->lost_and_found = 0;
944 ctx->bad_lost_and_found = 0;
945 ext2fs_free_inode_bitmap(ctx->inode_used_map);
946 ctx->inode_used_map = 0;
947 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
948 ctx->inode_dir_map = 0;
949 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
950 ctx->inode_reg_map = 0;
951 ext2fs_free_block_bitmap(ctx->block_found_map);
952 ctx->block_found_map = 0;
953 ext2fs_free_icount(ctx->inode_link_info);
954 ctx->inode_link_info = 0;
955 if (ctx->journal_io) {
956 if (ctx->fs && ctx->fs->io != ctx->journal_io)
957 io_channel_close(ctx->journal_io);
958 ctx->journal_io = 0;
959 }
960 if (ctx->fs) {
961 ext2fs_free_dblist(ctx->fs->dblist);
962 ctx->fs->dblist = 0;
963 }
964 e2fsck_free_dir_info(ctx);
965#ifdef ENABLE_HTREE
966 e2fsck_free_dx_dir_info(ctx);
967#endif
968 ea_refcount_free(ctx->refcount);
969 ctx->refcount = 0;
970 ea_refcount_free(ctx->refcount_extra);
971 ctx->refcount_extra = 0;
972 ext2fs_free_block_bitmap(ctx->block_dup_map);
973 ctx->block_dup_map = 0;
974 ext2fs_free_block_bitmap(ctx->block_ea_map);
975 ctx->block_ea_map = 0;
976 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
977 ctx->inode_bad_map = 0;
978 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
979 ctx->inode_imagic_map = 0;
980 ext2fs_u32_list_free(ctx->dirs_to_hash);
981 ctx->dirs_to_hash = 0;
982
983 /*
984 * Clear the array of invalid meta-data flags
985 */
986 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
987 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
988 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
989
990 /* Clear statistic counters */
991 ctx->fs_directory_count = 0;
992 ctx->fs_regular_count = 0;
993 ctx->fs_blockdev_count = 0;
994 ctx->fs_chardev_count = 0;
995 ctx->fs_links_count = 0;
996 ctx->fs_symlinks_count = 0;
997 ctx->fs_fast_symlinks_count = 0;
998 ctx->fs_fifo_count = 0;
999 ctx->fs_total_count = 0;
1000 ctx->fs_sockets_count = 0;
1001 ctx->fs_ind_count = 0;
1002 ctx->fs_dind_count = 0;
1003 ctx->fs_tind_count = 0;
1004 ctx->fs_fragmented = 0;
1005 ctx->large_files = 0;
1006
1007 /* Reset the superblock to the user's requested value */
1008 ctx->superblock = ctx->use_superblock;
1009
1010 return 0;
1011}
1012
1013static void e2fsck_free_context(e2fsck_t ctx)
1014{
1015 if (!ctx)
1016 return;
1017
1018 e2fsck_reset_context(ctx);
1019 if (ctx->blkid)
1020 blkid_put_cache(ctx->blkid);
1021
1022 ext2fs_free_mem(&ctx);
1023}
1024
1025/*
1026 * ea_refcount.c
1027 */
1028
1029/*
1030 * The strategy we use for keeping track of EA refcounts is as
1031 * follows. We keep a sorted array of first EA blocks and its
1032 * reference counts. Once the refcount has dropped to zero, it is
1033 * removed from the array to save memory space. Once the EA block is
1034 * checked, its bit is set in the block_ea_map bitmap.
1035 */
1036
1037
1038static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1039{
1040 ext2_refcount_t refcount;
1041 errcode_t retval;
1042 size_t bytes;
1043
1044 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1045 if (retval)
1046 return retval;
1047 memset(refcount, 0, sizeof(struct ea_refcount));
1048
1049 if (!size)
1050 size = 500;
1051 refcount->size = size;
1052 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1053#ifdef DEBUG
1054 printf("Refcount allocated %d entries, %d bytes.\n",
1055 refcount->size, bytes);
1056#endif
1057 retval = ext2fs_get_mem(bytes, &refcount->list);
1058 if (retval)
1059 goto errout;
1060 memset(refcount->list, 0, bytes);
1061
1062 refcount->count = 0;
1063 refcount->cursor = 0;
1064
1065 *ret = refcount;
1066 return 0;
1067
1068errout:
1069 ea_refcount_free(refcount);
1070 return retval;
1071}
1072
1073/*
1074 * collapse_refcount() --- go through the refcount array, and get rid
1075 * of any count == zero entries
1076 */
1077static void refcount_collapse(ext2_refcount_t refcount)
1078{
1079 unsigned int i, j;
1080 struct ea_refcount_el *list;
1081
1082 list = refcount->list;
1083 for (i = 0, j = 0; i < refcount->count; i++) {
1084 if (list[i].ea_count) {
1085 if (i != j)
1086 list[j] = list[i];
1087 j++;
1088 }
1089 }
1090#if defined(DEBUG) || defined(TEST_PROGRAM)
1091 printf("Refcount_collapse: size was %d, now %d\n",
1092 refcount->count, j);
1093#endif
1094 refcount->count = j;
1095}
1096
1097
1098/*
1099 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1100 * specified position.
1101 */
1102static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1103 blk_t blk, int pos)
1104{
1105 struct ea_refcount_el *el;
1106 errcode_t retval;
1107 blk_t new_size = 0;
1108 int num;
1109
1110 if (refcount->count >= refcount->size) {
1111 new_size = refcount->size + 100;
1112#ifdef DEBUG
1113 printf("Reallocating refcount %d entries...\n", new_size);
1114#endif
1115 retval = ext2fs_resize_mem((size_t) refcount->size *
1116 sizeof(struct ea_refcount_el),
1117 (size_t) new_size *
1118 sizeof(struct ea_refcount_el),
1119 &refcount->list);
1120 if (retval)
1121 return 0;
1122 refcount->size = new_size;
1123 }
1124 num = (int) refcount->count - pos;
1125 if (num < 0)
1126 return 0; /* should never happen */
1127 if (num) {
1128 memmove(&refcount->list[pos+1], &refcount->list[pos],
1129 sizeof(struct ea_refcount_el) * num);
1130 }
1131 refcount->count++;
1132 el = &refcount->list[pos];
1133 el->ea_count = 0;
1134 el->ea_blk = blk;
1135 return el;
1136}
1137
1138
1139/*
1140 * get_refcount_el() --- given an block number, try to find refcount
1141 * information in the sorted list. If the create flag is set,
1142 * and we can't find an entry, create one in the sorted list.
1143 */
1144static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1145 blk_t blk, int create)
1146{
1147 float range;
1148 int low, high, mid;
1149 blk_t lowval, highval;
1150
1151 if (!refcount || !refcount->list)
1152 return 0;
1153retry:
1154 low = 0;
1155 high = (int) refcount->count-1;
1156 if (create && ((refcount->count == 0) ||
1157 (blk > refcount->list[high].ea_blk))) {
1158 if (refcount->count >= refcount->size)
1159 refcount_collapse(refcount);
1160
1161 return insert_refcount_el(refcount, blk,
1162 (unsigned) refcount->count);
1163 }
1164 if (refcount->count == 0)
1165 return 0;
1166
1167 if (refcount->cursor >= refcount->count)
1168 refcount->cursor = 0;
1169 if (blk == refcount->list[refcount->cursor].ea_blk)
1170 return &refcount->list[refcount->cursor++];
1171#ifdef DEBUG
1172 printf("Non-cursor get_refcount_el: %u\n", blk);
1173#endif
1174 while (low <= high) {
1175 if (low == high)
1176 mid = low;
1177 else {
1178 /* Interpolate for efficiency */
1179 lowval = refcount->list[low].ea_blk;
1180 highval = refcount->list[high].ea_blk;
1181
1182 if (blk < lowval)
1183 range = 0;
1184 else if (blk > highval)
1185 range = 1;
1186 else
1187 range = ((float) (blk - lowval)) /
1188 (highval - lowval);
1189 mid = low + ((int) (range * (high-low)));
1190 }
1191
1192 if (blk == refcount->list[mid].ea_blk) {
1193 refcount->cursor = mid+1;
1194 return &refcount->list[mid];
1195 }
1196 if (blk < refcount->list[mid].ea_blk)
1197 high = mid-1;
1198 else
1199 low = mid+1;
1200 }
1201 /*
1202 * If we need to create a new entry, it should be right at
1203 * low (where high will be left at low-1).
1204 */
1205 if (create) {
1206 if (refcount->count >= refcount->size) {
1207 refcount_collapse(refcount);
1208 if (refcount->count < refcount->size)
1209 goto retry;
1210 }
1211 return insert_refcount_el(refcount, blk, low);
1212 }
1213 return 0;
1214}
1215
1216static errcode_t
1217ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1218{
1219 struct ea_refcount_el *el;
1220
1221 el = get_refcount_el(refcount, blk, 1);
1222 if (!el)
1223 return EXT2_ET_NO_MEMORY;
1224 el->ea_count++;
1225
1226 if (ret)
1227 *ret = el->ea_count;
1228 return 0;
1229}
1230
1231static errcode_t
1232ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1233{
1234 struct ea_refcount_el *el;
1235
1236 el = get_refcount_el(refcount, blk, 0);
1237 if (!el || el->ea_count == 0)
1238 return EXT2_ET_INVALID_ARGUMENT;
1239
1240 el->ea_count--;
1241
1242 if (ret)
1243 *ret = el->ea_count;
1244 return 0;
1245}
1246
1247static errcode_t
1248ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1249{
1250 struct ea_refcount_el *el;
1251
1252 /*
1253 * Get the refcount element
1254 */
1255 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1256 if (!el)
1257 return count ? EXT2_ET_NO_MEMORY : 0;
1258 el->ea_count = count;
1259 return 0;
1260}
1261
1262static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1263{
1264 refcount->cursor = 0;
1265}
1266
1267
1268static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1269{
1270 struct ea_refcount_el *list;
1271
1272 while (1) {
1273 if (refcount->cursor >= refcount->count)
1274 return 0;
1275 list = refcount->list;
1276 if (list[refcount->cursor].ea_count) {
1277 if (ret)
1278 *ret = list[refcount->cursor].ea_count;
1279 return list[refcount->cursor++].ea_blk;
1280 }
1281 refcount->cursor++;
1282 }
1283}
1284
1285
1286/*
1287 * ehandler.c --- handle bad block errors which come up during the
1288 * course of an e2fsck session.
1289 */
1290
1291
1292static const char *operation;
1293
1294static errcode_t
1295e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1296 void *data, size_t size FSCK_ATTR((unused)),
1297 int actual FSCK_ATTR((unused)), errcode_t error)
1298{
1299 int i;
1300 char *p;
1301 ext2_filsys fs = (ext2_filsys) channel->app_data;
1302 e2fsck_t ctx;
1303
1304 ctx = (e2fsck_t) fs->priv_data;
1305
1306 /*
1307 * If more than one block was read, try reading each block
1308 * separately. We could use the actual bytes read to figure
1309 * out where to start, but we don't bother.
1310 */
1311 if (count > 1) {
1312 p = (char *) data;
1313 for (i=0; i < count; i++, p += channel->block_size, block++) {
1314 error = io_channel_read_blk(channel, block,
1315 1, p);
1316 if (error)
1317 return error;
1318 }
1319 return 0;
1320 }
1321 if (operation)
1322 printf(_("Error reading block %lu (%s) while %s. "), block,
1323 error_message(error), operation);
1324 else
1325 printf(_("Error reading block %lu (%s). "), block,
1326 error_message(error));
1327 preenhalt(ctx);
1328 if (ask(ctx, _("Ignore error"), 1)) {
1329 if (ask(ctx, _("Force rewrite"), 1))
1330 io_channel_write_blk(channel, block, 1, data);
1331 return 0;
1332 }
1333
1334 return error;
1335}
1336
1337static errcode_t
1338e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1339 const void *data, size_t size FSCK_ATTR((unused)),
1340 int actual FSCK_ATTR((unused)), errcode_t error)
1341{
1342 int i;
1343 const char *p;
1344 ext2_filsys fs = (ext2_filsys) channel->app_data;
1345 e2fsck_t ctx;
1346
1347 ctx = (e2fsck_t) fs->priv_data;
1348
1349 /*
1350 * If more than one block was written, try writing each block
1351 * separately. We could use the actual bytes read to figure
1352 * out where to start, but we don't bother.
1353 */
1354 if (count > 1) {
1355 p = (const char *) data;
1356 for (i=0; i < count; i++, p += channel->block_size, block++) {
1357 error = io_channel_write_blk(channel, block,
1358 1, p);
1359 if (error)
1360 return error;
1361 }
1362 return 0;
1363 }
1364
1365 if (operation)
1366 printf(_("Error writing block %lu (%s) while %s. "), block,
1367 error_message(error), operation);
1368 else
1369 printf(_("Error writing block %lu (%s). "), block,
1370 error_message(error));
1371 preenhalt(ctx);
1372 if (ask(ctx, _("Ignore error"), 1))
1373 return 0;
1374
1375 return error;
1376}
1377
1378static const char *ehandler_operation(const char *op)
1379{
1380 const char *ret = operation;
1381
1382 operation = op;
1383 return ret;
1384}
1385
1386static void ehandler_init(io_channel channel)
1387{
1388 channel->read_error = e2fsck_handle_read_error;
1389 channel->write_error = e2fsck_handle_write_error;
1390}
1391
1392/*
1393 * journal.c --- code for handling the "ext3" journal
1394 *
1395 * Copyright (C) 2000 Andreas Dilger
1396 * Copyright (C) 2000 Theodore Ts'o
1397 *
1398 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1399 * Copyright (C) 1999 Red Hat Software
1400 *
1401 * This file may be redistributed under the terms of the
1402 * GNU General Public License version 2 or at your discretion
1403 * any later version.
1404 */
1405
1406/*
1407 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1408 * This creates a larger static binary, and a smaller binary using
1409 * shared libraries. It's also probably slightly less CPU-efficient,
1410 * which is why it's not on by default. But, it's a good way of
1411 * testing the functions in inode_io.c and fileio.c.
1412 */
1413#undef USE_INODE_IO
1414
1415/* Kernel compatibility functions for handling the journal. These allow us
1416 * to use the recovery.c file virtually unchanged from the kernel, so we
1417 * don't have to do much to keep kernel and user recovery in sync.
1418 */
1419static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1420{
1421#ifdef USE_INODE_IO
1422 *phys = block;
1423 return 0;
1424#else
1425 struct inode *inode = journal->j_inode;
1426 errcode_t retval;
1427 blk_t pblk;
1428
1429 if (!inode) {
1430 *phys = block;
1431 return 0;
1432 }
1433
1434 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1435 &inode->i_ext2, NULL, 0, block, &pblk);
1436 *phys = pblk;
1437 return retval;
1438#endif
1439}
1440
1441static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1442{
1443 struct buffer_head *bh;
1444
1445 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1446 if (!bh)
1447 return NULL;
1448
1449 bh->b_ctx = kdev->k_ctx;
1450 if (kdev->k_dev == K_DEV_FS)
1451 bh->b_io = kdev->k_ctx->fs->io;
1452 else
1453 bh->b_io = kdev->k_ctx->journal_io;
1454 bh->b_size = blocksize;
1455 bh->b_blocknr = blocknr;
1456
1457 return bh;
1458}
1459
1460static void sync_blockdev(kdev_t kdev)
1461{
1462 io_channel io;
1463
1464 if (kdev->k_dev == K_DEV_FS)
1465 io = kdev->k_ctx->fs->io;
1466 else
1467 io = kdev->k_ctx->journal_io;
1468
1469 io_channel_flush(io);
1470}
1471
1472static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1473{
1474 int retval;
1475 struct buffer_head *bh;
1476
1477 for (; nr > 0; --nr) {
1478 bh = *bhp++;
1479 if (rw == READ && !bh->b_uptodate) {
1480 retval = io_channel_read_blk(bh->b_io,
1481 bh->b_blocknr,
1482 1, bh->b_data);
1483 if (retval) {
1484 bb_error_msg("while reading block %lu",
1485 (unsigned long) bh->b_blocknr);
1486 bh->b_err = retval;
1487 continue;
1488 }
1489 bh->b_uptodate = 1;
1490 } else if (rw == WRITE && bh->b_dirty) {
1491 retval = io_channel_write_blk(bh->b_io,
1492 bh->b_blocknr,
1493 1, bh->b_data);
1494 if (retval) {
1495 bb_error_msg("while writing block %lu",
1496 (unsigned long) bh->b_blocknr);
1497 bh->b_err = retval;
1498 continue;
1499 }
1500 bh->b_dirty = 0;
1501 bh->b_uptodate = 1;
1502 }
1503 }
1504}
1505
1506static void mark_buffer_dirty(struct buffer_head *bh)
1507{
1508 bh->b_dirty = 1;
1509}
1510
1511static inline void mark_buffer_clean(struct buffer_head * bh)
1512{
1513 bh->b_dirty = 0;
1514}
1515
1516static void brelse(struct buffer_head *bh)
1517{
1518 if (bh->b_dirty)
1519 ll_rw_block(WRITE, 1, &bh);
1520 ext2fs_free_mem(&bh);
1521}
1522
1523static int buffer_uptodate(struct buffer_head *bh)
1524{
1525 return bh->b_uptodate;
1526}
1527
1528static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1529{
1530 bh->b_uptodate = val;
1531}
1532
1533static void wait_on_buffer(struct buffer_head *bh)
1534{
1535 if (!bh->b_uptodate)
1536 ll_rw_block(READ, 1, &bh);
1537}
1538
1539
1540static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1541{
1542 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1543
1544 /* if we had an error doing journal recovery, we need a full fsck */
1545 if (error)
1546 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1547 ext2fs_mark_super_dirty(ctx->fs);
1548}
1549
1550static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1551{
1552 struct ext2_super_block *sb = ctx->fs->super;
1553 struct ext2_super_block jsuper;
1554 struct problem_context pctx;
1555 struct buffer_head *bh;
1556 struct inode *j_inode = NULL;
1557 struct kdev_s *dev_fs = NULL, *dev_journal;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01001558 const char *journal_name = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001559 journal_t *journal = NULL;
1560 errcode_t retval = 0;
1561 io_manager io_ptr = 0;
1562 unsigned long start = 0;
1563 blk_t blk;
1564 int ext_journal = 0;
1565 int tried_backup_jnl = 0;
1566 int i;
1567
1568 clear_problem_context(&pctx);
1569
1570 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1571 if (!journal) {
1572 return EXT2_ET_NO_MEMORY;
1573 }
1574
1575 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1576 if (!dev_fs) {
1577 retval = EXT2_ET_NO_MEMORY;
1578 goto errout;
1579 }
1580 dev_journal = dev_fs+1;
1581
1582 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1583 dev_fs->k_dev = K_DEV_FS;
1584 dev_journal->k_dev = K_DEV_JOURNAL;
1585
1586 journal->j_dev = dev_journal;
1587 journal->j_fs_dev = dev_fs;
1588 journal->j_inode = NULL;
1589 journal->j_blocksize = ctx->fs->blocksize;
1590
1591 if (uuid_is_null(sb->s_journal_uuid)) {
1592 if (!sb->s_journal_inum)
1593 return EXT2_ET_BAD_INODE_NUM;
1594 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1595 "journal inode");
1596 if (!j_inode) {
1597 retval = EXT2_ET_NO_MEMORY;
1598 goto errout;
1599 }
1600
1601 j_inode->i_ctx = ctx;
1602 j_inode->i_ino = sb->s_journal_inum;
1603
1604 if ((retval = ext2fs_read_inode(ctx->fs,
1605 sb->s_journal_inum,
1606 &j_inode->i_ext2))) {
1607 try_backup_journal:
1608 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1609 tried_backup_jnl)
1610 goto errout;
1611 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1612 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1613 EXT2_N_BLOCKS*4);
1614 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1615 j_inode->i_ext2.i_links_count = 1;
1616 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1617 tried_backup_jnl++;
1618 }
1619 if (!j_inode->i_ext2.i_links_count ||
1620 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1621 retval = EXT2_ET_NO_JOURNAL;
1622 goto try_backup_journal;
1623 }
1624 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1625 JFS_MIN_JOURNAL_BLOCKS) {
1626 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1627 goto try_backup_journal;
1628 }
1629 for (i=0; i < EXT2_N_BLOCKS; i++) {
1630 blk = j_inode->i_ext2.i_block[i];
1631 if (!blk) {
1632 if (i < EXT2_NDIR_BLOCKS) {
1633 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1634 goto try_backup_journal;
1635 }
1636 continue;
1637 }
1638 if (blk < sb->s_first_data_block ||
1639 blk >= sb->s_blocks_count) {
1640 retval = EXT2_ET_BAD_BLOCK_NUM;
1641 goto try_backup_journal;
1642 }
1643 }
1644 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1645
1646#ifdef USE_INODE_IO
1647 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1648 &j_inode->i_ext2,
1649 &journal_name);
1650 if (retval)
1651 goto errout;
1652
1653 io_ptr = inode_io_manager;
1654#else
1655 journal->j_inode = j_inode;
1656 ctx->journal_io = ctx->fs->io;
1657 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1658 goto errout;
1659#endif
1660 } else {
1661 ext_journal = 1;
1662 if (!ctx->journal_name) {
1663 char uuid[37];
1664
1665 uuid_unparse(sb->s_journal_uuid, uuid);
1666 ctx->journal_name = blkid_get_devname(ctx->blkid,
1667 "UUID", uuid);
1668 if (!ctx->journal_name)
1669 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1670 }
1671 journal_name = ctx->journal_name;
1672
1673 if (!journal_name) {
1674 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1675 return EXT2_ET_LOAD_EXT_JOURNAL;
1676 }
1677
1678 io_ptr = unix_io_manager;
1679 }
1680
1681#ifndef USE_INODE_IO
1682 if (ext_journal)
1683#endif
1684 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1685 &ctx->journal_io);
1686 if (retval)
1687 goto errout;
1688
1689 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1690
1691 if (ext_journal) {
1692 if (ctx->fs->blocksize == 1024)
1693 start = 1;
1694 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1695 if (!bh) {
1696 retval = EXT2_ET_NO_MEMORY;
1697 goto errout;
1698 }
1699 ll_rw_block(READ, 1, &bh);
1700 if ((retval = bh->b_err) != 0)
1701 goto errout;
1702 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1703 sizeof(jsuper));
1704 brelse(bh);
1705#if BB_BIG_ENDIAN
1706 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1707 ext2fs_swap_super(&jsuper);
1708#endif
1709 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1710 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1711 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1712 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1713 goto errout;
1714 }
1715 /* Make sure the journal UUID is correct */
1716 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1717 sizeof(jsuper.s_uuid))) {
1718 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1719 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1720 goto errout;
1721 }
1722
1723 journal->j_maxlen = jsuper.s_blocks_count;
1724 start++;
1725 }
1726
1727 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1728 retval = EXT2_ET_NO_MEMORY;
1729 goto errout;
1730 }
1731
1732 journal->j_sb_buffer = bh;
1733 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1734
1735#ifdef USE_INODE_IO
1736 ext2fs_free_mem(&j_inode);
1737#endif
1738
1739 *ret_journal = journal;
1740 return 0;
1741
1742errout:
1743 ext2fs_free_mem(&dev_fs);
1744 ext2fs_free_mem(&j_inode);
1745 ext2fs_free_mem(&journal);
1746 return retval;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001747}
1748
1749static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1750 struct problem_context *pctx)
1751{
1752 struct ext2_super_block *sb = ctx->fs->super;
1753 int recover = ctx->fs->super->s_feature_incompat &
1754 EXT3_FEATURE_INCOMPAT_RECOVER;
1755 int has_journal = ctx->fs->super->s_feature_compat &
1756 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1757
1758 if (has_journal || sb->s_journal_inum) {
1759 /* The journal inode is bogus, remove and force full fsck */
1760 pctx->ino = sb->s_journal_inum;
1761 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1762 if (has_journal && sb->s_journal_inum)
1763 printf("*** ext3 journal has been deleted - "
1764 "filesystem is now ext2 only ***\n\n");
1765 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1766 sb->s_journal_inum = 0;
1767 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1768 e2fsck_clear_recover(ctx, 1);
1769 return 0;
1770 }
1771 return EXT2_ET_BAD_INODE_NUM;
1772 } else if (recover) {
1773 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1774 e2fsck_clear_recover(ctx, 1);
1775 return 0;
1776 }
1777 return EXT2_ET_UNSUPP_FEATURE;
1778 }
1779 return 0;
1780}
1781
1782#define V1_SB_SIZE 0x0024
1783static void clear_v2_journal_fields(journal_t *journal)
1784{
1785 e2fsck_t ctx = journal->j_dev->k_ctx;
1786 struct problem_context pctx;
1787
1788 clear_problem_context(&pctx);
1789
1790 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1791 return;
1792
1793 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1794 ctx->fs->blocksize-V1_SB_SIZE);
1795 mark_buffer_dirty(journal->j_sb_buffer);
1796}
1797
1798
1799static errcode_t e2fsck_journal_load(journal_t *journal)
1800{
1801 e2fsck_t ctx = journal->j_dev->k_ctx;
1802 journal_superblock_t *jsb;
1803 struct buffer_head *jbh = journal->j_sb_buffer;
1804 struct problem_context pctx;
1805
1806 clear_problem_context(&pctx);
1807
1808 ll_rw_block(READ, 1, &jbh);
1809 if (jbh->b_err) {
1810 bb_error_msg(_("reading journal superblock"));
1811 return jbh->b_err;
1812 }
1813
1814 jsb = journal->j_superblock;
1815 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1816 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1817 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1818
1819 switch (ntohl(jsb->s_header.h_blocktype)) {
1820 case JFS_SUPERBLOCK_V1:
1821 journal->j_format_version = 1;
1822 if (jsb->s_feature_compat ||
1823 jsb->s_feature_incompat ||
1824 jsb->s_feature_ro_compat ||
1825 jsb->s_nr_users)
1826 clear_v2_journal_fields(journal);
1827 break;
1828
1829 case JFS_SUPERBLOCK_V2:
1830 journal->j_format_version = 2;
1831 if (ntohl(jsb->s_nr_users) > 1 &&
1832 uuid_is_null(ctx->fs->super->s_journal_uuid))
1833 clear_v2_journal_fields(journal);
1834 if (ntohl(jsb->s_nr_users) > 1) {
1835 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1836 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1837 }
1838 break;
1839
1840 /*
1841 * These should never appear in a journal super block, so if
1842 * they do, the journal is badly corrupted.
1843 */
1844 case JFS_DESCRIPTOR_BLOCK:
1845 case JFS_COMMIT_BLOCK:
1846 case JFS_REVOKE_BLOCK:
1847 return EXT2_ET_CORRUPT_SUPERBLOCK;
1848
1849 /* If we don't understand the superblock major type, but there
1850 * is a magic number, then it is likely to be a new format we
1851 * just don't understand, so leave it alone. */
1852 default:
1853 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1854 }
1855
1856 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1857 return EXT2_ET_UNSUPP_FEATURE;
1858
1859 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1860 return EXT2_ET_RO_UNSUPP_FEATURE;
1861
1862 /* We have now checked whether we know enough about the journal
1863 * format to be able to proceed safely, so any other checks that
1864 * fail we should attempt to recover from. */
1865 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1866 bb_error_msg(_("%s: no valid journal superblock found"),
1867 ctx->device_name);
1868 return EXT2_ET_CORRUPT_SUPERBLOCK;
1869 }
1870
1871 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1872 journal->j_maxlen = ntohl(jsb->s_maxlen);
1873 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1874 bb_error_msg(_("%s: journal too short"),
1875 ctx->device_name);
1876 return EXT2_ET_CORRUPT_SUPERBLOCK;
1877 }
1878
1879 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1880 journal->j_transaction_sequence = journal->j_tail_sequence;
1881 journal->j_tail = ntohl(jsb->s_start);
1882 journal->j_first = ntohl(jsb->s_first);
1883 journal->j_last = ntohl(jsb->s_maxlen);
1884
1885 return 0;
1886}
1887
1888static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1889 journal_t *journal)
1890{
1891 char *p;
1892 union {
1893 uuid_t uuid;
1894 __u32 val[4];
1895 } u;
1896 __u32 new_seq = 0;
1897 int i;
1898
1899 /* Leave a valid existing V1 superblock signature alone.
Denys Vlasenkob22bbff2009-07-04 16:50:43 +02001900 * Anything unrecognizable we overwrite with a new V2
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001901 * signature. */
1902
1903 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1904 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1905 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1906 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1907 }
1908
1909 /* Zero out everything else beyond the superblock header */
1910
1911 p = ((char *) jsb) + sizeof(journal_header_t);
1912 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1913
1914 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1915 jsb->s_maxlen = htonl(journal->j_maxlen);
1916 jsb->s_first = htonl(1);
1917
1918 /* Initialize the journal sequence number so that there is "no"
1919 * chance we will find old "valid" transactions in the journal.
1920 * This avoids the need to zero the whole journal (slow to do,
1921 * and risky when we are just recovering the filesystem).
1922 */
1923 uuid_generate(u.uuid);
1924 for (i = 0; i < 4; i ++)
1925 new_seq ^= u.val[i];
1926 jsb->s_sequence = htonl(new_seq);
1927
1928 mark_buffer_dirty(journal->j_sb_buffer);
1929 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1930}
1931
1932static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1933 journal_t *journal,
1934 struct problem_context *pctx)
1935{
1936 struct ext2_super_block *sb = ctx->fs->super;
1937 int recover = ctx->fs->super->s_feature_incompat &
1938 EXT3_FEATURE_INCOMPAT_RECOVER;
1939
1940 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1941 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1942 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1943 journal);
1944 journal->j_transaction_sequence = 1;
1945 e2fsck_clear_recover(ctx, recover);
1946 return 0;
1947 }
1948 return EXT2_ET_CORRUPT_SUPERBLOCK;
1949 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1950 return EXT2_ET_CORRUPT_SUPERBLOCK;
1951
1952 return 0;
1953}
1954
1955static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1956 int reset, int drop)
1957{
1958 journal_superblock_t *jsb;
1959
1960 if (drop)
1961 mark_buffer_clean(journal->j_sb_buffer);
1962 else if (!(ctx->options & E2F_OPT_READONLY)) {
1963 jsb = journal->j_superblock;
1964 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1965 if (reset)
1966 jsb->s_start = 0; /* this marks the journal as empty */
1967 mark_buffer_dirty(journal->j_sb_buffer);
1968 }
1969 brelse(journal->j_sb_buffer);
1970
1971 if (ctx->journal_io) {
1972 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1973 io_channel_close(ctx->journal_io);
1974 ctx->journal_io = 0;
1975 }
1976
1977#ifndef USE_INODE_IO
1978 ext2fs_free_mem(&journal->j_inode);
1979#endif
1980 ext2fs_free_mem(&journal->j_fs_dev);
1981 ext2fs_free_mem(&journal);
1982}
1983
1984/*
1985 * This function makes sure that the superblock fields regarding the
1986 * journal are consistent.
1987 */
1988static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1989{
1990 struct ext2_super_block *sb = ctx->fs->super;
1991 journal_t *journal;
1992 int recover = ctx->fs->super->s_feature_incompat &
1993 EXT3_FEATURE_INCOMPAT_RECOVER;
1994 struct problem_context pctx;
1995 problem_t problem;
1996 int reset = 0, force_fsck = 0;
1997 int retval;
1998
1999 /* If we don't have any journal features, don't do anything more */
2000 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2001 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2002 uuid_is_null(sb->s_journal_uuid))
2003 return 0;
2004
2005 clear_problem_context(&pctx);
2006 pctx.num = sb->s_journal_inum;
2007
2008 retval = e2fsck_get_journal(ctx, &journal);
2009 if (retval) {
2010 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
2011 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
2012 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
2013 (retval == EXT2_ET_NO_JOURNAL))
2014 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2015 return retval;
2016 }
2017
2018 retval = e2fsck_journal_load(journal);
2019 if (retval) {
2020 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2021 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2022 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2023 &pctx))) ||
2024 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2025 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2026 &pctx))) ||
2027 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2028 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2029 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2030 &pctx);
2031 e2fsck_journal_release(ctx, journal, 0, 1);
2032 return retval;
2033 }
2034
2035 /*
2036 * We want to make the flags consistent here. We will not leave with
2037 * needs_recovery set but has_journal clear. We can't get in a loop
2038 * with -y, -n, or -p, only if a user isn't making up their mind.
2039 */
2040no_has_journal:
2041 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2042 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2043 pctx.str = "inode";
2044 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2045 if (recover &&
2046 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2047 goto no_has_journal;
2048 /*
2049 * Need a full fsck if we are releasing a
2050 * journal stored on a reserved inode.
2051 */
2052 force_fsck = recover ||
2053 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2054 /* Clear all of the journal fields */
2055 sb->s_journal_inum = 0;
2056 sb->s_journal_dev = 0;
2057 memset(sb->s_journal_uuid, 0,
2058 sizeof(sb->s_journal_uuid));
2059 e2fsck_clear_recover(ctx, force_fsck);
2060 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2061 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2062 ext2fs_mark_super_dirty(ctx->fs);
2063 }
2064 }
2065
2066 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2067 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2068 journal->j_superblock->s_start != 0) {
2069 /* Print status information */
2070 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2071 if (ctx->superblock)
2072 problem = PR_0_JOURNAL_RUN_DEFAULT;
2073 else
2074 problem = PR_0_JOURNAL_RUN;
2075 if (fix_problem(ctx, problem, &pctx)) {
2076 ctx->options |= E2F_OPT_FORCE;
2077 sb->s_feature_incompat |=
2078 EXT3_FEATURE_INCOMPAT_RECOVER;
2079 ext2fs_mark_super_dirty(ctx->fs);
2080 } else if (fix_problem(ctx,
2081 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2082 reset = 1;
2083 sb->s_state &= ~EXT2_VALID_FS;
2084 ext2fs_mark_super_dirty(ctx->fs);
2085 }
2086 /*
2087 * If the user answers no to the above question, we
2088 * ignore the fact that journal apparently has data;
2089 * accidentally replaying over valid data would be far
2090 * worse than skipping a questionable recovery.
2091 *
2092 * XXX should we abort with a fatal error here? What
2093 * will the ext3 kernel code do if a filesystem with
2094 * !NEEDS_RECOVERY but with a non-zero
2095 * journal->j_superblock->s_start is mounted?
2096 */
2097 }
2098
2099 e2fsck_journal_release(ctx, journal, reset, 0);
2100 return retval;
2101}
2102
2103static errcode_t recover_ext3_journal(e2fsck_t ctx)
2104{
2105 journal_t *journal;
2106 int retval;
2107
2108 journal_init_revoke_caches();
2109 retval = e2fsck_get_journal(ctx, &journal);
2110 if (retval)
2111 return retval;
2112
2113 retval = e2fsck_journal_load(journal);
2114 if (retval)
2115 goto errout;
2116
2117 retval = journal_init_revoke(journal, 1024);
2118 if (retval)
2119 goto errout;
2120
2121 retval = -journal_recover(journal);
2122 if (retval)
2123 goto errout;
2124
2125 if (journal->j_superblock->s_errno) {
2126 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2127 ext2fs_mark_super_dirty(ctx->fs);
2128 journal->j_superblock->s_errno = 0;
2129 mark_buffer_dirty(journal->j_sb_buffer);
2130 }
2131
2132errout:
2133 journal_destroy_revoke(journal);
2134 journal_destroy_revoke_caches();
2135 e2fsck_journal_release(ctx, journal, 1, 0);
2136 return retval;
2137}
2138
2139static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2140{
2141 io_manager io_ptr = ctx->fs->io->manager;
2142 int blocksize = ctx->fs->blocksize;
2143 errcode_t retval, recover_retval;
2144
2145 printf(_("%s: recovering journal\n"), ctx->device_name);
2146 if (ctx->options & E2F_OPT_READONLY) {
2147 printf(_("%s: won't do journal recovery while read-only\n"),
2148 ctx->device_name);
2149 return EXT2_ET_FILE_RO;
2150 }
2151
2152 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2153 ext2fs_flush(ctx->fs); /* Force out any modifications */
2154
2155 recover_retval = recover_ext3_journal(ctx);
2156
2157 /*
2158 * Reload the filesystem context to get up-to-date data from disk
2159 * because journal recovery will change the filesystem under us.
2160 */
2161 ext2fs_close(ctx->fs);
2162 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2163 ctx->superblock, blocksize, io_ptr,
2164 &ctx->fs);
2165
2166 if (retval) {
2167 bb_error_msg(_("while trying to re-open %s"),
2168 ctx->device_name);
2169 bb_error_msg_and_die(0);
2170 }
2171 ctx->fs->priv_data = ctx;
2172
2173 /* Set the superblock flags */
2174 e2fsck_clear_recover(ctx, recover_retval);
2175 return recover_retval;
2176}
2177
2178/*
2179 * This function will move the journal inode from a visible file in
2180 * the filesystem directory hierarchy to the reserved inode if necessary.
2181 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002182static const char *const journal_names[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002183 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2184
2185static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2186{
2187 struct ext2_super_block *sb = ctx->fs->super;
2188 struct problem_context pctx;
2189 struct ext2_inode inode;
2190 ext2_filsys fs = ctx->fs;
2191 ext2_ino_t ino;
2192 errcode_t retval;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002193 const char *const * cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002194 int group, mount_flags;
2195
2196 clear_problem_context(&pctx);
2197
2198 /*
2199 * If the filesystem is opened read-only, or there is no
2200 * journal, then do nothing.
2201 */
2202 if ((ctx->options & E2F_OPT_READONLY) ||
2203 (sb->s_journal_inum == 0) ||
2204 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2205 return;
2206
2207 /*
2208 * Read in the journal inode
2209 */
2210 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2211 return;
2212
2213 /*
2214 * If it's necessary to backup the journal inode, do so.
2215 */
2216 if ((sb->s_jnl_backup_type == 0) ||
2217 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2218 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2219 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2220 memcpy(sb->s_jnl_blocks, inode.i_block,
2221 EXT2_N_BLOCKS*4);
2222 sb->s_jnl_blocks[16] = inode.i_size;
2223 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2224 ext2fs_mark_super_dirty(fs);
2225 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2226 }
2227 }
2228
2229 /*
2230 * If the journal is already the hidden inode, then do nothing
2231 */
2232 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2233 return;
2234
2235 /*
2236 * The journal inode had better have only one link and not be readable.
2237 */
2238 if (inode.i_links_count != 1)
2239 return;
2240
2241 /*
2242 * If the filesystem is mounted, or we can't tell whether
2243 * or not it's mounted, do nothing.
2244 */
2245 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2246 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2247 return;
2248
2249 /*
2250 * If we can't find the name of the journal inode, then do
2251 * nothing.
2252 */
2253 for (cpp = journal_names; *cpp; cpp++) {
2254 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2255 strlen(*cpp), 0, &ino);
2256 if ((retval == 0) && (ino == sb->s_journal_inum))
2257 break;
2258 }
2259 if (*cpp == 0)
2260 return;
2261
2262 /* We need the inode bitmap to be loaded */
2263 retval = ext2fs_read_bitmaps(fs);
2264 if (retval)
2265 return;
2266
2267 pctx.str = *cpp;
2268 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2269 return;
2270
2271 /*
2272 * OK, we've done all the checks, let's actually move the
2273 * journal inode. Errors at this point mean we need to force
2274 * an ext2 filesystem check.
2275 */
2276 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2277 goto err_out;
2278 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2279 goto err_out;
2280 sb->s_journal_inum = EXT2_JOURNAL_INO;
2281 ext2fs_mark_super_dirty(fs);
2282 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2283 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00002284 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002285 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2286 goto err_out;
2287
2288 group = ext2fs_group_of_ino(fs, ino);
2289 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2290 ext2fs_mark_ib_dirty(fs);
2291 fs->group_desc[group].bg_free_inodes_count++;
2292 fs->super->s_free_inodes_count++;
2293 return;
2294
2295err_out:
2296 pctx.errcode = retval;
2297 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2298 fs->super->s_state &= ~EXT2_VALID_FS;
2299 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002300}
2301
2302/*
2303 * message.c --- print e2fsck messages (with compression)
2304 *
2305 * print_e2fsck_message() prints a message to the user, using
2306 * compression techniques and expansions of abbreviations.
2307 *
2308 * The following % expansions are supported:
2309 *
2310 * %b <blk> block number
2311 * %B <blkcount> integer
2312 * %c <blk2> block number
2313 * %Di <dirent>->ino inode number
2314 * %Dn <dirent>->name string
2315 * %Dr <dirent>->rec_len
2316 * %Dl <dirent>->name_len
2317 * %Dt <dirent>->filetype
2318 * %d <dir> inode number
2319 * %g <group> integer
2320 * %i <ino> inode number
2321 * %Is <inode> -> i_size
2322 * %IS <inode> -> i_extra_isize
2323 * %Ib <inode> -> i_blocks
2324 * %Il <inode> -> i_links_count
2325 * %Im <inode> -> i_mode
2326 * %IM <inode> -> i_mtime
2327 * %IF <inode> -> i_faddr
2328 * %If <inode> -> i_file_acl
2329 * %Id <inode> -> i_dir_acl
2330 * %Iu <inode> -> i_uid
2331 * %Ig <inode> -> i_gid
2332 * %j <ino2> inode number
2333 * %m <com_err error message>
2334 * %N <num>
2335 * %p ext2fs_get_pathname of directory <ino>
2336 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2337 * the containing directory. (If dirent is NULL
2338 * then return the pathname of directory <ino2>)
2339 * %q ext2fs_get_pathname of directory <dir>
2340 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2341 * the containing directory.
2342 * %s <str> miscellaneous string
2343 * %S backup superblock
2344 * %X <num> hexadecimal format
2345 *
2346 * The following '@' expansions are supported:
2347 *
2348 * @a extended attribute
2349 * @A error allocating
2350 * @b block
2351 * @B bitmap
2352 * @c compress
2353 * @C conflicts with some other fs block
2354 * @D deleted
2355 * @d directory
2356 * @e entry
2357 * @E Entry '%Dn' in %p (%i)
2358 * @f filesystem
2359 * @F for @i %i (%Q) is
2360 * @g group
2361 * @h HTREE directory inode
2362 * @i inode
2363 * @I illegal
2364 * @j journal
2365 * @l lost+found
2366 * @L is a link
2367 * @m multiply-claimed
2368 * @n invalid
2369 * @o orphaned
2370 * @p problem in
2371 * @r root inode
2372 * @s should be
2373 * @S superblock
2374 * @u unattached
2375 * @v device
2376 * @z zero-length
2377 */
2378
2379
2380/*
2381 * This structure defines the abbreviations used by the text strings
2382 * below. The first character in the string is the index letter. An
2383 * abbreviation of the form '@<i>' is expanded by looking up the index
2384 * letter <i> in the table below.
2385 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002386static const char *const abbrevs[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002387 N_("aextended attribute"),
2388 N_("Aerror allocating"),
2389 N_("bblock"),
2390 N_("Bbitmap"),
2391 N_("ccompress"),
2392 N_("Cconflicts with some other fs @b"),
2393 N_("iinode"),
2394 N_("Iillegal"),
2395 N_("jjournal"),
2396 N_("Ddeleted"),
2397 N_("ddirectory"),
2398 N_("eentry"),
2399 N_("E@e '%Dn' in %p (%i)"),
2400 N_("ffilesystem"),
2401 N_("Ffor @i %i (%Q) is"),
2402 N_("ggroup"),
2403 N_("hHTREE @d @i"),
2404 N_("llost+found"),
2405 N_("Lis a link"),
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002406 N_("mmultiply-claimed"),
2407 N_("ninvalid"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002408 N_("oorphaned"),
2409 N_("pproblem in"),
2410 N_("rroot @i"),
2411 N_("sshould be"),
2412 N_("Ssuper@b"),
2413 N_("uunattached"),
2414 N_("vdevice"),
2415 N_("zzero-length"),
2416 "@@",
2417 0
2418 };
2419
2420/*
2421 * Give more user friendly names to the "special" inodes.
2422 */
2423#define num_special_inodes 11
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002424static const char *const special_inode_name[] =
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002425{
2426 N_("<The NULL inode>"), /* 0 */
2427 N_("<The bad blocks inode>"), /* 1 */
2428 "/", /* 2 */
2429 N_("<The ACL index inode>"), /* 3 */
2430 N_("<The ACL data inode>"), /* 4 */
2431 N_("<The boot loader inode>"), /* 5 */
2432 N_("<The undelete directory inode>"), /* 6 */
2433 N_("<The group descriptor inode>"), /* 7 */
2434 N_("<The journal inode>"), /* 8 */
2435 N_("<Reserved inode 9>"), /* 9 */
2436 N_("<Reserved inode 10>"), /* 10 */
2437};
2438
2439/*
2440 * This function does "safe" printing. It will convert non-printable
2441 * ASCII characters using '^' and M- notation.
2442 */
2443static void safe_print(const char *cp, int len)
2444{
2445 unsigned char ch;
2446
2447 if (len < 0)
2448 len = strlen(cp);
2449
2450 while (len--) {
2451 ch = *cp++;
2452 if (ch > 128) {
2453 fputs("M-", stdout);
2454 ch -= 128;
2455 }
2456 if ((ch < 32) || (ch == 0x7f)) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002457 bb_putchar('^');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002458 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2459 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00002460 bb_putchar(ch);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002461 }
2462}
2463
2464
2465/*
2466 * This function prints a pathname, using the ext2fs_get_pathname
2467 * function
2468 */
2469static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2470{
2471 errcode_t retval;
2472 char *path;
2473
2474 if (!dir && (ino < num_special_inodes)) {
2475 fputs(_(special_inode_name[ino]), stdout);
2476 return;
2477 }
2478
2479 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2480 if (retval)
2481 fputs("???", stdout);
2482 else {
2483 safe_print(path, -1);
2484 ext2fs_free_mem(&path);
2485 }
2486}
2487
2488static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2489 struct problem_context *pctx, int first);
2490/*
2491 * This function handles the '@' expansion. We allow recursive
2492 * expansion; an @ expression can contain further '@' and '%'
2493 * expressions.
2494 */
2495static void expand_at_expression(e2fsck_t ctx, char ch,
2496 struct problem_context *pctx,
2497 int *first)
2498{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002499 const char *const *cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002500 const char *str;
2501
2502 /* Search for the abbreviation */
2503 for (cpp = abbrevs; *cpp; cpp++) {
2504 if (ch == *cpp[0])
2505 break;
2506 }
2507 if (*cpp) {
2508 str = _(*cpp) + 1;
2509 if (*first && islower(*str)) {
2510 *first = 0;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002511 bb_putchar(toupper(*str++));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002512 }
2513 print_e2fsck_message(ctx, str, pctx, *first);
2514 } else
2515 printf("@%c", ch);
2516}
2517
2518/*
2519 * This function expands '%IX' expressions
2520 */
2521static void expand_inode_expression(char ch,
2522 struct problem_context *ctx)
2523{
2524 struct ext2_inode *inode;
2525 struct ext2_inode_large *large_inode;
2526 char * time_str;
2527 time_t t;
2528 int do_gmt = -1;
2529
2530 if (!ctx || !ctx->inode)
2531 goto no_inode;
2532
2533 inode = ctx->inode;
2534 large_inode = (struct ext2_inode_large *) inode;
2535
2536 switch (ch) {
2537 case 's':
2538 if (LINUX_S_ISDIR(inode->i_mode))
2539 printf("%u", inode->i_size);
2540 else {
2541 printf("%"PRIu64, (inode->i_size |
2542 ((uint64_t) inode->i_size_high << 32)));
2543 }
2544 break;
2545 case 'S':
2546 printf("%u", large_inode->i_extra_isize);
2547 break;
2548 case 'b':
2549 printf("%u", inode->i_blocks);
2550 break;
2551 case 'l':
2552 printf("%d", inode->i_links_count);
2553 break;
2554 case 'm':
2555 printf("0%o", inode->i_mode);
2556 break;
2557 case 'M':
2558 /* The diet libc doesn't respect the TZ environemnt variable */
2559 if (do_gmt == -1) {
2560 time_str = getenv("TZ");
2561 if (!time_str)
2562 time_str = "";
2563 do_gmt = !strcmp(time_str, "GMT");
2564 }
2565 t = inode->i_mtime;
2566 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2567 printf("%.24s", time_str);
2568 break;
2569 case 'F':
2570 printf("%u", inode->i_faddr);
2571 break;
2572 case 'f':
2573 printf("%u", inode->i_file_acl);
2574 break;
2575 case 'd':
2576 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2577 inode->i_dir_acl : 0));
2578 break;
2579 case 'u':
2580 printf("%d", (inode->i_uid |
2581 (inode->osd2.linux2.l_i_uid_high << 16)));
2582 break;
2583 case 'g':
2584 printf("%d", (inode->i_gid |
2585 (inode->osd2.linux2.l_i_gid_high << 16)));
2586 break;
2587 default:
2588 no_inode:
2589 printf("%%I%c", ch);
2590 break;
2591 }
2592}
2593
2594/*
2595 * This function expands '%dX' expressions
2596 */
2597static void expand_dirent_expression(char ch,
2598 struct problem_context *ctx)
2599{
2600 struct ext2_dir_entry *dirent;
2601 int len;
2602
2603 if (!ctx || !ctx->dirent)
2604 goto no_dirent;
2605
2606 dirent = ctx->dirent;
2607
2608 switch (ch) {
2609 case 'i':
2610 printf("%u", dirent->inode);
2611 break;
2612 case 'n':
2613 len = dirent->name_len & 0xFF;
2614 if (len > EXT2_NAME_LEN)
2615 len = EXT2_NAME_LEN;
2616 if (len > dirent->rec_len)
2617 len = dirent->rec_len;
2618 safe_print(dirent->name, len);
2619 break;
2620 case 'r':
2621 printf("%u", dirent->rec_len);
2622 break;
2623 case 'l':
2624 printf("%u", dirent->name_len & 0xFF);
2625 break;
2626 case 't':
2627 printf("%u", dirent->name_len >> 8);
2628 break;
2629 default:
2630 no_dirent:
2631 printf("%%D%c", ch);
2632 break;
2633 }
2634}
2635
2636static void expand_percent_expression(ext2_filsys fs, char ch,
2637 struct problem_context *ctx)
2638{
2639 if (!ctx)
2640 goto no_context;
2641
2642 switch (ch) {
2643 case '%':
Denis Vlasenko4daad902007-09-27 10:20:47 +00002644 bb_putchar('%');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002645 break;
2646 case 'b':
2647 printf("%u", ctx->blk);
2648 break;
2649 case 'B':
2650 printf("%"PRIi64, ctx->blkcount);
2651 break;
2652 case 'c':
2653 printf("%u", ctx->blk2);
2654 break;
2655 case 'd':
2656 printf("%u", ctx->dir);
2657 break;
2658 case 'g':
2659 printf("%d", ctx->group);
2660 break;
2661 case 'i':
2662 printf("%u", ctx->ino);
2663 break;
2664 case 'j':
2665 printf("%u", ctx->ino2);
2666 break;
2667 case 'm':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002668 fputs(error_message(ctx->errcode), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002669 break;
2670 case 'N':
2671 printf("%"PRIi64, ctx->num);
2672 break;
2673 case 'p':
2674 print_pathname(fs, ctx->ino, 0);
2675 break;
2676 case 'P':
2677 print_pathname(fs, ctx->ino2,
2678 ctx->dirent ? ctx->dirent->inode : 0);
2679 break;
2680 case 'q':
2681 print_pathname(fs, ctx->dir, 0);
2682 break;
2683 case 'Q':
2684 print_pathname(fs, ctx->dir, ctx->ino);
2685 break;
2686 case 'S':
2687 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2688 break;
2689 case 's':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002690 fputs((ctx->str ? ctx->str : "NULL"), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002691 break;
2692 case 'X':
2693 printf("0x%"PRIi64, ctx->num);
2694 break;
2695 default:
2696 no_context:
2697 printf("%%%c", ch);
2698 break;
2699 }
2700}
2701
2702
2703static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2704 struct problem_context *pctx, int first)
2705{
2706 ext2_filsys fs = ctx->fs;
2707 const char * cp;
2708 int i;
2709
2710 e2fsck_clear_progbar(ctx);
2711 for (cp = msg; *cp; cp++) {
2712 if (cp[0] == '@') {
2713 cp++;
2714 expand_at_expression(ctx, *cp, pctx, &first);
2715 } else if (cp[0] == '%' && cp[1] == 'I') {
2716 cp += 2;
2717 expand_inode_expression(*cp, pctx);
2718 } else if (cp[0] == '%' && cp[1] == 'D') {
2719 cp += 2;
2720 expand_dirent_expression(*cp, pctx);
2721 } else if ((cp[0] == '%')) {
2722 cp++;
2723 expand_percent_expression(fs, *cp, pctx);
2724 } else {
2725 for (i=0; cp[i]; i++)
2726 if ((cp[i] == '@') || cp[i] == '%')
2727 break;
2728 printf("%.*s", i, cp);
2729 cp += i-1;
2730 }
2731 first = 0;
2732 }
2733}
2734
2735
2736/*
2737 * region.c --- code which manages allocations within a region.
2738 */
2739
2740struct region_el {
2741 region_addr_t start;
2742 region_addr_t end;
2743 struct region_el *next;
2744};
2745
2746struct region_struct {
2747 region_addr_t min;
2748 region_addr_t max;
2749 struct region_el *allocated;
2750};
2751
2752static region_t region_create(region_addr_t min, region_addr_t max)
2753{
2754 region_t region;
2755
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002756 region = xzalloc(sizeof(struct region_struct));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002757 region->min = min;
2758 region->max = max;
2759 return region;
2760}
2761
2762static void region_free(region_t region)
2763{
2764 struct region_el *r, *next;
2765
2766 for (r = region->allocated; r; r = next) {
2767 next = r->next;
2768 free(r);
2769 }
2770 memset(region, 0, sizeof(struct region_struct));
2771 free(region);
2772}
2773
2774static int region_allocate(region_t region, region_addr_t start, int n)
2775{
2776 struct region_el *r, *new_region, *prev, *next;
2777 region_addr_t end;
2778
2779 end = start+n;
2780 if ((start < region->min) || (end > region->max))
2781 return -1;
2782 if (n == 0)
2783 return 1;
2784
2785 /*
2786 * Search through the linked list. If we find that it
2787 * conflicts witih something that's already allocated, return
2788 * 1; if we can find an existing region which we can grow, do
2789 * so. Otherwise, stop when we find the appropriate place
2790 * insert a new region element into the linked list.
2791 */
2792 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2793 if (((start >= r->start) && (start < r->end)) ||
2794 ((end > r->start) && (end <= r->end)) ||
2795 ((start <= r->start) && (end >= r->end)))
2796 return 1;
2797 if (end == r->start) {
2798 r->start = start;
2799 return 0;
2800 }
2801 if (start == r->end) {
2802 if ((next = r->next)) {
2803 if (end > next->start)
2804 return 1;
2805 if (end == next->start) {
2806 r->end = next->end;
2807 r->next = next->next;
2808 free(next);
2809 return 0;
2810 }
2811 }
2812 r->end = end;
2813 return 0;
2814 }
2815 if (start < r->start)
2816 break;
2817 }
2818 /*
2819 * Insert a new region element structure into the linked list
2820 */
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002821 new_region = xmalloc(sizeof(struct region_el));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002822 new_region->start = start;
2823 new_region->end = start + n;
2824 new_region->next = r;
2825 if (prev)
2826 prev->next = new_region;
2827 else
2828 region->allocated = new_region;
2829 return 0;
2830}
2831
2832/*
2833 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2834 *
2835 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2836 * and applies the following tests to each inode:
2837 *
2838 * - The mode field of the inode must be legal.
2839 * - The size and block count fields of the inode are correct.
2840 * - A data block must not be used by another inode
2841 *
2842 * Pass 1 also gathers the collects the following information:
2843 *
2844 * - A bitmap of which inodes are in use. (inode_used_map)
2845 * - A bitmap of which inodes are directories. (inode_dir_map)
2846 * - A bitmap of which inodes are regular files. (inode_reg_map)
2847 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2848 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2849 * - A bitmap of which blocks are in use. (block_found_map)
2850 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2851 * - The data blocks of the directory inodes. (dir_map)
2852 *
2853 * Pass 1 is designed to stash away enough information so that the
2854 * other passes should not need to read in the inode information
2855 * during the normal course of a filesystem check. (Althogh if an
2856 * inconsistency is detected, other passes may need to read in an
2857 * inode to fix it.)
2858 *
2859 * Note that pass 1B will be invoked if there are any duplicate blocks
2860 * found.
2861 */
2862
2863
2864static int process_block(ext2_filsys fs, blk_t *blocknr,
2865 e2_blkcnt_t blockcnt, blk_t ref_blk,
2866 int ref_offset, void *priv_data);
2867static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2868 e2_blkcnt_t blockcnt, blk_t ref_blk,
2869 int ref_offset, void *priv_data);
2870static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2871 char *block_buf);
2872static void mark_table_blocks(e2fsck_t ctx);
2873static void alloc_imagic_map(e2fsck_t ctx);
2874static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2875static void handle_fs_bad_blocks(e2fsck_t ctx);
2876static void process_inodes(e2fsck_t ctx, char *block_buf);
2877static int process_inode_cmp(const void *a, const void *b);
2878static errcode_t scan_callback(ext2_filsys fs,
2879 dgrp_t group, void * priv_data);
2880static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2881 char *block_buf, int adjust_sign);
2882/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2883
2884static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2885 struct ext2_inode * inode, int bufsize,
2886 const char *proc);
2887
2888struct process_block_struct_1 {
2889 ext2_ino_t ino;
2890 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2891 fragmented:1, compressed:1, bbcheck:1;
2892 blk_t num_blocks;
2893 blk_t max_blocks;
2894 e2_blkcnt_t last_block;
2895 int num_illegal_blocks;
2896 blk_t previous_block;
2897 struct ext2_inode *inode;
2898 struct problem_context *pctx;
2899 ext2fs_block_bitmap fs_meta_blocks;
2900 e2fsck_t ctx;
2901};
2902
2903struct process_inode_block {
2904 ext2_ino_t ino;
2905 struct ext2_inode inode;
2906};
2907
2908struct scan_callback_struct {
2909 e2fsck_t ctx;
2910 char *block_buf;
2911};
2912
2913/*
2914 * For the inodes to process list.
2915 */
2916static struct process_inode_block *inodes_to_process;
2917static int process_inode_count;
2918
2919static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2920 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2921
2922/*
2923 * Free all memory allocated by pass1 in preparation for restarting
2924 * things.
2925 */
2926static void unwind_pass1(void)
2927{
2928 ext2fs_free_mem(&inodes_to_process);
2929}
2930
2931/*
2932 * Check to make sure a device inode is real. Returns 1 if the device
2933 * checks out, 0 if not.
2934 *
2935 * Note: this routine is now also used to check FIFO's and Sockets,
2936 * since they have the same requirement; the i_block fields should be
2937 * zero.
2938 */
2939static int
2940e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2941{
2942 int i;
2943
2944 /*
2945 * If i_blocks is non-zero, or the index flag is set, then
2946 * this is a bogus device/fifo/socket
2947 */
2948 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2949 (inode->i_flags & EXT2_INDEX_FL))
2950 return 0;
2951
2952 /*
2953 * We should be able to do the test below all the time, but
2954 * because the kernel doesn't forcibly clear the device
2955 * inode's additional i_block fields, there are some rare
2956 * occasions when a legitimate device inode will have non-zero
2957 * additional i_block fields. So for now, we only complain
2958 * when the immutable flag is set, which should never happen
2959 * for devices. (And that's when the problem is caused, since
2960 * you can't set or clear immutable flags for devices.) Once
2961 * the kernel has been fixed we can change this...
2962 */
2963 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2964 for (i=4; i < EXT2_N_BLOCKS; i++)
2965 if (inode->i_block[i])
2966 return 0;
2967 }
2968 return 1;
2969}
2970
2971/*
2972 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2973 * checks out, 0 if not.
2974 */
2975static int
2976e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2977{
2978 unsigned int len;
2979 int i;
2980 blk_t blocks;
2981
2982 if ((inode->i_size_high || inode->i_size == 0) ||
2983 (inode->i_flags & EXT2_INDEX_FL))
2984 return 0;
2985
2986 blocks = ext2fs_inode_data_blocks(fs, inode);
2987 if (blocks) {
2988 if ((inode->i_size >= fs->blocksize) ||
2989 (blocks != fs->blocksize >> 9) ||
2990 (inode->i_block[0] < fs->super->s_first_data_block) ||
2991 (inode->i_block[0] >= fs->super->s_blocks_count))
2992 return 0;
2993
2994 for (i = 1; i < EXT2_N_BLOCKS; i++)
2995 if (inode->i_block[i])
2996 return 0;
2997
2998 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2999 return 0;
3000
3001 len = strnlen(buf, fs->blocksize);
3002 if (len == fs->blocksize)
3003 return 0;
3004 } else {
3005 if (inode->i_size >= sizeof(inode->i_block))
3006 return 0;
3007
3008 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
3009 if (len == sizeof(inode->i_block))
3010 return 0;
3011 }
3012 if (len != inode->i_size)
3013 return 0;
3014 return 1;
3015}
3016
3017/*
3018 * If the immutable (or append-only) flag is set on the inode, offer
3019 * to clear it.
3020 */
3021#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3022static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3023{
3024 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3025 return;
3026
3027 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3028 return;
3029
3030 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3031 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3032}
3033
3034/*
3035 * If device, fifo or socket, check size is zero -- if not offer to
3036 * clear it
3037 */
3038static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3039{
3040 struct ext2_inode *inode = pctx->inode;
3041
3042 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3043 return;
3044
3045 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3046 return;
3047
3048 inode->i_size = 0;
3049 inode->i_size_high = 0;
3050 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3051}
3052
3053static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3054{
3055 struct ext2_super_block *sb = ctx->fs->super;
3056 struct ext2_inode_large *inode;
3057 struct ext2_ext_attr_entry *entry;
3058 char *start, *end;
3059 int storage_size, remain, offs;
3060 int problem = 0;
3061
3062 inode = (struct ext2_inode_large *) pctx->inode;
3063 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3064 inode->i_extra_isize;
3065 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3066 inode->i_extra_isize + sizeof(__u32);
3067 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3068 entry = (struct ext2_ext_attr_entry *) start;
3069
3070 /* scan all entry's headers first */
3071
3072 /* take finish entry 0UL into account */
3073 remain = storage_size - sizeof(__u32);
3074 offs = end - start;
3075
3076 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3077
3078 /* header eats this space */
3079 remain -= sizeof(struct ext2_ext_attr_entry);
3080
3081 /* is attribute name valid? */
3082 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3083 pctx->num = entry->e_name_len;
3084 problem = PR_1_ATTR_NAME_LEN;
3085 goto fix;
3086 }
3087
3088 /* attribute len eats this space */
3089 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3090
3091 /* check value size */
3092 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3093 pctx->num = entry->e_value_size;
3094 problem = PR_1_ATTR_VALUE_SIZE;
3095 goto fix;
3096 }
3097
3098 /* check value placement */
3099 if (entry->e_value_offs +
3100 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3101 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3102 pctx->num = entry->e_value_offs;
3103 problem = PR_1_ATTR_VALUE_OFFSET;
3104 goto fix;
3105 }
3106
3107 /* e_value_block must be 0 in inode's ea */
3108 if (entry->e_value_block != 0) {
3109 pctx->num = entry->e_value_block;
3110 problem = PR_1_ATTR_VALUE_BLOCK;
3111 goto fix;
3112 }
3113
3114 /* e_hash must be 0 in inode's ea */
3115 if (entry->e_hash != 0) {
3116 pctx->num = entry->e_hash;
3117 problem = PR_1_ATTR_HASH;
3118 goto fix;
3119 }
3120
3121 remain -= entry->e_value_size;
3122 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3123
3124 entry = EXT2_EXT_ATTR_NEXT(entry);
3125 }
3126fix:
3127 /*
3128 * it seems like a corruption. it's very unlikely we could repair
3129 * EA(s) in automatic fashion -bzzz
3130 */
3131 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3132 return;
3133
3134 /* simple remove all possible EA(s) */
3135 *((__u32 *)start) = 0UL;
3136 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3137 EXT2_INODE_SIZE(sb), "pass1");
3138}
3139
3140static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3141{
3142 struct ext2_super_block *sb = ctx->fs->super;
3143 struct ext2_inode_large *inode;
3144 __u32 *eamagic;
3145 int min, max;
3146
3147 inode = (struct ext2_inode_large *) pctx->inode;
3148 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3149 /* this isn't large inode. so, nothing to check */
3150 return;
3151 }
3152
3153 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3154 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3155 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3156 /*
3157 * For now we will allow i_extra_isize to be 0, but really
3158 * implementations should never allow i_extra_isize to be 0
3159 */
3160 if (inode->i_extra_isize &&
3161 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3162 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3163 return;
3164 inode->i_extra_isize = min;
3165 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3166 EXT2_INODE_SIZE(sb), "pass1");
3167 return;
3168 }
3169
3170 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3171 inode->i_extra_isize);
3172 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3173 /* it seems inode has an extended attribute(s) in body */
3174 check_ea_in_inode(ctx, pctx);
3175 }
3176}
3177
3178static void e2fsck_pass1(e2fsck_t ctx)
3179{
3180 int i;
3181 __u64 max_sizes;
3182 ext2_filsys fs = ctx->fs;
3183 ext2_ino_t ino;
3184 struct ext2_inode *inode;
3185 ext2_inode_scan scan;
3186 char *block_buf;
3187 unsigned char frag, fsize;
3188 struct problem_context pctx;
3189 struct scan_callback_struct scan_struct;
3190 struct ext2_super_block *sb = ctx->fs->super;
3191 int imagic_fs;
3192 int busted_fs_time = 0;
3193 int inode_size;
3194
3195 clear_problem_context(&pctx);
3196
3197 if (!(ctx->options & E2F_OPT_PREEN))
3198 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3199
3200 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3201 !(ctx->options & E2F_OPT_NO)) {
3202 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3203 ctx->dirs_to_hash = 0;
3204 }
3205
3206 /* Pass 1 */
3207
3208#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3209
3210 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3211 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3212 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3213 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3214 max_sizes = (max_sizes * (1UL << i)) - 1;
3215 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3216 }
3217#undef EXT2_BPP
3218
3219 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3220
3221 /*
3222 * Allocate bitmaps structures
3223 */
3224 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3225 &ctx->inode_used_map);
3226 if (pctx.errcode) {
3227 pctx.num = 1;
3228 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3229 ctx->flags |= E2F_FLAG_ABORT;
3230 return;
3231 }
3232 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3233 _("directory inode map"), &ctx->inode_dir_map);
3234 if (pctx.errcode) {
3235 pctx.num = 2;
3236 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3237 ctx->flags |= E2F_FLAG_ABORT;
3238 return;
3239 }
3240 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3241 _("regular file inode map"), &ctx->inode_reg_map);
3242 if (pctx.errcode) {
3243 pctx.num = 6;
3244 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3245 ctx->flags |= E2F_FLAG_ABORT;
3246 return;
3247 }
3248 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3249 &ctx->block_found_map);
3250 if (pctx.errcode) {
3251 pctx.num = 1;
3252 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3253 ctx->flags |= E2F_FLAG_ABORT;
3254 return;
3255 }
3256 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3257 &ctx->inode_link_info);
3258 if (pctx.errcode) {
3259 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3260 ctx->flags |= E2F_FLAG_ABORT;
3261 return;
3262 }
3263 inode_size = EXT2_INODE_SIZE(fs->super);
3264 inode = (struct ext2_inode *)
3265 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3266
3267 inodes_to_process = (struct process_inode_block *)
3268 e2fsck_allocate_memory(ctx,
3269 (ctx->process_inode_size *
3270 sizeof(struct process_inode_block)),
3271 "array of inodes to process");
3272 process_inode_count = 0;
3273
3274 pctx.errcode = ext2fs_init_dblist(fs, 0);
3275 if (pctx.errcode) {
3276 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3277 ctx->flags |= E2F_FLAG_ABORT;
3278 return;
3279 }
3280
3281 /*
3282 * If the last orphan field is set, clear it, since the pass1
3283 * processing will automatically find and clear the orphans.
3284 * In the future, we may want to try using the last_orphan
3285 * linked list ourselves, but for now, we clear it so that the
3286 * ext3 mount code won't get confused.
3287 */
3288 if (!(ctx->options & E2F_OPT_READONLY)) {
3289 if (fs->super->s_last_orphan) {
3290 fs->super->s_last_orphan = 0;
3291 ext2fs_mark_super_dirty(fs);
3292 }
3293 }
3294
3295 mark_table_blocks(ctx);
3296 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3297 "block interate buffer");
3298 e2fsck_use_inode_shortcuts(ctx, 1);
3299 ehandler_operation(_("doing inode scan"));
3300 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3301 &scan);
3302 if (pctx.errcode) {
3303 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3304 ctx->flags |= E2F_FLAG_ABORT;
3305 return;
3306 }
3307 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3308 ctx->stashed_inode = inode;
3309 scan_struct.ctx = ctx;
3310 scan_struct.block_buf = block_buf;
3311 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3312 if (ctx->progress)
3313 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3314 return;
3315 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3316 (fs->super->s_mtime < fs->super->s_inodes_count))
3317 busted_fs_time = 1;
3318
3319 while (1) {
3320 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3321 inode, inode_size);
3322 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3323 return;
3324 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3325 continue;
3326 }
3327 if (pctx.errcode) {
3328 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3329 ctx->flags |= E2F_FLAG_ABORT;
3330 return;
3331 }
3332 if (!ino)
3333 break;
3334 pctx.ino = ino;
3335 pctx.inode = inode;
3336 ctx->stashed_ino = ino;
3337 if (inode->i_links_count) {
3338 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3339 ino, inode->i_links_count);
3340 if (pctx.errcode) {
3341 pctx.num = inode->i_links_count;
3342 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3343 ctx->flags |= E2F_FLAG_ABORT;
3344 return;
3345 }
3346 }
3347 if (ino == EXT2_BAD_INO) {
3348 struct process_block_struct_1 pb;
3349
3350 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3351 &pb.fs_meta_blocks);
3352 if (pctx.errcode) {
3353 pctx.num = 4;
3354 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3355 ctx->flags |= E2F_FLAG_ABORT;
3356 return;
3357 }
3358 pb.ino = EXT2_BAD_INO;
3359 pb.num_blocks = pb.last_block = 0;
3360 pb.num_illegal_blocks = 0;
3361 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3362 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3363 pb.inode = inode;
3364 pb.pctx = &pctx;
3365 pb.ctx = ctx;
3366 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3367 block_buf, process_bad_block, &pb);
3368 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3369 if (pctx.errcode) {
3370 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3371 ctx->flags |= E2F_FLAG_ABORT;
3372 return;
3373 }
3374 if (pb.bbcheck)
3375 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3376 ctx->flags |= E2F_FLAG_ABORT;
3377 return;
3378 }
3379 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3380 clear_problem_context(&pctx);
3381 continue;
3382 } else if (ino == EXT2_ROOT_INO) {
3383 /*
3384 * Make sure the root inode is a directory; if
3385 * not, offer to clear it. It will be
3386 * regnerated in pass #3.
3387 */
3388 if (!LINUX_S_ISDIR(inode->i_mode)) {
3389 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003390 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003391 inode->i_links_count = 0;
3392 ext2fs_icount_store(ctx->inode_link_info,
3393 ino, 0);
3394 e2fsck_write_inode(ctx, ino, inode,
3395 "pass1");
3396 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003397 }
3398 /*
3399 * If dtime is set, offer to clear it. mke2fs
3400 * version 0.2b created filesystems with the
3401 * dtime field set for the root and lost+found
3402 * directories. We won't worry about
3403 * /lost+found, since that can be regenerated
3404 * easily. But we will fix the root directory
3405 * as a special case.
3406 */
3407 if (inode->i_dtime && inode->i_links_count) {
3408 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3409 inode->i_dtime = 0;
3410 e2fsck_write_inode(ctx, ino, inode,
3411 "pass1");
3412 }
3413 }
3414 } else if (ino == EXT2_JOURNAL_INO) {
3415 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3416 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3417 if (!LINUX_S_ISREG(inode->i_mode) &&
3418 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3419 &pctx)) {
3420 inode->i_mode = LINUX_S_IFREG;
3421 e2fsck_write_inode(ctx, ino, inode,
3422 "pass1");
3423 }
3424 check_blocks(ctx, &pctx, block_buf);
3425 continue;
3426 }
3427 if ((inode->i_links_count || inode->i_blocks ||
3428 inode->i_blocks || inode->i_block[0]) &&
3429 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3430 &pctx)) {
3431 memset(inode, 0, inode_size);
3432 ext2fs_icount_store(ctx->inode_link_info,
3433 ino, 0);
3434 e2fsck_write_inode_full(ctx, ino, inode,
3435 inode_size, "pass1");
3436 }
3437 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3438 int problem = 0;
3439
3440 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3441 if (ino == EXT2_BOOT_LOADER_INO) {
3442 if (LINUX_S_ISDIR(inode->i_mode))
3443 problem = PR_1_RESERVED_BAD_MODE;
3444 } else if (ino == EXT2_RESIZE_INO) {
3445 if (inode->i_mode &&
3446 !LINUX_S_ISREG(inode->i_mode))
3447 problem = PR_1_RESERVED_BAD_MODE;
3448 } else {
3449 if (inode->i_mode != 0)
3450 problem = PR_1_RESERVED_BAD_MODE;
3451 }
3452 if (problem) {
3453 if (fix_problem(ctx, problem, &pctx)) {
3454 inode->i_mode = 0;
3455 e2fsck_write_inode(ctx, ino, inode,
3456 "pass1");
3457 }
3458 }
3459 check_blocks(ctx, &pctx, block_buf);
3460 continue;
3461 }
3462 /*
3463 * Check for inodes who might have been part of the
3464 * orphaned list linked list. They should have gotten
3465 * dealt with by now, unless the list had somehow been
3466 * corrupted.
3467 *
3468 * FIXME: In the future, inodes which are still in use
3469 * (and which are therefore) pending truncation should
3470 * be handled specially. Right now we just clear the
3471 * dtime field, and the normal e2fsck handling of
3472 * inodes where i_size and the inode blocks are
3473 * inconsistent is to fix i_size, instead of releasing
3474 * the extra blocks. This won't catch the inodes that
3475 * was at the end of the orphan list, but it's better
3476 * than nothing. The right answer is that there
3477 * shouldn't be any bugs in the orphan list handling. :-)
3478 */
3479 if (inode->i_dtime && !busted_fs_time &&
3480 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3481 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3482 inode->i_dtime = inode->i_links_count ?
Denis Vlasenko04158e02009-02-02 10:48:06 +00003483 0 : time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003484 e2fsck_write_inode(ctx, ino, inode,
3485 "pass1");
3486 }
3487 }
3488
3489 /*
3490 * This code assumes that deleted inodes have
3491 * i_links_count set to 0.
3492 */
3493 if (!inode->i_links_count) {
3494 if (!inode->i_dtime && inode->i_mode) {
3495 if (fix_problem(ctx,
3496 PR_1_ZERO_DTIME, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003497 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003498 e2fsck_write_inode(ctx, ino, inode,
3499 "pass1");
3500 }
3501 }
3502 continue;
3503 }
3504 /*
3505 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3506 * deleted files. Oops.
3507 *
3508 * Since all new ext2 implementations get this right,
3509 * we now assume that the case of non-zero
3510 * i_links_count and non-zero dtime means that we
3511 * should keep the file, not delete it.
3512 *
3513 */
3514 if (inode->i_dtime) {
3515 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3516 inode->i_dtime = 0;
3517 e2fsck_write_inode(ctx, ino, inode, "pass1");
3518 }
3519 }
3520
3521 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3522 switch (fs->super->s_creator_os) {
3523 case EXT2_OS_LINUX:
3524 frag = inode->osd2.linux2.l_i_frag;
3525 fsize = inode->osd2.linux2.l_i_fsize;
3526 break;
3527 case EXT2_OS_HURD:
3528 frag = inode->osd2.hurd2.h_i_frag;
3529 fsize = inode->osd2.hurd2.h_i_fsize;
3530 break;
3531 case EXT2_OS_MASIX:
3532 frag = inode->osd2.masix2.m_i_frag;
3533 fsize = inode->osd2.masix2.m_i_fsize;
3534 break;
3535 default:
3536 frag = fsize = 0;
3537 }
3538
3539 if (inode->i_faddr || frag || fsize ||
3540 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3541 mark_inode_bad(ctx, ino);
3542 if (inode->i_flags & EXT2_IMAGIC_FL) {
3543 if (imagic_fs) {
3544 if (!ctx->inode_imagic_map)
3545 alloc_imagic_map(ctx);
3546 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3547 ino);
3548 } else {
3549 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3550 inode->i_flags &= ~EXT2_IMAGIC_FL;
3551 e2fsck_write_inode(ctx, ino,
3552 inode, "pass1");
3553 }
3554 }
3555 }
3556
3557 check_inode_extra_space(ctx, &pctx);
3558
3559 if (LINUX_S_ISDIR(inode->i_mode)) {
3560 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3561 e2fsck_add_dir_info(ctx, ino, 0);
3562 ctx->fs_directory_count++;
3563 } else if (LINUX_S_ISREG (inode->i_mode)) {
3564 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3565 ctx->fs_regular_count++;
3566 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3567 e2fsck_pass1_check_device_inode(fs, inode)) {
3568 check_immutable(ctx, &pctx);
3569 check_size(ctx, &pctx);
3570 ctx->fs_chardev_count++;
3571 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3572 e2fsck_pass1_check_device_inode(fs, inode)) {
3573 check_immutable(ctx, &pctx);
3574 check_size(ctx, &pctx);
3575 ctx->fs_blockdev_count++;
3576 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3577 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3578 check_immutable(ctx, &pctx);
3579 ctx->fs_symlinks_count++;
3580 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3581 ctx->fs_fast_symlinks_count++;
3582 check_blocks(ctx, &pctx, block_buf);
3583 continue;
3584 }
3585 }
3586 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3587 e2fsck_pass1_check_device_inode(fs, inode)) {
3588 check_immutable(ctx, &pctx);
3589 check_size(ctx, &pctx);
3590 ctx->fs_fifo_count++;
3591 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3592 e2fsck_pass1_check_device_inode(fs, inode)) {
3593 check_immutable(ctx, &pctx);
3594 check_size(ctx, &pctx);
3595 ctx->fs_sockets_count++;
3596 } else
3597 mark_inode_bad(ctx, ino);
3598 if (inode->i_block[EXT2_IND_BLOCK])
3599 ctx->fs_ind_count++;
3600 if (inode->i_block[EXT2_DIND_BLOCK])
3601 ctx->fs_dind_count++;
3602 if (inode->i_block[EXT2_TIND_BLOCK])
3603 ctx->fs_tind_count++;
3604 if (inode->i_block[EXT2_IND_BLOCK] ||
3605 inode->i_block[EXT2_DIND_BLOCK] ||
3606 inode->i_block[EXT2_TIND_BLOCK] ||
3607 inode->i_file_acl) {
3608 inodes_to_process[process_inode_count].ino = ino;
3609 inodes_to_process[process_inode_count].inode = *inode;
3610 process_inode_count++;
3611 } else
3612 check_blocks(ctx, &pctx, block_buf);
3613
3614 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3615 return;
3616
3617 if (process_inode_count >= ctx->process_inode_size) {
3618 process_inodes(ctx, block_buf);
3619
3620 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3621 return;
3622 }
3623 }
3624 process_inodes(ctx, block_buf);
3625 ext2fs_close_inode_scan(scan);
3626 ehandler_operation(0);
3627
3628 /*
3629 * If any extended attribute blocks' reference counts need to
3630 * be adjusted, either up (ctx->refcount_extra), or down
3631 * (ctx->refcount), then fix them.
3632 */
3633 if (ctx->refcount) {
3634 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3635 ea_refcount_free(ctx->refcount);
3636 ctx->refcount = 0;
3637 }
3638 if (ctx->refcount_extra) {
3639 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3640 block_buf, +1);
3641 ea_refcount_free(ctx->refcount_extra);
3642 ctx->refcount_extra = 0;
3643 }
3644
3645 if (ctx->invalid_bitmaps)
3646 handle_fs_bad_blocks(ctx);
3647
3648 /* We don't need the block_ea_map any more */
3649 ext2fs_free_block_bitmap(ctx->block_ea_map);
3650 ctx->block_ea_map = 0;
3651
3652 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3653 ext2fs_block_bitmap save_bmap;
3654
3655 save_bmap = fs->block_map;
3656 fs->block_map = ctx->block_found_map;
3657 clear_problem_context(&pctx);
3658 pctx.errcode = ext2fs_create_resize_inode(fs);
3659 if (pctx.errcode) {
3660 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3661 /* Should never get here */
3662 ctx->flags |= E2F_FLAG_ABORT;
3663 return;
3664 }
3665 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3666 "recreate inode");
Denis Vlasenko04158e02009-02-02 10:48:06 +00003667 inode->i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003668 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3669 "recreate inode");
3670 fs->block_map = save_bmap;
3671 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3672 }
3673
3674 if (ctx->flags & E2F_FLAG_RESTART) {
3675 /*
3676 * Only the master copy of the superblock and block
3677 * group descriptors are going to be written during a
3678 * restart, so set the superblock to be used to be the
3679 * master superblock.
3680 */
3681 ctx->use_superblock = 0;
3682 unwind_pass1();
3683 goto endit;
3684 }
3685
3686 if (ctx->block_dup_map) {
3687 if (ctx->options & E2F_OPT_PREEN) {
3688 clear_problem_context(&pctx);
3689 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3690 }
3691 e2fsck_pass1_dupblocks(ctx, block_buf);
3692 }
3693 ext2fs_free_mem(&inodes_to_process);
3694endit:
3695 e2fsck_use_inode_shortcuts(ctx, 0);
3696
3697 ext2fs_free_mem(&block_buf);
3698 ext2fs_free_mem(&inode);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003699}
3700
3701/*
3702 * When the inode_scan routines call this callback at the end of the
3703 * glock group, call process_inodes.
3704 */
3705static errcode_t scan_callback(ext2_filsys fs,
3706 dgrp_t group, void * priv_data)
3707{
3708 struct scan_callback_struct *scan_struct;
3709 e2fsck_t ctx;
3710
3711 scan_struct = (struct scan_callback_struct *) priv_data;
3712 ctx = scan_struct->ctx;
3713
3714 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3715
3716 if (ctx->progress)
3717 if ((ctx->progress)(ctx, 1, group+1,
3718 ctx->fs->group_desc_count))
3719 return EXT2_ET_CANCEL_REQUESTED;
3720
3721 return 0;
3722}
3723
3724/*
3725 * Process the inodes in the "inodes to process" list.
3726 */
3727static void process_inodes(e2fsck_t ctx, char *block_buf)
3728{
3729 int i;
3730 struct ext2_inode *old_stashed_inode;
3731 ext2_ino_t old_stashed_ino;
3732 const char *old_operation;
3733 char buf[80];
3734 struct problem_context pctx;
3735
3736 /* begin process_inodes */
3737 if (process_inode_count == 0)
3738 return;
3739 old_operation = ehandler_operation(0);
3740 old_stashed_inode = ctx->stashed_inode;
3741 old_stashed_ino = ctx->stashed_ino;
3742 qsort(inodes_to_process, process_inode_count,
3743 sizeof(struct process_inode_block), process_inode_cmp);
3744 clear_problem_context(&pctx);
3745 for (i=0; i < process_inode_count; i++) {
3746 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3747 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3748 sprintf(buf, _("reading indirect blocks of inode %u"),
3749 pctx.ino);
3750 ehandler_operation(buf);
3751 check_blocks(ctx, &pctx, block_buf);
3752 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3753 break;
3754 }
3755 ctx->stashed_inode = old_stashed_inode;
3756 ctx->stashed_ino = old_stashed_ino;
3757 process_inode_count = 0;
3758 /* end process inodes */
3759
3760 ehandler_operation(old_operation);
3761}
3762
3763static int process_inode_cmp(const void *a, const void *b)
3764{
3765 const struct process_inode_block *ib_a =
3766 (const struct process_inode_block *) a;
3767 const struct process_inode_block *ib_b =
3768 (const struct process_inode_block *) b;
3769 int ret;
3770
3771 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3772 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3773 if (ret == 0)
3774 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3775 return ret;
3776}
3777
3778/*
3779 * Mark an inode as being bad in some what
3780 */
3781static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3782{
3783 struct problem_context pctx;
3784
3785 if (!ctx->inode_bad_map) {
3786 clear_problem_context(&pctx);
3787
3788 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3789 _("bad inode map"), &ctx->inode_bad_map);
3790 if (pctx.errcode) {
3791 pctx.num = 3;
3792 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3793 /* Should never get here */
3794 ctx->flags |= E2F_FLAG_ABORT;
3795 return;
3796 }
3797 }
3798 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3799}
3800
3801
3802/*
3803 * This procedure will allocate the inode imagic table
3804 */
3805static void alloc_imagic_map(e2fsck_t ctx)
3806{
3807 struct problem_context pctx;
3808
3809 clear_problem_context(&pctx);
3810 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3811 _("imagic inode map"),
3812 &ctx->inode_imagic_map);
3813 if (pctx.errcode) {
3814 pctx.num = 5;
3815 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3816 /* Should never get here */
3817 ctx->flags |= E2F_FLAG_ABORT;
3818 return;
3819 }
3820}
3821
3822/*
3823 * Marks a block as in use, setting the dup_map if it's been set
3824 * already. Called by process_block and process_bad_block.
3825 *
3826 * WARNING: Assumes checks have already been done to make sure block
3827 * is valid. This is true in both process_block and process_bad_block.
3828 */
3829static void mark_block_used(e2fsck_t ctx, blk_t block)
3830{
3831 struct problem_context pctx;
3832
3833 clear_problem_context(&pctx);
3834
3835 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3836 if (!ctx->block_dup_map) {
3837 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3838 _("multiply claimed block map"),
3839 &ctx->block_dup_map);
3840 if (pctx.errcode) {
3841 pctx.num = 3;
3842 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3843 &pctx);
3844 /* Should never get here */
3845 ctx->flags |= E2F_FLAG_ABORT;
3846 return;
3847 }
3848 }
3849 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3850 } else {
3851 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3852 }
3853}
3854
3855/*
3856 * Adjust the extended attribute block's reference counts at the end
3857 * of pass 1, either by subtracting out references for EA blocks that
3858 * are still referenced in ctx->refcount, or by adding references for
3859 * EA blocks that had extra references as accounted for in
3860 * ctx->refcount_extra.
3861 */
3862static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3863 char *block_buf, int adjust_sign)
3864{
3865 struct ext2_ext_attr_header *header;
3866 struct problem_context pctx;
3867 ext2_filsys fs = ctx->fs;
3868 blk_t blk;
3869 __u32 should_be;
3870 int count;
3871
3872 clear_problem_context(&pctx);
3873
3874 ea_refcount_intr_begin(refcount);
3875 while (1) {
3876 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3877 break;
3878 pctx.blk = blk;
3879 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3880 if (pctx.errcode) {
3881 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3882 return;
3883 }
3884 header = (struct ext2_ext_attr_header *) block_buf;
3885 pctx.blkcount = header->h_refcount;
3886 should_be = header->h_refcount + adjust_sign * count;
3887 pctx.num = should_be;
3888 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3889 header->h_refcount = should_be;
3890 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3891 block_buf);
3892 if (pctx.errcode) {
3893 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3894 continue;
3895 }
3896 }
3897 }
3898}
3899
3900/*
3901 * Handle processing the extended attribute blocks
3902 */
3903static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3904 char *block_buf)
3905{
3906 ext2_filsys fs = ctx->fs;
3907 ext2_ino_t ino = pctx->ino;
3908 struct ext2_inode *inode = pctx->inode;
3909 blk_t blk;
3910 char * end;
3911 struct ext2_ext_attr_header *header;
3912 struct ext2_ext_attr_entry *entry;
3913 int count;
3914 region_t region;
3915
3916 blk = inode->i_file_acl;
3917 if (blk == 0)
3918 return 0;
3919
3920 /*
3921 * If the Extended attribute flag isn't set, then a non-zero
3922 * file acl means that the inode is corrupted.
3923 *
3924 * Or if the extended attribute block is an invalid block,
3925 * then the inode is also corrupted.
3926 */
3927 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3928 (blk < fs->super->s_first_data_block) ||
3929 (blk >= fs->super->s_blocks_count)) {
3930 mark_inode_bad(ctx, ino);
3931 return 0;
3932 }
3933
3934 /* If ea bitmap hasn't been allocated, create it */
3935 if (!ctx->block_ea_map) {
3936 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3937 _("ext attr block map"),
3938 &ctx->block_ea_map);
3939 if (pctx->errcode) {
3940 pctx->num = 2;
3941 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3942 ctx->flags |= E2F_FLAG_ABORT;
3943 return 0;
3944 }
3945 }
3946
3947 /* Create the EA refcount structure if necessary */
3948 if (!ctx->refcount) {
3949 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3950 if (pctx->errcode) {
3951 pctx->num = 1;
3952 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3953 ctx->flags |= E2F_FLAG_ABORT;
3954 return 0;
3955 }
3956 }
3957
3958 /* Have we seen this EA block before? */
3959 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3960 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3961 return 1;
3962 /* Ooops, this EA was referenced more than it stated */
3963 if (!ctx->refcount_extra) {
3964 pctx->errcode = ea_refcount_create(0,
3965 &ctx->refcount_extra);
3966 if (pctx->errcode) {
3967 pctx->num = 2;
3968 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3969 ctx->flags |= E2F_FLAG_ABORT;
3970 return 0;
3971 }
3972 }
3973 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3974 return 1;
3975 }
3976
3977 /*
3978 * OK, we haven't seen this EA block yet. So we need to
3979 * validate it
3980 */
3981 pctx->blk = blk;
3982 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3983 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3984 goto clear_extattr;
3985 header = (struct ext2_ext_attr_header *) block_buf;
3986 pctx->blk = inode->i_file_acl;
3987 if (((ctx->ext_attr_ver == 1) &&
3988 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3989 ((ctx->ext_attr_ver == 2) &&
3990 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3991 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3992 goto clear_extattr;
3993 }
3994
3995 if (header->h_blocks != 1) {
3996 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3997 goto clear_extattr;
3998 }
3999
4000 region = region_create(0, fs->blocksize);
4001 if (!region) {
4002 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
4003 ctx->flags |= E2F_FLAG_ABORT;
4004 return 0;
4005 }
4006 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
4007 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4008 goto clear_extattr;
4009 }
4010
4011 entry = (struct ext2_ext_attr_entry *)(header+1);
4012 end = block_buf + fs->blocksize;
4013 while ((char *)entry < end && *(__u32 *)entry) {
4014 if (region_allocate(region, (char *)entry - (char *)header,
4015 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4016 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4017 goto clear_extattr;
4018 }
4019 if ((ctx->ext_attr_ver == 1 &&
4020 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4021 (ctx->ext_attr_ver == 2 &&
4022 entry->e_name_index == 0)) {
4023 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4024 goto clear_extattr;
4025 }
4026 if (entry->e_value_block != 0) {
4027 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4028 goto clear_extattr;
4029 }
4030 if (entry->e_value_size &&
4031 region_allocate(region, entry->e_value_offs,
4032 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4033 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4034 goto clear_extattr;
4035 }
4036 entry = EXT2_EXT_ATTR_NEXT(entry);
4037 }
4038 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4039 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4040 goto clear_extattr;
4041 }
4042 region_free(region);
4043
4044 count = header->h_refcount - 1;
4045 if (count)
4046 ea_refcount_store(ctx->refcount, blk, count);
4047 mark_block_used(ctx, blk);
4048 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4049
4050 return 1;
4051
4052clear_extattr:
4053 inode->i_file_acl = 0;
4054 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4055 return 0;
4056}
4057
4058/* Returns 1 if bad htree, 0 if OK */
4059static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4060 ext2_ino_t ino FSCK_ATTR((unused)),
4061 struct ext2_inode *inode,
4062 char *block_buf)
4063{
4064 struct ext2_dx_root_info *root;
4065 ext2_filsys fs = ctx->fs;
4066 errcode_t retval;
4067 blk_t blk;
4068
4069 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4070 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4071 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4072 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4073 return 1;
4074
4075 blk = inode->i_block[0];
4076 if (((blk == 0) ||
4077 (blk < fs->super->s_first_data_block) ||
4078 (blk >= fs->super->s_blocks_count)) &&
4079 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4080 return 1;
4081
4082 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4083 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4084 return 1;
4085
4086 /* XXX should check that beginning matches a directory */
4087 root = (struct ext2_dx_root_info *) (block_buf + 24);
4088
4089 if ((root->reserved_zero || root->info_length < 8) &&
4090 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4091 return 1;
4092
4093 pctx->num = root->hash_version;
4094 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4095 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4096 (root->hash_version != EXT2_HASH_TEA) &&
4097 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4098 return 1;
4099
4100 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4101 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4102 return 1;
4103
4104 pctx->num = root->indirect_levels;
4105 if ((root->indirect_levels > 1) &&
4106 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4107 return 1;
4108
4109 return 0;
4110}
4111
4112/*
4113 * This subroutine is called on each inode to account for all of the
4114 * blocks used by that inode.
4115 */
4116static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4117 char *block_buf)
4118{
4119 ext2_filsys fs = ctx->fs;
4120 struct process_block_struct_1 pb;
4121 ext2_ino_t ino = pctx->ino;
4122 struct ext2_inode *inode = pctx->inode;
4123 int bad_size = 0;
4124 int dirty_inode = 0;
4125 __u64 size;
4126
4127 pb.ino = ino;
4128 pb.num_blocks = 0;
4129 pb.last_block = -1;
4130 pb.num_illegal_blocks = 0;
4131 pb.suppress = 0; pb.clear = 0;
4132 pb.fragmented = 0;
4133 pb.compressed = 0;
4134 pb.previous_block = 0;
4135 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4136 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4137 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4138 pb.inode = inode;
4139 pb.pctx = pctx;
4140 pb.ctx = ctx;
4141 pctx->ino = ino;
4142 pctx->errcode = 0;
4143
4144 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4145 if (fs->super->s_feature_incompat &
4146 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4147 pb.compressed = 1;
4148 else {
4149 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4150 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4151 dirty_inode++;
4152 }
4153 }
4154 }
4155
4156 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4157 pb.num_blocks++;
4158
4159 if (ext2fs_inode_has_valid_blocks(inode))
4160 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4161 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4162 block_buf, process_block, &pb);
4163 end_problem_latch(ctx, PR_LATCH_BLOCK);
4164 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4165 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4166 goto out;
4167 if (pctx->errcode)
4168 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4169
4170 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4171 ctx->fs_fragmented++;
4172
4173 if (pb.clear) {
4174 inode->i_links_count = 0;
4175 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004176 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004177 dirty_inode++;
4178 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4179 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4180 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4181 /*
4182 * The inode was probably partially accounted for
4183 * before processing was aborted, so we need to
4184 * restart the pass 1 scan.
4185 */
4186 ctx->flags |= E2F_FLAG_RESTART;
4187 goto out;
4188 }
4189
4190 if (inode->i_flags & EXT2_INDEX_FL) {
4191 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4192 inode->i_flags &= ~EXT2_INDEX_FL;
4193 dirty_inode++;
4194 } else {
4195#ifdef ENABLE_HTREE
4196 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4197#endif
4198 }
4199 }
4200 if (ctx->dirs_to_hash && pb.is_dir &&
4201 !(inode->i_flags & EXT2_INDEX_FL) &&
4202 ((inode->i_size / fs->blocksize) >= 3))
4203 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4204
4205 if (!pb.num_blocks && pb.is_dir) {
4206 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4207 inode->i_links_count = 0;
4208 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004209 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004210 dirty_inode++;
4211 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4212 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4213 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4214 ctx->fs_directory_count--;
4215 goto out;
4216 }
4217 }
4218
4219 pb.num_blocks *= (fs->blocksize / 512);
4220
4221 if (pb.is_dir) {
4222 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4223 if (nblock > (pb.last_block + 1))
4224 bad_size = 1;
4225 else if (nblock < (pb.last_block + 1)) {
4226 if (((pb.last_block + 1) - nblock) >
4227 fs->super->s_prealloc_dir_blocks)
4228 bad_size = 2;
4229 }
4230 } else {
4231 size = EXT2_I_SIZE(inode);
4232 if ((pb.last_block >= 0) &&
4233 (size < (__u64) pb.last_block * fs->blocksize))
4234 bad_size = 3;
4235 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4236 bad_size = 4;
4237 }
4238 /* i_size for symlinks is checked elsewhere */
4239 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4240 pctx->num = (pb.last_block+1) * fs->blocksize;
4241 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4242 inode->i_size = pctx->num;
4243 if (!LINUX_S_ISDIR(inode->i_mode))
4244 inode->i_size_high = pctx->num >> 32;
4245 dirty_inode++;
4246 }
4247 pctx->num = 0;
4248 }
4249 if (LINUX_S_ISREG(inode->i_mode) &&
4250 (inode->i_size_high || inode->i_size & 0x80000000UL))
4251 ctx->large_files++;
4252 if (pb.num_blocks != inode->i_blocks) {
4253 pctx->num = pb.num_blocks;
4254 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4255 inode->i_blocks = pb.num_blocks;
4256 dirty_inode++;
4257 }
4258 pctx->num = 0;
4259 }
4260out:
4261 if (dirty_inode)
4262 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4263}
4264
4265
4266/*
4267 * This is a helper function for check_blocks().
4268 */
4269static int process_block(ext2_filsys fs,
4270 blk_t *block_nr,
4271 e2_blkcnt_t blockcnt,
4272 blk_t ref_block FSCK_ATTR((unused)),
4273 int ref_offset FSCK_ATTR((unused)),
4274 void *priv_data)
4275{
4276 struct process_block_struct_1 *p;
4277 struct problem_context *pctx;
4278 blk_t blk = *block_nr;
4279 int ret_code = 0;
4280 int problem = 0;
4281 e2fsck_t ctx;
4282
4283 p = (struct process_block_struct_1 *) priv_data;
4284 pctx = p->pctx;
4285 ctx = p->ctx;
4286
4287 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4288 /* todo: Check that the comprblk_fl is high, that the
4289 blkaddr pattern looks right (all non-holes up to
4290 first EXT2FS_COMPRESSED_BLKADDR, then all
4291 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4292 that the feature_incompat bit is high, and that the
4293 inode is a regular file. If we're doing a "full
4294 check" (a concept introduced to e2fsck by e2compr,
4295 meaning that we look at data blocks as well as
4296 metadata) then call some library routine that
4297 checks the compressed data. I'll have to think
4298 about this, because one particularly important
4299 problem to be able to fix is to recalculate the
4300 cluster size if necessary. I think that perhaps
4301 we'd better do most/all e2compr-specific checks
4302 separately, after the non-e2compr checks. If not
4303 doing a full check, it may be useful to test that
4304 the personality is linux; e.g. if it isn't then
4305 perhaps this really is just an illegal block. */
4306 return 0;
4307 }
4308
4309 if (blk == 0) {
4310 if (p->is_dir == 0) {
4311 /*
4312 * Should never happen, since only directories
4313 * get called with BLOCK_FLAG_HOLE
4314 */
4315#ifdef DEBUG_E2FSCK
4316 printf("process_block() called with blk == 0, "
4317 "blockcnt=%d, inode %lu???\n",
4318 blockcnt, p->ino);
4319#endif
4320 return 0;
4321 }
4322 if (blockcnt < 0)
4323 return 0;
4324 if (blockcnt * fs->blocksize < p->inode->i_size) {
4325 goto mark_dir;
4326 }
4327 return 0;
4328 }
4329
4330 /*
4331 * Simplistic fragmentation check. We merely require that the
4332 * file be contiguous. (Which can never be true for really
4333 * big files that are greater than a block group.)
4334 */
4335 if (!HOLE_BLKADDR(p->previous_block)) {
4336 if (p->previous_block+1 != blk)
4337 p->fragmented = 1;
4338 }
4339 p->previous_block = blk;
4340
4341 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4342 problem = PR_1_TOOBIG_DIR;
4343 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4344 problem = PR_1_TOOBIG_REG;
4345 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4346 problem = PR_1_TOOBIG_SYMLINK;
4347
4348 if (blk < fs->super->s_first_data_block ||
4349 blk >= fs->super->s_blocks_count)
4350 problem = PR_1_ILLEGAL_BLOCK_NUM;
4351
4352 if (problem) {
4353 p->num_illegal_blocks++;
4354 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4355 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4356 p->clear = 1;
4357 return BLOCK_ABORT;
4358 }
4359 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4360 p->suppress = 1;
4361 set_latch_flags(PR_LATCH_BLOCK,
4362 PRL_SUPPRESS, 0);
4363 }
4364 }
4365 pctx->blk = blk;
4366 pctx->blkcount = blockcnt;
4367 if (fix_problem(ctx, problem, pctx)) {
4368 blk = *block_nr = 0;
4369 ret_code = BLOCK_CHANGED;
4370 goto mark_dir;
4371 } else
4372 return 0;
4373 }
4374
4375 if (p->ino == EXT2_RESIZE_INO) {
4376 /*
4377 * The resize inode has already be sanity checked
4378 * during pass #0 (the superblock checks). All we
4379 * have to do is mark the double indirect block as
4380 * being in use; all of the other blocks are handled
4381 * by mark_table_blocks()).
4382 */
4383 if (blockcnt == BLOCK_COUNT_DIND)
4384 mark_block_used(ctx, blk);
4385 } else
4386 mark_block_used(ctx, blk);
4387 p->num_blocks++;
4388 if (blockcnt >= 0)
4389 p->last_block = blockcnt;
4390mark_dir:
4391 if (p->is_dir && (blockcnt >= 0)) {
4392 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4393 blk, blockcnt);
4394 if (pctx->errcode) {
4395 pctx->blk = blk;
4396 pctx->num = blockcnt;
4397 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4398 /* Should never get here */
4399 ctx->flags |= E2F_FLAG_ABORT;
4400 return BLOCK_ABORT;
4401 }
4402 }
4403 return ret_code;
4404}
4405
4406static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4407 blk_t *block_nr,
4408 e2_blkcnt_t blockcnt,
4409 blk_t ref_block FSCK_ATTR((unused)),
4410 int ref_offset FSCK_ATTR((unused)),
4411 void *priv_data EXT2FS_ATTR((unused)))
4412{
4413 /*
4414 * Note: This function processes blocks for the bad blocks
4415 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4416 */
4417
4418 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4419 return BLOCK_ERROR;
4420}
4421
4422/*
4423 * This routine gets called at the end of pass 1 if bad blocks are
4424 * detected in the superblock, group descriptors, inode_bitmaps, or
4425 * block bitmaps. At this point, all of the blocks have been mapped
4426 * out, so we can try to allocate new block(s) to replace the bad
4427 * blocks.
4428 */
4429static void handle_fs_bad_blocks(e2fsck_t ctx)
4430{
4431 printf("Bad blocks detected on your filesystem\n"
4432 "You should get your data off as the device will soon die\n");
4433}
4434
4435/*
4436 * This routine marks all blocks which are used by the superblock,
4437 * group descriptors, inode bitmaps, and block bitmaps.
4438 */
4439static void mark_table_blocks(e2fsck_t ctx)
4440{
4441 ext2_filsys fs = ctx->fs;
4442 blk_t block, b;
4443 dgrp_t i;
4444 int j;
4445 struct problem_context pctx;
4446
4447 clear_problem_context(&pctx);
4448
4449 block = fs->super->s_first_data_block;
4450 for (i = 0; i < fs->group_desc_count; i++) {
4451 pctx.group = i;
4452
4453 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4454
4455 /*
4456 * Mark the blocks used for the inode table
4457 */
4458 if (fs->group_desc[i].bg_inode_table) {
4459 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4460 j < fs->inode_blocks_per_group;
4461 j++, b++) {
4462 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4463 b)) {
4464 pctx.blk = b;
4465 if (fix_problem(ctx,
4466 PR_1_ITABLE_CONFLICT, &pctx)) {
4467 ctx->invalid_inode_table_flag[i]++;
4468 ctx->invalid_bitmaps++;
4469 }
4470 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004471 ext2fs_mark_block_bitmap(ctx->block_found_map, b);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004472 }
4473 }
4474 }
4475
4476 /*
4477 * Mark block used for the block bitmap
4478 */
4479 if (fs->group_desc[i].bg_block_bitmap) {
4480 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4481 fs->group_desc[i].bg_block_bitmap)) {
4482 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4483 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4484 ctx->invalid_block_bitmap_flag[i]++;
4485 ctx->invalid_bitmaps++;
4486 }
4487 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004488 ext2fs_mark_block_bitmap(ctx->block_found_map,
4489 fs->group_desc[i].bg_block_bitmap);
4490 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004491 }
4492 /*
4493 * Mark block used for the inode bitmap
4494 */
4495 if (fs->group_desc[i].bg_inode_bitmap) {
4496 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4497 fs->group_desc[i].bg_inode_bitmap)) {
4498 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4499 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4500 ctx->invalid_inode_bitmap_flag[i]++;
4501 ctx->invalid_bitmaps++;
4502 }
4503 } else {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +02004504 ext2fs_mark_block_bitmap(ctx->block_found_map,
4505 fs->group_desc[i].bg_inode_bitmap);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004506 }
4507 }
4508 block += fs->super->s_blocks_per_group;
4509 }
4510}
4511
4512/*
4513 * Thes subroutines short circuits ext2fs_get_blocks and
4514 * ext2fs_check_directory; we use them since we already have the inode
4515 * structure, so there's no point in letting the ext2fs library read
4516 * the inode again.
4517 */
4518static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4519 blk_t *blocks)
4520{
4521 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4522 int i;
4523
4524 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4525 return EXT2_ET_CALLBACK_NOTHANDLED;
4526
4527 for (i=0; i < EXT2_N_BLOCKS; i++)
4528 blocks[i] = ctx->stashed_inode->i_block[i];
4529 return 0;
4530}
4531
4532static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4533 struct ext2_inode *inode)
4534{
4535 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4536
4537 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4538 return EXT2_ET_CALLBACK_NOTHANDLED;
4539 *inode = *ctx->stashed_inode;
4540 return 0;
4541}
4542
4543static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4544 struct ext2_inode *inode)
4545{
4546 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4547
4548 if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4549 *ctx->stashed_inode = *inode;
4550 return EXT2_ET_CALLBACK_NOTHANDLED;
4551}
4552
4553static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4554{
4555 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4556
4557 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4558 return EXT2_ET_CALLBACK_NOTHANDLED;
4559
4560 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4561 return EXT2_ET_NO_DIRECTORY;
4562 return 0;
4563}
4564
4565void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4566{
4567 ext2_filsys fs = ctx->fs;
4568
4569 if (bool) {
4570 fs->get_blocks = pass1_get_blocks;
4571 fs->check_directory = pass1_check_directory;
4572 fs->read_inode = pass1_read_inode;
4573 fs->write_inode = pass1_write_inode;
4574 ctx->stashed_ino = 0;
4575 } else {
4576 fs->get_blocks = 0;
4577 fs->check_directory = 0;
4578 fs->read_inode = 0;
4579 fs->write_inode = 0;
4580 }
4581}
4582
4583/*
4584 * pass1b.c --- Pass #1b of e2fsck
4585 *
4586 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4587 * only invoked if pass 1 discovered blocks which are in use by more
4588 * than one inode.
4589 *
4590 * Pass1B scans the data blocks of all the inodes again, generating a
4591 * complete list of duplicate blocks and which inodes have claimed
4592 * them.
4593 *
4594 * Pass1C does a tree-traversal of the filesystem, to determine the
4595 * parent directories of these inodes. This step is necessary so that
4596 * e2fsck can print out the pathnames of affected inodes.
4597 *
4598 * Pass1D is a reconciliation pass. For each inode with duplicate
4599 * blocks, the user is prompted if s/he would like to clone the file
4600 * (so that the file gets a fresh copy of the duplicated blocks) or
4601 * simply to delete the file.
4602 *
4603 */
4604
4605
4606/* Needed for architectures where sizeof(int) != sizeof(void *) */
4607#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4608#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4609
4610/* Define an extension to the ext2 library's block count information */
4611#define BLOCK_COUNT_EXTATTR (-5)
4612
4613struct block_el {
4614 blk_t block;
4615 struct block_el *next;
4616};
4617
4618struct inode_el {
4619 ext2_ino_t inode;
4620 struct inode_el *next;
4621};
4622
4623struct dup_block {
4624 int num_bad;
4625 struct inode_el *inode_list;
4626};
4627
4628/*
4629 * This structure stores information about a particular inode which
4630 * is sharing blocks with other inodes. This information is collected
4631 * to display to the user, so that the user knows what files he or she
4632 * is dealing with, when trying to decide how to resolve the conflict
4633 * of multiply-claimed blocks.
4634 */
4635struct dup_inode {
4636 ext2_ino_t dir;
4637 int num_dupblocks;
4638 struct ext2_inode inode;
4639 struct block_el *block_list;
4640};
4641
4642static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4643 e2_blkcnt_t blockcnt, blk_t ref_blk,
4644 int ref_offset, void *priv_data);
4645static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4646 struct dup_inode *dp, char *block_buf);
4647static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4648 struct dup_inode *dp, char* block_buf);
4649static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4650
4651static void pass1b(e2fsck_t ctx, char *block_buf);
4652static void pass1c(e2fsck_t ctx, char *block_buf);
4653static void pass1d(e2fsck_t ctx, char *block_buf);
4654
4655static int dup_inode_count = 0;
4656
4657static dict_t blk_dict, ino_dict;
4658
4659static ext2fs_inode_bitmap inode_dup_map;
4660
4661static int dict_int_cmp(const void *a, const void *b)
4662{
4663 intptr_t ia, ib;
4664
4665 ia = (intptr_t)a;
4666 ib = (intptr_t)b;
4667
4668 return (ia-ib);
4669}
4670
4671/*
4672 * Add a duplicate block record
4673 */
4674static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4675 struct ext2_inode *inode)
4676{
4677 dnode_t *n;
4678 struct dup_block *db;
4679 struct dup_inode *di;
4680 struct block_el *blk_el;
4681 struct inode_el *ino_el;
4682
4683 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4684 if (n)
4685 db = (struct dup_block *) dnode_get(n);
4686 else {
4687 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4688 sizeof(struct dup_block), "duplicate block header");
4689 db->num_bad = 0;
4690 db->inode_list = 0;
4691 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4692 }
4693 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4694 sizeof(struct inode_el), "inode element");
4695 ino_el->inode = ino;
4696 ino_el->next = db->inode_list;
4697 db->inode_list = ino_el;
4698 db->num_bad++;
4699
4700 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4701 if (n)
4702 di = (struct dup_inode *) dnode_get(n);
4703 else {
4704 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4705 sizeof(struct dup_inode), "duplicate inode header");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00004706 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004707 di->num_dupblocks = 0;
4708 di->block_list = 0;
4709 di->inode = *inode;
4710 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4711 }
4712 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4713 sizeof(struct block_el), "block element");
4714 blk_el->block = blk;
4715 blk_el->next = di->block_list;
4716 di->block_list = blk_el;
4717 di->num_dupblocks++;
4718}
4719
4720/*
4721 * Free a duplicate inode record
4722 */
4723static void inode_dnode_free(dnode_t *node)
4724{
4725 struct dup_inode *di;
4726 struct block_el *p, *next;
4727
4728 di = (struct dup_inode *) dnode_get(node);
4729 for (p = di->block_list; p; p = next) {
4730 next = p->next;
4731 free(p);
4732 }
4733 free(node);
4734}
4735
4736/*
4737 * Free a duplicate block record
4738 */
4739static void block_dnode_free(dnode_t *node)
4740{
4741 struct dup_block *db;
4742 struct inode_el *p, *next;
4743
4744 db = (struct dup_block *) dnode_get(node);
4745 for (p = db->inode_list; p; p = next) {
4746 next = p->next;
4747 free(p);
4748 }
4749 free(node);
4750}
4751
4752
4753/*
4754 * Main procedure for handling duplicate blocks
4755 */
4756void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4757{
4758 ext2_filsys fs = ctx->fs;
4759 struct problem_context pctx;
4760
4761 clear_problem_context(&pctx);
4762
4763 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4764 _("multiply claimed inode map"), &inode_dup_map);
4765 if (pctx.errcode) {
4766 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4767 ctx->flags |= E2F_FLAG_ABORT;
4768 return;
4769 }
4770
4771 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4772 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4773 dict_set_allocator(&ino_dict, inode_dnode_free);
4774 dict_set_allocator(&blk_dict, block_dnode_free);
4775
4776 pass1b(ctx, block_buf);
4777 pass1c(ctx, block_buf);
4778 pass1d(ctx, block_buf);
4779
4780 /*
4781 * Time to free all of the accumulated data structures that we
4782 * don't need anymore.
4783 */
4784 dict_free_nodes(&ino_dict);
4785 dict_free_nodes(&blk_dict);
4786}
4787
4788/*
4789 * Scan the inodes looking for inodes that contain duplicate blocks.
4790 */
4791struct process_block_struct_1b {
4792 e2fsck_t ctx;
4793 ext2_ino_t ino;
4794 int dup_blocks;
4795 struct ext2_inode *inode;
4796 struct problem_context *pctx;
4797};
4798
4799static void pass1b(e2fsck_t ctx, char *block_buf)
4800{
4801 ext2_filsys fs = ctx->fs;
4802 ext2_ino_t ino;
4803 struct ext2_inode inode;
4804 ext2_inode_scan scan;
4805 struct process_block_struct_1b pb;
4806 struct problem_context pctx;
4807
4808 clear_problem_context(&pctx);
4809
4810 if (!(ctx->options & E2F_OPT_PREEN))
4811 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4812 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4813 &scan);
4814 if (pctx.errcode) {
4815 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4816 ctx->flags |= E2F_FLAG_ABORT;
4817 return;
4818 }
4819 ctx->stashed_inode = &inode;
4820 pb.ctx = ctx;
4821 pb.pctx = &pctx;
4822 pctx.str = "pass1b";
4823 while (1) {
4824 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4825 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4826 continue;
4827 if (pctx.errcode) {
4828 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4829 ctx->flags |= E2F_FLAG_ABORT;
4830 return;
4831 }
4832 if (!ino)
4833 break;
4834 pctx.ino = ctx->stashed_ino = ino;
4835 if ((ino != EXT2_BAD_INO) &&
4836 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4837 continue;
4838
4839 pb.ino = ino;
4840 pb.dup_blocks = 0;
4841 pb.inode = &inode;
4842
4843 if (ext2fs_inode_has_valid_blocks(&inode) ||
4844 (ino == EXT2_BAD_INO))
4845 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4846 0, block_buf, process_pass1b_block, &pb);
4847 if (inode.i_file_acl)
4848 process_pass1b_block(fs, &inode.i_file_acl,
4849 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4850 if (pb.dup_blocks) {
4851 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4852 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4853 ino == EXT2_ROOT_INO)
4854 dup_inode_count++;
4855 }
4856 if (pctx.errcode)
4857 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4858 }
4859 ext2fs_close_inode_scan(scan);
4860 e2fsck_use_inode_shortcuts(ctx, 0);
4861}
4862
4863static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4864 blk_t *block_nr,
4865 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4866 blk_t ref_blk FSCK_ATTR((unused)),
4867 int ref_offset FSCK_ATTR((unused)),
4868 void *priv_data)
4869{
4870 struct process_block_struct_1b *p;
4871 e2fsck_t ctx;
4872
4873 if (HOLE_BLKADDR(*block_nr))
4874 return 0;
4875 p = (struct process_block_struct_1b *) priv_data;
4876 ctx = p->ctx;
4877
4878 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4879 return 0;
4880
4881 /* OK, this is a duplicate block */
4882 if (p->ino != EXT2_BAD_INO) {
4883 p->pctx->blk = *block_nr;
4884 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4885 }
4886 p->dup_blocks++;
4887 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4888
4889 add_dupe(ctx, p->ino, *block_nr, p->inode);
4890
4891 return 0;
4892}
4893
4894/*
4895 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4896 * is used so that we can print pathnames when prompting the user for
4897 * what to do.
4898 */
4899struct search_dir_struct {
4900 int count;
4901 ext2_ino_t first_inode;
4902 ext2_ino_t max_inode;
4903};
4904
4905static int search_dirent_proc(ext2_ino_t dir, int entry,
4906 struct ext2_dir_entry *dirent,
4907 int offset FSCK_ATTR((unused)),
4908 int blocksize FSCK_ATTR((unused)),
4909 char *buf FSCK_ATTR((unused)),
4910 void *priv_data)
4911{
4912 struct search_dir_struct *sd;
4913 struct dup_inode *p;
4914 dnode_t *n;
4915
4916 sd = (struct search_dir_struct *) priv_data;
4917
4918 if (dirent->inode > sd->max_inode)
4919 /* Should abort this inode, but not everything */
4920 return 0;
4921
4922 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4923 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4924 return 0;
4925
4926 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4927 if (!n)
4928 return 0;
4929 p = (struct dup_inode *) dnode_get(n);
4930 p->dir = dir;
4931 sd->count--;
4932
4933 return sd->count ? 0 : DIRENT_ABORT;
4934}
4935
4936
4937static void pass1c(e2fsck_t ctx, char *block_buf)
4938{
4939 ext2_filsys fs = ctx->fs;
4940 struct search_dir_struct sd;
4941 struct problem_context pctx;
4942
4943 clear_problem_context(&pctx);
4944
4945 if (!(ctx->options & E2F_OPT_PREEN))
4946 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4947
4948 /*
4949 * Search through all directories to translate inodes to names
4950 * (by searching for the containing directory for that inode.)
4951 */
4952 sd.count = dup_inode_count;
4953 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4954 sd.max_inode = fs->super->s_inodes_count;
4955 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4956 search_dirent_proc, &sd);
4957}
4958
4959static void pass1d(e2fsck_t ctx, char *block_buf)
4960{
4961 ext2_filsys fs = ctx->fs;
4962 struct dup_inode *p, *t;
4963 struct dup_block *q;
4964 ext2_ino_t *shared, ino;
4965 int shared_len;
4966 int i;
4967 int file_ok;
4968 int meta_data = 0;
4969 struct problem_context pctx;
4970 dnode_t *n, *m;
4971 struct block_el *s;
4972 struct inode_el *r;
4973
4974 clear_problem_context(&pctx);
4975
4976 if (!(ctx->options & E2F_OPT_PREEN))
4977 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4978 e2fsck_read_bitmaps(ctx);
4979
4980 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4981 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4982 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4983 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4984 "Shared inode list");
4985 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4986 p = (struct dup_inode *) dnode_get(n);
4987 shared_len = 0;
4988 file_ok = 1;
4989 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4990 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4991 continue;
4992
4993 /*
4994 * Find all of the inodes which share blocks with this
4995 * one. First we find all of the duplicate blocks
4996 * belonging to this inode, and then search each block
4997 * get the list of inodes, and merge them together.
4998 */
4999 for (s = p->block_list; s; s = s->next) {
5000 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
5001 if (!m)
5002 continue; /* Should never happen... */
5003 q = (struct dup_block *) dnode_get(m);
5004 if (q->num_bad > 1)
5005 file_ok = 0;
5006 if (check_if_fs_block(ctx, s->block)) {
5007 file_ok = 0;
5008 meta_data = 1;
5009 }
5010
5011 /*
5012 * Add all inodes used by this block to the
5013 * shared[] --- which is a unique list, so
5014 * if an inode is already in shared[], don't
5015 * add it again.
5016 */
5017 for (r = q->inode_list; r; r = r->next) {
5018 if (r->inode == ino)
5019 continue;
5020 for (i = 0; i < shared_len; i++)
5021 if (shared[i] == r->inode)
5022 break;
5023 if (i == shared_len) {
5024 shared[shared_len++] = r->inode;
5025 }
5026 }
5027 }
5028
5029 /*
5030 * Report the inode that we are working on
5031 */
5032 pctx.inode = &p->inode;
5033 pctx.ino = ino;
5034 pctx.dir = p->dir;
5035 pctx.blkcount = p->num_dupblocks;
5036 pctx.num = meta_data ? shared_len+1 : shared_len;
5037 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5038 pctx.blkcount = 0;
5039 pctx.num = 0;
5040
5041 if (meta_data)
5042 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5043
5044 for (i = 0; i < shared_len; i++) {
5045 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5046 if (!m)
5047 continue; /* should never happen */
5048 t = (struct dup_inode *) dnode_get(m);
5049 /*
5050 * Report the inode that we are sharing with
5051 */
5052 pctx.inode = &t->inode;
5053 pctx.ino = shared[i];
5054 pctx.dir = t->dir;
5055 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5056 }
5057 if (file_ok) {
5058 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5059 continue;
5060 }
5061 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5062 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5063 if (pctx.errcode)
5064 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5065 else
5066 continue;
5067 }
5068 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5069 delete_file(ctx, ino, p, block_buf);
5070 else
5071 ext2fs_unmark_valid(fs);
5072 }
5073 ext2fs_free_mem(&shared);
5074}
5075
5076/*
5077 * Drop the refcount on the dup_block structure, and clear the entry
5078 * in the block_dup_map if appropriate.
5079 */
5080static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5081{
5082 p->num_bad--;
5083 if (p->num_bad <= 0 ||
5084 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5085 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5086}
5087
5088static int delete_file_block(ext2_filsys fs,
5089 blk_t *block_nr,
5090 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5091 blk_t ref_block FSCK_ATTR((unused)),
5092 int ref_offset FSCK_ATTR((unused)),
5093 void *priv_data)
5094{
5095 struct process_block_struct_1b *pb;
5096 struct dup_block *p;
5097 dnode_t *n;
5098 e2fsck_t ctx;
5099
5100 pb = (struct process_block_struct_1b *) priv_data;
5101 ctx = pb->ctx;
5102
5103 if (HOLE_BLKADDR(*block_nr))
5104 return 0;
5105
5106 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5107 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5108 if (n) {
5109 p = (struct dup_block *) dnode_get(n);
5110 decrement_badcount(ctx, *block_nr, p);
5111 } else
5112 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5113 *block_nr);
5114 } else {
5115 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5116 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5117 }
5118
5119 return 0;
5120}
5121
5122static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5123 struct dup_inode *dp, char* block_buf)
5124{
5125 ext2_filsys fs = ctx->fs;
5126 struct process_block_struct_1b pb;
5127 struct ext2_inode inode;
5128 struct problem_context pctx;
5129 unsigned int count;
5130
5131 clear_problem_context(&pctx);
5132 pctx.ino = pb.ino = ino;
5133 pb.dup_blocks = dp->num_dupblocks;
5134 pb.ctx = ctx;
5135 pctx.str = "delete_file";
5136
5137 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5138 if (ext2fs_inode_has_valid_blocks(&inode))
5139 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5140 delete_file_block, &pb);
5141 if (pctx.errcode)
5142 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5143 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5144 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5145 if (ctx->inode_bad_map)
5146 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5147 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5148
5149 /* Inode may have changed by block_iterate, so reread it */
5150 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5151 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00005152 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005153 if (inode.i_file_acl &&
5154 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5155 count = 1;
5156 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5157 block_buf, -1, &count);
5158 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5159 pctx.errcode = 0;
5160 count = 1;
5161 }
5162 if (pctx.errcode) {
5163 pctx.blk = inode.i_file_acl;
5164 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5165 }
5166 /*
5167 * If the count is zero, then arrange to have the
5168 * block deleted. If the block is in the block_dup_map,
5169 * also call delete_file_block since it will take care
5170 * of keeping the accounting straight.
5171 */
5172 if ((count == 0) ||
5173 ext2fs_test_block_bitmap(ctx->block_dup_map,
5174 inode.i_file_acl))
5175 delete_file_block(fs, &inode.i_file_acl,
5176 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5177 }
5178 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5179}
5180
5181struct clone_struct {
5182 errcode_t errcode;
5183 ext2_ino_t dir;
5184 char *buf;
5185 e2fsck_t ctx;
5186};
5187
5188static int clone_file_block(ext2_filsys fs,
5189 blk_t *block_nr,
5190 e2_blkcnt_t blockcnt,
5191 blk_t ref_block FSCK_ATTR((unused)),
5192 int ref_offset FSCK_ATTR((unused)),
5193 void *priv_data)
5194{
5195 struct dup_block *p;
5196 blk_t new_block;
5197 errcode_t retval;
5198 struct clone_struct *cs = (struct clone_struct *) priv_data;
5199 dnode_t *n;
5200 e2fsck_t ctx;
5201
5202 ctx = cs->ctx;
5203
5204 if (HOLE_BLKADDR(*block_nr))
5205 return 0;
5206
5207 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5208 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5209 if (n) {
5210 p = (struct dup_block *) dnode_get(n);
5211 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5212 &new_block);
5213 if (retval) {
5214 cs->errcode = retval;
5215 return BLOCK_ABORT;
5216 }
5217 if (cs->dir && (blockcnt >= 0)) {
5218 retval = ext2fs_set_dir_block(fs->dblist,
5219 cs->dir, new_block, blockcnt);
5220 if (retval) {
5221 cs->errcode = retval;
5222 return BLOCK_ABORT;
5223 }
5224 }
5225
5226 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5227 cs->buf);
5228 if (retval) {
5229 cs->errcode = retval;
5230 return BLOCK_ABORT;
5231 }
5232 retval = io_channel_write_blk(fs->io, new_block, 1,
5233 cs->buf);
5234 if (retval) {
5235 cs->errcode = retval;
5236 return BLOCK_ABORT;
5237 }
5238 decrement_badcount(ctx, *block_nr, p);
5239 *block_nr = new_block;
5240 ext2fs_mark_block_bitmap(ctx->block_found_map,
5241 new_block);
5242 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5243 return BLOCK_CHANGED;
5244 } else
5245 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5246 *block_nr);
5247 }
5248 return 0;
5249}
5250
5251static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5252 struct dup_inode *dp, char* block_buf)
5253{
5254 ext2_filsys fs = ctx->fs;
5255 errcode_t retval;
5256 struct clone_struct cs;
5257 struct problem_context pctx;
5258 blk_t blk;
5259 dnode_t *n;
5260 struct inode_el *ino_el;
5261 struct dup_block *db;
5262 struct dup_inode *di;
5263
5264 clear_problem_context(&pctx);
5265 cs.errcode = 0;
5266 cs.dir = 0;
5267 cs.ctx = ctx;
5268 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5269 if (retval)
5270 return retval;
5271
5272 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5273 cs.dir = ino;
5274
5275 pctx.ino = ino;
5276 pctx.str = "clone_file";
5277 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5278 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5279 clone_file_block, &cs);
5280 ext2fs_mark_bb_dirty(fs);
5281 if (pctx.errcode) {
5282 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5283 retval = pctx.errcode;
5284 goto errout;
5285 }
5286 if (cs.errcode) {
5287 bb_error_msg(_("returned from clone_file_block"));
5288 retval = cs.errcode;
5289 goto errout;
5290 }
5291 /* The inode may have changed on disk, so we have to re-read it */
5292 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5293 blk = dp->inode.i_file_acl;
5294 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5295 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5296 BLOCK_CHANGED)) {
5297 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5298 /*
5299 * If we cloned the EA block, find all other inodes
5300 * which refered to that EA block, and modify
5301 * them to point to the new EA block.
5302 */
5303 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5304 db = (struct dup_block *) dnode_get(n);
5305 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5306 if (ino_el->inode == ino)
5307 continue;
5308 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5309 di = (struct dup_inode *) dnode_get(n);
5310 if (di->inode.i_file_acl == blk) {
5311 di->inode.i_file_acl = dp->inode.i_file_acl;
5312 e2fsck_write_inode(ctx, ino_el->inode,
5313 &di->inode, "clone file EA");
5314 decrement_badcount(ctx, blk, db);
5315 }
5316 }
5317 }
5318 retval = 0;
5319errout:
5320 ext2fs_free_mem(&cs.buf);
5321 return retval;
5322}
5323
5324/*
5325 * This routine returns 1 if a block overlaps with one of the superblocks,
5326 * group descriptors, inode bitmaps, or block bitmaps.
5327 */
5328static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5329{
5330 ext2_filsys fs = ctx->fs;
5331 blk_t block;
5332 dgrp_t i;
5333
5334 block = fs->super->s_first_data_block;
5335 for (i = 0; i < fs->group_desc_count; i++) {
5336
5337 /* Check superblocks/block group descriptros */
5338 if (ext2fs_bg_has_super(fs, i)) {
5339 if (test_block >= block &&
5340 (test_block <= block + fs->desc_blocks))
5341 return 1;
5342 }
5343
5344 /* Check the inode table */
5345 if ((fs->group_desc[i].bg_inode_table) &&
5346 (test_block >= fs->group_desc[i].bg_inode_table) &&
5347 (test_block < (fs->group_desc[i].bg_inode_table +
5348 fs->inode_blocks_per_group)))
5349 return 1;
5350
5351 /* Check the bitmap blocks */
5352 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5353 (test_block == fs->group_desc[i].bg_inode_bitmap))
5354 return 1;
5355
5356 block += fs->super->s_blocks_per_group;
5357 }
5358 return 0;
5359}
5360/*
5361 * pass2.c --- check directory structure
5362 *
5363 * Pass 2 of e2fsck iterates through all active directory inodes, and
5364 * applies to following tests to each directory entry in the directory
5365 * blocks in the inodes:
5366 *
5367 * - The length of the directory entry (rec_len) should be at
5368 * least 8 bytes, and no more than the remaining space
5369 * left in the directory block.
5370 * - The length of the name in the directory entry (name_len)
5371 * should be less than (rec_len - 8).
5372 * - The inode number in the directory entry should be within
5373 * legal bounds.
5374 * - The inode number should refer to a in-use inode.
5375 * - The first entry should be '.', and its inode should be
5376 * the inode of the directory.
5377 * - The second entry should be '..'.
5378 *
5379 * To minimize disk seek time, the directory blocks are processed in
5380 * sorted order of block numbers.
5381 *
5382 * Pass 2 also collects the following information:
5383 * - The inode numbers of the subdirectories for each directory.
5384 *
5385 * Pass 2 relies on the following information from previous passes:
5386 * - The directory information collected in pass 1.
5387 * - The inode_used_map bitmap
5388 * - The inode_bad_map bitmap
5389 * - The inode_dir_map bitmap
5390 *
5391 * Pass 2 frees the following data structures
5392 * - The inode_bad_map bitmap
5393 * - The inode_reg_map bitmap
5394 */
5395
5396/*
5397 * Keeps track of how many times an inode is referenced.
5398 */
5399static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5400static int check_dir_block(ext2_filsys fs,
5401 struct ext2_db_entry *dir_blocks_info,
5402 void *priv_data);
5403static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5404 struct problem_context *pctx);
5405static int update_dir_block(ext2_filsys fs,
5406 blk_t *block_nr,
5407 e2_blkcnt_t blockcnt,
5408 blk_t ref_block,
5409 int ref_offset,
5410 void *priv_data);
5411static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5412static int htree_depth(struct dx_dir_info *dx_dir,
5413 struct dx_dirblock_info *dx_db);
5414static int special_dir_block_cmp(const void *a, const void *b);
5415
5416struct check_dir_struct {
5417 char *buf;
5418 struct problem_context pctx;
5419 int count, max;
5420 e2fsck_t ctx;
5421};
5422
5423static void e2fsck_pass2(e2fsck_t ctx)
5424{
5425 struct ext2_super_block *sb = ctx->fs->super;
5426 struct problem_context pctx;
5427 ext2_filsys fs = ctx->fs;
5428 char *buf;
5429 struct dir_info *dir;
5430 struct check_dir_struct cd;
5431 struct dx_dir_info *dx_dir;
5432 struct dx_dirblock_info *dx_db, *dx_parent;
5433 int b;
5434 int i, depth;
5435 problem_t code;
5436 int bad_dir;
5437
5438 clear_problem_context(&cd.pctx);
5439
5440 /* Pass 2 */
5441
5442 if (!(ctx->options & E2F_OPT_PREEN))
5443 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5444
5445 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5446 0, ctx->inode_link_info,
5447 &ctx->inode_count);
5448 if (cd.pctx.errcode) {
5449 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5450 ctx->flags |= E2F_FLAG_ABORT;
5451 return;
5452 }
5453 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5454 "directory scan buffer");
5455
5456 /*
5457 * Set up the parent pointer for the root directory, if
5458 * present. (If the root directory is not present, we will
5459 * create it in pass 3.)
5460 */
5461 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5462 if (dir)
5463 dir->parent = EXT2_ROOT_INO;
5464
5465 cd.buf = buf;
5466 cd.ctx = ctx;
5467 cd.count = 1;
5468 cd.max = ext2fs_dblist_count(fs->dblist);
5469
5470 if (ctx->progress)
5471 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5472
5473 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5474 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5475
5476 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5477 &cd);
5478 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5479 return;
5480 if (cd.pctx.errcode) {
5481 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5482 ctx->flags |= E2F_FLAG_ABORT;
5483 return;
5484 }
5485
5486#ifdef ENABLE_HTREE
5487 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5488 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5489 return;
5490 if (dx_dir->numblocks == 0)
5491 continue;
5492 clear_problem_context(&pctx);
5493 bad_dir = 0;
5494 pctx.dir = dx_dir->ino;
5495 dx_db = dx_dir->dx_block;
5496 if (dx_db->flags & DX_FLAG_REFERENCED)
5497 dx_db->flags |= DX_FLAG_DUP_REF;
5498 else
5499 dx_db->flags |= DX_FLAG_REFERENCED;
5500 /*
5501 * Find all of the first and last leaf blocks, and
5502 * update their parent's min and max hash values
5503 */
5504 for (b=0, dx_db = dx_dir->dx_block;
5505 b < dx_dir->numblocks;
5506 b++, dx_db++) {
5507 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5508 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5509 continue;
5510 dx_parent = &dx_dir->dx_block[dx_db->parent];
5511 /*
5512 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5513 */
5514 if (dx_db->flags & DX_FLAG_FIRST)
5515 dx_parent->min_hash = dx_db->min_hash;
5516 /*
5517 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5518 */
5519 if (dx_db->flags & DX_FLAG_LAST)
5520 dx_parent->max_hash = dx_db->max_hash;
5521 }
5522
5523 for (b=0, dx_db = dx_dir->dx_block;
5524 b < dx_dir->numblocks;
5525 b++, dx_db++) {
5526 pctx.blkcount = b;
5527 pctx.group = dx_db->parent;
5528 code = 0;
5529 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5530 (dx_db->min_hash < dx_db->node_min_hash)) {
5531 pctx.blk = dx_db->min_hash;
5532 pctx.blk2 = dx_db->node_min_hash;
5533 code = PR_2_HTREE_MIN_HASH;
5534 fix_problem(ctx, code, &pctx);
5535 bad_dir++;
5536 }
5537 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5538 depth = htree_depth(dx_dir, dx_db);
5539 if (depth != dx_dir->depth) {
5540 code = PR_2_HTREE_BAD_DEPTH;
5541 fix_problem(ctx, code, &pctx);
5542 bad_dir++;
5543 }
5544 }
5545 /*
5546 * This test doesn't apply for the root block
5547 * at block #0
5548 */
5549 if (b &&
5550 (dx_db->max_hash > dx_db->node_max_hash)) {
5551 pctx.blk = dx_db->max_hash;
5552 pctx.blk2 = dx_db->node_max_hash;
5553 code = PR_2_HTREE_MAX_HASH;
5554 fix_problem(ctx, code, &pctx);
5555 bad_dir++;
5556 }
5557 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5558 code = PR_2_HTREE_NOTREF;
5559 fix_problem(ctx, code, &pctx);
5560 bad_dir++;
5561 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5562 code = PR_2_HTREE_DUPREF;
5563 fix_problem(ctx, code, &pctx);
5564 bad_dir++;
5565 }
5566 if (code == 0)
5567 continue;
5568 }
5569 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5570 clear_htree(ctx, dx_dir->ino);
5571 dx_dir->numblocks = 0;
5572 }
5573 }
5574#endif
5575 ext2fs_free_mem(&buf);
5576 ext2fs_free_dblist(fs->dblist);
5577
5578 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5579 ctx->inode_bad_map = 0;
5580 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5581 ctx->inode_reg_map = 0;
5582
5583 clear_problem_context(&pctx);
5584 if (ctx->large_files) {
5585 if (!(sb->s_feature_ro_compat &
5586 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5587 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5588 sb->s_feature_ro_compat |=
5589 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5590 ext2fs_mark_super_dirty(fs);
5591 }
5592 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5593 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5594 ext2fs_update_dynamic_rev(fs);
5595 ext2fs_mark_super_dirty(fs);
5596 }
5597 } else if (!ctx->large_files &&
5598 (sb->s_feature_ro_compat &
5599 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5600 if (fs->flags & EXT2_FLAG_RW) {
5601 sb->s_feature_ro_compat &=
5602 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5603 ext2fs_mark_super_dirty(fs);
5604 }
5605 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005606}
5607
5608#define MAX_DEPTH 32000
5609static int htree_depth(struct dx_dir_info *dx_dir,
5610 struct dx_dirblock_info *dx_db)
5611{
5612 int depth = 0;
5613
5614 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5615 dx_db = &dx_dir->dx_block[dx_db->parent];
5616 depth++;
5617 }
5618 return depth;
5619}
5620
5621static int dict_de_cmp(const void *a, const void *b)
5622{
5623 const struct ext2_dir_entry *de_a, *de_b;
5624 int a_len, b_len;
5625
5626 de_a = (const struct ext2_dir_entry *) a;
5627 a_len = de_a->name_len & 0xFF;
5628 de_b = (const struct ext2_dir_entry *) b;
5629 b_len = de_b->name_len & 0xFF;
5630
5631 if (a_len != b_len)
5632 return (a_len - b_len);
5633
5634 return strncmp(de_a->name, de_b->name, a_len);
5635}
5636
5637/*
5638 * This is special sort function that makes sure that directory blocks
5639 * with a dirblock of zero are sorted to the beginning of the list.
5640 * This guarantees that the root node of the htree directories are
5641 * processed first, so we know what hash version to use.
5642 */
5643static int special_dir_block_cmp(const void *a, const void *b)
5644{
5645 const struct ext2_db_entry *db_a =
5646 (const struct ext2_db_entry *) a;
5647 const struct ext2_db_entry *db_b =
5648 (const struct ext2_db_entry *) b;
5649
5650 if (db_a->blockcnt && !db_b->blockcnt)
5651 return 1;
5652
5653 if (!db_a->blockcnt && db_b->blockcnt)
5654 return -1;
5655
5656 if (db_a->blk != db_b->blk)
5657 return (int) (db_a->blk - db_b->blk);
5658
5659 if (db_a->ino != db_b->ino)
5660 return (int) (db_a->ino - db_b->ino);
5661
5662 return (int) (db_a->blockcnt - db_b->blockcnt);
5663}
5664
5665
5666/*
5667 * Make sure the first entry in the directory is '.', and that the
5668 * directory entry is sane.
5669 */
5670static int check_dot(e2fsck_t ctx,
5671 struct ext2_dir_entry *dirent,
5672 ext2_ino_t ino, struct problem_context *pctx)
5673{
5674 struct ext2_dir_entry *nextdir;
5675 int status = 0;
5676 int created = 0;
5677 int new_len;
5678 int problem = 0;
5679
5680 if (!dirent->inode)
5681 problem = PR_2_MISSING_DOT;
5682 else if (((dirent->name_len & 0xFF) != 1) ||
5683 (dirent->name[0] != '.'))
5684 problem = PR_2_1ST_NOT_DOT;
5685 else if (dirent->name[1] != '\0')
5686 problem = PR_2_DOT_NULL_TERM;
5687
5688 if (problem) {
5689 if (fix_problem(ctx, problem, pctx)) {
5690 if (dirent->rec_len < 12)
5691 dirent->rec_len = 12;
5692 dirent->inode = ino;
5693 dirent->name_len = 1;
5694 dirent->name[0] = '.';
5695 dirent->name[1] = '\0';
5696 status = 1;
5697 created = 1;
5698 }
5699 }
5700 if (dirent->inode != ino) {
5701 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5702 dirent->inode = ino;
5703 status = 1;
5704 }
5705 }
5706 if (dirent->rec_len > 12) {
5707 new_len = dirent->rec_len - 12;
5708 if (new_len > 12) {
5709 if (created ||
5710 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5711 nextdir = (struct ext2_dir_entry *)
5712 ((char *) dirent + 12);
5713 dirent->rec_len = 12;
5714 nextdir->rec_len = new_len;
5715 nextdir->inode = 0;
5716 nextdir->name_len = 0;
5717 status = 1;
5718 }
5719 }
5720 }
5721 return status;
5722}
5723
5724/*
5725 * Make sure the second entry in the directory is '..', and that the
5726 * directory entry is sane. We do not check the inode number of '..'
5727 * here; this gets done in pass 3.
5728 */
5729static int check_dotdot(e2fsck_t ctx,
5730 struct ext2_dir_entry *dirent,
5731 struct dir_info *dir, struct problem_context *pctx)
5732{
5733 int problem = 0;
5734
5735 if (!dirent->inode)
5736 problem = PR_2_MISSING_DOT_DOT;
5737 else if (((dirent->name_len & 0xFF) != 2) ||
5738 (dirent->name[0] != '.') ||
5739 (dirent->name[1] != '.'))
5740 problem = PR_2_2ND_NOT_DOT_DOT;
5741 else if (dirent->name[2] != '\0')
5742 problem = PR_2_DOT_DOT_NULL_TERM;
5743
5744 if (problem) {
5745 if (fix_problem(ctx, problem, pctx)) {
5746 if (dirent->rec_len < 12)
5747 dirent->rec_len = 12;
5748 /*
5749 * Note: we don't have the parent inode just
5750 * yet, so we will fill it in with the root
5751 * inode. This will get fixed in pass 3.
5752 */
5753 dirent->inode = EXT2_ROOT_INO;
5754 dirent->name_len = 2;
5755 dirent->name[0] = '.';
5756 dirent->name[1] = '.';
5757 dirent->name[2] = '\0';
5758 return 1;
5759 }
5760 return 0;
5761 }
5762 dir->dotdot = dirent->inode;
5763 return 0;
5764}
5765
5766/*
5767 * Check to make sure a directory entry doesn't contain any illegal
5768 * characters.
5769 */
5770static int check_name(e2fsck_t ctx,
5771 struct ext2_dir_entry *dirent,
5772 struct problem_context *pctx)
5773{
5774 int i;
5775 int fixup = -1;
5776 int ret = 0;
5777
5778 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5779 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5780 if (fixup < 0) {
5781 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5782 }
5783 if (fixup) {
5784 dirent->name[i] = '.';
5785 ret = 1;
5786 }
5787 }
5788 }
5789 return ret;
5790}
5791
5792/*
5793 * Check the directory filetype (if present)
5794 */
5795
5796/*
5797 * Given a mode, return the ext2 file type
5798 */
5799static int ext2_file_type(unsigned int mode)
5800{
5801 if (LINUX_S_ISREG(mode))
5802 return EXT2_FT_REG_FILE;
5803
5804 if (LINUX_S_ISDIR(mode))
5805 return EXT2_FT_DIR;
5806
5807 if (LINUX_S_ISCHR(mode))
5808 return EXT2_FT_CHRDEV;
5809
5810 if (LINUX_S_ISBLK(mode))
5811 return EXT2_FT_BLKDEV;
5812
5813 if (LINUX_S_ISLNK(mode))
5814 return EXT2_FT_SYMLINK;
5815
5816 if (LINUX_S_ISFIFO(mode))
5817 return EXT2_FT_FIFO;
5818
5819 if (LINUX_S_ISSOCK(mode))
5820 return EXT2_FT_SOCK;
5821
5822 return 0;
5823}
5824
5825static int check_filetype(e2fsck_t ctx,
5826 struct ext2_dir_entry *dirent,
5827 struct problem_context *pctx)
5828{
5829 int filetype = dirent->name_len >> 8;
5830 int should_be = EXT2_FT_UNKNOWN;
5831 struct ext2_inode inode;
5832
5833 if (!(ctx->fs->super->s_feature_incompat &
5834 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5835 if (filetype == 0 ||
5836 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5837 return 0;
5838 dirent->name_len = dirent->name_len & 0xFF;
5839 return 1;
5840 }
5841
5842 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5843 should_be = EXT2_FT_DIR;
5844 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5845 dirent->inode)) {
5846 should_be = EXT2_FT_REG_FILE;
5847 } else if (ctx->inode_bad_map &&
5848 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5849 dirent->inode))
5850 should_be = 0;
5851 else {
5852 e2fsck_read_inode(ctx, dirent->inode, &inode,
5853 "check_filetype");
5854 should_be = ext2_file_type(inode.i_mode);
5855 }
5856 if (filetype == should_be)
5857 return 0;
5858 pctx->num = should_be;
5859
5860 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5861 pctx) == 0)
5862 return 0;
5863
5864 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5865 return 1;
5866}
5867
5868#ifdef ENABLE_HTREE
5869static void parse_int_node(ext2_filsys fs,
5870 struct ext2_db_entry *db,
5871 struct check_dir_struct *cd,
5872 struct dx_dir_info *dx_dir,
5873 char *block_buf)
5874{
5875 struct ext2_dx_root_info *root;
5876 struct ext2_dx_entry *ent;
5877 struct ext2_dx_countlimit *limit;
5878 struct dx_dirblock_info *dx_db;
5879 int i, expect_limit, count;
5880 blk_t blk;
5881 ext2_dirhash_t min_hash = 0xffffffff;
5882 ext2_dirhash_t max_hash = 0;
5883 ext2_dirhash_t hash = 0, prev_hash;
5884
5885 if (db->blockcnt == 0) {
5886 root = (struct ext2_dx_root_info *) (block_buf + 24);
5887 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5888 } else {
5889 ent = (struct ext2_dx_entry *) (block_buf+8);
5890 }
5891 limit = (struct ext2_dx_countlimit *) ent;
5892
5893 count = ext2fs_le16_to_cpu(limit->count);
5894 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5895 sizeof(struct ext2_dx_entry);
5896 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5897 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5898 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5899 goto clear_and_exit;
5900 }
5901 if (count > expect_limit) {
5902 cd->pctx.num = count;
5903 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5904 goto clear_and_exit;
5905 count = expect_limit;
5906 }
5907
5908 for (i=0; i < count; i++) {
5909 prev_hash = hash;
5910 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5911 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5912 /* Check to make sure the block is valid */
5913 if (blk > (blk_t) dx_dir->numblocks) {
5914 cd->pctx.blk = blk;
5915 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5916 &cd->pctx))
5917 goto clear_and_exit;
5918 }
5919 if (hash < prev_hash &&
5920 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5921 goto clear_and_exit;
5922 dx_db = &dx_dir->dx_block[blk];
5923 if (dx_db->flags & DX_FLAG_REFERENCED) {
5924 dx_db->flags |= DX_FLAG_DUP_REF;
5925 } else {
5926 dx_db->flags |= DX_FLAG_REFERENCED;
5927 dx_db->parent = db->blockcnt;
5928 }
5929 if (hash < min_hash)
5930 min_hash = hash;
5931 if (hash > max_hash)
5932 max_hash = hash;
5933 dx_db->node_min_hash = hash;
5934 if ((i+1) < count)
5935 dx_db->node_max_hash =
5936 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5937 else {
5938 dx_db->node_max_hash = 0xfffffffe;
5939 dx_db->flags |= DX_FLAG_LAST;
5940 }
5941 if (i == 0)
5942 dx_db->flags |= DX_FLAG_FIRST;
5943 }
5944 dx_db = &dx_dir->dx_block[db->blockcnt];
5945 dx_db->min_hash = min_hash;
5946 dx_db->max_hash = max_hash;
5947 return;
5948
5949clear_and_exit:
5950 clear_htree(cd->ctx, cd->pctx.ino);
5951 dx_dir->numblocks = 0;
5952}
5953#endif /* ENABLE_HTREE */
5954
5955/*
5956 * Given a busted directory, try to salvage it somehow.
5957 *
5958 */
5959static void salvage_directory(ext2_filsys fs,
5960 struct ext2_dir_entry *dirent,
5961 struct ext2_dir_entry *prev,
5962 unsigned int *offset)
5963{
5964 char *cp = (char *) dirent;
5965 int left = fs->blocksize - *offset - dirent->rec_len;
5966 int name_len = dirent->name_len & 0xFF;
5967
5968 /*
5969 * Special case of directory entry of size 8: copy what's left
5970 * of the directory block up to cover up the invalid hole.
5971 */
5972 if ((left >= 12) && (dirent->rec_len == 8)) {
5973 memmove(cp, cp+8, left);
5974 memset(cp + left, 0, 8);
5975 return;
5976 }
5977 /*
5978 * If the directory entry overruns the end of the directory
5979 * block, and the name is small enough to fit, then adjust the
5980 * record length.
5981 */
5982 if ((left < 0) &&
5983 (name_len + 8 <= dirent->rec_len + left) &&
5984 dirent->inode <= fs->super->s_inodes_count &&
5985 strnlen(dirent->name, name_len) == name_len) {
5986 dirent->rec_len += left;
5987 return;
5988 }
5989 /*
5990 * If the directory entry is a multiple of four, so it is
5991 * valid, let the previous directory entry absorb the invalid
5992 * one.
5993 */
5994 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5995 prev->rec_len += dirent->rec_len;
5996 *offset += dirent->rec_len;
5997 return;
5998 }
5999 /*
6000 * Default salvage method --- kill all of the directory
6001 * entries for the rest of the block. We will either try to
6002 * absorb it into the previous directory entry, or create a
6003 * new empty directory entry the rest of the directory block.
6004 */
6005 if (prev) {
6006 prev->rec_len += fs->blocksize - *offset;
6007 *offset = fs->blocksize;
6008 } else {
6009 dirent->rec_len = fs->blocksize - *offset;
6010 dirent->name_len = 0;
6011 dirent->inode = 0;
6012 }
6013}
6014
6015static int check_dir_block(ext2_filsys fs,
6016 struct ext2_db_entry *db,
6017 void *priv_data)
6018{
6019 struct dir_info *subdir, *dir;
6020 struct dx_dir_info *dx_dir;
6021#ifdef ENABLE_HTREE
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01006022 struct dx_dirblock_info *dx_db = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006023#endif /* ENABLE_HTREE */
6024 struct ext2_dir_entry *dirent, *prev;
6025 ext2_dirhash_t hash;
6026 unsigned int offset = 0;
6027 int dir_modified = 0;
6028 int dot_state;
6029 blk_t block_nr = db->blk;
6030 ext2_ino_t ino = db->ino;
6031 __u16 links;
6032 struct check_dir_struct *cd;
6033 char *buf;
6034 e2fsck_t ctx;
6035 int problem;
6036 struct ext2_dx_root_info *root;
6037 struct ext2_dx_countlimit *limit;
6038 static dict_t de_dict;
6039 struct problem_context pctx;
6040 int dups_found = 0;
6041
6042 cd = (struct check_dir_struct *) priv_data;
6043 buf = cd->buf;
6044 ctx = cd->ctx;
6045
6046 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6047 return DIRENT_ABORT;
6048
6049 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6050 return DIRENT_ABORT;
6051
6052 /*
6053 * Make sure the inode is still in use (could have been
6054 * deleted in the duplicate/bad blocks pass.
6055 */
6056 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6057 return 0;
6058
6059 cd->pctx.ino = ino;
6060 cd->pctx.blk = block_nr;
6061 cd->pctx.blkcount = db->blockcnt;
6062 cd->pctx.ino2 = 0;
6063 cd->pctx.dirent = 0;
6064 cd->pctx.num = 0;
6065
6066 if (db->blk == 0) {
6067 if (allocate_dir_block(ctx, db, &cd->pctx))
6068 return 0;
6069 block_nr = db->blk;
6070 }
6071
6072 if (db->blockcnt)
6073 dot_state = 2;
6074 else
6075 dot_state = 0;
6076
6077 if (ctx->dirs_to_hash &&
6078 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6079 dups_found++;
6080
6081 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6082 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6083 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6084 if (cd->pctx.errcode) {
6085 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6086 ctx->flags |= E2F_FLAG_ABORT;
6087 return DIRENT_ABORT;
6088 }
6089 memset(buf, 0, fs->blocksize);
6090 }
6091#ifdef ENABLE_HTREE
6092 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6093 if (dx_dir && dx_dir->numblocks) {
6094 if (db->blockcnt >= dx_dir->numblocks) {
6095 printf("XXX should never happen!!!\n");
6096 abort();
6097 }
6098 dx_db = &dx_dir->dx_block[db->blockcnt];
6099 dx_db->type = DX_DIRBLOCK_LEAF;
6100 dx_db->phys = block_nr;
6101 dx_db->min_hash = ~0;
6102 dx_db->max_hash = 0;
6103
6104 dirent = (struct ext2_dir_entry *) buf;
6105 limit = (struct ext2_dx_countlimit *) (buf+8);
6106 if (db->blockcnt == 0) {
6107 root = (struct ext2_dx_root_info *) (buf + 24);
6108 dx_db->type = DX_DIRBLOCK_ROOT;
6109 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6110 if ((root->reserved_zero ||
6111 root->info_length < 8 ||
6112 root->indirect_levels > 1) &&
6113 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6114 clear_htree(ctx, ino);
6115 dx_dir->numblocks = 0;
6116 dx_db = 0;
6117 }
6118 dx_dir->hashversion = root->hash_version;
6119 dx_dir->depth = root->indirect_levels + 1;
6120 } else if ((dirent->inode == 0) &&
6121 (dirent->rec_len == fs->blocksize) &&
6122 (dirent->name_len == 0) &&
6123 (ext2fs_le16_to_cpu(limit->limit) ==
6124 ((fs->blocksize-8) /
6125 sizeof(struct ext2_dx_entry))))
6126 dx_db->type = DX_DIRBLOCK_NODE;
6127 }
6128#endif /* ENABLE_HTREE */
6129
6130 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6131 prev = 0;
6132 do {
6133 problem = 0;
6134 dirent = (struct ext2_dir_entry *) (buf + offset);
6135 cd->pctx.dirent = dirent;
6136 cd->pctx.num = offset;
6137 if (((offset + dirent->rec_len) > fs->blocksize) ||
6138 (dirent->rec_len < 12) ||
6139 ((dirent->rec_len % 4) != 0) ||
6140 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6141 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6142 salvage_directory(fs, dirent, prev, &offset);
6143 dir_modified++;
6144 continue;
6145 } else
6146 goto abort_free_dict;
6147 }
6148 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6149 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6150 dirent->name_len = EXT2_NAME_LEN;
6151 dir_modified++;
6152 }
6153 }
6154
6155 if (dot_state == 0) {
6156 if (check_dot(ctx, dirent, ino, &cd->pctx))
6157 dir_modified++;
6158 } else if (dot_state == 1) {
6159 dir = e2fsck_get_dir_info(ctx, ino);
6160 if (!dir) {
6161 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6162 goto abort_free_dict;
6163 }
6164 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6165 dir_modified++;
6166 } else if (dirent->inode == ino) {
6167 problem = PR_2_LINK_DOT;
6168 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6169 dirent->inode = 0;
6170 dir_modified++;
6171 goto next;
6172 }
6173 }
6174 if (!dirent->inode)
6175 goto next;
6176
6177 /*
6178 * Make sure the inode listed is a legal one.
6179 */
6180 if (((dirent->inode != EXT2_ROOT_INO) &&
6181 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6182 (dirent->inode > fs->super->s_inodes_count)) {
6183 problem = PR_2_BAD_INO;
6184 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6185 dirent->inode))) {
6186 /*
6187 * If the inode is unused, offer to clear it.
6188 */
6189 problem = PR_2_UNUSED_INODE;
6190 } else if ((dot_state > 1) &&
6191 ((dirent->name_len & 0xFF) == 1) &&
6192 (dirent->name[0] == '.')) {
6193 /*
6194 * If there's a '.' entry in anything other
6195 * than the first directory entry, it's a
6196 * duplicate entry that should be removed.
6197 */
6198 problem = PR_2_DUP_DOT;
6199 } else if ((dot_state > 1) &&
6200 ((dirent->name_len & 0xFF) == 2) &&
6201 (dirent->name[0] == '.') &&
6202 (dirent->name[1] == '.')) {
6203 /*
6204 * If there's a '..' entry in anything other
6205 * than the second directory entry, it's a
6206 * duplicate entry that should be removed.
6207 */
6208 problem = PR_2_DUP_DOT_DOT;
6209 } else if ((dot_state > 1) &&
6210 (dirent->inode == EXT2_ROOT_INO)) {
6211 /*
6212 * Don't allow links to the root directory.
6213 * We check this specially to make sure we
6214 * catch this error case even if the root
6215 * directory hasn't been created yet.
6216 */
6217 problem = PR_2_LINK_ROOT;
6218 } else if ((dot_state > 1) &&
6219 (dirent->name_len & 0xFF) == 0) {
6220 /*
6221 * Don't allow zero-length directory names.
6222 */
6223 problem = PR_2_NULL_NAME;
6224 }
6225
6226 if (problem) {
6227 if (fix_problem(ctx, problem, &cd->pctx)) {
6228 dirent->inode = 0;
6229 dir_modified++;
6230 goto next;
6231 } else {
6232 ext2fs_unmark_valid(fs);
6233 if (problem == PR_2_BAD_INO)
6234 goto next;
6235 }
6236 }
6237
6238 /*
6239 * If the inode was marked as having bad fields in
6240 * pass1, process it and offer to fix/clear it.
6241 * (We wait until now so that we can display the
6242 * pathname to the user.)
6243 */
6244 if (ctx->inode_bad_map &&
6245 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6246 dirent->inode)) {
6247 if (e2fsck_process_bad_inode(ctx, ino,
6248 dirent->inode,
6249 buf + fs->blocksize)) {
6250 dirent->inode = 0;
6251 dir_modified++;
6252 goto next;
6253 }
6254 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6255 return DIRENT_ABORT;
6256 }
6257
6258 if (check_name(ctx, dirent, &cd->pctx))
6259 dir_modified++;
6260
6261 if (check_filetype(ctx, dirent, &cd->pctx))
6262 dir_modified++;
6263
6264#ifdef ENABLE_HTREE
6265 if (dx_db) {
6266 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6267 (dirent->name_len & 0xFF),
6268 fs->super->s_hash_seed, &hash, 0);
6269 if (hash < dx_db->min_hash)
6270 dx_db->min_hash = hash;
6271 if (hash > dx_db->max_hash)
6272 dx_db->max_hash = hash;
6273 }
6274#endif
6275
6276 /*
6277 * If this is a directory, then mark its parent in its
6278 * dir_info structure. If the parent field is already
6279 * filled in, then this directory has more than one
6280 * hard link. We assume the first link is correct,
6281 * and ask the user if he/she wants to clear this one.
6282 */
6283 if ((dot_state > 1) &&
6284 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6285 dirent->inode))) {
6286 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6287 if (!subdir) {
6288 cd->pctx.ino = dirent->inode;
6289 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6290 goto abort_free_dict;
6291 }
6292 if (subdir->parent) {
6293 cd->pctx.ino2 = subdir->parent;
6294 if (fix_problem(ctx, PR_2_LINK_DIR,
6295 &cd->pctx)) {
6296 dirent->inode = 0;
6297 dir_modified++;
6298 goto next;
6299 }
6300 cd->pctx.ino2 = 0;
6301 } else
6302 subdir->parent = ino;
6303 }
6304
6305 if (dups_found) {
6306 ;
6307 } else if (dict_lookup(&de_dict, dirent)) {
6308 clear_problem_context(&pctx);
6309 pctx.ino = ino;
6310 pctx.dirent = dirent;
6311 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6312 if (!ctx->dirs_to_hash)
6313 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6314 if (ctx->dirs_to_hash)
6315 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6316 dups_found++;
6317 } else
6318 dict_alloc_insert(&de_dict, dirent, dirent);
6319
6320 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6321 &links);
6322 if (links > 1)
6323 ctx->fs_links_count++;
6324 ctx->fs_total_count++;
6325 next:
6326 prev = dirent;
6327 offset += dirent->rec_len;
6328 dot_state++;
6329 } while (offset < fs->blocksize);
6330#ifdef ENABLE_HTREE
6331 if (dx_db) {
6332 cd->pctx.dir = cd->pctx.ino;
6333 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6334 (dx_db->type == DX_DIRBLOCK_NODE))
6335 parse_int_node(fs, db, cd, dx_dir, buf);
6336 }
6337#endif /* ENABLE_HTREE */
6338 if (offset != fs->blocksize) {
6339 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6340 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6341 dirent->rec_len = cd->pctx.num;
6342 dir_modified++;
6343 }
6344 }
6345 if (dir_modified) {
6346 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6347 if (cd->pctx.errcode) {
6348 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6349 &cd->pctx))
6350 goto abort_free_dict;
6351 }
6352 ext2fs_mark_changed(fs);
6353 }
6354 dict_free_nodes(&de_dict);
6355 return 0;
6356abort_free_dict:
6357 dict_free_nodes(&de_dict);
6358 ctx->flags |= E2F_FLAG_ABORT;
6359 return DIRENT_ABORT;
6360}
6361
6362/*
6363 * This function is called to deallocate a block, and is an interator
6364 * functioned called by deallocate inode via ext2fs_iterate_block().
6365 */
6366static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6367 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6368 blk_t ref_block FSCK_ATTR((unused)),
6369 int ref_offset FSCK_ATTR((unused)),
6370 void *priv_data)
6371{
6372 e2fsck_t ctx = (e2fsck_t) priv_data;
6373
6374 if (HOLE_BLKADDR(*block_nr))
6375 return 0;
6376 if ((*block_nr < fs->super->s_first_data_block) ||
6377 (*block_nr >= fs->super->s_blocks_count))
6378 return 0;
6379 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6380 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6381 return 0;
6382}
6383
6384/*
6385 * This fuction deallocates an inode
6386 */
6387static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6388{
6389 ext2_filsys fs = ctx->fs;
6390 struct ext2_inode inode;
6391 struct problem_context pctx;
6392 __u32 count;
6393
6394 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6395 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6396 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006397 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006398 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6399 clear_problem_context(&pctx);
6400 pctx.ino = ino;
6401
6402 /*
6403 * Fix up the bitmaps...
6404 */
6405 e2fsck_read_bitmaps(ctx);
6406 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6407 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6408 if (ctx->inode_bad_map)
6409 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6410 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6411
6412 if (inode.i_file_acl &&
6413 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6414 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6415 block_buf, -1, &count);
6416 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6417 pctx.errcode = 0;
6418 count = 1;
6419 }
6420 if (pctx.errcode) {
6421 pctx.blk = inode.i_file_acl;
6422 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6423 ctx->flags |= E2F_FLAG_ABORT;
6424 return;
6425 }
6426 if (count == 0) {
6427 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6428 inode.i_file_acl);
6429 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6430 }
6431 inode.i_file_acl = 0;
6432 }
6433
6434 if (!ext2fs_inode_has_valid_blocks(&inode))
6435 return;
6436
6437 if (LINUX_S_ISREG(inode.i_mode) &&
6438 (inode.i_size_high || inode.i_size & 0x80000000UL))
6439 ctx->large_files--;
6440
6441 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6442 deallocate_inode_block, ctx);
6443 if (pctx.errcode) {
6444 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6445 ctx->flags |= E2F_FLAG_ABORT;
6446 return;
6447 }
6448}
6449
6450/*
6451 * This fuction clears the htree flag on an inode
6452 */
6453static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6454{
6455 struct ext2_inode inode;
6456
6457 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6458 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6459 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6460 if (ctx->dirs_to_hash)
6461 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6462}
6463
6464
6465static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6466 ext2_ino_t ino, char *buf)
6467{
6468 ext2_filsys fs = ctx->fs;
6469 struct ext2_inode inode;
6470 int inode_modified = 0;
6471 int not_fixed = 0;
6472 unsigned char *frag, *fsize;
6473 struct problem_context pctx;
6474 int problem = 0;
6475
6476 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6477
6478 clear_problem_context(&pctx);
6479 pctx.ino = ino;
6480 pctx.dir = dir;
6481 pctx.inode = &inode;
6482
6483 if (inode.i_file_acl &&
6484 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6485 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6486 inode.i_file_acl = 0;
6487#if BB_BIG_ENDIAN
6488 /*
6489 * This is a special kludge to deal with long symlinks
6490 * on big endian systems. i_blocks had already been
6491 * decremented earlier in pass 1, but since i_file_acl
6492 * hadn't yet been cleared, ext2fs_read_inode()
6493 * assumed that the file was short symlink and would
6494 * not have byte swapped i_block[0]. Hence, we have
6495 * to byte-swap it here.
6496 */
6497 if (LINUX_S_ISLNK(inode.i_mode) &&
6498 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6499 (inode.i_blocks == fs->blocksize >> 9))
6500 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6501#endif
6502 inode_modified++;
6503 } else
6504 not_fixed++;
6505
6506 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6507 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6508 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6509 !(LINUX_S_ISSOCK(inode.i_mode)))
6510 problem = PR_2_BAD_MODE;
6511 else if (LINUX_S_ISCHR(inode.i_mode)
6512 && !e2fsck_pass1_check_device_inode(fs, &inode))
6513 problem = PR_2_BAD_CHAR_DEV;
6514 else if (LINUX_S_ISBLK(inode.i_mode)
6515 && !e2fsck_pass1_check_device_inode(fs, &inode))
6516 problem = PR_2_BAD_BLOCK_DEV;
6517 else if (LINUX_S_ISFIFO(inode.i_mode)
6518 && !e2fsck_pass1_check_device_inode(fs, &inode))
6519 problem = PR_2_BAD_FIFO;
6520 else if (LINUX_S_ISSOCK(inode.i_mode)
6521 && !e2fsck_pass1_check_device_inode(fs, &inode))
6522 problem = PR_2_BAD_SOCKET;
6523 else if (LINUX_S_ISLNK(inode.i_mode)
6524 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6525 problem = PR_2_INVALID_SYMLINK;
6526 }
6527
6528 if (problem) {
6529 if (fix_problem(ctx, problem, &pctx)) {
6530 deallocate_inode(ctx, ino, 0);
6531 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6532 return 0;
6533 return 1;
6534 } else
6535 not_fixed++;
6536 problem = 0;
6537 }
6538
6539 if (inode.i_faddr) {
6540 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6541 inode.i_faddr = 0;
6542 inode_modified++;
6543 } else
6544 not_fixed++;
6545 }
6546
6547 switch (fs->super->s_creator_os) {
6548 case EXT2_OS_LINUX:
6549 frag = &inode.osd2.linux2.l_i_frag;
6550 fsize = &inode.osd2.linux2.l_i_fsize;
6551 break;
6552 case EXT2_OS_HURD:
6553 frag = &inode.osd2.hurd2.h_i_frag;
6554 fsize = &inode.osd2.hurd2.h_i_fsize;
6555 break;
6556 case EXT2_OS_MASIX:
6557 frag = &inode.osd2.masix2.m_i_frag;
6558 fsize = &inode.osd2.masix2.m_i_fsize;
6559 break;
6560 default:
6561 frag = fsize = 0;
6562 }
6563 if (frag && *frag) {
6564 pctx.num = *frag;
6565 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6566 *frag = 0;
6567 inode_modified++;
6568 } else
6569 not_fixed++;
6570 pctx.num = 0;
6571 }
6572 if (fsize && *fsize) {
6573 pctx.num = *fsize;
6574 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6575 *fsize = 0;
6576 inode_modified++;
6577 } else
6578 not_fixed++;
6579 pctx.num = 0;
6580 }
6581
6582 if (inode.i_file_acl &&
6583 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6584 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6585 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6586 inode.i_file_acl = 0;
6587 inode_modified++;
6588 } else
6589 not_fixed++;
6590 }
6591 if (inode.i_dir_acl &&
6592 LINUX_S_ISDIR(inode.i_mode)) {
6593 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6594 inode.i_dir_acl = 0;
6595 inode_modified++;
6596 } else
6597 not_fixed++;
6598 }
6599
6600 if (inode_modified)
6601 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6602 if (!not_fixed)
6603 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6604 return 0;
6605}
6606
6607
6608/*
6609 * allocate_dir_block --- this function allocates a new directory
6610 * block for a particular inode; this is done if a directory has
6611 * a "hole" in it, or if a directory has a illegal block number
6612 * that was zeroed out and now needs to be replaced.
6613 */
6614static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6615 struct problem_context *pctx)
6616{
6617 ext2_filsys fs = ctx->fs;
6618 blk_t blk;
6619 char *block;
6620 struct ext2_inode inode;
6621
6622 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6623 return 1;
6624
6625 /*
6626 * Read the inode and block bitmaps in; we'll be messing with
6627 * them.
6628 */
6629 e2fsck_read_bitmaps(ctx);
6630
6631 /*
6632 * First, find a free block
6633 */
6634 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6635 if (pctx->errcode) {
6636 pctx->str = "ext2fs_new_block";
6637 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6638 return 1;
6639 }
6640 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6641 ext2fs_mark_block_bitmap(fs->block_map, blk);
6642 ext2fs_mark_bb_dirty(fs);
6643
6644 /*
6645 * Now let's create the actual data block for the inode
6646 */
6647 if (db->blockcnt)
6648 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6649 else
6650 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6651 EXT2_ROOT_INO, &block);
6652
6653 if (pctx->errcode) {
6654 pctx->str = "ext2fs_new_dir_block";
6655 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6656 return 1;
6657 }
6658
6659 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6660 ext2fs_free_mem(&block);
6661 if (pctx->errcode) {
6662 pctx->str = "ext2fs_write_dir_block";
6663 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6664 return 1;
6665 }
6666
6667 /*
6668 * Update the inode block count
6669 */
6670 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6671 inode.i_blocks += fs->blocksize / 512;
6672 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6673 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6674 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6675
6676 /*
6677 * Finally, update the block pointers for the inode
6678 */
6679 db->blk = blk;
6680 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6681 0, update_dir_block, db);
6682 if (pctx->errcode) {
6683 pctx->str = "ext2fs_block_iterate";
6684 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6685 return 1;
6686 }
6687
6688 return 0;
6689}
6690
6691/*
6692 * This is a helper function for allocate_dir_block().
6693 */
6694static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6695 blk_t *block_nr,
6696 e2_blkcnt_t blockcnt,
6697 blk_t ref_block FSCK_ATTR((unused)),
6698 int ref_offset FSCK_ATTR((unused)),
6699 void *priv_data)
6700{
6701 struct ext2_db_entry *db;
6702
6703 db = (struct ext2_db_entry *) priv_data;
6704 if (db->blockcnt == (int) blockcnt) {
6705 *block_nr = db->blk;
6706 return BLOCK_CHANGED;
6707 }
6708 return 0;
6709}
6710
6711/*
6712 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6713 *
6714 * Pass #3 assures that all directories are connected to the
6715 * filesystem tree, using the following algorithm:
6716 *
6717 * First, the root directory is checked to make sure it exists; if
6718 * not, e2fsck will offer to create a new one. It is then marked as
6719 * "done".
6720 *
6721 * Then, pass3 interates over all directory inodes; for each directory
6722 * it attempts to trace up the filesystem tree, using dirinfo.parent
6723 * until it reaches a directory which has been marked "done". If it
6724 * cannot do so, then the directory must be disconnected, and e2fsck
6725 * will offer to reconnect it to /lost+found. While it is chasing
6726 * parent pointers up the filesystem tree, if pass3 sees a directory
6727 * twice, then it has detected a filesystem loop, and it will again
6728 * offer to reconnect the directory to /lost+found in to break the
6729 * filesystem loop.
6730 *
6731 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6732 * reconnect inodes to /lost+found; this subroutine is also used by
6733 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6734 * is responsible for creating /lost+found if it does not exist.
6735 *
6736 * Pass 3 frees the following data structures:
6737 * - The dirinfo directory information cache.
6738 */
6739
6740static void check_root(e2fsck_t ctx);
6741static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6742 struct problem_context *pctx);
6743static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6744
6745static ext2fs_inode_bitmap inode_loop_detect;
6746static ext2fs_inode_bitmap inode_done_map;
6747
6748static void e2fsck_pass3(e2fsck_t ctx)
6749{
6750 ext2_filsys fs = ctx->fs;
6751 int i;
6752 struct problem_context pctx;
6753 struct dir_info *dir;
6754 unsigned long maxdirs, count;
6755
6756 clear_problem_context(&pctx);
6757
6758 /* Pass 3 */
6759
6760 if (!(ctx->options & E2F_OPT_PREEN))
6761 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6762
6763 /*
6764 * Allocate some bitmaps to do loop detection.
6765 */
6766 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6767 &inode_done_map);
6768 if (pctx.errcode) {
6769 pctx.num = 2;
6770 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6771 ctx->flags |= E2F_FLAG_ABORT;
6772 goto abort_exit;
6773 }
6774 check_root(ctx);
6775 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6776 goto abort_exit;
6777
6778 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6779
6780 maxdirs = e2fsck_get_num_dirinfo(ctx);
6781 count = 1;
6782
6783 if (ctx->progress)
6784 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6785 goto abort_exit;
6786
6787 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6788 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6789 goto abort_exit;
6790 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6791 goto abort_exit;
6792 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6793 if (check_directory(ctx, dir, &pctx))
6794 goto abort_exit;
6795 }
6796
6797 /*
6798 * Force the creation of /lost+found if not present
6799 */
6800 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6801 e2fsck_get_lost_and_found(ctx, 1);
6802
6803 /*
6804 * If there are any directories that need to be indexed or
6805 * optimized, do it here.
6806 */
6807 e2fsck_rehash_directories(ctx);
6808
6809abort_exit:
6810 e2fsck_free_dir_info(ctx);
6811 ext2fs_free_inode_bitmap(inode_loop_detect);
6812 inode_loop_detect = 0;
6813 ext2fs_free_inode_bitmap(inode_done_map);
6814 inode_done_map = 0;
6815}
6816
6817/*
6818 * This makes sure the root inode is present; if not, we ask if the
6819 * user wants us to create it. Not creating it is a fatal error.
6820 */
6821static void check_root(e2fsck_t ctx)
6822{
6823 ext2_filsys fs = ctx->fs;
6824 blk_t blk;
6825 struct ext2_inode inode;
6826 char * block;
6827 struct problem_context pctx;
6828
6829 clear_problem_context(&pctx);
6830
6831 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6832 /*
6833 * If the root inode is not a directory, die here. The
6834 * user must have answered 'no' in pass1 when we
6835 * offered to clear it.
6836 */
6837 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6838 EXT2_ROOT_INO))) {
6839 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6840 ctx->flags |= E2F_FLAG_ABORT;
6841 }
6842 return;
6843 }
6844
6845 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6846 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6847 ctx->flags |= E2F_FLAG_ABORT;
6848 return;
6849 }
6850
6851 e2fsck_read_bitmaps(ctx);
6852
6853 /*
6854 * First, find a free block
6855 */
6856 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6857 if (pctx.errcode) {
6858 pctx.str = "ext2fs_new_block";
6859 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6860 ctx->flags |= E2F_FLAG_ABORT;
6861 return;
6862 }
6863 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6864 ext2fs_mark_block_bitmap(fs->block_map, blk);
6865 ext2fs_mark_bb_dirty(fs);
6866
6867 /*
6868 * Now let's create the actual data block for the inode
6869 */
6870 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6871 &block);
6872 if (pctx.errcode) {
6873 pctx.str = "ext2fs_new_dir_block";
6874 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6875 ctx->flags |= E2F_FLAG_ABORT;
6876 return;
6877 }
6878
6879 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6880 if (pctx.errcode) {
6881 pctx.str = "ext2fs_write_dir_block";
6882 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6883 ctx->flags |= E2F_FLAG_ABORT;
6884 return;
6885 }
6886 ext2fs_free_mem(&block);
6887
6888 /*
6889 * Set up the inode structure
6890 */
6891 memset(&inode, 0, sizeof(inode));
6892 inode.i_mode = 040755;
6893 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006894 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006895 inode.i_links_count = 2;
6896 inode.i_blocks = fs->blocksize / 512;
6897 inode.i_block[0] = blk;
6898
6899 /*
6900 * Write out the inode.
6901 */
6902 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6903 if (pctx.errcode) {
6904 pctx.str = "ext2fs_write_inode";
6905 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6906 ctx->flags |= E2F_FLAG_ABORT;
6907 return;
6908 }
6909
6910 /*
6911 * Miscellaneous bookkeeping...
6912 */
6913 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6914 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6915 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6916
6917 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6918 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6919 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6920 ext2fs_mark_ib_dirty(fs);
6921}
6922
6923/*
6924 * This subroutine is responsible for making sure that a particular
6925 * directory is connected to the root; if it isn't we trace it up as
6926 * far as we can go, and then offer to connect the resulting parent to
6927 * the lost+found. We have to do loop detection; if we ever discover
6928 * a loop, we treat that as a disconnected directory and offer to
6929 * reparent it to lost+found.
6930 *
6931 * However, loop detection is expensive, because for very large
6932 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6933 * is non-trivial. Loops in filesystems are also a rare error case,
6934 * and we shouldn't optimize for error cases. So we try two passes of
6935 * the algorithm. The first time, we ignore loop detection and merely
6936 * increment a counter; if the counter exceeds some extreme threshold,
6937 * then we try again with the loop detection bitmap enabled.
6938 */
6939static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6940 struct problem_context *pctx)
6941{
6942 ext2_filsys fs = ctx->fs;
6943 struct dir_info *p = dir;
6944 int loop_pass = 0, parent_count = 0;
6945
6946 if (!p)
6947 return 0;
6948
6949 while (1) {
6950 /*
6951 * Mark this inode as being "done"; by the time we
6952 * return from this function, the inode we either be
6953 * verified as being connected to the directory tree,
6954 * or we will have offered to reconnect this to
6955 * lost+found.
6956 *
6957 * If it was marked done already, then we've reached a
6958 * parent we've already checked.
6959 */
6960 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6961 break;
6962
6963 /*
6964 * If this directory doesn't have a parent, or we've
6965 * seen the parent once already, then offer to
6966 * reparent it to lost+found
6967 */
6968 if (!p->parent ||
6969 (loop_pass &&
6970 (ext2fs_test_inode_bitmap(inode_loop_detect,
6971 p->parent)))) {
6972 pctx->ino = p->ino;
6973 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6974 if (e2fsck_reconnect_file(ctx, pctx->ino))
6975 ext2fs_unmark_valid(fs);
6976 else {
6977 p = e2fsck_get_dir_info(ctx, pctx->ino);
6978 p->parent = ctx->lost_and_found;
6979 fix_dotdot(ctx, p, ctx->lost_and_found);
6980 }
6981 }
6982 break;
6983 }
6984 p = e2fsck_get_dir_info(ctx, p->parent);
6985 if (!p) {
6986 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6987 return 0;
6988 }
6989 if (loop_pass) {
6990 ext2fs_mark_inode_bitmap(inode_loop_detect,
6991 p->ino);
6992 } else if (parent_count++ > 2048) {
6993 /*
6994 * If we've run into a path depth that's
6995 * greater than 2048, try again with the inode
6996 * loop bitmap turned on and start from the
6997 * top.
6998 */
6999 loop_pass = 1;
7000 if (inode_loop_detect)
7001 ext2fs_clear_inode_bitmap(inode_loop_detect);
7002 else {
7003 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
7004 if (pctx->errcode) {
7005 pctx->num = 1;
7006 fix_problem(ctx,
7007 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
7008 ctx->flags |= E2F_FLAG_ABORT;
7009 return -1;
7010 }
7011 }
7012 p = dir;
7013 }
7014 }
7015
7016 /*
7017 * Make sure that .. and the parent directory are the same;
7018 * offer to fix it if not.
7019 */
7020 if (dir->parent != dir->dotdot) {
7021 pctx->ino = dir->ino;
7022 pctx->ino2 = dir->dotdot;
7023 pctx->dir = dir->parent;
7024 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7025 fix_dotdot(ctx, dir, dir->parent);
7026 }
7027 return 0;
7028}
7029
7030/*
7031 * This routine gets the lost_and_found inode, making it a directory
7032 * if necessary
7033 */
7034ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7035{
7036 ext2_filsys fs = ctx->fs;
7037 ext2_ino_t ino;
7038 blk_t blk;
7039 errcode_t retval;
7040 struct ext2_inode inode;
7041 char * block;
7042 static const char name[] = "lost+found";
7043 struct problem_context pctx;
7044 struct dir_info *dirinfo;
7045
7046 if (ctx->lost_and_found)
7047 return ctx->lost_and_found;
7048
7049 clear_problem_context(&pctx);
7050
7051 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7052 sizeof(name)-1, 0, &ino);
7053 if (retval && !fix)
7054 return 0;
7055 if (!retval) {
7056 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7057 ctx->lost_and_found = ino;
7058 return ino;
7059 }
7060
7061 /* Lost+found isn't a directory! */
7062 if (!fix)
7063 return 0;
7064 pctx.ino = ino;
7065 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7066 return 0;
7067
7068 /* OK, unlink the old /lost+found file. */
7069 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7070 if (pctx.errcode) {
7071 pctx.str = "ext2fs_unlink";
7072 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7073 return 0;
7074 }
7075 dirinfo = e2fsck_get_dir_info(ctx, ino);
7076 if (dirinfo)
7077 dirinfo->parent = 0;
7078 e2fsck_adjust_inode_count(ctx, ino, -1);
7079 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7080 pctx.errcode = retval;
7081 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7082 }
7083 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7084 return 0;
7085
7086 /*
7087 * Read the inode and block bitmaps in; we'll be messing with
7088 * them.
7089 */
7090 e2fsck_read_bitmaps(ctx);
7091
7092 /*
7093 * First, find a free block
7094 */
7095 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7096 if (retval) {
7097 pctx.errcode = retval;
7098 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7099 return 0;
7100 }
7101 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7102 ext2fs_block_alloc_stats(fs, blk, +1);
7103
7104 /*
7105 * Next find a free inode.
7106 */
7107 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7108 ctx->inode_used_map, &ino);
7109 if (retval) {
7110 pctx.errcode = retval;
7111 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7112 return 0;
7113 }
7114 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7115 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7116 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7117
7118 /*
7119 * Now let's create the actual data block for the inode
7120 */
7121 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7122 if (retval) {
7123 pctx.errcode = retval;
7124 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7125 return 0;
7126 }
7127
7128 retval = ext2fs_write_dir_block(fs, blk, block);
7129 ext2fs_free_mem(&block);
7130 if (retval) {
7131 pctx.errcode = retval;
7132 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7133 return 0;
7134 }
7135
7136 /*
7137 * Set up the inode structure
7138 */
7139 memset(&inode, 0, sizeof(inode));
7140 inode.i_mode = 040700;
7141 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007142 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007143 inode.i_links_count = 2;
7144 inode.i_blocks = fs->blocksize / 512;
7145 inode.i_block[0] = blk;
7146
7147 /*
7148 * Next, write out the inode.
7149 */
7150 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7151 if (pctx.errcode) {
7152 pctx.str = "ext2fs_write_inode";
7153 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7154 return 0;
7155 }
7156 /*
7157 * Finally, create the directory link
7158 */
7159 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7160 if (pctx.errcode) {
7161 pctx.str = "ext2fs_link";
7162 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7163 return 0;
7164 }
7165
7166 /*
7167 * Miscellaneous bookkeeping that needs to be kept straight.
7168 */
7169 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7170 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7171 ext2fs_icount_store(ctx->inode_count, ino, 2);
7172 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7173 ctx->lost_and_found = ino;
7174 return ino;
7175}
7176
7177/*
7178 * This routine will connect a file to lost+found
7179 */
7180int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7181{
7182 ext2_filsys fs = ctx->fs;
7183 errcode_t retval;
7184 char name[80];
7185 struct problem_context pctx;
7186 struct ext2_inode inode;
7187 int file_type = 0;
7188
7189 clear_problem_context(&pctx);
7190 pctx.ino = ino;
7191
7192 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7193 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7194 ctx->bad_lost_and_found++;
7195 }
7196 if (ctx->bad_lost_and_found) {
7197 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7198 return 1;
7199 }
7200
7201 sprintf(name, "#%u", ino);
7202 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7203 file_type = ext2_file_type(inode.i_mode);
7204 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7205 if (retval == EXT2_ET_DIR_NO_SPACE) {
7206 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7207 return 1;
7208 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7209 1, 0);
7210 if (retval) {
7211 pctx.errcode = retval;
7212 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7213 return 1;
7214 }
7215 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7216 ino, file_type);
7217 }
7218 if (retval) {
7219 pctx.errcode = retval;
7220 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7221 return 1;
7222 }
7223 e2fsck_adjust_inode_count(ctx, ino, 1);
7224
7225 return 0;
7226}
7227
7228/*
7229 * Utility routine to adjust the inode counts on an inode.
7230 */
7231errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7232{
7233 ext2_filsys fs = ctx->fs;
7234 errcode_t retval;
7235 struct ext2_inode inode;
7236
7237 if (!ino)
7238 return 0;
7239
7240 retval = ext2fs_read_inode(fs, ino, &inode);
7241 if (retval)
7242 return retval;
7243
7244 if (adj == 1) {
7245 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7246 if (inode.i_links_count == (__u16) ~0)
7247 return 0;
7248 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7249 inode.i_links_count++;
7250 } else if (adj == -1) {
7251 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7252 if (inode.i_links_count == 0)
7253 return 0;
7254 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7255 inode.i_links_count--;
7256 }
7257
7258 retval = ext2fs_write_inode(fs, ino, &inode);
7259 if (retval)
7260 return retval;
7261
7262 return 0;
7263}
7264
7265/*
7266 * Fix parent --- this routine fixes up the parent of a directory.
7267 */
7268struct fix_dotdot_struct {
7269 ext2_filsys fs;
7270 ext2_ino_t parent;
7271 int done;
7272 e2fsck_t ctx;
7273};
7274
7275static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7276 int offset FSCK_ATTR((unused)),
7277 int blocksize FSCK_ATTR((unused)),
7278 char *buf FSCK_ATTR((unused)),
7279 void *priv_data)
7280{
7281 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7282 errcode_t retval;
7283 struct problem_context pctx;
7284
7285 if ((dirent->name_len & 0xFF) != 2)
7286 return 0;
7287 if (strncmp(dirent->name, "..", 2))
7288 return 0;
7289
7290 clear_problem_context(&pctx);
7291
7292 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7293 if (retval) {
7294 pctx.errcode = retval;
7295 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7296 }
7297 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7298 if (retval) {
7299 pctx.errcode = retval;
7300 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7301 }
7302 dirent->inode = fp->parent;
7303
7304 fp->done++;
7305 return DIRENT_ABORT | DIRENT_CHANGED;
7306}
7307
7308static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7309{
7310 ext2_filsys fs = ctx->fs;
7311 errcode_t retval;
7312 struct fix_dotdot_struct fp;
7313 struct problem_context pctx;
7314
7315 fp.fs = fs;
7316 fp.parent = parent;
7317 fp.done = 0;
7318 fp.ctx = ctx;
7319
7320 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7321 0, fix_dotdot_proc, &fp);
7322 if (retval || !fp.done) {
7323 clear_problem_context(&pctx);
7324 pctx.ino = dir->ino;
7325 pctx.errcode = retval;
7326 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7327 PR_3_FIX_PARENT_NOFIND, &pctx);
7328 ext2fs_unmark_valid(fs);
7329 }
7330 dir->dotdot = parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007331}
7332
7333/*
7334 * These routines are responsible for expanding a /lost+found if it is
7335 * too small.
7336 */
7337
7338struct expand_dir_struct {
7339 int num;
7340 int guaranteed_size;
7341 int newblocks;
7342 int last_block;
7343 errcode_t err;
7344 e2fsck_t ctx;
7345};
7346
7347static int expand_dir_proc(ext2_filsys fs,
7348 blk_t *blocknr,
7349 e2_blkcnt_t blockcnt,
7350 blk_t ref_block FSCK_ATTR((unused)),
7351 int ref_offset FSCK_ATTR((unused)),
7352 void *priv_data)
7353{
7354 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7355 blk_t new_blk;
7356 static blk_t last_blk = 0;
7357 char *block;
7358 errcode_t retval;
7359 e2fsck_t ctx;
7360
7361 ctx = es->ctx;
7362
7363 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7364 return BLOCK_ABORT;
7365
7366 if (blockcnt > 0)
7367 es->last_block = blockcnt;
7368 if (*blocknr) {
7369 last_blk = *blocknr;
7370 return 0;
7371 }
7372 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7373 &new_blk);
7374 if (retval) {
7375 es->err = retval;
7376 return BLOCK_ABORT;
7377 }
7378 if (blockcnt > 0) {
7379 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7380 if (retval) {
7381 es->err = retval;
7382 return BLOCK_ABORT;
7383 }
7384 es->num--;
7385 retval = ext2fs_write_dir_block(fs, new_blk, block);
7386 } else {
7387 retval = ext2fs_get_mem(fs->blocksize, &block);
7388 if (retval) {
7389 es->err = retval;
7390 return BLOCK_ABORT;
7391 }
7392 memset(block, 0, fs->blocksize);
7393 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7394 }
7395 if (retval) {
7396 es->err = retval;
7397 return BLOCK_ABORT;
7398 }
7399 ext2fs_free_mem(&block);
7400 *blocknr = new_blk;
7401 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7402 ext2fs_block_alloc_stats(fs, new_blk, +1);
7403 es->newblocks++;
7404
7405 if (es->num == 0)
7406 return (BLOCK_CHANGED | BLOCK_ABORT);
7407 else
7408 return BLOCK_CHANGED;
7409}
7410
7411errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7412 int num, int guaranteed_size)
7413{
7414 ext2_filsys fs = ctx->fs;
7415 errcode_t retval;
7416 struct expand_dir_struct es;
7417 struct ext2_inode inode;
7418
7419 if (!(fs->flags & EXT2_FLAG_RW))
7420 return EXT2_ET_RO_FILSYS;
7421
7422 /*
7423 * Read the inode and block bitmaps in; we'll be messing with
7424 * them.
7425 */
7426 e2fsck_read_bitmaps(ctx);
7427
7428 retval = ext2fs_check_directory(fs, dir);
7429 if (retval)
7430 return retval;
7431
7432 es.num = num;
7433 es.guaranteed_size = guaranteed_size;
7434 es.last_block = 0;
7435 es.err = 0;
7436 es.newblocks = 0;
7437 es.ctx = ctx;
7438
7439 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7440 0, expand_dir_proc, &es);
7441
7442 if (es.err)
7443 return es.err;
7444
7445 /*
7446 * Update the size and block count fields in the inode.
7447 */
7448 retval = ext2fs_read_inode(fs, dir, &inode);
7449 if (retval)
7450 return retval;
7451
7452 inode.i_size = (es.last_block + 1) * fs->blocksize;
7453 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7454
7455 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7456
7457 return 0;
7458}
7459
7460/*
7461 * pass4.c -- pass #4 of e2fsck: Check reference counts
7462 *
7463 * Pass 4 frees the following data structures:
7464 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7465 */
7466
7467/*
7468 * This routine is called when an inode is not connected to the
7469 * directory tree.
7470 *
7471 * This subroutine returns 1 then the caller shouldn't bother with the
7472 * rest of the pass 4 tests.
7473 */
7474static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7475{
7476 ext2_filsys fs = ctx->fs;
7477 struct ext2_inode inode;
7478 struct problem_context pctx;
7479
7480 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7481 clear_problem_context(&pctx);
7482 pctx.ino = i;
7483 pctx.inode = &inode;
7484
7485 /*
7486 * Offer to delete any zero-length files that does not have
7487 * blocks. If there is an EA block, it might have useful
7488 * information, so we won't prompt to delete it, but let it be
7489 * reconnected to lost+found.
7490 */
7491 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7492 LINUX_S_ISDIR(inode.i_mode))) {
7493 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7494 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7495 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007496 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007497 e2fsck_write_inode(ctx, i, &inode,
7498 "disconnect_inode");
7499 /*
7500 * Fix up the bitmaps...
7501 */
7502 e2fsck_read_bitmaps(ctx);
7503 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7504 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7505 ext2fs_inode_alloc_stats2(fs, i, -1,
7506 LINUX_S_ISDIR(inode.i_mode));
7507 return 0;
7508 }
7509 }
7510
7511 /*
7512 * Prompt to reconnect.
7513 */
7514 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7515 if (e2fsck_reconnect_file(ctx, i))
7516 ext2fs_unmark_valid(fs);
7517 } else {
7518 /*
7519 * If we don't attach the inode, then skip the
7520 * i_links_test since there's no point in trying to
7521 * force i_links_count to zero.
7522 */
7523 ext2fs_unmark_valid(fs);
7524 return 1;
7525 }
7526 return 0;
7527}
7528
7529
7530static void e2fsck_pass4(e2fsck_t ctx)
7531{
7532 ext2_filsys fs = ctx->fs;
7533 ext2_ino_t i;
7534 struct ext2_inode inode;
7535 struct problem_context pctx;
7536 __u16 link_count, link_counted;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01007537 char *buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007538 int group, maxgroup;
7539
7540 /* Pass 4 */
7541
7542 clear_problem_context(&pctx);
7543
7544 if (!(ctx->options & E2F_OPT_PREEN))
7545 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7546
7547 group = 0;
7548 maxgroup = fs->group_desc_count;
7549 if (ctx->progress)
7550 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7551 return;
7552
7553 for (i=1; i <= fs->super->s_inodes_count; i++) {
7554 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7555 return;
7556 if ((i % fs->super->s_inodes_per_group) == 0) {
7557 group++;
7558 if (ctx->progress)
7559 if ((ctx->progress)(ctx, 4, group, maxgroup))
7560 return;
7561 }
7562 if (i == EXT2_BAD_INO ||
7563 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7564 continue;
7565 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7566 (ctx->inode_imagic_map &&
7567 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7568 continue;
7569 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7570 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7571 if (link_counted == 0) {
7572 if (!buf)
7573 buf = e2fsck_allocate_memory(ctx,
7574 fs->blocksize, "bad_inode buffer");
7575 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7576 continue;
7577 if (disconnect_inode(ctx, i))
7578 continue;
7579 ext2fs_icount_fetch(ctx->inode_link_info, i,
7580 &link_count);
7581 ext2fs_icount_fetch(ctx->inode_count, i,
7582 &link_counted);
7583 }
7584 if (link_counted != link_count) {
7585 e2fsck_read_inode(ctx, i, &inode, "pass4");
7586 pctx.ino = i;
7587 pctx.inode = &inode;
7588 if (link_count != inode.i_links_count) {
7589 pctx.num = link_count;
7590 fix_problem(ctx,
7591 PR_4_INCONSISTENT_COUNT, &pctx);
7592 }
7593 pctx.num = link_counted;
7594 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7595 inode.i_links_count = link_counted;
7596 e2fsck_write_inode(ctx, i, &inode, "pass4");
7597 }
7598 }
7599 }
7600 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7601 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7602 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7603 ctx->inode_imagic_map = 0;
7604 ext2fs_free_mem(&buf);
7605}
7606
7607/*
7608 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7609 */
7610
7611#define NO_BLK ((blk_t) -1)
7612
7613static void print_bitmap_problem(e2fsck_t ctx, int problem,
7614 struct problem_context *pctx)
7615{
7616 switch (problem) {
7617 case PR_5_BLOCK_UNUSED:
7618 if (pctx->blk == pctx->blk2)
7619 pctx->blk2 = 0;
7620 else
7621 problem = PR_5_BLOCK_RANGE_UNUSED;
7622 break;
7623 case PR_5_BLOCK_USED:
7624 if (pctx->blk == pctx->blk2)
7625 pctx->blk2 = 0;
7626 else
7627 problem = PR_5_BLOCK_RANGE_USED;
7628 break;
7629 case PR_5_INODE_UNUSED:
7630 if (pctx->ino == pctx->ino2)
7631 pctx->ino2 = 0;
7632 else
7633 problem = PR_5_INODE_RANGE_UNUSED;
7634 break;
7635 case PR_5_INODE_USED:
7636 if (pctx->ino == pctx->ino2)
7637 pctx->ino2 = 0;
7638 else
7639 problem = PR_5_INODE_RANGE_USED;
7640 break;
7641 }
7642 fix_problem(ctx, problem, pctx);
7643 pctx->blk = pctx->blk2 = NO_BLK;
7644 pctx->ino = pctx->ino2 = 0;
7645}
7646
7647static void check_block_bitmaps(e2fsck_t ctx)
7648{
7649 ext2_filsys fs = ctx->fs;
7650 blk_t i;
7651 int *free_array;
7652 int group = 0;
7653 unsigned int blocks = 0;
7654 unsigned int free_blocks = 0;
7655 int group_free = 0;
7656 int actual, bitmap;
7657 struct problem_context pctx;
7658 int problem, save_problem, fixit, had_problem;
7659 errcode_t retval;
7660
7661 clear_problem_context(&pctx);
7662 free_array = (int *) e2fsck_allocate_memory(ctx,
7663 fs->group_desc_count * sizeof(int), "free block count array");
7664
7665 if ((fs->super->s_first_data_block <
7666 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7667 (fs->super->s_blocks_count-1 >
7668 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7669 pctx.num = 1;
7670 pctx.blk = fs->super->s_first_data_block;
7671 pctx.blk2 = fs->super->s_blocks_count -1;
7672 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7673 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7674 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7675
7676 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7677 return;
7678 }
7679
7680 if ((fs->super->s_first_data_block <
7681 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7682 (fs->super->s_blocks_count-1 >
7683 ext2fs_get_block_bitmap_end(fs->block_map))) {
7684 pctx.num = 2;
7685 pctx.blk = fs->super->s_first_data_block;
7686 pctx.blk2 = fs->super->s_blocks_count -1;
7687 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7688 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7689 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7690
7691 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7692 return;
7693 }
7694
7695redo_counts:
7696 had_problem = 0;
7697 save_problem = 0;
7698 pctx.blk = pctx.blk2 = NO_BLK;
7699 for (i = fs->super->s_first_data_block;
7700 i < fs->super->s_blocks_count;
7701 i++) {
7702 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7703 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7704
7705 if (actual == bitmap)
7706 goto do_counts;
7707
7708 if (!actual && bitmap) {
7709 /*
7710 * Block not used, but marked in use in the bitmap.
7711 */
7712 problem = PR_5_BLOCK_UNUSED;
7713 } else {
7714 /*
7715 * Block used, but not marked in use in the bitmap.
7716 */
7717 problem = PR_5_BLOCK_USED;
7718 }
7719 if (pctx.blk == NO_BLK) {
7720 pctx.blk = pctx.blk2 = i;
7721 save_problem = problem;
7722 } else {
7723 if ((problem == save_problem) &&
7724 (pctx.blk2 == i-1))
7725 pctx.blk2++;
7726 else {
7727 print_bitmap_problem(ctx, save_problem, &pctx);
7728 pctx.blk = pctx.blk2 = i;
7729 save_problem = problem;
7730 }
7731 }
7732 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7733 had_problem++;
7734
7735 do_counts:
7736 if (!bitmap) {
7737 group_free++;
7738 free_blocks++;
7739 }
7740 blocks ++;
7741 if ((blocks == fs->super->s_blocks_per_group) ||
7742 (i == fs->super->s_blocks_count-1)) {
7743 free_array[group] = group_free;
7744 group ++;
7745 blocks = 0;
7746 group_free = 0;
7747 if (ctx->progress)
7748 if ((ctx->progress)(ctx, 5, group,
7749 fs->group_desc_count*2))
7750 return;
7751 }
7752 }
7753 if (pctx.blk != NO_BLK)
7754 print_bitmap_problem(ctx, save_problem, &pctx);
7755 if (had_problem)
7756 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7757 else
7758 fixit = -1;
7759 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7760
7761 if (fixit == 1) {
7762 ext2fs_free_block_bitmap(fs->block_map);
7763 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7764 &fs->block_map);
7765 if (retval) {
7766 clear_problem_context(&pctx);
7767 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7768 ctx->flags |= E2F_FLAG_ABORT;
7769 return;
7770 }
7771 ext2fs_set_bitmap_padding(fs->block_map);
7772 ext2fs_mark_bb_dirty(fs);
7773
7774 /* Redo the counts */
7775 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7776 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7777 goto redo_counts;
7778 } else if (fixit == 0)
7779 ext2fs_unmark_valid(fs);
7780
7781 for (i = 0; i < fs->group_desc_count; i++) {
7782 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7783 pctx.group = i;
7784 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7785 pctx.blk2 = free_array[i];
7786
7787 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7788 &pctx)) {
7789 fs->group_desc[i].bg_free_blocks_count =
7790 free_array[i];
7791 ext2fs_mark_super_dirty(fs);
7792 } else
7793 ext2fs_unmark_valid(fs);
7794 }
7795 }
7796 if (free_blocks != fs->super->s_free_blocks_count) {
7797 pctx.group = 0;
7798 pctx.blk = fs->super->s_free_blocks_count;
7799 pctx.blk2 = free_blocks;
7800
7801 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7802 fs->super->s_free_blocks_count = free_blocks;
7803 ext2fs_mark_super_dirty(fs);
7804 } else
7805 ext2fs_unmark_valid(fs);
7806 }
7807 ext2fs_free_mem(&free_array);
7808}
7809
7810static void check_inode_bitmaps(e2fsck_t ctx)
7811{
7812 ext2_filsys fs = ctx->fs;
7813 ext2_ino_t i;
7814 unsigned int free_inodes = 0;
7815 int group_free = 0;
7816 int dirs_count = 0;
7817 int group = 0;
7818 unsigned int inodes = 0;
7819 int *free_array;
7820 int *dir_array;
7821 int actual, bitmap;
7822 errcode_t retval;
7823 struct problem_context pctx;
7824 int problem, save_problem, fixit, had_problem;
7825
7826 clear_problem_context(&pctx);
7827 free_array = (int *) e2fsck_allocate_memory(ctx,
7828 fs->group_desc_count * sizeof(int), "free inode count array");
7829
7830 dir_array = (int *) e2fsck_allocate_memory(ctx,
7831 fs->group_desc_count * sizeof(int), "directory count array");
7832
7833 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7834 (fs->super->s_inodes_count >
7835 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7836 pctx.num = 3;
7837 pctx.blk = 1;
7838 pctx.blk2 = fs->super->s_inodes_count;
7839 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7840 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7841 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7842
7843 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7844 return;
7845 }
7846 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7847 (fs->super->s_inodes_count >
7848 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7849 pctx.num = 4;
7850 pctx.blk = 1;
7851 pctx.blk2 = fs->super->s_inodes_count;
7852 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7853 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7854 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7855
7856 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7857 return;
7858 }
7859
7860redo_counts:
7861 had_problem = 0;
7862 save_problem = 0;
7863 pctx.ino = pctx.ino2 = 0;
7864 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7865 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7866 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7867
7868 if (actual == bitmap)
7869 goto do_counts;
7870
7871 if (!actual && bitmap) {
7872 /*
7873 * Inode wasn't used, but marked in bitmap
7874 */
7875 problem = PR_5_INODE_UNUSED;
7876 } else /* if (actual && !bitmap) */ {
7877 /*
7878 * Inode used, but not in bitmap
7879 */
7880 problem = PR_5_INODE_USED;
7881 }
7882 if (pctx.ino == 0) {
7883 pctx.ino = pctx.ino2 = i;
7884 save_problem = problem;
7885 } else {
7886 if ((problem == save_problem) &&
7887 (pctx.ino2 == i-1))
7888 pctx.ino2++;
7889 else {
7890 print_bitmap_problem(ctx, save_problem, &pctx);
7891 pctx.ino = pctx.ino2 = i;
7892 save_problem = problem;
7893 }
7894 }
7895 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7896 had_problem++;
7897
7898do_counts:
7899 if (!bitmap) {
7900 group_free++;
7901 free_inodes++;
7902 } else {
7903 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7904 dirs_count++;
7905 }
7906 inodes++;
7907 if ((inodes == fs->super->s_inodes_per_group) ||
7908 (i == fs->super->s_inodes_count)) {
7909 free_array[group] = group_free;
7910 dir_array[group] = dirs_count;
7911 group ++;
7912 inodes = 0;
7913 group_free = 0;
7914 dirs_count = 0;
7915 if (ctx->progress)
7916 if ((ctx->progress)(ctx, 5,
7917 group + fs->group_desc_count,
7918 fs->group_desc_count*2))
7919 return;
7920 }
7921 }
7922 if (pctx.ino)
7923 print_bitmap_problem(ctx, save_problem, &pctx);
7924
7925 if (had_problem)
7926 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7927 else
7928 fixit = -1;
7929 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7930
7931 if (fixit == 1) {
7932 ext2fs_free_inode_bitmap(fs->inode_map);
7933 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7934 &fs->inode_map);
7935 if (retval) {
7936 clear_problem_context(&pctx);
7937 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7938 ctx->flags |= E2F_FLAG_ABORT;
7939 return;
7940 }
7941 ext2fs_set_bitmap_padding(fs->inode_map);
7942 ext2fs_mark_ib_dirty(fs);
7943
7944 /* redo counts */
7945 inodes = 0; free_inodes = 0; group_free = 0;
7946 dirs_count = 0; group = 0;
7947 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7948 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7949 goto redo_counts;
7950 } else if (fixit == 0)
7951 ext2fs_unmark_valid(fs);
7952
7953 for (i = 0; i < fs->group_desc_count; i++) {
7954 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7955 pctx.group = i;
7956 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7957 pctx.ino2 = free_array[i];
7958 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7959 &pctx)) {
7960 fs->group_desc[i].bg_free_inodes_count =
7961 free_array[i];
7962 ext2fs_mark_super_dirty(fs);
7963 } else
7964 ext2fs_unmark_valid(fs);
7965 }
7966 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7967 pctx.group = i;
7968 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7969 pctx.ino2 = dir_array[i];
7970
7971 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7972 &pctx)) {
7973 fs->group_desc[i].bg_used_dirs_count =
7974 dir_array[i];
7975 ext2fs_mark_super_dirty(fs);
7976 } else
7977 ext2fs_unmark_valid(fs);
7978 }
7979 }
7980 if (free_inodes != fs->super->s_free_inodes_count) {
7981 pctx.group = -1;
7982 pctx.ino = fs->super->s_free_inodes_count;
7983 pctx.ino2 = free_inodes;
7984
7985 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7986 fs->super->s_free_inodes_count = free_inodes;
7987 ext2fs_mark_super_dirty(fs);
7988 } else
7989 ext2fs_unmark_valid(fs);
7990 }
7991 ext2fs_free_mem(&free_array);
7992 ext2fs_free_mem(&dir_array);
7993}
7994
7995static void check_inode_end(e2fsck_t ctx)
7996{
7997 ext2_filsys fs = ctx->fs;
7998 ext2_ino_t end, save_inodes_count, i;
7999 struct problem_context pctx;
8000
8001 clear_problem_context(&pctx);
8002
8003 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
8004 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
8005 &save_inodes_count);
8006 if (pctx.errcode) {
8007 pctx.num = 1;
8008 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8009 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8010 return;
8011 }
8012 if (save_inodes_count == end)
8013 return;
8014
8015 for (i = save_inodes_count + 1; i <= end; i++) {
8016 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8017 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8018 for (i = save_inodes_count + 1; i <= end; i++)
8019 ext2fs_mark_inode_bitmap(fs->inode_map,
8020 i);
8021 ext2fs_mark_ib_dirty(fs);
8022 } else
8023 ext2fs_unmark_valid(fs);
8024 break;
8025 }
8026 }
8027
8028 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8029 save_inodes_count, 0);
8030 if (pctx.errcode) {
8031 pctx.num = 2;
8032 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8033 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8034 return;
8035 }
8036}
8037
8038static void check_block_end(e2fsck_t ctx)
8039{
8040 ext2_filsys fs = ctx->fs;
8041 blk_t end, save_blocks_count, i;
8042 struct problem_context pctx;
8043
8044 clear_problem_context(&pctx);
8045
8046 end = fs->block_map->start +
8047 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8048 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8049 &save_blocks_count);
8050 if (pctx.errcode) {
8051 pctx.num = 3;
8052 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8053 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8054 return;
8055 }
8056 if (save_blocks_count == end)
8057 return;
8058
8059 for (i = save_blocks_count + 1; i <= end; i++) {
8060 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8061 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8062 for (i = save_blocks_count + 1; i <= end; i++)
8063 ext2fs_mark_block_bitmap(fs->block_map,
8064 i);
8065 ext2fs_mark_bb_dirty(fs);
8066 } else
8067 ext2fs_unmark_valid(fs);
8068 break;
8069 }
8070 }
8071
8072 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8073 save_blocks_count, 0);
8074 if (pctx.errcode) {
8075 pctx.num = 4;
8076 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8077 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8078 return;
8079 }
8080}
8081
8082static void e2fsck_pass5(e2fsck_t ctx)
8083{
8084 struct problem_context pctx;
8085
8086 /* Pass 5 */
8087
8088 clear_problem_context(&pctx);
8089
8090 if (!(ctx->options & E2F_OPT_PREEN))
8091 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8092
8093 if (ctx->progress)
8094 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8095 return;
8096
8097 e2fsck_read_bitmaps(ctx);
8098
8099 check_block_bitmaps(ctx);
8100 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8101 return;
8102 check_inode_bitmaps(ctx);
8103 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8104 return;
8105 check_inode_end(ctx);
8106 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8107 return;
8108 check_block_end(ctx);
8109 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8110 return;
8111
8112 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8113 ctx->inode_used_map = 0;
8114 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8115 ctx->inode_dir_map = 0;
8116 ext2fs_free_block_bitmap(ctx->block_found_map);
8117 ctx->block_found_map = 0;
8118}
8119
8120/*
8121 * problem.c --- report filesystem problems to the user
8122 */
8123
8124#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8125#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8126#define PR_NO_DEFAULT 0x000004 /* Default to no */
8127#define PR_MSG_ONLY 0x000008 /* Print message only */
8128
8129/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8130
8131#define PR_FATAL 0x001000 /* Fatal error */
8132#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8133 /* ask another */
8134#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8135#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8136#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8137#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8138#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8139
8140
8141#define PROMPT_NONE 0
8142#define PROMPT_FIX 1
8143#define PROMPT_CLEAR 2
8144#define PROMPT_RELOCATE 3
8145#define PROMPT_ALLOCATE 4
8146#define PROMPT_EXPAND 5
8147#define PROMPT_CONNECT 6
8148#define PROMPT_CREATE 7
8149#define PROMPT_SALVAGE 8
8150#define PROMPT_TRUNCATE 9
8151#define PROMPT_CLEAR_INODE 10
8152#define PROMPT_ABORT 11
8153#define PROMPT_SPLIT 12
8154#define PROMPT_CONTINUE 13
8155#define PROMPT_CLONE 14
8156#define PROMPT_DELETE 15
8157#define PROMPT_SUPPRESS 16
8158#define PROMPT_UNLINK 17
8159#define PROMPT_CLEAR_HTREE 18
8160#define PROMPT_RECREATE 19
8161#define PROMPT_NULL 20
8162
8163struct e2fsck_problem {
8164 problem_t e2p_code;
8165 const char * e2p_description;
8166 char prompt;
8167 int flags;
8168 problem_t second_code;
8169};
8170
8171struct latch_descr {
8172 int latch_code;
8173 problem_t question;
8174 problem_t end_message;
8175 int flags;
8176};
8177
8178/*
8179 * These are the prompts which are used to ask the user if they want
8180 * to fix a problem.
8181 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008182static const char *const prompt[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008183 N_("(no prompt)"), /* 0 */
8184 N_("Fix"), /* 1 */
8185 N_("Clear"), /* 2 */
8186 N_("Relocate"), /* 3 */
8187 N_("Allocate"), /* 4 */
8188 N_("Expand"), /* 5 */
8189 N_("Connect to /lost+found"), /* 6 */
8190 N_("Create"), /* 7 */
8191 N_("Salvage"), /* 8 */
8192 N_("Truncate"), /* 9 */
8193 N_("Clear inode"), /* 10 */
8194 N_("Abort"), /* 11 */
8195 N_("Split"), /* 12 */
8196 N_("Continue"), /* 13 */
8197 N_("Clone multiply-claimed blocks"), /* 14 */
8198 N_("Delete file"), /* 15 */
8199 N_("Suppress messages"),/* 16 */
8200 N_("Unlink"), /* 17 */
8201 N_("Clear HTree index"),/* 18 */
8202 N_("Recreate"), /* 19 */
8203 "", /* 20 */
8204};
8205
8206/*
8207 * These messages are printed when we are preen mode and we will be
8208 * automatically fixing the problem.
8209 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008210static const char *const preen_msg[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008211 N_("(NONE)"), /* 0 */
8212 N_("FIXED"), /* 1 */
8213 N_("CLEARED"), /* 2 */
8214 N_("RELOCATED"), /* 3 */
8215 N_("ALLOCATED"), /* 4 */
8216 N_("EXPANDED"), /* 5 */
8217 N_("RECONNECTED"), /* 6 */
8218 N_("CREATED"), /* 7 */
8219 N_("SALVAGED"), /* 8 */
8220 N_("TRUNCATED"), /* 9 */
8221 N_("INODE CLEARED"), /* 10 */
8222 N_("ABORTED"), /* 11 */
8223 N_("SPLIT"), /* 12 */
8224 N_("CONTINUING"), /* 13 */
8225 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8226 N_("FILE DELETED"), /* 15 */
8227 N_("SUPPRESSED"), /* 16 */
8228 N_("UNLINKED"), /* 17 */
8229 N_("HTREE INDEX CLEARED"),/* 18 */
8230 N_("WILL RECREATE"), /* 19 */
8231 "", /* 20 */
8232};
8233
8234static const struct e2fsck_problem problem_table[] = {
8235
8236 /* Pre-Pass 1 errors */
8237
8238 /* Block bitmap not in group */
8239 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8240 PROMPT_RELOCATE, PR_LATCH_RELOC },
8241
8242 /* Inode bitmap not in group */
8243 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8244 PROMPT_RELOCATE, PR_LATCH_RELOC },
8245
8246 /* Inode table not in group */
8247 { PR_0_ITABLE_NOT_GROUP,
8248 N_("@i table for @g %g is not in @g. (@b %b)\n"
8249 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8250 PROMPT_RELOCATE, PR_LATCH_RELOC },
8251
8252 /* Superblock corrupt */
8253 { PR_0_SB_CORRUPT,
8254 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8255 "@f. If the @v is valid and it really contains an ext2\n"
8256 "@f (and not swap or ufs or something else), then the @S\n"
8257 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8258 " e2fsck -b %S <@v>\n\n"),
8259 PROMPT_NONE, PR_FATAL },
8260
8261 /* Filesystem size is wrong */
8262 { PR_0_FS_SIZE_WRONG,
8263 N_("The @f size (according to the @S) is %b @bs\n"
8264 "The physical size of the @v is %c @bs\n"
8265 "Either the @S or the partition table is likely to be corrupt!\n"),
8266 PROMPT_ABORT, 0 },
8267
8268 /* Fragments not supported */
8269 { PR_0_NO_FRAGMENTS,
8270 N_("@S @b_size = %b, fragsize = %c.\n"
8271 "This version of e2fsck does not support fragment sizes different\n"
8272 "from the @b size.\n"),
8273 PROMPT_NONE, PR_FATAL },
8274
8275 /* Bad blocks_per_group */
8276 { PR_0_BLOCKS_PER_GROUP,
8277 N_("@S @bs_per_group = %b, should have been %c\n"),
8278 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8279
8280 /* Bad first_data_block */
8281 { PR_0_FIRST_DATA_BLOCK,
8282 N_("@S first_data_@b = %b, should have been %c\n"),
8283 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8284
8285 /* Adding UUID to filesystem */
8286 { PR_0_ADD_UUID,
8287 N_("@f did not have a UUID; generating one.\n\n"),
8288 PROMPT_NONE, 0 },
8289
8290 /* Relocate hint */
8291 { PR_0_RELOCATE_HINT,
8292 N_("Note: if several inode or block bitmap blocks or part\n"
8293 "of the inode table require relocation, you may wish to try\n"
8294 "running e2fsck with the '-b %S' option first. The problem\n"
8295 "may lie only with the primary block group descriptors, and\n"
8296 "the backup block group descriptors may be OK.\n\n"),
8297 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8298
8299 /* Miscellaneous superblock corruption */
8300 { PR_0_MISC_CORRUPT_SUPER,
8301 N_("Corruption found in @S. (%s = %N).\n"),
8302 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8303
8304 /* Error determing physical device size of filesystem */
8305 { PR_0_GETSIZE_ERROR,
8306 N_("Error determining size of the physical @v: %m\n"),
8307 PROMPT_NONE, PR_FATAL },
8308
8309 /* Inode count in superblock is incorrect */
8310 { PR_0_INODE_COUNT_WRONG,
8311 N_("@i count in @S is %i, @s %j.\n"),
8312 PROMPT_FIX, 0 },
8313
8314 { PR_0_HURD_CLEAR_FILETYPE,
8315 N_("The Hurd does not support the filetype feature.\n"),
8316 PROMPT_CLEAR, 0 },
8317
8318 /* Journal inode is invalid */
8319 { PR_0_JOURNAL_BAD_INODE,
8320 N_("@S has an @n ext3 @j (@i %i).\n"),
8321 PROMPT_CLEAR, PR_PREEN_OK },
8322
8323 /* The external journal has (unsupported) multiple filesystems */
8324 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8325 N_("External @j has multiple @f users (unsupported).\n"),
8326 PROMPT_NONE, PR_FATAL },
8327
8328 /* Can't find external journal */
8329 { PR_0_CANT_FIND_JOURNAL,
8330 N_("Can't find external @j\n"),
8331 PROMPT_NONE, PR_FATAL },
8332
8333 /* External journal has bad superblock */
8334 { PR_0_EXT_JOURNAL_BAD_SUPER,
8335 N_("External @j has bad @S\n"),
8336 PROMPT_NONE, PR_FATAL },
8337
8338 /* Superblock has a bad journal UUID */
8339 { PR_0_JOURNAL_BAD_UUID,
8340 N_("External @j does not support this @f\n"),
8341 PROMPT_NONE, PR_FATAL },
8342
8343 /* Journal has an unknown superblock type */
8344 { PR_0_JOURNAL_UNSUPP_SUPER,
8345 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8346 "It is likely that your copy of e2fsck is old and/or doesn't "
8347 "support this @j format.\n"
8348 "It is also possible the @j @S is corrupt.\n"),
8349 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8350
8351 /* Journal superblock is corrupt */
8352 { PR_0_JOURNAL_BAD_SUPER,
8353 N_("Ext3 @j @S is corrupt.\n"),
8354 PROMPT_FIX, PR_PREEN_OK },
8355
8356 /* Superblock flag should be cleared */
8357 { PR_0_JOURNAL_HAS_JOURNAL,
8358 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8359 PROMPT_CLEAR, PR_PREEN_OK },
8360
8361 /* Superblock flag is incorrect */
8362 { PR_0_JOURNAL_RECOVER_SET,
8363 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8364 PROMPT_CLEAR, PR_PREEN_OK },
8365
8366 /* Journal has data, but recovery flag is clear */
8367 { PR_0_JOURNAL_RECOVERY_CLEAR,
8368 N_("ext3 recovery flag is clear, but @j has data.\n"),
8369 PROMPT_NONE, 0 },
8370
8371 /* Ask if we should clear the journal */
8372 { PR_0_JOURNAL_RESET_JOURNAL,
8373 N_("Clear @j"),
8374 PROMPT_NULL, PR_PREEN_NOMSG },
8375
8376 /* Ask if we should run the journal anyway */
8377 { PR_0_JOURNAL_RUN,
8378 N_("Run @j anyway"),
8379 PROMPT_NULL, 0 },
8380
8381 /* Run the journal by default */
8382 { PR_0_JOURNAL_RUN_DEFAULT,
8383 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8384 PROMPT_NONE, 0 },
8385
8386 /* Clearing orphan inode */
8387 { PR_0_ORPHAN_CLEAR_INODE,
8388 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8389 PROMPT_NONE, 0 },
8390
8391 /* Illegal block found in orphaned inode */
8392 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8393 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8394 PROMPT_NONE, 0 },
8395
8396 /* Already cleared block found in orphaned inode */
8397 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8398 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8399 PROMPT_NONE, 0 },
8400
8401 /* Illegal orphan inode in superblock */
8402 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8403 N_("@I @o @i %i in @S.\n"),
8404 PROMPT_NONE, 0 },
8405
8406 /* Illegal inode in orphaned inode list */
8407 { PR_0_ORPHAN_ILLEGAL_INODE,
8408 N_("@I @i %i in @o @i list.\n"),
8409 PROMPT_NONE, 0 },
8410
8411 /* Filesystem revision is 0, but feature flags are set */
8412 { PR_0_FS_REV_LEVEL,
8413 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8414 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8415
8416 /* Journal superblock has an unknown read-only feature flag set */
8417 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8418 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8419 PROMPT_ABORT, 0 },
8420
8421 /* Journal superblock has an unknown incompatible feature flag set */
8422 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8423 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8424 PROMPT_ABORT, 0 },
8425
8426 /* Journal has unsupported version number */
8427 { PR_0_JOURNAL_UNSUPP_VERSION,
8428 N_("@j version not supported by this e2fsck.\n"),
8429 PROMPT_ABORT, 0 },
8430
8431 /* Moving journal to hidden file */
8432 { PR_0_MOVE_JOURNAL,
8433 N_("Moving @j from /%s to hidden @i.\n\n"),
8434 PROMPT_NONE, 0 },
8435
8436 /* Error moving journal to hidden file */
8437 { PR_0_ERR_MOVE_JOURNAL,
8438 N_("Error moving @j: %m\n\n"),
8439 PROMPT_NONE, 0 },
8440
8441 /* Clearing V2 journal superblock */
8442 { PR_0_CLEAR_V2_JOURNAL,
8443 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8444 "Clearing fields beyond the V1 @j @S...\n\n"),
8445 PROMPT_NONE, 0 },
8446
8447 /* Backup journal inode blocks */
8448 { PR_0_BACKUP_JNL,
8449 N_("Backing up @j @i @b information.\n\n"),
8450 PROMPT_NONE, 0 },
8451
8452 /* Reserved blocks w/o resize_inode */
8453 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8454 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8455 "is %N; @s zero. "),
8456 PROMPT_FIX, 0 },
8457
8458 /* Resize_inode not enabled, but resize inode is non-zero */
8459 { PR_0_CLEAR_RESIZE_INODE,
8460 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8461 PROMPT_CLEAR, 0 },
8462
8463 /* Resize inode invalid */
8464 { PR_0_RESIZE_INODE_INVALID,
8465 N_("Resize @i not valid. "),
8466 PROMPT_RECREATE, 0 },
8467
8468 /* Pass 1 errors */
8469
8470 /* Pass 1: Checking inodes, blocks, and sizes */
8471 { PR_1_PASS_HEADER,
8472 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8473 PROMPT_NONE, 0 },
8474
8475 /* Root directory is not an inode */
8476 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8477 PROMPT_CLEAR, 0 },
8478
8479 /* Root directory has dtime set */
8480 { PR_1_ROOT_DTIME,
8481 N_("@r has dtime set (probably due to old mke2fs). "),
8482 PROMPT_FIX, PR_PREEN_OK },
8483
8484 /* Reserved inode has bad mode */
8485 { PR_1_RESERVED_BAD_MODE,
8486 N_("Reserved @i %i (%Q) has @n mode. "),
8487 PROMPT_CLEAR, PR_PREEN_OK },
8488
8489 /* Deleted inode has zero dtime */
8490 { PR_1_ZERO_DTIME,
8491 N_("@D @i %i has zero dtime. "),
8492 PROMPT_FIX, PR_PREEN_OK },
8493
8494 /* Inode in use, but dtime set */
8495 { PR_1_SET_DTIME,
8496 N_("@i %i is in use, but has dtime set. "),
8497 PROMPT_FIX, PR_PREEN_OK },
8498
8499 /* Zero-length directory */
8500 { PR_1_ZERO_LENGTH_DIR,
8501 N_("@i %i is a @z @d. "),
8502 PROMPT_CLEAR, PR_PREEN_OK },
8503
8504 /* Block bitmap conflicts with some other fs block */
8505 { PR_1_BB_CONFLICT,
8506 N_("@g %g's @b @B at %b @C.\n"),
8507 PROMPT_RELOCATE, 0 },
8508
8509 /* Inode bitmap conflicts with some other fs block */
8510 { PR_1_IB_CONFLICT,
8511 N_("@g %g's @i @B at %b @C.\n"),
8512 PROMPT_RELOCATE, 0 },
8513
8514 /* Inode table conflicts with some other fs block */
8515 { PR_1_ITABLE_CONFLICT,
8516 N_("@g %g's @i table at %b @C.\n"),
8517 PROMPT_RELOCATE, 0 },
8518
8519 /* Block bitmap is on a bad block */
8520 { PR_1_BB_BAD_BLOCK,
8521 N_("@g %g's @b @B (%b) is bad. "),
8522 PROMPT_RELOCATE, 0 },
8523
8524 /* Inode bitmap is on a bad block */
8525 { PR_1_IB_BAD_BLOCK,
8526 N_("@g %g's @i @B (%b) is bad. "),
8527 PROMPT_RELOCATE, 0 },
8528
8529 /* Inode has incorrect i_size */
8530 { PR_1_BAD_I_SIZE,
8531 N_("@i %i, i_size is %Is, @s %N. "),
8532 PROMPT_FIX, PR_PREEN_OK },
8533
8534 /* Inode has incorrect i_blocks */
8535 { PR_1_BAD_I_BLOCKS,
8536 N_("@i %i, i_@bs is %Ib, @s %N. "),
8537 PROMPT_FIX, PR_PREEN_OK },
8538
8539 /* Illegal blocknumber in inode */
8540 { PR_1_ILLEGAL_BLOCK_NUM,
8541 N_("@I @b #%B (%b) in @i %i. "),
8542 PROMPT_CLEAR, PR_LATCH_BLOCK },
8543
8544 /* Block number overlaps fs metadata */
8545 { PR_1_BLOCK_OVERLAPS_METADATA,
8546 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8547 PROMPT_CLEAR, PR_LATCH_BLOCK },
8548
8549 /* Inode has illegal blocks (latch question) */
8550 { PR_1_INODE_BLOCK_LATCH,
8551 N_("@i %i has illegal @b(s). "),
8552 PROMPT_CLEAR, 0 },
8553
8554 /* Too many bad blocks in inode */
8555 { PR_1_TOO_MANY_BAD_BLOCKS,
8556 N_("Too many illegal @bs in @i %i.\n"),
8557 PROMPT_CLEAR_INODE, PR_NO_OK },
8558
8559 /* Illegal block number in bad block inode */
8560 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8561 N_("@I @b #%B (%b) in bad @b @i. "),
8562 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8563
8564 /* Bad block inode has illegal blocks (latch question) */
8565 { PR_1_INODE_BBLOCK_LATCH,
8566 N_("Bad @b @i has illegal @b(s). "),
8567 PROMPT_CLEAR, 0 },
8568
8569 /* Duplicate or bad blocks in use! */
8570 { PR_1_DUP_BLOCKS_PREENSTOP,
8571 N_("Duplicate or bad @b in use!\n"),
8572 PROMPT_NONE, 0 },
8573
8574 /* Bad block used as bad block indirect block */
8575 { PR_1_BBINODE_BAD_METABLOCK,
8576 N_("Bad @b %b used as bad @b @i indirect @b. "),
8577 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8578
8579 /* Inconsistency can't be fixed prompt */
8580 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8581 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8582 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8583 "in the @f.\n"),
8584 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8585
8586 /* Bad primary block */
8587 { PR_1_BAD_PRIMARY_BLOCK,
8588 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8589 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8590
8591 /* Bad primary block prompt */
8592 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8593 N_("You can remove this @b from the bad @b list and hope\n"
8594 "that the @b is really OK. But there are no guarantees.\n\n"),
8595 PROMPT_CLEAR, PR_PREEN_NOMSG },
8596
8597 /* Bad primary superblock */
8598 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8599 N_("The primary @S (%b) is on the bad @b list.\n"),
8600 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8601
8602 /* Bad primary block group descriptors */
8603 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8604 N_("Block %b in the primary @g descriptors "
8605 "is on the bad @b list\n"),
8606 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8607
8608 /* Bad superblock in group */
8609 { PR_1_BAD_SUPERBLOCK,
8610 N_("Warning: Group %g's @S (%b) is bad.\n"),
8611 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8612
8613 /* Bad block group descriptors in group */
8614 { PR_1_BAD_GROUP_DESCRIPTORS,
8615 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8616 "@b (%b).\n"),
8617 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8618
8619 /* Block claimed for no reason */
8620 { PR_1_PROGERR_CLAIMED_BLOCK,
8621 N_("Programming error? @b #%b claimed for no reason in "
8622 "process_bad_@b.\n"),
8623 PROMPT_NONE, PR_PREEN_OK },
8624
8625 /* Error allocating blocks for relocating metadata */
8626 { PR_1_RELOC_BLOCK_ALLOCATE,
8627 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8628 PROMPT_NONE, PR_PREEN_OK },
8629
8630 /* Error allocating block buffer during relocation process */
8631 { PR_1_RELOC_MEMORY_ALLOCATE,
8632 N_("@A @b buffer for relocating %s\n"),
8633 PROMPT_NONE, PR_PREEN_OK },
8634
8635 /* Relocating metadata group information from X to Y */
8636 { PR_1_RELOC_FROM_TO,
8637 N_("Relocating @g %g's %s from %b to %c...\n"),
8638 PROMPT_NONE, PR_PREEN_OK },
8639
8640 /* Relocating metatdata group information to X */
8641 { PR_1_RELOC_TO,
8642 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8643 PROMPT_NONE, PR_PREEN_OK },
8644
8645 /* Block read error during relocation process */
8646 { PR_1_RELOC_READ_ERR,
8647 N_("Warning: could not read @b %b of %s: %m\n"),
8648 PROMPT_NONE, PR_PREEN_OK },
8649
8650 /* Block write error during relocation process */
8651 { PR_1_RELOC_WRITE_ERR,
8652 N_("Warning: could not write @b %b for %s: %m\n"),
8653 PROMPT_NONE, PR_PREEN_OK },
8654
8655 /* Error allocating inode bitmap */
8656 { PR_1_ALLOCATE_IBITMAP_ERROR,
8657 N_("@A @i @B (%N): %m\n"),
8658 PROMPT_NONE, PR_FATAL },
8659
8660 /* Error allocating block bitmap */
8661 { PR_1_ALLOCATE_BBITMAP_ERROR,
8662 N_("@A @b @B (%N): %m\n"),
8663 PROMPT_NONE, PR_FATAL },
8664
8665 /* Error allocating icount structure */
8666 { PR_1_ALLOCATE_ICOUNT,
8667 N_("@A icount link information: %m\n"),
8668 PROMPT_NONE, PR_FATAL },
8669
8670 /* Error allocating dbcount */
8671 { PR_1_ALLOCATE_DBCOUNT,
8672 N_("@A @d @b array: %m\n"),
8673 PROMPT_NONE, PR_FATAL },
8674
8675 /* Error while scanning inodes */
8676 { PR_1_ISCAN_ERROR,
8677 N_("Error while scanning @is (%i): %m\n"),
8678 PROMPT_NONE, PR_FATAL },
8679
8680 /* Error while iterating over blocks */
8681 { PR_1_BLOCK_ITERATE,
8682 N_("Error while iterating over @bs in @i %i: %m\n"),
8683 PROMPT_NONE, PR_FATAL },
8684
8685 /* Error while storing inode count information */
8686 { PR_1_ICOUNT_STORE,
8687 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8688 PROMPT_NONE, PR_FATAL },
8689
8690 /* Error while storing directory block information */
8691 { PR_1_ADD_DBLOCK,
8692 N_("Error storing @d @b information "
8693 "(@i=%i, @b=%b, num=%N): %m\n"),
8694 PROMPT_NONE, PR_FATAL },
8695
8696 /* Error while reading inode (for clearing) */
8697 { PR_1_READ_INODE,
8698 N_("Error reading @i %i: %m\n"),
8699 PROMPT_NONE, PR_FATAL },
8700
8701 /* Suppress messages prompt */
8702 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8703
8704 /* Imagic flag set on an inode when filesystem doesn't support it */
8705 { PR_1_SET_IMAGIC,
8706 N_("@i %i has imagic flag set. "),
8707 PROMPT_CLEAR, 0 },
8708
8709 /* Immutable flag set on a device or socket inode */
8710 { PR_1_SET_IMMUTABLE,
8711 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8712 "or append-only flag set. "),
8713 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8714
8715 /* Compression flag set on an inode when filesystem doesn't support it */
8716 { PR_1_COMPR_SET,
8717 N_("@i %i has @cion flag set on @f without @cion support. "),
8718 PROMPT_CLEAR, 0 },
8719
8720 /* Non-zero size for device, fifo or socket inode */
8721 { PR_1_SET_NONZSIZE,
8722 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8723 PROMPT_FIX, PR_PREEN_OK },
8724
8725 /* Filesystem revision is 0, but feature flags are set */
8726 { PR_1_FS_REV_LEVEL,
8727 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8728 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8729
8730 /* Journal inode is not in use, but contains data */
8731 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8732 N_("@j @i is not in use, but contains data. "),
8733 PROMPT_CLEAR, PR_PREEN_OK },
8734
8735 /* Journal has bad mode */
8736 { PR_1_JOURNAL_BAD_MODE,
8737 N_("@j is not regular file. "),
8738 PROMPT_FIX, PR_PREEN_OK },
8739
8740 /* Deal with inodes that were part of orphan linked list */
8741 { PR_1_LOW_DTIME,
8742 N_("@i %i was part of the @o @i list. "),
8743 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8744
8745 /* Deal with inodes that were part of corrupted orphan linked
8746 list (latch question) */
8747 { PR_1_ORPHAN_LIST_REFUGEES,
8748 N_("@is that were part of a corrupted orphan linked list found. "),
8749 PROMPT_FIX, 0 },
8750
8751 /* Error allocating refcount structure */
8752 { PR_1_ALLOCATE_REFCOUNT,
8753 N_("@A refcount structure (%N): %m\n"),
8754 PROMPT_NONE, PR_FATAL },
8755
8756 /* Error reading extended attribute block */
8757 { PR_1_READ_EA_BLOCK,
8758 N_("Error reading @a @b %b for @i %i. "),
8759 PROMPT_CLEAR, 0 },
8760
8761 /* Invalid extended attribute block */
8762 { PR_1_BAD_EA_BLOCK,
8763 N_("@i %i has a bad @a @b %b. "),
8764 PROMPT_CLEAR, 0 },
8765
8766 /* Error reading Extended Attribute block while fixing refcount */
8767 { PR_1_EXTATTR_READ_ABORT,
8768 N_("Error reading @a @b %b (%m). "),
8769 PROMPT_ABORT, 0 },
8770
8771 /* Extended attribute reference count incorrect */
8772 { PR_1_EXTATTR_REFCOUNT,
8773 N_("@a @b %b has reference count %B, @s %N. "),
8774 PROMPT_FIX, 0 },
8775
8776 /* Error writing Extended Attribute block while fixing refcount */
8777 { PR_1_EXTATTR_WRITE,
8778 N_("Error writing @a @b %b (%m). "),
8779 PROMPT_ABORT, 0 },
8780
8781 /* Multiple EA blocks not supported */
8782 { PR_1_EA_MULTI_BLOCK,
8783 N_("@a @b %b has h_@bs > 1. "),
8784 PROMPT_CLEAR, 0},
8785
8786 /* Error allocating EA region allocation structure */
8787 { PR_1_EA_ALLOC_REGION,
8788 N_("@A @a @b %b. "),
8789 PROMPT_ABORT, 0},
8790
8791 /* Error EA allocation collision */
8792 { PR_1_EA_ALLOC_COLLISION,
8793 N_("@a @b %b is corrupt (allocation collision). "),
8794 PROMPT_CLEAR, 0},
8795
8796 /* Bad extended attribute name */
8797 { PR_1_EA_BAD_NAME,
8798 N_("@a @b %b is corrupt (@n name). "),
8799 PROMPT_CLEAR, 0},
8800
8801 /* Bad extended attribute value */
8802 { PR_1_EA_BAD_VALUE,
8803 N_("@a @b %b is corrupt (@n value). "),
8804 PROMPT_CLEAR, 0},
8805
8806 /* Inode too big (latch question) */
8807 { PR_1_INODE_TOOBIG,
8808 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8809
8810 /* Directory too big */
8811 { PR_1_TOOBIG_DIR,
8812 N_("@b #%B (%b) causes @d to be too big. "),
8813 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8814
8815 /* Regular file too big */
8816 { PR_1_TOOBIG_REG,
8817 N_("@b #%B (%b) causes file to be too big. "),
8818 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8819
8820 /* Symlink too big */
8821 { PR_1_TOOBIG_SYMLINK,
8822 N_("@b #%B (%b) causes symlink to be too big. "),
8823 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8824
8825 /* INDEX_FL flag set on a non-HTREE filesystem */
8826 { PR_1_HTREE_SET,
8827 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8828 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8829
8830 /* INDEX_FL flag set on a non-directory */
8831 { PR_1_HTREE_NODIR,
8832 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8833 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8834
8835 /* Invalid root node in HTREE directory */
8836 { PR_1_HTREE_BADROOT,
8837 N_("@h %i has an @n root node.\n"),
8838 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8839
8840 /* Unsupported hash version in HTREE directory */
8841 { PR_1_HTREE_HASHV,
8842 N_("@h %i has an unsupported hash version (%N)\n"),
8843 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8844
8845 /* Incompatible flag in HTREE root node */
8846 { PR_1_HTREE_INCOMPAT,
8847 N_("@h %i uses an incompatible htree root node flag.\n"),
8848 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8849
8850 /* HTREE too deep */
8851 { PR_1_HTREE_DEPTH,
8852 N_("@h %i has a tree depth (%N) which is too big\n"),
8853 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8854
8855 /* Bad block has indirect block that conflicts with filesystem block */
8856 { PR_1_BB_FS_BLOCK,
8857 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8858 "@f metadata. "),
8859 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8860
8861 /* Resize inode failed */
8862 { PR_1_RESIZE_INODE_CREATE,
8863 N_("Resize @i (re)creation failed: %m."),
8864 PROMPT_ABORT, 0 },
8865
8866 /* invalid inode->i_extra_isize */
8867 { PR_1_EXTRA_ISIZE,
8868 N_("@i %i has a extra size (%IS) which is @n\n"),
8869 PROMPT_FIX, PR_PREEN_OK },
8870
8871 /* invalid ea entry->e_name_len */
8872 { PR_1_ATTR_NAME_LEN,
8873 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8874 PROMPT_CLEAR, PR_PREEN_OK },
8875
8876 /* invalid ea entry->e_value_size */
8877 { PR_1_ATTR_VALUE_SIZE,
8878 N_("@a in @i %i has a value size (%N) which is @n\n"),
8879 PROMPT_CLEAR, PR_PREEN_OK },
8880
8881 /* invalid ea entry->e_value_offs */
8882 { PR_1_ATTR_VALUE_OFFSET,
8883 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8884 PROMPT_CLEAR, PR_PREEN_OK },
8885
8886 /* invalid ea entry->e_value_block */
8887 { PR_1_ATTR_VALUE_BLOCK,
8888 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8889 PROMPT_CLEAR, PR_PREEN_OK },
8890
8891 /* invalid ea entry->e_hash */
8892 { PR_1_ATTR_HASH,
8893 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8894 PROMPT_CLEAR, PR_PREEN_OK },
8895
8896 /* Pass 1b errors */
8897
8898 /* Pass 1B: Rescan for duplicate/bad blocks */
8899 { PR_1B_PASS_HEADER,
8900 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8901 "Pass 1B: Rescanning for @m @bs\n"),
8902 PROMPT_NONE, 0 },
8903
8904 /* Duplicate/bad block(s) header */
8905 { PR_1B_DUP_BLOCK_HEADER,
8906 N_("@m @b(s) in @i %i:"),
8907 PROMPT_NONE, 0 },
8908
8909 /* Duplicate/bad block(s) in inode */
8910 { PR_1B_DUP_BLOCK,
8911 " %b",
8912 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8913
8914 /* Duplicate/bad block(s) end */
8915 { PR_1B_DUP_BLOCK_END,
8916 "\n",
8917 PROMPT_NONE, PR_PREEN_NOHDR },
8918
8919 /* Error while scanning inodes */
8920 { PR_1B_ISCAN_ERROR,
8921 N_("Error while scanning inodes (%i): %m\n"),
8922 PROMPT_NONE, PR_FATAL },
8923
8924 /* Error allocating inode bitmap */
8925 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8926 N_("@A @i @B (@i_dup_map): %m\n"),
8927 PROMPT_NONE, PR_FATAL },
8928
8929 /* Error while iterating over blocks */
8930 { PR_1B_BLOCK_ITERATE,
8931 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8932 PROMPT_NONE, 0 },
8933
8934 /* Error adjusting EA refcount */
8935 { PR_1B_ADJ_EA_REFCOUNT,
8936 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8937 PROMPT_NONE, 0 },
8938
8939
8940 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8941 { PR_1C_PASS_HEADER,
8942 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8943 PROMPT_NONE, 0 },
8944
8945
8946 /* Pass 1D: Reconciling multiply-claimed blocks */
8947 { PR_1D_PASS_HEADER,
8948 N_("Pass 1D: Reconciling @m @bs\n"),
8949 PROMPT_NONE, 0 },
8950
8951 /* File has duplicate blocks */
8952 { PR_1D_DUP_FILE,
8953 N_("File %Q (@i #%i, mod time %IM)\n"
8954 " has %B @m @b(s), shared with %N file(s):\n"),
8955 PROMPT_NONE, 0 },
8956
8957 /* List of files sharing duplicate blocks */
8958 { PR_1D_DUP_FILE_LIST,
8959 N_("\t%Q (@i #%i, mod time %IM)\n"),
8960 PROMPT_NONE, 0 },
8961
8962 /* File sharing blocks with filesystem metadata */
8963 { PR_1D_SHARE_METADATA,
8964 N_("\t<@f metadata>\n"),
8965 PROMPT_NONE, 0 },
8966
8967 /* Report of how many duplicate/bad inodes */
8968 { PR_1D_NUM_DUP_INODES,
8969 N_("(There are %N @is containing @m @bs.)\n\n"),
8970 PROMPT_NONE, 0 },
8971
8972 /* Duplicated blocks already reassigned or cloned. */
8973 { PR_1D_DUP_BLOCKS_DEALT,
8974 N_("@m @bs already reassigned or cloned.\n\n"),
8975 PROMPT_NONE, 0 },
8976
8977 /* Clone duplicate/bad blocks? */
8978 { PR_1D_CLONE_QUESTION,
8979 "", PROMPT_CLONE, PR_NO_OK },
8980
8981 /* Delete file? */
8982 { PR_1D_DELETE_QUESTION,
8983 "", PROMPT_DELETE, 0 },
8984
8985 /* Couldn't clone file (error) */
8986 { PR_1D_CLONE_ERROR,
8987 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8988
8989 /* Pass 2 errors */
8990
8991 /* Pass 2: Checking directory structure */
8992 { PR_2_PASS_HEADER,
8993 N_("Pass 2: Checking @d structure\n"),
8994 PROMPT_NONE, 0 },
8995
8996 /* Bad inode number for '.' */
8997 { PR_2_BAD_INODE_DOT,
8998 N_("@n @i number for '.' in @d @i %i.\n"),
8999 PROMPT_FIX, 0 },
9000
9001 /* Directory entry has bad inode number */
9002 { PR_2_BAD_INO,
9003 N_("@E has @n @i #: %Di.\n"),
9004 PROMPT_CLEAR, 0 },
9005
9006 /* Directory entry has deleted or unused inode */
9007 { PR_2_UNUSED_INODE,
9008 N_("@E has @D/unused @i %Di. "),
9009 PROMPT_CLEAR, PR_PREEN_OK },
9010
9011 /* Directry entry is link to '.' */
9012 { PR_2_LINK_DOT,
9013 N_("@E @L to '.' "),
9014 PROMPT_CLEAR, 0 },
9015
9016 /* Directory entry points to inode now located in a bad block */
9017 { PR_2_BB_INODE,
9018 N_("@E points to @i (%Di) located in a bad @b.\n"),
9019 PROMPT_CLEAR, 0 },
9020
9021 /* Directory entry contains a link to a directory */
9022 { PR_2_LINK_DIR,
9023 N_("@E @L to @d %P (%Di).\n"),
9024 PROMPT_CLEAR, 0 },
9025
9026 /* Directory entry contains a link to the root directry */
9027 { PR_2_LINK_ROOT,
9028 N_("@E @L to the @r.\n"),
9029 PROMPT_CLEAR, 0 },
9030
9031 /* Directory entry has illegal characters in its name */
9032 { PR_2_BAD_NAME,
9033 N_("@E has illegal characters in its name.\n"),
9034 PROMPT_FIX, 0 },
9035
9036 /* Missing '.' in directory inode */
9037 { PR_2_MISSING_DOT,
9038 N_("Missing '.' in @d @i %i.\n"),
9039 PROMPT_FIX, 0 },
9040
9041 /* Missing '..' in directory inode */
9042 { PR_2_MISSING_DOT_DOT,
9043 N_("Missing '..' in @d @i %i.\n"),
9044 PROMPT_FIX, 0 },
9045
9046 /* First entry in directory inode doesn't contain '.' */
9047 { PR_2_1ST_NOT_DOT,
9048 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9049 PROMPT_FIX, 0 },
9050
9051 /* Second entry in directory inode doesn't contain '..' */
9052 { PR_2_2ND_NOT_DOT_DOT,
9053 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9054 PROMPT_FIX, 0 },
9055
9056 /* i_faddr should be zero */
9057 { PR_2_FADDR_ZERO,
9058 N_("i_faddr @F %IF, @s zero.\n"),
9059 PROMPT_CLEAR, 0 },
9060
9061 /* i_file_acl should be zero */
9062 { PR_2_FILE_ACL_ZERO,
9063 N_("i_file_acl @F %If, @s zero.\n"),
9064 PROMPT_CLEAR, 0 },
9065
9066 /* i_dir_acl should be zero */
9067 { PR_2_DIR_ACL_ZERO,
9068 N_("i_dir_acl @F %Id, @s zero.\n"),
9069 PROMPT_CLEAR, 0 },
9070
9071 /* i_frag should be zero */
9072 { PR_2_FRAG_ZERO,
9073 N_("i_frag @F %N, @s zero.\n"),
9074 PROMPT_CLEAR, 0 },
9075
9076 /* i_fsize should be zero */
9077 { PR_2_FSIZE_ZERO,
9078 N_("i_fsize @F %N, @s zero.\n"),
9079 PROMPT_CLEAR, 0 },
9080
9081 /* inode has bad mode */
9082 { PR_2_BAD_MODE,
9083 N_("@i %i (%Q) has @n mode (%Im).\n"),
9084 PROMPT_CLEAR, 0 },
9085
9086 /* directory corrupted */
9087 { PR_2_DIR_CORRUPTED,
9088 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9089 PROMPT_SALVAGE, 0 },
9090
9091 /* filename too long */
9092 { PR_2_FILENAME_LONG,
9093 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9094 PROMPT_TRUNCATE, 0 },
9095
9096 /* Directory inode has a missing block (hole) */
9097 { PR_2_DIRECTORY_HOLE,
9098 N_("@d @i %i has an unallocated @b #%B. "),
9099 PROMPT_ALLOCATE, 0 },
9100
9101 /* '.' is not NULL terminated */
9102 { PR_2_DOT_NULL_TERM,
9103 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9104 PROMPT_FIX, 0 },
9105
9106 /* '..' is not NULL terminated */
9107 { PR_2_DOT_DOT_NULL_TERM,
9108 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9109 PROMPT_FIX, 0 },
9110
9111 /* Illegal character device inode */
9112 { PR_2_BAD_CHAR_DEV,
9113 N_("@i %i (%Q) is an @I character @v.\n"),
9114 PROMPT_CLEAR, 0 },
9115
9116 /* Illegal block device inode */
9117 { PR_2_BAD_BLOCK_DEV,
9118 N_("@i %i (%Q) is an @I @b @v.\n"),
9119 PROMPT_CLEAR, 0 },
9120
9121 /* Duplicate '.' entry */
9122 { PR_2_DUP_DOT,
9123 N_("@E is duplicate '.' @e.\n"),
9124 PROMPT_FIX, 0 },
9125
9126 /* Duplicate '..' entry */
9127 { PR_2_DUP_DOT_DOT,
9128 N_("@E is duplicate '..' @e.\n"),
9129 PROMPT_FIX, 0 },
9130
9131 /* Internal error: couldn't find dir_info */
9132 { PR_2_NO_DIRINFO,
9133 N_("Internal error: cannot find dir_info for %i.\n"),
9134 PROMPT_NONE, PR_FATAL },
9135
9136 /* Final rec_len is wrong */
9137 { PR_2_FINAL_RECLEN,
9138 N_("@E has rec_len of %Dr, @s %N.\n"),
9139 PROMPT_FIX, 0 },
9140
9141 /* Error allocating icount structure */
9142 { PR_2_ALLOCATE_ICOUNT,
9143 N_("@A icount structure: %m\n"),
9144 PROMPT_NONE, PR_FATAL },
9145
9146 /* Error iterating over directory blocks */
9147 { PR_2_DBLIST_ITERATE,
9148 N_("Error iterating over @d @bs: %m\n"),
9149 PROMPT_NONE, PR_FATAL },
9150
9151 /* Error reading directory block */
9152 { PR_2_READ_DIRBLOCK,
9153 N_("Error reading @d @b %b (@i %i): %m\n"),
9154 PROMPT_CONTINUE, 0 },
9155
9156 /* Error writing directory block */
9157 { PR_2_WRITE_DIRBLOCK,
9158 N_("Error writing @d @b %b (@i %i): %m\n"),
9159 PROMPT_CONTINUE, 0 },
9160
9161 /* Error allocating new directory block */
9162 { PR_2_ALLOC_DIRBOCK,
9163 N_("@A new @d @b for @i %i (%s): %m\n"),
9164 PROMPT_NONE, 0 },
9165
9166 /* Error deallocating inode */
9167 { PR_2_DEALLOC_INODE,
9168 N_("Error deallocating @i %i: %m\n"),
9169 PROMPT_NONE, PR_FATAL },
9170
9171 /* Directory entry for '.' is big. Split? */
9172 { PR_2_SPLIT_DOT,
9173 N_("@d @e for '.' is big. "),
9174 PROMPT_SPLIT, PR_NO_OK },
9175
9176 /* Illegal FIFO inode */
9177 { PR_2_BAD_FIFO,
9178 N_("@i %i (%Q) is an @I FIFO.\n"),
9179 PROMPT_CLEAR, 0 },
9180
9181 /* Illegal socket inode */
9182 { PR_2_BAD_SOCKET,
9183 N_("@i %i (%Q) is an @I socket.\n"),
9184 PROMPT_CLEAR, 0 },
9185
9186 /* Directory filetype not set */
9187 { PR_2_SET_FILETYPE,
9188 N_("Setting filetype for @E to %N.\n"),
9189 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9190
9191 /* Directory filetype incorrect */
9192 { PR_2_BAD_FILETYPE,
9193 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9194 PROMPT_FIX, 0 },
9195
9196 /* Directory filetype set on filesystem */
9197 { PR_2_CLEAR_FILETYPE,
9198 N_("@E has filetype set.\n"),
9199 PROMPT_CLEAR, PR_PREEN_OK },
9200
9201 /* Directory filename is null */
9202 { PR_2_NULL_NAME,
9203 N_("@E has a @z name.\n"),
9204 PROMPT_CLEAR, 0 },
9205
9206 /* Invalid symlink */
9207 { PR_2_INVALID_SYMLINK,
9208 N_("Symlink %Q (@i #%i) is @n.\n"),
9209 PROMPT_CLEAR, 0 },
9210
9211 /* i_file_acl (extended attribute block) is bad */
9212 { PR_2_FILE_ACL_BAD,
9213 N_("@a @b @F @n (%If).\n"),
9214 PROMPT_CLEAR, 0 },
9215
9216 /* Filesystem contains large files, but has no such flag in sb */
9217 { PR_2_FEATURE_LARGE_FILES,
9218 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9219 PROMPT_FIX, 0 },
9220
9221 /* Node in HTREE directory not referenced */
9222 { PR_2_HTREE_NOTREF,
9223 N_("@p @h %d: node (%B) not referenced\n"),
9224 PROMPT_NONE, 0 },
9225
9226 /* Node in HTREE directory referenced twice */
9227 { PR_2_HTREE_DUPREF,
9228 N_("@p @h %d: node (%B) referenced twice\n"),
9229 PROMPT_NONE, 0 },
9230
9231 /* Node in HTREE directory has bad min hash */
9232 { PR_2_HTREE_MIN_HASH,
9233 N_("@p @h %d: node (%B) has bad min hash\n"),
9234 PROMPT_NONE, 0 },
9235
9236 /* Node in HTREE directory has bad max hash */
9237 { PR_2_HTREE_MAX_HASH,
9238 N_("@p @h %d: node (%B) has bad max hash\n"),
9239 PROMPT_NONE, 0 },
9240
9241 /* Clear invalid HTREE directory */
9242 { PR_2_HTREE_CLEAR,
9243 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9244
9245 /* Bad block in htree interior node */
9246 { PR_2_HTREE_BADBLK,
9247 N_("@p @h %d (%q): bad @b number %b.\n"),
9248 PROMPT_CLEAR_HTREE, 0 },
9249
9250 /* Error adjusting EA refcount */
9251 { PR_2_ADJ_EA_REFCOUNT,
9252 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9253 PROMPT_NONE, PR_FATAL },
9254
9255 /* Invalid HTREE root node */
9256 { PR_2_HTREE_BAD_ROOT,
9257 N_("@p @h %d: root node is @n\n"),
9258 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9259
9260 /* Invalid HTREE limit */
9261 { PR_2_HTREE_BAD_LIMIT,
9262 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9263 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9264
9265 /* Invalid HTREE count */
9266 { PR_2_HTREE_BAD_COUNT,
9267 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9268 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9269
9270 /* HTREE interior node has out-of-order hashes in table */
9271 { PR_2_HTREE_HASH_ORDER,
9272 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9273 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9274
9275 /* Node in HTREE directory has invalid depth */
9276 { PR_2_HTREE_BAD_DEPTH,
9277 N_("@p @h %d: node (%B) has @n depth\n"),
9278 PROMPT_NONE, 0 },
9279
9280 /* Duplicate directory entry found */
9281 { PR_2_DUPLICATE_DIRENT,
9282 N_("Duplicate @E found. "),
9283 PROMPT_CLEAR, 0 },
9284
9285 /* Non-unique filename found */
9286 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9287 N_("@E has a non-unique filename.\nRename to %s"),
9288 PROMPT_NULL, 0 },
9289
9290 /* Duplicate directory entry found */
9291 { PR_2_REPORT_DUP_DIRENT,
9292 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9293 PROMPT_NONE, 0 },
9294
9295 /* Pass 3 errors */
9296
9297 /* Pass 3: Checking directory connectivity */
9298 { PR_3_PASS_HEADER,
9299 N_("Pass 3: Checking @d connectivity\n"),
9300 PROMPT_NONE, 0 },
9301
9302 /* Root inode not allocated */
9303 { PR_3_NO_ROOT_INODE,
9304 N_("@r not allocated. "),
9305 PROMPT_ALLOCATE, 0 },
9306
9307 /* No room in lost+found */
9308 { PR_3_EXPAND_LF_DIR,
9309 N_("No room in @l @d. "),
9310 PROMPT_EXPAND, 0 },
9311
9312 /* Unconnected directory inode */
9313 { PR_3_UNCONNECTED_DIR,
9314 N_("Unconnected @d @i %i (%p)\n"),
9315 PROMPT_CONNECT, 0 },
9316
9317 /* /lost+found not found */
9318 { PR_3_NO_LF_DIR,
9319 N_("/@l not found. "),
9320 PROMPT_CREATE, PR_PREEN_OK },
9321
9322 /* .. entry is incorrect */
9323 { PR_3_BAD_DOT_DOT,
9324 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9325 PROMPT_FIX, 0 },
9326
9327 /* Bad or non-existent /lost+found. Cannot reconnect */
9328 { PR_3_NO_LPF,
9329 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9330 PROMPT_NONE, 0 },
9331
9332 /* Could not expand /lost+found */
9333 { PR_3_CANT_EXPAND_LPF,
9334 N_("Could not expand /@l: %m\n"),
9335 PROMPT_NONE, 0 },
9336
9337 /* Could not reconnect inode */
9338 { PR_3_CANT_RECONNECT,
9339 N_("Could not reconnect %i: %m\n"),
9340 PROMPT_NONE, 0 },
9341
9342 /* Error while trying to find /lost+found */
9343 { PR_3_ERR_FIND_LPF,
9344 N_("Error while trying to find /@l: %m\n"),
9345 PROMPT_NONE, 0 },
9346
9347 /* Error in ext2fs_new_block while creating /lost+found */
9348 { PR_3_ERR_LPF_NEW_BLOCK,
9349 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9350 PROMPT_NONE, 0 },
9351
9352 /* Error in ext2fs_new_inode while creating /lost+found */
9353 { PR_3_ERR_LPF_NEW_INODE,
9354 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9355 PROMPT_NONE, 0 },
9356
9357 /* Error in ext2fs_new_dir_block while creating /lost+found */
9358 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9359 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9360 PROMPT_NONE, 0 },
9361
9362 /* Error while writing directory block for /lost+found */
9363 { PR_3_ERR_LPF_WRITE_BLOCK,
9364 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9365 PROMPT_NONE, 0 },
9366
9367 /* Error while adjusting inode count */
9368 { PR_3_ADJUST_INODE,
9369 N_("Error while adjusting @i count on @i %i\n"),
9370 PROMPT_NONE, 0 },
9371
9372 /* Couldn't fix parent directory -- error */
9373 { PR_3_FIX_PARENT_ERR,
9374 N_("Couldn't fix parent of @i %i: %m\n\n"),
9375 PROMPT_NONE, 0 },
9376
9377 /* Couldn't fix parent directory -- couldn't find it */
9378 { PR_3_FIX_PARENT_NOFIND,
9379 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9380 PROMPT_NONE, 0 },
9381
9382 /* Error allocating inode bitmap */
9383 { PR_3_ALLOCATE_IBITMAP_ERROR,
9384 N_("@A @i @B (%N): %m\n"),
9385 PROMPT_NONE, PR_FATAL },
9386
9387 /* Error creating root directory */
9388 { PR_3_CREATE_ROOT_ERROR,
9389 N_("Error creating root @d (%s): %m\n"),
9390 PROMPT_NONE, PR_FATAL },
9391
9392 /* Error creating lost and found directory */
9393 { PR_3_CREATE_LPF_ERROR,
9394 N_("Error creating /@l @d (%s): %m\n"),
9395 PROMPT_NONE, PR_FATAL },
9396
9397 /* Root inode is not directory; aborting */
9398 { PR_3_ROOT_NOT_DIR_ABORT,
9399 N_("@r is not a @d; aborting.\n"),
9400 PROMPT_NONE, PR_FATAL },
9401
9402 /* Cannot proceed without a root inode. */
9403 { PR_3_NO_ROOT_INODE_ABORT,
Denys Vlasenko6331cf02009-11-13 09:08:27 +01009404 N_("can't proceed without a @r.\n"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009405 PROMPT_NONE, PR_FATAL },
9406
9407 /* Internal error: couldn't find dir_info */
9408 { PR_3_NO_DIRINFO,
9409 N_("Internal error: cannot find dir_info for %i.\n"),
9410 PROMPT_NONE, PR_FATAL },
9411
9412 /* Lost+found not a directory */
9413 { PR_3_LPF_NOTDIR,
9414 N_("/@l is not a @d (ino=%i)\n"),
9415 PROMPT_UNLINK, 0 },
9416
9417 /* Pass 3A Directory Optimization */
9418
9419 /* Pass 3A: Optimizing directories */
9420 { PR_3A_PASS_HEADER,
9421 N_("Pass 3A: Optimizing directories\n"),
9422 PROMPT_NONE, PR_PREEN_NOMSG },
9423
9424 /* Error iterating over directories */
9425 { PR_3A_OPTIMIZE_ITER,
9426 N_("Failed to create dirs_to_hash iterator: %m"),
9427 PROMPT_NONE, 0 },
9428
9429 /* Error rehash directory */
9430 { PR_3A_OPTIMIZE_DIR_ERR,
9431 N_("Failed to optimize directory %q (%d): %m"),
9432 PROMPT_NONE, 0 },
9433
9434 /* Rehashing dir header */
9435 { PR_3A_OPTIMIZE_DIR_HEADER,
9436 N_("Optimizing directories: "),
9437 PROMPT_NONE, PR_MSG_ONLY },
9438
9439 /* Rehashing directory %d */
9440 { PR_3A_OPTIMIZE_DIR,
9441 " %d",
9442 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9443
9444 /* Rehashing dir end */
9445 { PR_3A_OPTIMIZE_DIR_END,
9446 "\n",
9447 PROMPT_NONE, PR_PREEN_NOHDR },
9448
9449 /* Pass 4 errors */
9450
9451 /* Pass 4: Checking reference counts */
9452 { PR_4_PASS_HEADER,
9453 N_("Pass 4: Checking reference counts\n"),
9454 PROMPT_NONE, 0 },
9455
9456 /* Unattached zero-length inode */
9457 { PR_4_ZERO_LEN_INODE,
9458 N_("@u @z @i %i. "),
9459 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9460
9461 /* Unattached inode */
9462 { PR_4_UNATTACHED_INODE,
9463 N_("@u @i %i\n"),
9464 PROMPT_CONNECT, 0 },
9465
9466 /* Inode ref count wrong */
9467 { PR_4_BAD_REF_COUNT,
9468 N_("@i %i ref count is %Il, @s %N. "),
9469 PROMPT_FIX, PR_PREEN_OK },
9470
9471 { PR_4_INCONSISTENT_COUNT,
9472 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9473 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9474 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9475 "They @s the same!\n"),
9476 PROMPT_NONE, 0 },
9477
9478 /* Pass 5 errors */
9479
9480 /* Pass 5: Checking group summary information */
9481 { PR_5_PASS_HEADER,
9482 N_("Pass 5: Checking @g summary information\n"),
9483 PROMPT_NONE, 0 },
9484
9485 /* Padding at end of inode bitmap is not set. */
9486 { PR_5_INODE_BMAP_PADDING,
9487 N_("Padding at end of @i @B is not set. "),
9488 PROMPT_FIX, PR_PREEN_OK },
9489
9490 /* Padding at end of block bitmap is not set. */
9491 { PR_5_BLOCK_BMAP_PADDING,
9492 N_("Padding at end of @b @B is not set. "),
9493 PROMPT_FIX, PR_PREEN_OK },
9494
9495 /* Block bitmap differences header */
9496 { PR_5_BLOCK_BITMAP_HEADER,
9497 N_("@b @B differences: "),
9498 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9499
9500 /* Block not used, but marked in bitmap */
9501 { PR_5_BLOCK_UNUSED,
9502 " -%b",
9503 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9504
9505 /* Block used, but not marked used in bitmap */
9506 { PR_5_BLOCK_USED,
9507 " +%b",
9508 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9509
9510 /* Block bitmap differences end */
9511 { PR_5_BLOCK_BITMAP_END,
9512 "\n",
9513 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9514
9515 /* Inode bitmap differences header */
9516 { PR_5_INODE_BITMAP_HEADER,
9517 N_("@i @B differences: "),
9518 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9519
9520 /* Inode not used, but marked in bitmap */
9521 { PR_5_INODE_UNUSED,
9522 " -%i",
9523 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9524
9525 /* Inode used, but not marked used in bitmap */
9526 { PR_5_INODE_USED,
9527 " +%i",
9528 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9529
9530 /* Inode bitmap differences end */
9531 { PR_5_INODE_BITMAP_END,
9532 "\n",
9533 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9534
9535 /* Free inodes count for group wrong */
9536 { PR_5_FREE_INODE_COUNT_GROUP,
9537 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9538 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9539
9540 /* Directories count for group wrong */
9541 { PR_5_FREE_DIR_COUNT_GROUP,
9542 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9543 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9544
9545 /* Free inodes count wrong */
9546 { PR_5_FREE_INODE_COUNT,
9547 N_("Free @is count wrong (%i, counted=%j).\n"),
9548 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9549
9550 /* Free blocks count for group wrong */
9551 { PR_5_FREE_BLOCK_COUNT_GROUP,
9552 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9553 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9554
9555 /* Free blocks count wrong */
9556 { PR_5_FREE_BLOCK_COUNT,
9557 N_("Free @bs count wrong (%b, counted=%c).\n"),
9558 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9559
9560 /* Programming error: bitmap endpoints don't match */
9561 { PR_5_BMAP_ENDPOINTS,
9562 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9563 "match calculated @B endpoints (%i, %j)\n"),
9564 PROMPT_NONE, PR_FATAL },
9565
9566 /* Internal error: fudging end of bitmap */
9567 { PR_5_FUDGE_BITMAP_ERROR,
9568 N_("Internal error: fudging end of bitmap (%N)\n"),
9569 PROMPT_NONE, PR_FATAL },
9570
9571 /* Error copying in replacement inode bitmap */
9572 { PR_5_COPY_IBITMAP_ERROR,
9573 N_("Error copying in replacement @i @B: %m\n"),
9574 PROMPT_NONE, PR_FATAL },
9575
9576 /* Error copying in replacement block bitmap */
9577 { PR_5_COPY_BBITMAP_ERROR,
9578 N_("Error copying in replacement @b @B: %m\n"),
9579 PROMPT_NONE, PR_FATAL },
9580
9581 /* Block range not used, but marked in bitmap */
9582 { PR_5_BLOCK_RANGE_UNUSED,
9583 " -(%b--%c)",
9584 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9585
9586 /* Block range used, but not marked used in bitmap */
9587 { PR_5_BLOCK_RANGE_USED,
9588 " +(%b--%c)",
9589 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9590
9591 /* Inode range not used, but marked in bitmap */
9592 { PR_5_INODE_RANGE_UNUSED,
9593 " -(%i--%j)",
9594 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9595
9596 /* Inode range used, but not marked used in bitmap */
9597 { PR_5_INODE_RANGE_USED,
9598 " +(%i--%j)",
9599 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9600
9601 { 0 }
9602};
9603
9604/*
9605 * This is the latch flags register. It allows several problems to be
9606 * "latched" together. This means that the user has to answer but one
9607 * question for the set of problems, and all of the associated
9608 * problems will be either fixed or not fixed.
9609 */
9610static struct latch_descr pr_latch_info[] = {
9611 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9612 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9613 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9614 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9615 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9616 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9617 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9618 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9619 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9620 { -1, 0, 0 },
9621};
9622
9623static const struct e2fsck_problem *find_problem(problem_t code)
9624{
9625 int i;
9626
9627 for (i=0; problem_table[i].e2p_code; i++) {
9628 if (problem_table[i].e2p_code == code)
9629 return &problem_table[i];
9630 }
9631 return 0;
9632}
9633
9634static struct latch_descr *find_latch(int code)
9635{
9636 int i;
9637
9638 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9639 if (pr_latch_info[i].latch_code == code)
9640 return &pr_latch_info[i];
9641 }
9642 return 0;
9643}
9644
9645int end_problem_latch(e2fsck_t ctx, int mask)
9646{
9647 struct latch_descr *ldesc;
9648 struct problem_context pctx;
9649 int answer = -1;
9650
9651 ldesc = find_latch(mask);
9652 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9653 clear_problem_context(&pctx);
9654 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9655 }
9656 ldesc->flags &= ~(PRL_VARIABLE);
9657 return answer;
9658}
9659
9660int set_latch_flags(int mask, int setflags, int clearflags)
9661{
9662 struct latch_descr *ldesc;
9663
9664 ldesc = find_latch(mask);
9665 if (!ldesc)
9666 return -1;
9667 ldesc->flags |= setflags;
9668 ldesc->flags &= ~clearflags;
9669 return 0;
9670}
9671
9672void clear_problem_context(struct problem_context *ctx)
9673{
9674 memset(ctx, 0, sizeof(struct problem_context));
9675 ctx->blkcount = -1;
9676 ctx->group = -1;
9677}
9678
9679int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9680{
9681 ext2_filsys fs = ctx->fs;
9682 const struct e2fsck_problem *ptr;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +01009683 struct latch_descr *ldesc = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009684 const char *message;
9685 int def_yn, answer, ans;
9686 int print_answer = 0;
9687 int suppress = 0;
9688
9689 ptr = find_problem(code);
9690 if (!ptr) {
9691 printf(_("Unhandled error code (0x%x)!\n"), code);
9692 return 0;
9693 }
9694 def_yn = 1;
9695 if ((ptr->flags & PR_NO_DEFAULT) ||
9696 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9697 (ctx->options & E2F_OPT_NO))
9698 def_yn= 0;
9699
9700 /*
9701 * Do special latch processing. This is where we ask the
9702 * latch question, if it exists
9703 */
9704 if (ptr->flags & PR_LATCH_MASK) {
9705 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9706 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9707 ans = fix_problem(ctx, ldesc->question, pctx);
9708 if (ans == 1)
9709 ldesc->flags |= PRL_YES;
9710 if (ans == 0)
9711 ldesc->flags |= PRL_NO;
9712 ldesc->flags |= PRL_LATCHED;
9713 }
9714 if (ldesc->flags & PRL_SUPPRESS)
9715 suppress++;
9716 }
9717 if ((ptr->flags & PR_PREEN_NOMSG) &&
9718 (ctx->options & E2F_OPT_PREEN))
9719 suppress++;
9720 if ((ptr->flags & PR_NO_NOMSG) &&
9721 (ctx->options & E2F_OPT_NO))
9722 suppress++;
9723 if (!suppress) {
9724 message = ptr->e2p_description;
9725 if ((ctx->options & E2F_OPT_PREEN) &&
9726 !(ptr->flags & PR_PREEN_NOHDR)) {
9727 printf("%s: ", ctx->device_name ?
9728 ctx->device_name : ctx->filesystem_name);
9729 }
9730 if (*message)
9731 print_e2fsck_message(ctx, _(message), pctx, 1);
9732 }
9733 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9734 preenhalt(ctx);
9735
9736 if (ptr->flags & PR_FATAL)
9737 bb_error_msg_and_die(0);
9738
9739 if (ptr->prompt == PROMPT_NONE) {
9740 if (ptr->flags & PR_NOCOLLATE)
9741 answer = -1;
9742 else
9743 answer = def_yn;
9744 } else {
9745 if (ctx->options & E2F_OPT_PREEN) {
9746 answer = def_yn;
9747 if (!(ptr->flags & PR_PREEN_NOMSG))
9748 print_answer = 1;
9749 } else if ((ptr->flags & PR_LATCH_MASK) &&
9750 (ldesc->flags & (PRL_YES | PRL_NO))) {
9751 if (!suppress)
9752 print_answer = 1;
9753 if (ldesc->flags & PRL_YES)
9754 answer = 1;
9755 else
9756 answer = 0;
9757 } else
9758 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9759 if (!answer && !(ptr->flags & PR_NO_OK))
9760 ext2fs_unmark_valid(fs);
9761
9762 if (print_answer)
9763 printf("%s.\n", answer ?
9764 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009765 }
9766
9767 if ((ptr->prompt == PROMPT_ABORT) && answer)
9768 bb_error_msg_and_die(0);
9769
9770 if (ptr->flags & PR_AFTER_CODE)
9771 answer = fix_problem(ctx, ptr->second_code, pctx);
9772
9773 return answer;
9774}
9775
9776/*
9777 * linux/fs/recovery.c
9778 *
9779 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9780 */
9781
9782/*
9783 * Maintain information about the progress of the recovery job, so that
9784 * the different passes can carry information between them.
9785 */
9786struct recovery_info
9787{
9788 tid_t start_transaction;
9789 tid_t end_transaction;
9790
9791 int nr_replays;
9792 int nr_revokes;
9793 int nr_revoke_hits;
9794};
9795
9796enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9797static int do_one_pass(journal_t *journal,
9798 struct recovery_info *info, enum passtype pass);
9799static int scan_revoke_records(journal_t *, struct buffer_head *,
9800 tid_t, struct recovery_info *);
9801
9802/*
9803 * Read a block from the journal
9804 */
9805
9806static int jread(struct buffer_head **bhp, journal_t *journal,
9807 unsigned int offset)
9808{
9809 int err;
9810 unsigned long blocknr;
9811 struct buffer_head *bh;
9812
9813 *bhp = NULL;
9814
9815 err = journal_bmap(journal, offset, &blocknr);
9816
9817 if (err) {
9818 printf("JBD: bad block at offset %u\n", offset);
9819 return err;
9820 }
9821
9822 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9823 if (!bh)
9824 return -ENOMEM;
9825
9826 if (!buffer_uptodate(bh)) {
9827 /* If this is a brand new buffer, start readahead.
9828 Otherwise, we assume we are already reading it. */
9829 if (!buffer_req(bh))
9830 do_readahead(journal, offset);
9831 wait_on_buffer(bh);
9832 }
9833
9834 if (!buffer_uptodate(bh)) {
9835 printf("JBD: Failed to read block at offset %u\n", offset);
9836 brelse(bh);
9837 return -EIO;
9838 }
9839
9840 *bhp = bh;
9841 return 0;
9842}
9843
9844
9845/*
9846 * Count the number of in-use tags in a journal descriptor block.
9847 */
9848
9849static int count_tags(struct buffer_head *bh, int size)
9850{
9851 char * tagp;
9852 journal_block_tag_t * tag;
9853 int nr = 0;
9854
9855 tagp = &bh->b_data[sizeof(journal_header_t)];
9856
9857 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9858 tag = (journal_block_tag_t *) tagp;
9859
9860 nr++;
9861 tagp += sizeof(journal_block_tag_t);
9862 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9863 tagp += 16;
9864
9865 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9866 break;
9867 }
9868
9869 return nr;
9870}
9871
9872
9873/* Make sure we wrap around the log correctly! */
9874#define wrap(journal, var) \
9875do { \
9876 if (var >= (journal)->j_last) \
9877 var -= ((journal)->j_last - (journal)->j_first); \
9878} while (0)
9879
9880/**
9881 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9882 * @journal: the journal to recover
9883 *
9884 * The primary function for recovering the log contents when mounting a
9885 * journaled device.
9886 *
9887 * Recovery is done in three passes. In the first pass, we look for the
9888 * end of the log. In the second, we assemble the list of revoke
9889 * blocks. In the third and final pass, we replay any un-revoked blocks
9890 * in the log.
9891 */
9892int journal_recover(journal_t *journal)
9893{
9894 int err;
9895 journal_superblock_t * sb;
9896
9897 struct recovery_info info;
9898
9899 memset(&info, 0, sizeof(info));
9900 sb = journal->j_superblock;
9901
9902 /*
9903 * The journal superblock's s_start field (the current log head)
9904 * is always zero if, and only if, the journal was cleanly
9905 * unmounted.
9906 */
9907
9908 if (!sb->s_start) {
9909 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9910 return 0;
9911 }
9912
9913 err = do_one_pass(journal, &info, PASS_SCAN);
9914 if (!err)
9915 err = do_one_pass(journal, &info, PASS_REVOKE);
9916 if (!err)
9917 err = do_one_pass(journal, &info, PASS_REPLAY);
9918
9919 /* Restart the log at the next transaction ID, thus invalidating
9920 * any existing commit records in the log. */
9921 journal->j_transaction_sequence = ++info.end_transaction;
9922
9923 journal_clear_revoke(journal);
9924 sync_blockdev(journal->j_fs_dev);
9925 return err;
9926}
9927
9928static int do_one_pass(journal_t *journal,
9929 struct recovery_info *info, enum passtype pass)
9930{
9931 unsigned int first_commit_ID, next_commit_ID;
9932 unsigned long next_log_block;
9933 int err, success = 0;
9934 journal_superblock_t * sb;
9935 journal_header_t * tmp;
9936 struct buffer_head * bh;
9937 unsigned int sequence;
9938 int blocktype;
9939
9940 /* Precompute the maximum metadata descriptors in a descriptor block */
9941 int MAX_BLOCKS_PER_DESC;
9942 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9943 / sizeof(journal_block_tag_t));
9944
9945 /*
9946 * First thing is to establish what we expect to find in the log
9947 * (in terms of transaction IDs), and where (in terms of log
9948 * block offsets): query the superblock.
9949 */
9950
9951 sb = journal->j_superblock;
9952 next_commit_ID = ntohl(sb->s_sequence);
9953 next_log_block = ntohl(sb->s_start);
9954
9955 first_commit_ID = next_commit_ID;
9956 if (pass == PASS_SCAN)
9957 info->start_transaction = first_commit_ID;
9958
9959 /*
9960 * Now we walk through the log, transaction by transaction,
9961 * making sure that each transaction has a commit block in the
9962 * expected place. Each complete transaction gets replayed back
9963 * into the main filesystem.
9964 */
9965
9966 while (1) {
9967 int flags;
9968 char * tagp;
9969 journal_block_tag_t * tag;
9970 struct buffer_head * obh;
9971 struct buffer_head * nbh;
9972
9973 /* If we already know where to stop the log traversal,
9974 * check right now that we haven't gone past the end of
9975 * the log. */
9976
9977 if (pass != PASS_SCAN)
9978 if (tid_geq(next_commit_ID, info->end_transaction))
9979 break;
9980
9981 /* Skip over each chunk of the transaction looking
9982 * either the next descriptor block or the final commit
9983 * record. */
9984
9985 err = jread(&bh, journal, next_log_block);
9986 if (err)
9987 goto failed;
9988
9989 next_log_block++;
9990 wrap(journal, next_log_block);
9991
9992 /* What kind of buffer is it?
9993 *
9994 * If it is a descriptor block, check that it has the
9995 * expected sequence number. Otherwise, we're all done
9996 * here. */
9997
9998 tmp = (journal_header_t *)bh->b_data;
9999
10000 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
10001 brelse(bh);
10002 break;
10003 }
10004
10005 blocktype = ntohl(tmp->h_blocktype);
10006 sequence = ntohl(tmp->h_sequence);
10007
10008 if (sequence != next_commit_ID) {
10009 brelse(bh);
10010 break;
10011 }
10012
10013 /* OK, we have a valid descriptor block which matches
10014 * all of the sequence number checks. What are we going
10015 * to do with it? That depends on the pass... */
10016
Denis Vlasenkobb045062008-09-27 14:06:06 +000010017 switch (blocktype) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010018 case JFS_DESCRIPTOR_BLOCK:
10019 /* If it is a valid descriptor block, replay it
10020 * in pass REPLAY; otherwise, just skip over the
10021 * blocks it describes. */
10022 if (pass != PASS_REPLAY) {
10023 next_log_block +=
10024 count_tags(bh, journal->j_blocksize);
10025 wrap(journal, next_log_block);
10026 brelse(bh);
10027 continue;
10028 }
10029
10030 /* A descriptor block: we can now write all of
10031 * the data blocks. Yay, useful work is finally
10032 * getting done here! */
10033
10034 tagp = &bh->b_data[sizeof(journal_header_t)];
10035 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10036 <= journal->j_blocksize) {
10037 unsigned long io_block;
10038
10039 tag = (journal_block_tag_t *) tagp;
10040 flags = ntohl(tag->t_flags);
10041
10042 io_block = next_log_block++;
10043 wrap(journal, next_log_block);
10044 err = jread(&obh, journal, io_block);
10045 if (err) {
10046 /* Recover what we can, but
10047 * report failure at the end. */
10048 success = err;
10049 printf("JBD: IO error %d recovering "
10050 "block %ld in log\n",
10051 err, io_block);
10052 } else {
10053 unsigned long blocknr;
10054
10055 blocknr = ntohl(tag->t_blocknr);
10056
10057 /* If the block has been
10058 * revoked, then we're all done
10059 * here. */
10060 if (journal_test_revoke
10061 (journal, blocknr,
10062 next_commit_ID)) {
10063 brelse(obh);
10064 ++info->nr_revoke_hits;
10065 goto skip_write;
10066 }
10067
10068 /* Find a buffer for the new
10069 * data being restored */
10070 nbh = getblk(journal->j_fs_dev,
10071 blocknr,
10072 journal->j_blocksize);
10073 if (nbh == NULL) {
10074 printf("JBD: Out of memory "
10075 "during recovery.\n");
10076 err = -ENOMEM;
10077 brelse(bh);
10078 brelse(obh);
10079 goto failed;
10080 }
10081
10082 lock_buffer(nbh);
10083 memcpy(nbh->b_data, obh->b_data,
10084 journal->j_blocksize);
10085 if (flags & JFS_FLAG_ESCAPE) {
10086 *((unsigned int *)bh->b_data) =
10087 htonl(JFS_MAGIC_NUMBER);
10088 }
10089
10090 mark_buffer_uptodate(nbh, 1);
10091 mark_buffer_dirty(nbh);
10092 ++info->nr_replays;
10093 /* ll_rw_block(WRITE, 1, &nbh); */
10094 unlock_buffer(nbh);
10095 brelse(obh);
10096 brelse(nbh);
10097 }
10098
10099 skip_write:
10100 tagp += sizeof(journal_block_tag_t);
10101 if (!(flags & JFS_FLAG_SAME_UUID))
10102 tagp += 16;
10103
10104 if (flags & JFS_FLAG_LAST_TAG)
10105 break;
10106 }
10107
10108 brelse(bh);
10109 continue;
10110
10111 case JFS_COMMIT_BLOCK:
10112 /* Found an expected commit block: not much to
10113 * do other than move on to the next sequence
10114 * number. */
10115 brelse(bh);
10116 next_commit_ID++;
10117 continue;
10118
10119 case JFS_REVOKE_BLOCK:
10120 /* If we aren't in the REVOKE pass, then we can
10121 * just skip over this block. */
10122 if (pass != PASS_REVOKE) {
10123 brelse(bh);
10124 continue;
10125 }
10126
10127 err = scan_revoke_records(journal, bh,
10128 next_commit_ID, info);
10129 brelse(bh);
10130 if (err)
10131 goto failed;
10132 continue;
10133
10134 default:
10135 goto done;
10136 }
10137 }
10138
10139 done:
10140 /*
10141 * We broke out of the log scan loop: either we came to the
10142 * known end of the log or we found an unexpected block in the
10143 * log. If the latter happened, then we know that the "current"
10144 * transaction marks the end of the valid log.
10145 */
10146
10147 if (pass == PASS_SCAN)
10148 info->end_transaction = next_commit_ID;
10149 else {
10150 /* It's really bad news if different passes end up at
10151 * different places (but possible due to IO errors). */
10152 if (info->end_transaction != next_commit_ID) {
10153 printf("JBD: recovery pass %d ended at "
10154 "transaction %u, expected %u\n",
10155 pass, next_commit_ID, info->end_transaction);
10156 if (!success)
10157 success = -EIO;
10158 }
10159 }
10160
10161 return success;
10162
10163 failed:
10164 return err;
10165}
10166
10167
10168/* Scan a revoke record, marking all blocks mentioned as revoked. */
10169
10170static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10171 tid_t sequence, struct recovery_info *info)
10172{
10173 journal_revoke_header_t *header;
10174 int offset, max;
10175
10176 header = (journal_revoke_header_t *) bh->b_data;
10177 offset = sizeof(journal_revoke_header_t);
10178 max = ntohl(header->r_count);
10179
10180 while (offset < max) {
10181 unsigned long blocknr;
10182 int err;
10183
10184 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10185 offset += 4;
10186 err = journal_set_revoke(journal, blocknr, sequence);
10187 if (err)
10188 return err;
10189 ++info->nr_revokes;
10190 }
10191 return 0;
10192}
10193
10194
10195/*
10196 * rehash.c --- rebuild hash tree directories
10197 *
10198 * This algorithm is designed for simplicity of implementation and to
10199 * pack the directory as much as possible. It however requires twice
10200 * as much memory as the size of the directory. The maximum size
10201 * directory supported using a 4k blocksize is roughly a gigabyte, and
10202 * so there may very well be problems with machines that don't have
10203 * virtual memory, and obscenely large directories.
10204 *
10205 * An alternate algorithm which is much more disk intensive could be
10206 * written, and probably will need to be written in the future. The
10207 * design goals of such an algorithm are: (a) use (roughly) constant
10208 * amounts of memory, no matter how large the directory, (b) the
10209 * directory must be safe at all times, even if e2fsck is interrupted
10210 * in the middle, (c) we must use minimal amounts of extra disk
10211 * blocks. This pretty much requires an incremental approach, where
10212 * we are reading from one part of the directory, and inserting into
10213 * the front half. So the algorithm will have to keep track of a
10214 * moving block boundary between the new tree and the old tree, and
10215 * files will need to be moved from the old directory and inserted
10216 * into the new tree. If the new directory requires space which isn't
10217 * yet available, blocks from the beginning part of the old directory
10218 * may need to be moved to the end of the directory to make room for
10219 * the new tree:
10220 *
10221 * --------------------------------------------------------
10222 * | new tree | | old tree |
10223 * --------------------------------------------------------
10224 * ^ ptr ^ptr
10225 * tail new head old
10226 *
10227 * This is going to be a pain in the tuckus to implement, and will
10228 * require a lot more disk accesses. So I'm going to skip it for now;
10229 * it's only really going to be an issue for really, really big
10230 * filesystems (when we reach the level of tens of millions of files
10231 * in a single directory). It will probably be easier to simply
10232 * require that e2fsck use VM first.
10233 */
10234
10235struct fill_dir_struct {
10236 char *buf;
10237 struct ext2_inode *inode;
10238 int err;
10239 e2fsck_t ctx;
10240 struct hash_entry *harray;
10241 int max_array, num_array;
10242 int dir_size;
10243 int compress;
10244 ino_t parent;
10245};
10246
10247struct hash_entry {
10248 ext2_dirhash_t hash;
10249 ext2_dirhash_t minor_hash;
10250 struct ext2_dir_entry *dir;
10251};
10252
10253struct out_dir {
10254 int num;
10255 int max;
10256 char *buf;
10257 ext2_dirhash_t *hashes;
10258};
10259
10260static int fill_dir_block(ext2_filsys fs,
10261 blk_t *block_nr,
10262 e2_blkcnt_t blockcnt,
10263 blk_t ref_block FSCK_ATTR((unused)),
10264 int ref_offset FSCK_ATTR((unused)),
10265 void *priv_data)
10266{
10267 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10268 struct hash_entry *new_array, *ent;
10269 struct ext2_dir_entry *dirent;
10270 char *dir;
10271 unsigned int offset, dir_offset;
10272
10273 if (blockcnt < 0)
10274 return 0;
10275
10276 offset = blockcnt * fs->blocksize;
10277 if (offset + fs->blocksize > fd->inode->i_size) {
10278 fd->err = EXT2_ET_DIR_CORRUPTED;
10279 return BLOCK_ABORT;
10280 }
10281 dir = (fd->buf+offset);
10282 if (HOLE_BLKADDR(*block_nr)) {
10283 memset(dir, 0, fs->blocksize);
10284 dirent = (struct ext2_dir_entry *) dir;
10285 dirent->rec_len = fs->blocksize;
10286 } else {
10287 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10288 if (fd->err)
10289 return BLOCK_ABORT;
10290 }
10291 /* While the directory block is "hot", index it. */
10292 dir_offset = 0;
10293 while (dir_offset < fs->blocksize) {
10294 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10295 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10296 (dirent->rec_len < 8) ||
10297 ((dirent->rec_len % 4) != 0) ||
10298 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10299 fd->err = EXT2_ET_DIR_CORRUPTED;
10300 return BLOCK_ABORT;
10301 }
10302 dir_offset += dirent->rec_len;
10303 if (dirent->inode == 0)
10304 continue;
10305 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10306 (dirent->name[0] == '.'))
10307 continue;
10308 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10309 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10310 fd->parent = dirent->inode;
10311 continue;
10312 }
10313 if (fd->num_array >= fd->max_array) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010314 new_array = xrealloc(fd->harray,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010315 sizeof(struct hash_entry) * (fd->max_array+500));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010316 fd->harray = new_array;
10317 fd->max_array += 500;
10318 }
10319 ent = fd->harray + fd->num_array++;
10320 ent->dir = dirent;
10321 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10322 if (fd->compress)
10323 ent->hash = ent->minor_hash = 0;
10324 else {
10325 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10326 dirent->name,
10327 dirent->name_len & 0xFF,
10328 fs->super->s_hash_seed,
10329 &ent->hash, &ent->minor_hash);
10330 if (fd->err)
10331 return BLOCK_ABORT;
10332 }
10333 }
10334
10335 return 0;
10336}
10337
10338/* Used for sorting the hash entry */
10339static int name_cmp(const void *a, const void *b)
10340{
10341 const struct hash_entry *he_a = (const struct hash_entry *) a;
10342 const struct hash_entry *he_b = (const struct hash_entry *) b;
10343 int ret;
10344 int min_len;
10345
10346 min_len = he_a->dir->name_len;
10347 if (min_len > he_b->dir->name_len)
10348 min_len = he_b->dir->name_len;
10349
10350 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10351 if (ret == 0) {
10352 if (he_a->dir->name_len > he_b->dir->name_len)
10353 ret = 1;
10354 else if (he_a->dir->name_len < he_b->dir->name_len)
10355 ret = -1;
10356 else
10357 ret = he_b->dir->inode - he_a->dir->inode;
10358 }
10359 return ret;
10360}
10361
10362/* Used for sorting the hash entry */
10363static int hash_cmp(const void *a, const void *b)
10364{
10365 const struct hash_entry *he_a = (const struct hash_entry *) a;
10366 const struct hash_entry *he_b = (const struct hash_entry *) b;
10367 int ret;
10368
10369 if (he_a->hash > he_b->hash)
10370 ret = 1;
10371 else if (he_a->hash < he_b->hash)
10372 ret = -1;
10373 else {
10374 if (he_a->minor_hash > he_b->minor_hash)
10375 ret = 1;
10376 else if (he_a->minor_hash < he_b->minor_hash)
10377 ret = -1;
10378 else
10379 ret = name_cmp(a, b);
10380 }
10381 return ret;
10382}
10383
10384static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10385 int blocks)
10386{
10387 void *new_mem;
10388
10389 if (outdir->max) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010390 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010391 outdir->buf = new_mem;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010392 new_mem = xrealloc(outdir->hashes,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010393 blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010394 outdir->hashes = new_mem;
10395 } else {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010396 outdir->buf = xmalloc(blocks * fs->blocksize);
10397 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010398 outdir->num = 0;
10399 }
10400 outdir->max = blocks;
10401 return 0;
10402}
10403
10404static void free_out_dir(struct out_dir *outdir)
10405{
10406 free(outdir->buf);
10407 free(outdir->hashes);
10408 outdir->max = 0;
10409 outdir->num =0;
10410}
10411
10412static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10413 char ** ret)
10414{
10415 errcode_t retval;
10416
10417 if (outdir->num >= outdir->max) {
10418 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10419 if (retval)
10420 return retval;
10421 }
10422 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10423 memset(*ret, 0, fs->blocksize);
10424 return 0;
10425}
10426
10427/*
10428 * This function is used to make a unique filename. We do this by
10429 * appending ~0, and then incrementing the number. However, we cannot
10430 * expand the length of the filename beyond the padding available in
10431 * the directory entry.
10432 */
10433static void mutate_name(char *str, __u16 *len)
10434{
10435 int i;
10436 __u16 l = *len & 0xFF, h = *len & 0xff00;
10437
10438 /*
10439 * First check to see if it looks the name has been mutated
10440 * already
10441 */
10442 for (i = l-1; i > 0; i--) {
10443 if (!isdigit(str[i]))
10444 break;
10445 }
10446 if ((i == l-1) || (str[i] != '~')) {
10447 if (((l-1) & 3) < 2)
10448 l += 2;
10449 else
10450 l = (l+3) & ~3;
10451 str[l-2] = '~';
10452 str[l-1] = '0';
10453 *len = l | h;
10454 return;
10455 }
10456 for (i = l-1; i >= 0; i--) {
10457 if (isdigit(str[i])) {
10458 if (str[i] == '9')
10459 str[i] = '0';
10460 else {
10461 str[i]++;
10462 return;
10463 }
10464 continue;
10465 }
10466 if (i == 1) {
10467 if (str[0] == 'z')
10468 str[0] = 'A';
10469 else if (str[0] == 'Z') {
10470 str[0] = '~';
10471 str[1] = '0';
10472 } else
10473 str[0]++;
10474 } else if (i > 0) {
10475 str[i] = '1';
10476 str[i-1] = '~';
10477 } else {
10478 if (str[0] == '~')
10479 str[0] = 'a';
10480 else
10481 str[0]++;
10482 }
10483 break;
10484 }
10485}
10486
10487static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10488 ext2_ino_t ino,
10489 struct fill_dir_struct *fd)
10490{
10491 struct problem_context pctx;
10492 struct hash_entry *ent, *prev;
10493 int i, j;
10494 int fixed = 0;
10495 char new_name[256];
10496 __u16 new_len;
10497
10498 clear_problem_context(&pctx);
10499 pctx.ino = ino;
10500
10501 for (i=1; i < fd->num_array; i++) {
10502 ent = fd->harray + i;
10503 prev = ent - 1;
10504 if (!ent->dir->inode ||
10505 ((ent->dir->name_len & 0xFF) !=
10506 (prev->dir->name_len & 0xFF)) ||
10507 (strncmp(ent->dir->name, prev->dir->name,
10508 ent->dir->name_len & 0xFF)))
10509 continue;
10510 pctx.dirent = ent->dir;
10511 if ((ent->dir->inode == prev->dir->inode) &&
10512 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10513 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10514 ent->dir->inode = 0;
10515 fixed++;
10516 continue;
10517 }
10518 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10519 new_len = ent->dir->name_len;
10520 mutate_name(new_name, &new_len);
10521 for (j=0; j < fd->num_array; j++) {
10522 if ((i==j) ||
10523 ((ent->dir->name_len & 0xFF) !=
10524 (fd->harray[j].dir->name_len & 0xFF)) ||
10525 (strncmp(new_name, fd->harray[j].dir->name,
10526 new_len & 0xFF)))
10527 continue;
10528 mutate_name(new_name, &new_len);
10529
10530 j = -1;
10531 }
10532 new_name[new_len & 0xFF] = 0;
10533 pctx.str = new_name;
10534 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10535 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10536 ent->dir->name_len = new_len;
10537 ext2fs_dirhash(fs->super->s_def_hash_version,
10538 ent->dir->name,
10539 ent->dir->name_len & 0xFF,
10540 fs->super->s_hash_seed,
10541 &ent->hash, &ent->minor_hash);
10542 fixed++;
10543 }
10544 }
10545 return fixed;
10546}
10547
10548
10549static errcode_t copy_dir_entries(ext2_filsys fs,
10550 struct fill_dir_struct *fd,
10551 struct out_dir *outdir)
10552{
10553 errcode_t retval;
10554 char *block_start;
10555 struct hash_entry *ent;
10556 struct ext2_dir_entry *dirent;
10557 int i, rec_len, left;
10558 ext2_dirhash_t prev_hash;
10559 int offset;
10560
10561 outdir->max = 0;
10562 retval = alloc_size_dir(fs, outdir,
10563 (fd->dir_size / fs->blocksize) + 2);
10564 if (retval)
10565 return retval;
10566 outdir->num = fd->compress ? 0 : 1;
10567 offset = 0;
10568 outdir->hashes[0] = 0;
10569 prev_hash = 1;
10570 if ((retval = get_next_block(fs, outdir, &block_start)))
10571 return retval;
10572 dirent = (struct ext2_dir_entry *) block_start;
10573 left = fs->blocksize;
10574 for (i=0; i < fd->num_array; i++) {
10575 ent = fd->harray + i;
10576 if (ent->dir->inode == 0)
10577 continue;
10578 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10579 if (rec_len > left) {
10580 if (left)
10581 dirent->rec_len += left;
10582 if ((retval = get_next_block(fs, outdir,
10583 &block_start)))
10584 return retval;
10585 offset = 0;
10586 }
10587 left = fs->blocksize - offset;
10588 dirent = (struct ext2_dir_entry *) (block_start + offset);
10589 if (offset == 0) {
10590 if (ent->hash == prev_hash)
10591 outdir->hashes[outdir->num-1] = ent->hash | 1;
10592 else
10593 outdir->hashes[outdir->num-1] = ent->hash;
10594 }
10595 dirent->inode = ent->dir->inode;
10596 dirent->name_len = ent->dir->name_len;
10597 dirent->rec_len = rec_len;
10598 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10599 offset += rec_len;
10600 left -= rec_len;
10601 if (left < 12) {
10602 dirent->rec_len += left;
10603 offset += left;
10604 left = 0;
10605 }
10606 prev_hash = ent->hash;
10607 }
10608 if (left)
10609 dirent->rec_len += left;
10610
10611 return 0;
10612}
10613
10614
10615static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10616 ext2_ino_t ino, ext2_ino_t parent)
10617{
10618 struct ext2_dir_entry *dir;
10619 struct ext2_dx_root_info *root;
10620 struct ext2_dx_countlimit *limits;
10621 int filetype = 0;
10622
10623 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10624 filetype = EXT2_FT_DIR << 8;
10625
10626 memset(buf, 0, fs->blocksize);
10627 dir = (struct ext2_dir_entry *) buf;
10628 dir->inode = ino;
10629 dir->name[0] = '.';
10630 dir->name_len = 1 | filetype;
10631 dir->rec_len = 12;
10632 dir = (struct ext2_dir_entry *) (buf + 12);
10633 dir->inode = parent;
10634 dir->name[0] = '.';
10635 dir->name[1] = '.';
10636 dir->name_len = 2 | filetype;
10637 dir->rec_len = fs->blocksize - 12;
10638
10639 root = (struct ext2_dx_root_info *) (buf+24);
10640 root->reserved_zero = 0;
10641 root->hash_version = fs->super->s_def_hash_version;
10642 root->info_length = 8;
10643 root->indirect_levels = 0;
10644 root->unused_flags = 0;
10645
10646 limits = (struct ext2_dx_countlimit *) (buf+32);
10647 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10648 limits->count = 0;
10649
10650 return root;
10651}
10652
10653
10654static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10655{
10656 struct ext2_dir_entry *dir;
10657 struct ext2_dx_countlimit *limits;
10658
10659 memset(buf, 0, fs->blocksize);
10660 dir = (struct ext2_dir_entry *) buf;
10661 dir->inode = 0;
10662 dir->rec_len = fs->blocksize;
10663
10664 limits = (struct ext2_dx_countlimit *) (buf+8);
10665 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10666 limits->count = 0;
10667
10668 return (struct ext2_dx_entry *) limits;
10669}
10670
10671/*
10672 * This function takes the leaf nodes which have been written in
10673 * outdir, and populates the root node and any necessary interior nodes.
10674 */
10675static errcode_t calculate_tree(ext2_filsys fs,
10676 struct out_dir *outdir,
10677 ext2_ino_t ino,
10678 ext2_ino_t parent)
10679{
10680 struct ext2_dx_root_info *root_info;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010681 struct ext2_dx_entry *root, *dx_ent = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010682 struct ext2_dx_countlimit *root_limit, *limit;
10683 errcode_t retval;
10684 char * block_start;
10685 int i, c1, c2, nblks;
10686 int limit_offset, root_offset;
10687
10688 root_info = set_root_node(fs, outdir->buf, ino, parent);
10689 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10690 root_info->info_length;
10691 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10692 c1 = root_limit->limit;
10693 nblks = outdir->num;
10694
10695 /* Write out the pointer blocks */
10696 if (nblks-1 <= c1) {
10697 /* Just write out the root block, and we're done */
10698 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10699 for (i=1; i < nblks; i++) {
10700 root->block = ext2fs_cpu_to_le32(i);
10701 if (i != 1)
10702 root->hash =
10703 ext2fs_cpu_to_le32(outdir->hashes[i]);
10704 root++;
10705 c1--;
10706 }
10707 } else {
10708 c2 = 0;
10709 limit = 0;
10710 root_info->indirect_levels = 1;
10711 for (i=1; i < nblks; i++) {
10712 if (c1 == 0)
10713 return ENOSPC;
10714 if (c2 == 0) {
10715 if (limit)
10716 limit->limit = limit->count =
10717 ext2fs_cpu_to_le16(limit->limit);
10718 root = (struct ext2_dx_entry *)
10719 (outdir->buf + root_offset);
10720 root->block = ext2fs_cpu_to_le32(outdir->num);
10721 if (i != 1)
10722 root->hash =
10723 ext2fs_cpu_to_le32(outdir->hashes[i]);
10724 if ((retval = get_next_block(fs, outdir,
10725 &block_start)))
10726 return retval;
10727 dx_ent = set_int_node(fs, block_start);
10728 limit = (struct ext2_dx_countlimit *) dx_ent;
10729 c2 = limit->limit;
10730 root_offset += sizeof(struct ext2_dx_entry);
10731 c1--;
10732 }
10733 dx_ent->block = ext2fs_cpu_to_le32(i);
10734 if (c2 != limit->limit)
10735 dx_ent->hash =
10736 ext2fs_cpu_to_le32(outdir->hashes[i]);
10737 dx_ent++;
10738 c2--;
10739 }
10740 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10741 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10742 }
10743 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10744 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10745 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10746
10747 return 0;
10748}
10749
10750struct write_dir_struct {
10751 struct out_dir *outdir;
10752 errcode_t err;
10753 e2fsck_t ctx;
10754 int cleared;
10755};
10756
10757/*
10758 * Helper function which writes out a directory block.
10759 */
10760static int write_dir_block(ext2_filsys fs,
10761 blk_t *block_nr,
10762 e2_blkcnt_t blockcnt,
10763 blk_t ref_block FSCK_ATTR((unused)),
10764 int ref_offset FSCK_ATTR((unused)),
10765 void *priv_data)
10766{
10767 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10768 blk_t blk;
10769 char *dir;
10770
10771 if (*block_nr == 0)
10772 return 0;
10773 if (blockcnt >= wd->outdir->num) {
10774 e2fsck_read_bitmaps(wd->ctx);
10775 blk = *block_nr;
10776 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10777 ext2fs_block_alloc_stats(fs, blk, -1);
10778 *block_nr = 0;
10779 wd->cleared++;
10780 return BLOCK_CHANGED;
10781 }
10782 if (blockcnt < 0)
10783 return 0;
10784
10785 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10786 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10787 if (wd->err)
10788 return BLOCK_ABORT;
10789 return 0;
10790}
10791
10792static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10793 struct out_dir *outdir,
10794 ext2_ino_t ino, int compress)
10795{
10796 struct write_dir_struct wd;
10797 errcode_t retval;
10798 struct ext2_inode inode;
10799
10800 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10801 if (retval)
10802 return retval;
10803
10804 wd.outdir = outdir;
10805 wd.err = 0;
10806 wd.ctx = ctx;
10807 wd.cleared = 0;
10808
10809 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10810 write_dir_block, &wd);
10811 if (retval)
10812 return retval;
10813 if (wd.err)
10814 return wd.err;
10815
10816 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10817 if (compress)
10818 inode.i_flags &= ~EXT2_INDEX_FL;
10819 else
10820 inode.i_flags |= EXT2_INDEX_FL;
10821 inode.i_size = outdir->num * fs->blocksize;
10822 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10823 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10824
10825 return 0;
10826}
10827
10828static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10829{
10830 ext2_filsys fs = ctx->fs;
10831 errcode_t retval;
10832 struct ext2_inode inode;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010010833 char *dir_buf = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010834 struct fill_dir_struct fd;
10835 struct out_dir outdir;
10836
10837 outdir.max = outdir.num = 0;
10838 outdir.buf = 0;
10839 outdir.hashes = 0;
10840 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10841
10842 retval = ENOMEM;
10843 fd.harray = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010844 dir_buf = xmalloc(inode.i_size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010845
10846 fd.max_array = inode.i_size / 32;
10847 fd.num_array = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010848 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010849
10850 fd.ctx = ctx;
10851 fd.buf = dir_buf;
10852 fd.inode = &inode;
10853 fd.err = 0;
10854 fd.dir_size = 0;
10855 fd.compress = 0;
10856 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10857 (inode.i_size / fs->blocksize) < 2)
10858 fd.compress = 1;
10859 fd.parent = 0;
10860
10861 /* Read in the entire directory into memory */
10862 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10863 fill_dir_block, &fd);
10864 if (fd.err) {
10865 retval = fd.err;
10866 goto errout;
10867 }
10868
10869 /* Sort the list */
10870resort:
10871 if (fd.compress)
10872 qsort(fd.harray+2, fd.num_array-2,
10873 sizeof(struct hash_entry), name_cmp);
10874 else
10875 qsort(fd.harray, fd.num_array,
10876 sizeof(struct hash_entry), hash_cmp);
10877
10878 /*
10879 * Look for duplicates
10880 */
10881 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10882 goto resort;
10883
10884 if (ctx->options & E2F_OPT_NO) {
10885 retval = 0;
10886 goto errout;
10887 }
10888
10889 /*
10890 * Copy the directory entries. In a htree directory these
10891 * will become the leaf nodes.
10892 */
10893 retval = copy_dir_entries(fs, &fd, &outdir);
10894 if (retval)
10895 goto errout;
10896
10897 free(dir_buf); dir_buf = 0;
10898
10899 if (!fd.compress) {
10900 /* Calculate the interior nodes */
10901 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10902 if (retval)
10903 goto errout;
10904 }
10905
10906 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10907
10908errout:
10909 free(dir_buf);
10910 free(fd.harray);
10911
10912 free_out_dir(&outdir);
10913 return retval;
10914}
10915
10916void e2fsck_rehash_directories(e2fsck_t ctx)
10917{
10918 struct problem_context pctx;
10919 struct dir_info *dir;
10920 ext2_u32_iterate iter;
10921 ext2_ino_t ino;
10922 errcode_t retval;
10923 int i, cur, max, all_dirs, dir_index, first = 1;
10924
10925 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10926
10927 if (!ctx->dirs_to_hash && !all_dirs)
10928 return;
10929
10930 e2fsck_get_lost_and_found(ctx, 0);
10931
10932 clear_problem_context(&pctx);
10933
10934 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10935 cur = 0;
10936 if (all_dirs) {
10937 i = 0;
10938 max = e2fsck_get_num_dirinfo(ctx);
10939 } else {
10940 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10941 &iter);
10942 if (retval) {
10943 pctx.errcode = retval;
10944 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10945 return;
10946 }
10947 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10948 }
10949 while (1) {
10950 if (all_dirs) {
10951 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10952 break;
10953 ino = dir->ino;
10954 } else {
10955 if (!ext2fs_u32_list_iterate(iter, &ino))
10956 break;
10957 }
10958 if (ino == ctx->lost_and_found)
10959 continue;
10960 pctx.dir = ino;
10961 if (first) {
10962 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10963 first = 0;
10964 }
10965 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10966 if (pctx.errcode) {
10967 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10968 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10969 }
10970 if (ctx->progress && !ctx->progress_fd)
10971 e2fsck_simple_progress(ctx, "Rebuilding directory",
10972 100.0 * (float) (++cur) / (float) max, ino);
10973 }
10974 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10975 if (!all_dirs)
10976 ext2fs_u32_list_iterate_end(iter);
10977
10978 ext2fs_u32_list_free(ctx->dirs_to_hash);
10979 ctx->dirs_to_hash = 0;
10980}
10981
10982/*
10983 * linux/fs/revoke.c
10984 *
10985 * Journal revoke routines for the generic filesystem journaling code;
10986 * part of the ext2fs journaling system.
10987 *
10988 * Revoke is the mechanism used to prevent old log records for deleted
10989 * metadata from being replayed on top of newer data using the same
10990 * blocks. The revoke mechanism is used in two separate places:
10991 *
10992 * + Commit: during commit we write the entire list of the current
10993 * transaction's revoked blocks to the journal
10994 *
10995 * + Recovery: during recovery we record the transaction ID of all
10996 * revoked blocks. If there are multiple revoke records in the log
10997 * for a single block, only the last one counts, and if there is a log
10998 * entry for a block beyond the last revoke, then that log entry still
10999 * gets replayed.
11000 *
11001 * We can get interactions between revokes and new log data within a
11002 * single transaction:
11003 *
11004 * Block is revoked and then journaled:
11005 * The desired end result is the journaling of the new block, so we
11006 * cancel the revoke before the transaction commits.
11007 *
11008 * Block is journaled and then revoked:
11009 * The revoke must take precedence over the write of the block, so we
11010 * need either to cancel the journal entry or to write the revoke
11011 * later in the log than the log block. In this case, we choose the
11012 * latter: journaling a block cancels any revoke record for that block
11013 * in the current transaction, so any revoke for that block in the
11014 * transaction must have happened after the block was journaled and so
11015 * the revoke must take precedence.
11016 *
11017 * Block is revoked and then written as data:
11018 * The data write is allowed to succeed, but the revoke is _not_
11019 * cancelled. We still need to prevent old log records from
11020 * overwriting the new data. We don't even need to clear the revoke
11021 * bit here.
11022 *
11023 * Revoke information on buffers is a tri-state value:
11024 *
11025 * RevokeValid clear: no cached revoke status, need to look it up
11026 * RevokeValid set, Revoked clear:
11027 * buffer has not been revoked, and cancel_revoke
11028 * need do nothing.
11029 * RevokeValid set, Revoked set:
11030 * buffer has been revoked.
11031 */
11032
11033static kmem_cache_t *revoke_record_cache;
11034static kmem_cache_t *revoke_table_cache;
11035
11036/* Each revoke record represents one single revoked block. During
11037 journal replay, this involves recording the transaction ID of the
11038 last transaction to revoke this block. */
11039
11040struct jbd_revoke_record_s
11041{
11042 struct list_head hash;
11043 tid_t sequence; /* Used for recovery only */
11044 unsigned long blocknr;
11045};
11046
11047
11048/* The revoke table is just a simple hash table of revoke records. */
11049struct jbd_revoke_table_s
11050{
11051 /* It is conceivable that we might want a larger hash table
11052 * for recovery. Must be a power of two. */
11053 int hash_size;
11054 int hash_shift;
11055 struct list_head *hash_table;
11056};
11057
11058
11059/* Utility functions to maintain the revoke table */
11060
11061/* Borrowed from buffer.c: this is a tried and tested block hash function */
11062static int hash(journal_t *journal, unsigned long block)
11063{
11064 struct jbd_revoke_table_s *table = journal->j_revoke;
11065 int hash_shift = table->hash_shift;
11066
11067 return ((block << (hash_shift - 6)) ^
11068 (block >> 13) ^
11069 (block << (hash_shift - 12))) & (table->hash_size - 1);
11070}
11071
11072static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11073 tid_t seq)
11074{
11075 struct list_head *hash_list;
11076 struct jbd_revoke_record_s *record;
11077
11078 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11079 if (!record)
11080 goto oom;
11081
11082 record->sequence = seq;
11083 record->blocknr = blocknr;
11084 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11085 list_add(&record->hash, hash_list);
11086 return 0;
11087
11088oom:
11089 return -ENOMEM;
11090}
11091
11092/* Find a revoke record in the journal's hash table. */
11093
11094static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11095 unsigned long blocknr)
11096{
11097 struct list_head *hash_list;
11098 struct jbd_revoke_record_s *record;
11099
11100 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11101
11102 record = (struct jbd_revoke_record_s *) hash_list->next;
11103 while (&(record->hash) != hash_list) {
11104 if (record->blocknr == blocknr)
11105 return record;
11106 record = (struct jbd_revoke_record_s *) record->hash.next;
11107 }
11108 return NULL;
11109}
11110
11111int journal_init_revoke_caches(void)
11112{
11113 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11114 if (revoke_record_cache == 0)
11115 return -ENOMEM;
11116
11117 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11118 if (revoke_table_cache == 0) {
11119 do_cache_destroy(revoke_record_cache);
11120 revoke_record_cache = NULL;
11121 return -ENOMEM;
11122 }
11123 return 0;
11124}
11125
11126void journal_destroy_revoke_caches(void)
11127{
11128 do_cache_destroy(revoke_record_cache);
11129 revoke_record_cache = 0;
11130 do_cache_destroy(revoke_table_cache);
11131 revoke_table_cache = 0;
11132}
11133
11134/* Initialise the revoke table for a given journal to a given size. */
11135
11136int journal_init_revoke(journal_t *journal, int hash_size)
11137{
11138 int shift, tmp;
11139
11140 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11141 if (!journal->j_revoke)
11142 return -ENOMEM;
11143
11144 /* Check that the hash_size is a power of two */
11145 journal->j_revoke->hash_size = hash_size;
11146
11147 shift = 0;
11148 tmp = hash_size;
Denis Vlasenkobb045062008-09-27 14:06:06 +000011149 while ((tmp >>= 1UL) != 0UL)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011150 shift++;
11151 journal->j_revoke->hash_shift = shift;
11152
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010011153 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011154
11155 for (tmp = 0; tmp < hash_size; tmp++)
11156 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11157
11158 return 0;
11159}
11160
11161/* Destoy a journal's revoke table. The table must already be empty! */
11162
11163void journal_destroy_revoke(journal_t *journal)
11164{
11165 struct jbd_revoke_table_s *table;
11166 struct list_head *hash_list;
11167 int i;
11168
11169 table = journal->j_revoke;
11170 if (!table)
11171 return;
11172
11173 for (i=0; i<table->hash_size; i++) {
11174 hash_list = &table->hash_table[i];
11175 }
11176
11177 free(table->hash_table);
11178 free(table);
11179 journal->j_revoke = NULL;
11180}
11181
11182/*
11183 * Revoke support for recovery.
11184 *
11185 * Recovery needs to be able to:
11186 *
11187 * record all revoke records, including the tid of the latest instance
11188 * of each revoke in the journal
11189 *
11190 * check whether a given block in a given transaction should be replayed
11191 * (ie. has not been revoked by a revoke record in that or a subsequent
11192 * transaction)
11193 *
11194 * empty the revoke table after recovery.
11195 */
11196
11197/*
11198 * First, setting revoke records. We create a new revoke record for
11199 * every block ever revoked in the log as we scan it for recovery, and
11200 * we update the existing records if we find multiple revokes for a
11201 * single block.
11202 */
11203
11204int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11205 tid_t sequence)
11206{
11207 struct jbd_revoke_record_s *record;
11208
11209 record = find_revoke_record(journal, blocknr);
11210 if (record) {
11211 /* If we have multiple occurences, only record the
11212 * latest sequence number in the hashed record */
11213 if (tid_gt(sequence, record->sequence))
11214 record->sequence = sequence;
11215 return 0;
11216 }
11217 return insert_revoke_hash(journal, blocknr, sequence);
11218}
11219
11220/*
11221 * Test revoke records. For a given block referenced in the log, has
11222 * that block been revoked? A revoke record with a given transaction
11223 * sequence number revokes all blocks in that transaction and earlier
11224 * ones, but later transactions still need replayed.
11225 */
11226
11227int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11228 tid_t sequence)
11229{
11230 struct jbd_revoke_record_s *record;
11231
11232 record = find_revoke_record(journal, blocknr);
11233 if (!record)
11234 return 0;
11235 if (tid_gt(sequence, record->sequence))
11236 return 0;
11237 return 1;
11238}
11239
11240/*
11241 * Finally, once recovery is over, we need to clear the revoke table so
11242 * that it can be reused by the running filesystem.
11243 */
11244
11245void journal_clear_revoke(journal_t *journal)
11246{
11247 int i;
11248 struct list_head *hash_list;
11249 struct jbd_revoke_record_s *record;
11250 struct jbd_revoke_table_s *revoke_var;
11251
11252 revoke_var = journal->j_revoke;
11253
11254 for (i = 0; i < revoke_var->hash_size; i++) {
11255 hash_list = &revoke_var->hash_table[i];
11256 while (!list_empty(hash_list)) {
11257 record = (struct jbd_revoke_record_s*) hash_list->next;
11258 list_del(&record->hash);
11259 free(record);
11260 }
11261 }
11262}
11263
11264/*
11265 * e2fsck.c - superblock checks
11266 */
11267
11268#define MIN_CHECK 1
11269#define MAX_CHECK 2
11270
11271static void check_super_value(e2fsck_t ctx, const char *descr,
11272 unsigned long value, int flags,
11273 unsigned long min_val, unsigned long max_val)
11274{
11275 struct problem_context pctx;
11276
11277 if (((flags & MIN_CHECK) && (value < min_val)) ||
11278 ((flags & MAX_CHECK) && (value > max_val))) {
11279 clear_problem_context(&pctx);
11280 pctx.num = value;
11281 pctx.str = descr;
11282 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11283 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11284 }
11285}
11286
11287/*
11288 * This routine may get stubbed out in special compilations of the
11289 * e2fsck code..
11290 */
11291#ifndef EXT2_SPECIAL_DEVICE_SIZE
11292static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11293{
11294 return (ext2fs_get_device_size(ctx->filesystem_name,
11295 EXT2_BLOCK_SIZE(ctx->fs->super),
11296 &ctx->num_blocks));
11297}
11298#endif
11299
11300/*
11301 * helper function to release an inode
11302 */
11303struct process_block_struct {
11304 e2fsck_t ctx;
11305 char *buf;
11306 struct problem_context *pctx;
11307 int truncating;
11308 int truncate_offset;
11309 e2_blkcnt_t truncate_block;
11310 int truncated_blocks;
11311 int abort;
11312 errcode_t errcode;
11313};
11314
11315static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11316 e2_blkcnt_t blockcnt,
11317 blk_t ref_blk FSCK_ATTR((unused)),
11318 int ref_offset FSCK_ATTR((unused)),
11319 void *priv_data)
11320{
11321 struct process_block_struct *pb;
11322 e2fsck_t ctx;
11323 struct problem_context *pctx;
11324 blk_t blk = *block_nr;
11325 int retval = 0;
11326
11327 pb = (struct process_block_struct *) priv_data;
11328 ctx = pb->ctx;
11329 pctx = pb->pctx;
11330
11331 pctx->blk = blk;
11332 pctx->blkcount = blockcnt;
11333
11334 if (HOLE_BLKADDR(blk))
11335 return 0;
11336
11337 if ((blk < fs->super->s_first_data_block) ||
11338 (blk >= fs->super->s_blocks_count)) {
11339 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011340 return_abort:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011341 pb->abort = 1;
11342 return BLOCK_ABORT;
11343 }
11344
11345 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11346 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11347 goto return_abort;
11348 }
11349
11350 /*
11351 * If we are deleting an orphan, then we leave the fields alone.
11352 * If we are truncating an orphan, then update the inode fields
11353 * and clean up any partial block data.
11354 */
11355 if (pb->truncating) {
11356 /*
11357 * We only remove indirect blocks if they are
11358 * completely empty.
11359 */
11360 if (blockcnt < 0) {
11361 int i, limit;
11362 blk_t *bp;
11363
11364 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11365 pb->buf);
11366 if (pb->errcode)
11367 goto return_abort;
11368
11369 limit = fs->blocksize >> 2;
11370 for (i = 0, bp = (blk_t *) pb->buf;
11371 i < limit; i++, bp++)
11372 if (*bp)
11373 return 0;
11374 }
11375 /*
11376 * We don't remove direct blocks until we've reached
11377 * the truncation block.
11378 */
11379 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11380 return 0;
11381 /*
11382 * If part of the last block needs truncating, we do
11383 * it here.
11384 */
11385 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11386 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11387 pb->buf);
11388 if (pb->errcode)
11389 goto return_abort;
11390 memset(pb->buf + pb->truncate_offset, 0,
11391 fs->blocksize - pb->truncate_offset);
11392 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11393 pb->buf);
11394 if (pb->errcode)
11395 goto return_abort;
11396 }
11397 pb->truncated_blocks++;
11398 *block_nr = 0;
11399 retval |= BLOCK_CHANGED;
11400 }
11401
11402 ext2fs_block_alloc_stats(fs, blk, -1);
11403 return retval;
11404}
11405
11406/*
11407 * This function releases an inode. Returns 1 if an inconsistency was
11408 * found. If the inode has a link count, then it is being truncated and
11409 * not deleted.
11410 */
11411static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11412 struct ext2_inode *inode, char *block_buf,
11413 struct problem_context *pctx)
11414{
11415 struct process_block_struct pb;
11416 ext2_filsys fs = ctx->fs;
11417 errcode_t retval;
11418 __u32 count;
11419
11420 if (!ext2fs_inode_has_valid_blocks(inode))
11421 return 0;
11422
11423 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11424 pb.ctx = ctx;
11425 pb.abort = 0;
11426 pb.errcode = 0;
11427 pb.pctx = pctx;
11428 if (inode->i_links_count) {
11429 pb.truncating = 1;
11430 pb.truncate_block = (e2_blkcnt_t)
11431 ((((long long)inode->i_size_high << 32) +
11432 inode->i_size + fs->blocksize - 1) /
11433 fs->blocksize);
11434 pb.truncate_offset = inode->i_size % fs->blocksize;
11435 } else {
11436 pb.truncating = 0;
11437 pb.truncate_block = 0;
11438 pb.truncate_offset = 0;
11439 }
11440 pb.truncated_blocks = 0;
11441 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11442 block_buf, release_inode_block, &pb);
11443 if (retval) {
11444 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11445 ino);
11446 return 1;
11447 }
11448 if (pb.abort)
11449 return 1;
11450
11451 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11452 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11453
11454 if (pb.truncated_blocks)
11455 inode->i_blocks -= pb.truncated_blocks *
11456 (fs->blocksize / 512);
11457
11458 if (inode->i_file_acl) {
11459 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11460 block_buf, -1, &count);
11461 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11462 retval = 0;
11463 count = 1;
11464 }
11465 if (retval) {
11466 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11467 ino);
11468 return 1;
11469 }
11470 if (count == 0)
11471 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11472 inode->i_file_acl = 0;
11473 }
11474 return 0;
11475}
11476
11477/*
11478 * This function releases all of the orphan inodes. It returns 1 if
11479 * it hit some error, and 0 on success.
11480 */
11481static int release_orphan_inodes(e2fsck_t ctx)
11482{
11483 ext2_filsys fs = ctx->fs;
11484 ext2_ino_t ino, next_ino;
11485 struct ext2_inode inode;
11486 struct problem_context pctx;
11487 char *block_buf;
11488
11489 if ((ino = fs->super->s_last_orphan) == 0)
11490 return 0;
11491
11492 /*
11493 * Win or lose, we won't be using the head of the orphan inode
11494 * list again.
11495 */
11496 fs->super->s_last_orphan = 0;
11497 ext2fs_mark_super_dirty(fs);
11498
11499 /*
11500 * If the filesystem contains errors, don't run the orphan
11501 * list, since the orphan list can't be trusted; and we're
11502 * going to be running a full e2fsck run anyway...
11503 */
11504 if (fs->super->s_state & EXT2_ERROR_FS)
11505 return 0;
11506
11507 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11508 (ino > fs->super->s_inodes_count)) {
11509 clear_problem_context(&pctx);
11510 pctx.ino = ino;
11511 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11512 return 1;
11513 }
11514
11515 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11516 "block iterate buffer");
11517 e2fsck_read_bitmaps(ctx);
11518
11519 while (ino) {
11520 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11521 clear_problem_context(&pctx);
11522 pctx.ino = ino;
11523 pctx.inode = &inode;
11524 pctx.str = inode.i_links_count ? _("Truncating") :
11525 _("Clearing");
11526
11527 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11528
11529 next_ino = inode.i_dtime;
11530 if (next_ino &&
11531 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11532 (next_ino > fs->super->s_inodes_count))) {
11533 pctx.ino = next_ino;
11534 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11535 goto return_abort;
11536 }
11537
11538 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11539 goto return_abort;
11540
11541 if (!inode.i_links_count) {
11542 ext2fs_inode_alloc_stats2(fs, ino, -1,
11543 LINUX_S_ISDIR(inode.i_mode));
Denis Vlasenko04158e02009-02-02 10:48:06 +000011544 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011545 } else {
11546 inode.i_dtime = 0;
11547 }
11548 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11549 ino = next_ino;
11550 }
11551 ext2fs_free_mem(&block_buf);
11552 return 0;
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011553 return_abort:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011554 ext2fs_free_mem(&block_buf);
11555 return 1;
11556}
11557
11558/*
11559 * Check the resize inode to make sure it is sane. We check both for
11560 * the case where on-line resizing is not enabled (in which case the
11561 * resize inode should be cleared) as well as the case where on-line
11562 * resizing is enabled.
11563 */
11564static void check_resize_inode(e2fsck_t ctx)
11565{
11566 ext2_filsys fs = ctx->fs;
11567 struct ext2_inode inode;
11568 struct problem_context pctx;
11569 int i, j, gdt_off, ind_off;
11570 blk_t blk, pblk, expect;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010011571 __u32 *dind_buf = NULL, *ind_buf;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011572 errcode_t retval;
11573
11574 clear_problem_context(&pctx);
11575
11576 /*
11577 * If the resize inode feature isn't set, then
11578 * s_reserved_gdt_blocks must be zero.
11579 */
11580 if (!(fs->super->s_feature_compat &
11581 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11582 if (fs->super->s_reserved_gdt_blocks) {
11583 pctx.num = fs->super->s_reserved_gdt_blocks;
11584 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11585 &pctx)) {
11586 fs->super->s_reserved_gdt_blocks = 0;
11587 ext2fs_mark_super_dirty(fs);
11588 }
11589 }
11590 }
11591
11592 /* Read the resize inode */
11593 pctx.ino = EXT2_RESIZE_INO;
11594 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11595 if (retval) {
11596 if (fs->super->s_feature_compat &
11597 EXT2_FEATURE_COMPAT_RESIZE_INODE)
11598 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11599 return;
11600 }
11601
11602 /*
11603 * If the resize inode feature isn't set, check to make sure
11604 * the resize inode is cleared; then we're done.
11605 */
11606 if (!(fs->super->s_feature_compat &
11607 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11608 for (i=0; i < EXT2_N_BLOCKS; i++) {
11609 if (inode.i_block[i])
11610 break;
11611 }
11612 if ((i < EXT2_N_BLOCKS) &&
11613 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11614 memset(&inode, 0, sizeof(inode));
11615 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11616 "clear_resize");
11617 }
11618 return;
11619 }
11620
11621 /*
11622 * The resize inode feature is enabled; check to make sure the
11623 * only block in use is the double indirect block
11624 */
11625 blk = inode.i_block[EXT2_DIND_BLOCK];
11626 for (i=0; i < EXT2_N_BLOCKS; i++) {
11627 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11628 break;
11629 }
11630 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11631 !(inode.i_mode & LINUX_S_IFREG) ||
11632 (blk < fs->super->s_first_data_block ||
11633 blk >= fs->super->s_blocks_count)) {
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011634 resize_inode_invalid:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011635 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11636 memset(&inode, 0, sizeof(inode));
11637 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11638 "clear_resize");
11639 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11640 }
11641 if (!(ctx->options & E2F_OPT_READONLY)) {
11642 fs->super->s_state &= ~EXT2_VALID_FS;
11643 ext2fs_mark_super_dirty(fs);
11644 }
11645 goto cleanup;
11646 }
11647 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11648 "resize dind buffer");
11649 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11650
11651 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11652 if (retval)
11653 goto resize_inode_invalid;
11654
11655 gdt_off = fs->desc_blocks;
11656 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11657 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11658 i++, gdt_off++, pblk++) {
11659 gdt_off %= fs->blocksize/4;
11660 if (dind_buf[gdt_off] != pblk)
11661 goto resize_inode_invalid;
11662 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11663 if (retval)
11664 goto resize_inode_invalid;
11665 ind_off = 0;
11666 for (j = 1; j < fs->group_desc_count; j++) {
11667 if (!ext2fs_bg_has_super(fs, j))
11668 continue;
11669 expect = pblk + (j * fs->super->s_blocks_per_group);
11670 if (ind_buf[ind_off] != expect)
11671 goto resize_inode_invalid;
11672 ind_off++;
11673 }
11674 }
11675
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011676 cleanup:
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011677 ext2fs_free_mem(&dind_buf);
Denys Vlasenkof3ea7922010-07-26 01:06:14 +020011678}
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011679
11680static void check_super_block(e2fsck_t ctx)
11681{
11682 ext2_filsys fs = ctx->fs;
11683 blk_t first_block, last_block;
11684 struct ext2_super_block *sb = fs->super;
11685 struct ext2_group_desc *gd;
11686 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11687 blk_t bpg_max;
11688 int inodes_per_block;
11689 int ipg_max;
11690 int inode_size;
11691 dgrp_t i;
11692 blk_t should_be;
11693 struct problem_context pctx;
11694 __u32 free_blocks = 0, free_inodes = 0;
11695
11696 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11697 ipg_max = inodes_per_block * (blocks_per_group - 4);
11698 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11699 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11700 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11701 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11702 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11703
11704 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11705 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11706 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11707 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11708 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11709 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11710
11711 clear_problem_context(&pctx);
11712
11713 /*
11714 * Verify the super block constants...
11715 */
11716 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11717 MIN_CHECK, 1, 0);
11718 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11719 MIN_CHECK, 1, 0);
11720 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11721 MAX_CHECK, 0, sb->s_blocks_count);
11722 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11723 MIN_CHECK | MAX_CHECK, 0,
11724 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11725 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11726 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11727 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11728 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11729 bpg_max);
11730 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11731 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11732 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11733 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11734 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11735 MAX_CHECK, 0, sb->s_blocks_count / 2);
11736 check_super_value(ctx, "reserved_gdt_blocks",
11737 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11738 fs->blocksize/4);
11739 inode_size = EXT2_INODE_SIZE(sb);
11740 check_super_value(ctx, "inode_size",
11741 inode_size, MIN_CHECK | MAX_CHECK,
11742 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11743 if (inode_size & (inode_size - 1)) {
11744 pctx.num = inode_size;
11745 pctx.str = "inode_size";
11746 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11747 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11748 return;
11749 }
11750
11751 if (!ctx->num_blocks) {
11752 pctx.errcode = e2fsck_get_device_size(ctx);
11753 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11754 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11755 ctx->flags |= E2F_FLAG_ABORT;
11756 return;
11757 }
11758 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11759 (ctx->num_blocks < sb->s_blocks_count)) {
11760 pctx.blk = sb->s_blocks_count;
11761 pctx.blk2 = ctx->num_blocks;
11762 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11763 ctx->flags |= E2F_FLAG_ABORT;
11764 return;
11765 }
11766 }
11767 }
11768
11769 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11770 pctx.blk = EXT2_BLOCK_SIZE(sb);
11771 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11772 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11773 ctx->flags |= E2F_FLAG_ABORT;
11774 return;
11775 }
11776
11777 should_be = sb->s_frags_per_group >>
11778 (sb->s_log_block_size - sb->s_log_frag_size);
11779 if (sb->s_blocks_per_group != should_be) {
11780 pctx.blk = sb->s_blocks_per_group;
11781 pctx.blk2 = should_be;
11782 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11783 ctx->flags |= E2F_FLAG_ABORT;
11784 return;
11785 }
11786
11787 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11788 if (sb->s_first_data_block != should_be) {
11789 pctx.blk = sb->s_first_data_block;
11790 pctx.blk2 = should_be;
11791 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11792 ctx->flags |= E2F_FLAG_ABORT;
11793 return;
11794 }
11795
11796 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11797 if (sb->s_inodes_count != should_be) {
11798 pctx.ino = sb->s_inodes_count;
11799 pctx.ino2 = should_be;
11800 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11801 sb->s_inodes_count = should_be;
11802 ext2fs_mark_super_dirty(fs);
11803 }
11804 }
11805
11806 /*
11807 * Verify the group descriptors....
11808 */
11809 first_block = sb->s_first_data_block;
11810 last_block = first_block + blocks_per_group;
11811
11812 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11813 pctx.group = i;
11814
11815 if (i == fs->group_desc_count - 1)
11816 last_block = sb->s_blocks_count;
11817 if ((gd->bg_block_bitmap < first_block) ||
11818 (gd->bg_block_bitmap >= last_block)) {
11819 pctx.blk = gd->bg_block_bitmap;
11820 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11821 gd->bg_block_bitmap = 0;
11822 }
11823 if (gd->bg_block_bitmap == 0) {
11824 ctx->invalid_block_bitmap_flag[i]++;
11825 ctx->invalid_bitmaps++;
11826 }
11827 if ((gd->bg_inode_bitmap < first_block) ||
11828 (gd->bg_inode_bitmap >= last_block)) {
11829 pctx.blk = gd->bg_inode_bitmap;
11830 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11831 gd->bg_inode_bitmap = 0;
11832 }
11833 if (gd->bg_inode_bitmap == 0) {
11834 ctx->invalid_inode_bitmap_flag[i]++;
11835 ctx->invalid_bitmaps++;
11836 }
11837 if ((gd->bg_inode_table < first_block) ||
11838 ((gd->bg_inode_table +
11839 fs->inode_blocks_per_group - 1) >= last_block)) {
11840 pctx.blk = gd->bg_inode_table;
11841 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11842 gd->bg_inode_table = 0;
11843 }
11844 if (gd->bg_inode_table == 0) {
11845 ctx->invalid_inode_table_flag[i]++;
11846 ctx->invalid_bitmaps++;
11847 }
11848 free_blocks += gd->bg_free_blocks_count;
11849 free_inodes += gd->bg_free_inodes_count;
11850 first_block += sb->s_blocks_per_group;
11851 last_block += sb->s_blocks_per_group;
11852
11853 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11854 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11855 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11856 ext2fs_unmark_valid(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011857 }
11858
11859 /*
11860 * Update the global counts from the block group counts. This
11861 * is needed for an experimental patch which eliminates
11862 * locking the entire filesystem when allocating blocks or
11863 * inodes; if the filesystem is not unmounted cleanly, the
11864 * global counts may not be accurate.
11865 */
11866 if ((free_blocks != sb->s_free_blocks_count) ||
11867 (free_inodes != sb->s_free_inodes_count)) {
11868 if (ctx->options & E2F_OPT_READONLY)
11869 ext2fs_unmark_valid(fs);
11870 else {
11871 sb->s_free_blocks_count = free_blocks;
11872 sb->s_free_inodes_count = free_inodes;
11873 ext2fs_mark_super_dirty(fs);
11874 }
11875 }
11876
11877 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11878 (sb->s_free_inodes_count > sb->s_inodes_count))
11879 ext2fs_unmark_valid(fs);
11880
11881
11882 /*
11883 * If we have invalid bitmaps, set the error state of the
11884 * filesystem.
11885 */
11886 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11887 sb->s_state &= ~EXT2_VALID_FS;
11888 ext2fs_mark_super_dirty(fs);
11889 }
11890
11891 clear_problem_context(&pctx);
11892
11893 /*
11894 * If the UUID field isn't assigned, assign it.
11895 */
11896 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11897 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11898 uuid_generate(sb->s_uuid);
11899 ext2fs_mark_super_dirty(fs);
11900 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11901 }
11902 }
11903
11904 /* FIXME - HURD support?
11905 * For the Hurd, check to see if the filetype option is set,
11906 * since it doesn't support it.
11907 */
11908 if (!(ctx->options & E2F_OPT_READONLY) &&
11909 fs->super->s_creator_os == EXT2_OS_HURD &&
11910 (fs->super->s_feature_incompat &
11911 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11912 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11913 fs->super->s_feature_incompat &=
11914 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11915 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011916 }
11917 }
11918
11919 /*
11920 * If we have any of the compatibility flags set, we need to have a
11921 * revision 1 filesystem. Most kernels will not check the flags on
11922 * a rev 0 filesystem and we may have corruption issues because of
11923 * the incompatible changes to the filesystem.
11924 */
11925 if (!(ctx->options & E2F_OPT_READONLY) &&
11926 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11927 (fs->super->s_feature_compat ||
11928 fs->super->s_feature_ro_compat ||
11929 fs->super->s_feature_incompat) &&
11930 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11931 ext2fs_update_dynamic_rev(fs);
11932 ext2fs_mark_super_dirty(fs);
11933 }
11934
11935 check_resize_inode(ctx);
11936
11937 /*
11938 * Clean up any orphan inodes, if present.
11939 */
11940 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11941 fs->super->s_state &= ~EXT2_VALID_FS;
11942 ext2fs_mark_super_dirty(fs);
11943 }
11944
11945 /*
11946 * Move the ext3 journal file, if necessary.
11947 */
11948 e2fsck_move_ext3_journal(ctx);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011949}
11950
11951/*
11952 * swapfs.c --- byte-swap an ext2 filesystem
11953 */
11954
11955#ifdef ENABLE_SWAPFS
11956
11957struct swap_block_struct {
11958 ext2_ino_t ino;
11959 int isdir;
11960 errcode_t errcode;
11961 char *dir_buf;
11962 struct ext2_inode *inode;
11963};
11964
11965/*
11966 * This is a helper function for block_iterate. We mark all of the
11967 * indirect and direct blocks as changed, so that block_iterate will
11968 * write them out.
11969 */
11970static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11971 void *priv_data)
11972{
11973 errcode_t retval;
11974
11975 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11976
11977 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11978 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11979 if (retval) {
11980 sb->errcode = retval;
11981 return BLOCK_ABORT;
11982 }
11983 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11984 if (retval) {
11985 sb->errcode = retval;
11986 return BLOCK_ABORT;
11987 }
11988 }
11989 if (blockcnt >= 0) {
11990 if (blockcnt < EXT2_NDIR_BLOCKS)
11991 return 0;
11992 return BLOCK_CHANGED;
11993 }
11994 if (blockcnt == BLOCK_COUNT_IND) {
11995 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11996 return 0;
11997 return BLOCK_CHANGED;
11998 }
11999 if (blockcnt == BLOCK_COUNT_DIND) {
12000 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
12001 return 0;
12002 return BLOCK_CHANGED;
12003 }
12004 if (blockcnt == BLOCK_COUNT_TIND) {
12005 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12006 return 0;
12007 return BLOCK_CHANGED;
12008 }
12009 return BLOCK_CHANGED;
12010}
12011
12012/*
12013 * This function is responsible for byte-swapping all of the indirect,
12014 * block pointers. It is also responsible for byte-swapping directories.
12015 */
12016static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12017 struct ext2_inode *inode)
12018{
12019 errcode_t retval;
12020 struct swap_block_struct sb;
12021
12022 sb.ino = ino;
12023 sb.inode = inode;
12024 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12025 sb.errcode = 0;
12026 sb.isdir = 0;
12027 if (LINUX_S_ISDIR(inode->i_mode))
12028 sb.isdir = 1;
12029
12030 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12031 swap_block, &sb);
12032 if (retval) {
12033 bb_error_msg(_("while calling ext2fs_block_iterate"));
12034 ctx->flags |= E2F_FLAG_ABORT;
12035 return;
12036 }
12037 if (sb.errcode) {
12038 bb_error_msg(_("while calling iterator function"));
12039 ctx->flags |= E2F_FLAG_ABORT;
12040 return;
12041 }
12042}
12043
12044static void swap_inodes(e2fsck_t ctx)
12045{
12046 ext2_filsys fs = ctx->fs;
12047 dgrp_t group;
12048 unsigned int i;
12049 ext2_ino_t ino = 1;
12050 char *buf, *block_buf;
12051 errcode_t retval;
12052 struct ext2_inode * inode;
12053
12054 e2fsck_use_inode_shortcuts(ctx, 1);
12055
12056 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12057 &buf);
12058 if (retval) {
12059 bb_error_msg(_("while allocating inode buffer"));
12060 ctx->flags |= E2F_FLAG_ABORT;
12061 return;
12062 }
12063 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12064 "block interate buffer");
12065 for (group = 0; group < fs->group_desc_count; group++) {
12066 retval = io_channel_read_blk(fs->io,
12067 fs->group_desc[group].bg_inode_table,
12068 fs->inode_blocks_per_group, buf);
12069 if (retval) {
12070 bb_error_msg(_("while reading inode table (group %d)"),
12071 group);
12072 ctx->flags |= E2F_FLAG_ABORT;
12073 return;
12074 }
12075 inode = (struct ext2_inode *) buf;
12076 for (i=0; i < fs->super->s_inodes_per_group;
12077 i++, ino++, inode++) {
12078 ctx->stashed_ino = ino;
12079 ctx->stashed_inode = inode;
12080
12081 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12082 ext2fs_swap_inode(fs, inode, inode, 0);
12083
12084 /*
12085 * Skip deleted files.
12086 */
12087 if (inode->i_links_count == 0)
12088 continue;
12089
12090 if (LINUX_S_ISDIR(inode->i_mode) ||
12091 ((inode->i_block[EXT2_IND_BLOCK] ||
12092 inode->i_block[EXT2_DIND_BLOCK] ||
12093 inode->i_block[EXT2_TIND_BLOCK]) &&
12094 ext2fs_inode_has_valid_blocks(inode)))
12095 swap_inode_blocks(ctx, ino, block_buf, inode);
12096
12097 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12098 return;
12099
12100 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12101 ext2fs_swap_inode(fs, inode, inode, 1);
12102 }
12103 retval = io_channel_write_blk(fs->io,
12104 fs->group_desc[group].bg_inode_table,
12105 fs->inode_blocks_per_group, buf);
12106 if (retval) {
12107 bb_error_msg(_("while writing inode table (group %d)"),
12108 group);
12109 ctx->flags |= E2F_FLAG_ABORT;
12110 return;
12111 }
12112 }
12113 ext2fs_free_mem(&buf);
12114 ext2fs_free_mem(&block_buf);
12115 e2fsck_use_inode_shortcuts(ctx, 0);
12116 ext2fs_flush_icache(fs);
12117}
12118
12119#if defined(__powerpc__) && BB_BIG_ENDIAN
12120/*
12121 * On the PowerPC, the big-endian variant of the ext2 filesystem
12122 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12123 * of each word. Thus a bitmap with only bit 0 set would be, as
12124 * a string of bytes, 00 00 00 01 00 ...
12125 * To cope with this, we byte-reverse each word of a bitmap if
12126 * we have a big-endian filesystem, that is, if we are *not*
12127 * byte-swapping other word-sized numbers.
12128 */
12129#define EXT2_BIG_ENDIAN_BITMAPS
12130#endif
12131
12132#ifdef EXT2_BIG_ENDIAN_BITMAPS
12133static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12134{
12135 __u32 *p = (__u32 *) bmap->bitmap;
12136 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12137
12138 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12139 *p = ext2fs_swab32(*p);
12140}
12141#endif
12142
12143
12144#ifdef ENABLE_SWAPFS
12145static void swap_filesys(e2fsck_t ctx)
12146{
12147 ext2_filsys fs = ctx->fs;
12148 if (!(ctx->options & E2F_OPT_PREEN))
12149 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12150
12151 /* Byte swap */
12152
12153 if (fs->super->s_mnt_count) {
12154 fprintf(stderr, _("%s: the filesystem must be freshly "
12155 "checked using fsck\n"
12156 "and not mounted before trying to "
12157 "byte-swap it.\n"), ctx->device_name);
12158 ctx->flags |= E2F_FLAG_ABORT;
12159 return;
12160 }
12161 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12162 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12163 EXT2_FLAG_SWAP_BYTES_WRITE);
12164 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12165 } else {
12166 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12167 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12168 }
12169 swap_inodes(ctx);
12170 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12171 return;
12172 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12173 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12174 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12175 EXT2_FLAG_SWAP_BYTES_WRITE);
12176
12177#ifdef EXT2_BIG_ENDIAN_BITMAPS
12178 e2fsck_read_bitmaps(ctx);
12179 ext2fs_swap_bitmap(fs->inode_map);
12180 ext2fs_swap_bitmap(fs->block_map);
12181 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12182#endif
12183 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12184 ext2fs_flush(fs);
12185 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12186}
12187#endif /* ENABLE_SWAPFS */
12188
12189#endif
12190
12191/*
12192 * util.c --- miscellaneous utilities
12193 */
12194
12195
12196void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12197 const char *description)
12198{
12199 void *ret;
12200 char buf[256];
12201
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012202 ret = xzalloc(size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012203 return ret;
12204}
12205
12206static char *string_copy(const char *str, int len)
12207{
12208 char *ret;
12209
12210 if (!str)
12211 return NULL;
12212 if (!len)
12213 len = strlen(str);
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012214 ret = xmalloc(len+1);
12215 strncpy(ret, str, len);
12216 ret[len] = 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012217 return ret;
12218}
12219
12220#ifndef HAVE_CONIO_H
12221static int read_a_char(void)
12222{
12223 char c;
12224 int r;
12225 int fail = 0;
12226
Denis Vlasenkobb045062008-09-27 14:06:06 +000012227 while (1) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012228 if (e2fsck_global_ctx &&
12229 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12230 return 3;
12231 }
12232 r = read(0, &c, 1);
12233 if (r == 1)
12234 return c;
12235 if (fail++ > 100)
12236 break;
12237 }
12238 return EOF;
12239}
12240#endif
12241
12242static int ask_yn(const char * string, int def)
12243{
12244 int c;
12245 const char *defstr;
12246 static const char short_yes[] = "yY";
12247 static const char short_no[] = "nN";
12248
12249#ifdef HAVE_TERMIOS_H
12250 struct termios termios, tmp;
12251
12252 tcgetattr (0, &termios);
12253 tmp = termios;
12254 tmp.c_lflag &= ~(ICANON | ECHO);
12255 tmp.c_cc[VMIN] = 1;
12256 tmp.c_cc[VTIME] = 0;
Denis Vlasenko202ac502008-11-05 13:20:58 +000012257 tcsetattr_stdin_TCSANOW(&tmp);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012258#endif
12259
12260 if (def == 1)
12261 defstr = "<y>";
12262 else if (def == 0)
12263 defstr = "<n>";
12264 else
12265 defstr = " (y/n)";
12266 printf("%s%s? ", string, defstr);
12267 while (1) {
12268 fflush (stdout);
12269 if ((c = read_a_char()) == EOF)
12270 break;
12271 if (c == 3) {
12272#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012273 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012274#endif
12275 if (e2fsck_global_ctx &&
12276 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12277 puts("\n");
12278 longjmp(e2fsck_global_ctx->abort_loc, 1);
12279 }
12280 puts(_("cancelled!\n"));
12281 return 0;
12282 }
12283 if (strchr(short_yes, (char) c)) {
12284 def = 1;
12285 break;
12286 }
12287 else if (strchr(short_no, (char) c)) {
12288 def = 0;
12289 break;
12290 }
12291 else if ((c == ' ' || c == '\n') && (def != -1))
12292 break;
12293 }
12294 if (def)
12295 puts("yes\n");
12296 else
12297 puts ("no\n");
12298#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012299 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012300#endif
12301 return def;
12302}
12303
12304int ask (e2fsck_t ctx, const char * string, int def)
12305{
12306 if (ctx->options & E2F_OPT_NO) {
12307 printf(_("%s? no\n\n"), string);
12308 return 0;
12309 }
12310 if (ctx->options & E2F_OPT_YES) {
12311 printf(_("%s? yes\n\n"), string);
12312 return 1;
12313 }
12314 if (ctx->options & E2F_OPT_PREEN) {
12315 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12316 return def;
12317 }
12318 return ask_yn(string, def);
12319}
12320
12321void e2fsck_read_bitmaps(e2fsck_t ctx)
12322{
12323 ext2_filsys fs = ctx->fs;
12324 errcode_t retval;
12325
12326 if (ctx->invalid_bitmaps) {
12327 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12328 ctx->device_name);
12329 bb_error_msg_and_die(0);
12330 }
12331
12332 ehandler_operation(_("reading inode and block bitmaps"));
12333 retval = ext2fs_read_bitmaps(fs);
12334 ehandler_operation(0);
12335 if (retval) {
12336 bb_error_msg(_("while retrying to read bitmaps for %s"),
12337 ctx->device_name);
12338 bb_error_msg_and_die(0);
12339 }
12340}
12341
12342static void e2fsck_write_bitmaps(e2fsck_t ctx)
12343{
12344 ext2_filsys fs = ctx->fs;
12345 errcode_t retval;
12346
12347 if (ext2fs_test_bb_dirty(fs)) {
12348 ehandler_operation(_("writing block bitmaps"));
12349 retval = ext2fs_write_block_bitmap(fs);
12350 ehandler_operation(0);
12351 if (retval) {
12352 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12353 ctx->device_name);
12354 bb_error_msg_and_die(0);
12355 }
12356 }
12357
12358 if (ext2fs_test_ib_dirty(fs)) {
12359 ehandler_operation(_("writing inode bitmaps"));
12360 retval = ext2fs_write_inode_bitmap(fs);
12361 ehandler_operation(0);
12362 if (retval) {
12363 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12364 ctx->device_name);
12365 bb_error_msg_and_die(0);
12366 }
12367 }
12368}
12369
12370void preenhalt(e2fsck_t ctx)
12371{
12372 ext2_filsys fs = ctx->fs;
12373
12374 if (!(ctx->options & E2F_OPT_PREEN))
12375 return;
12376 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12377 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12378 ctx->device_name);
12379 if (fs != NULL) {
12380 fs->super->s_state |= EXT2_ERROR_FS;
12381 ext2fs_mark_super_dirty(fs);
12382 ext2fs_close(fs);
12383 }
12384 exit(EXIT_UNCORRECTED);
12385}
12386
12387void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12388 struct ext2_inode * inode, const char *proc)
12389{
12390 int retval;
12391
12392 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12393 if (retval) {
12394 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12395 bb_error_msg_and_die(0);
12396 }
12397}
12398
12399extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12400 struct ext2_inode * inode, int bufsize,
12401 const char *proc)
12402{
12403 int retval;
12404
12405 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12406 if (retval) {
12407 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12408 bb_error_msg_and_die(0);
12409 }
12410}
12411
12412extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12413 struct ext2_inode * inode, const char *proc)
12414{
12415 int retval;
12416
12417 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12418 if (retval) {
12419 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12420 bb_error_msg_and_die(0);
12421 }
12422}
12423
12424blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12425 io_manager manager)
12426{
12427 struct ext2_super_block *sb;
12428 io_channel io = NULL;
12429 void *buf = NULL;
12430 int blocksize;
12431 blk_t superblock, ret_sb = 8193;
12432
12433 if (fs && fs->super) {
12434 ret_sb = (fs->super->s_blocks_per_group +
12435 fs->super->s_first_data_block);
12436 if (ctx) {
12437 ctx->superblock = ret_sb;
12438 ctx->blocksize = fs->blocksize;
12439 }
12440 return ret_sb;
12441 }
12442
12443 if (ctx) {
12444 if (ctx->blocksize) {
12445 ret_sb = ctx->blocksize * 8;
12446 if (ctx->blocksize == 1024)
12447 ret_sb++;
12448 ctx->superblock = ret_sb;
12449 return ret_sb;
12450 }
12451 ctx->superblock = ret_sb;
12452 ctx->blocksize = 1024;
12453 }
12454
12455 if (!name || !manager)
12456 goto cleanup;
12457
12458 if (manager->open(name, 0, &io) != 0)
12459 goto cleanup;
12460
12461 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12462 goto cleanup;
12463 sb = (struct ext2_super_block *) buf;
12464
12465 for (blocksize = EXT2_MIN_BLOCK_SIZE;
Denis Vlasenkob71c6682007-07-21 15:08:09 +000012466 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012467 superblock = blocksize*8;
12468 if (blocksize == 1024)
12469 superblock++;
12470 io_channel_set_blksize(io, blocksize);
12471 if (io_channel_read_blk(io, superblock,
12472 -SUPERBLOCK_SIZE, buf))
12473 continue;
12474#if BB_BIG_ENDIAN
12475 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12476 ext2fs_swap_super(sb);
12477#endif
12478 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12479 ret_sb = superblock;
12480 if (ctx) {
12481 ctx->superblock = superblock;
12482 ctx->blocksize = blocksize;
12483 }
12484 break;
12485 }
12486 }
12487
12488cleanup:
12489 if (io)
12490 io_channel_close(io);
12491 ext2fs_free_mem(&buf);
12492 return ret_sb;
12493}
12494
12495
12496/*
12497 * This function runs through the e2fsck passes and calls them all,
12498 * returning restart, abort, or cancel as necessary...
12499 */
12500typedef void (*pass_t)(e2fsck_t ctx);
12501
12502static const pass_t e2fsck_passes[] = {
12503 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12504 e2fsck_pass5, 0 };
12505
12506#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12507
12508static int e2fsck_run(e2fsck_t ctx)
12509{
12510 int i;
12511 pass_t e2fsck_pass;
12512
12513 if (setjmp(ctx->abort_loc)) {
12514 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12515 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12516 }
12517 ctx->flags |= E2F_FLAG_SETJMP_OK;
12518
12519 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12520 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12521 break;
12522 e2fsck_pass(ctx);
12523 if (ctx->progress)
12524 (void) (ctx->progress)(ctx, 0, 0, 0);
12525 }
12526 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12527
12528 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12529 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12530 return 0;
12531}
12532
12533
12534/*
12535 * unix.c - The unix-specific code for e2fsck
12536 */
12537
12538
12539/* Command line options */
12540static int swapfs;
12541#ifdef ENABLE_SWAPFS
12542static int normalize_swapfs;
12543#endif
12544static int cflag; /* check disk */
12545static int show_version_only;
12546static int verbose;
12547
12548#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12549
12550static void show_stats(e2fsck_t ctx)
12551{
12552 ext2_filsys fs = ctx->fs;
12553 int inodes, inodes_used, blocks, blocks_used;
12554 int dir_links;
12555 int num_files, num_links;
12556 int frag_percent;
12557
12558 dir_links = 2 * ctx->fs_directory_count - 1;
12559 num_files = ctx->fs_total_count - dir_links;
12560 num_links = ctx->fs_links_count - dir_links;
12561 inodes = fs->super->s_inodes_count;
12562 inodes_used = (fs->super->s_inodes_count -
12563 fs->super->s_free_inodes_count);
12564 blocks = fs->super->s_blocks_count;
12565 blocks_used = (fs->super->s_blocks_count -
12566 fs->super->s_free_blocks_count);
12567
12568 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12569 frag_percent = (frag_percent + 5) / 10;
12570
12571 if (!verbose) {
12572 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12573 ctx->device_name, inodes_used, inodes,
12574 frag_percent / 10, frag_percent % 10,
12575 blocks_used, blocks);
12576 return;
12577 }
12578 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12579 100 * inodes_used / inodes);
12580 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12581 P_E2("", "s", ctx->fs_fragmented),
12582 frag_percent / 10, frag_percent % 10);
12583 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12584 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12585 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12586 (int) ((long long) 100 * blocks_used / blocks));
12587 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12588 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12589 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12590 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12591 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12592 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12593 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12594 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12595 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12596 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12597 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12598}
12599
12600static void check_mount(e2fsck_t ctx)
12601{
12602 errcode_t retval;
12603 int cont;
12604
12605 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12606 &ctx->mount_flags);
12607 if (retval) {
Denis Vlasenko54d10052008-12-24 03:11:43 +000012608 bb_error_msg(_("while determining whether %s is mounted"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012609 ctx->filesystem_name);
12610 return;
12611 }
12612
12613 /*
12614 * If the filesystem isn't mounted, or it's the root filesystem
12615 * and it's mounted read-only, then everything's fine.
12616 */
12617 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12618 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12619 (ctx->mount_flags & EXT2_MF_READONLY)))
12620 return;
12621
12622 if (ctx->options & E2F_OPT_READONLY) {
12623 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12624 return;
12625 }
12626
12627 printf(_("%s is mounted. "), ctx->filesystem_name);
12628 if (!ctx->interactive)
Denys Vlasenko6331cf02009-11-13 09:08:27 +010012629 bb_error_msg_and_die(_("can't continue, aborting"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012630 printf(_("\n\n\007\007\007\007WARNING!!! "
12631 "Running e2fsck on a mounted filesystem may cause\n"
12632 "SEVERE filesystem damage.\007\007\007\n\n"));
12633 cont = ask_yn(_("Do you really want to continue"), -1);
12634 if (!cont) {
12635 printf(_("check aborted.\n"));
Denis Vlasenko6398cf42007-04-11 17:04:29 +000012636 exit(0);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012637 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012638}
12639
12640static int is_on_batt(void)
12641{
12642 FILE *f;
12643 DIR *d;
12644 char tmp[80], tmp2[80], fname[80];
12645 unsigned int acflag;
12646 struct dirent* de;
12647
Denis Vlasenko5415c852008-07-21 23:05:26 +000012648 f = fopen_for_read("/proc/apm");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012649 if (f) {
12650 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12651 acflag = 1;
12652 fclose(f);
12653 return (acflag != 1);
12654 }
12655 d = opendir("/proc/acpi/ac_adapter");
12656 if (d) {
12657 while ((de=readdir(d)) != NULL) {
12658 if (!strncmp(".", de->d_name, 1))
12659 continue;
12660 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12661 de->d_name);
Denis Vlasenko5415c852008-07-21 23:05:26 +000012662 f = fopen_for_read(fname);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012663 if (!f)
12664 continue;
12665 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12666 tmp[0] = 0;
12667 fclose(f);
12668 if (strncmp(tmp, "off-line", 8) == 0) {
12669 closedir(d);
12670 return 1;
12671 }
12672 }
12673 closedir(d);
12674 }
12675 return 0;
12676}
12677
12678/*
12679 * This routine checks to see if a filesystem can be skipped; if so,
12680 * it will exit with EXIT_OK. Under some conditions it will print a
12681 * message explaining why a check is being forced.
12682 */
12683static void check_if_skip(e2fsck_t ctx)
12684{
12685 ext2_filsys fs = ctx->fs;
12686 const char *reason = NULL;
12687 unsigned int reason_arg = 0;
12688 long next_check;
12689 int batt = is_on_batt();
Denis Vlasenko04158e02009-02-02 10:48:06 +000012690 time_t now = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012691
12692 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12693 return;
12694
12695 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12696 !ext2fs_test_valid(fs))
12697 reason = _(" contains a file system with errors");
12698 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12699 reason = _(" was not cleanly unmounted");
12700 else if ((fs->super->s_max_mnt_count > 0) &&
12701 (fs->super->s_mnt_count >=
12702 (unsigned) fs->super->s_max_mnt_count)) {
12703 reason = _(" has been mounted %u times without being checked");
12704 reason_arg = fs->super->s_mnt_count;
12705 if (batt && (fs->super->s_mnt_count <
12706 (unsigned) fs->super->s_max_mnt_count*2))
12707 reason = 0;
12708 } else if (fs->super->s_checkinterval &&
12709 ((now - fs->super->s_lastcheck) >=
12710 fs->super->s_checkinterval)) {
12711 reason = _(" has gone %u days without being checked");
12712 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12713 if (batt && ((now - fs->super->s_lastcheck) <
12714 fs->super->s_checkinterval*2))
12715 reason = 0;
12716 }
12717 if (reason) {
12718 fputs(ctx->device_name, stdout);
12719 printf(reason, reason_arg);
12720 fputs(_(", check forced.\n"), stdout);
12721 return;
12722 }
12723 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12724 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12725 fs->super->s_inodes_count,
12726 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12727 fs->super->s_blocks_count);
12728 next_check = 100000;
12729 if (fs->super->s_max_mnt_count > 0) {
12730 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12731 if (next_check <= 0)
12732 next_check = 1;
12733 }
12734 if (fs->super->s_checkinterval &&
12735 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12736 next_check = 1;
12737 if (next_check <= 5) {
12738 if (next_check == 1)
12739 fputs(_(" (check after next mount)"), stdout);
12740 else
12741 printf(_(" (check in %ld mounts)"), next_check);
12742 }
Denis Vlasenko4daad902007-09-27 10:20:47 +000012743 bb_putchar('\n');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012744 ext2fs_close(fs);
12745 ctx->fs = NULL;
12746 e2fsck_free_context(ctx);
12747 exit(EXIT_OK);
12748}
12749
12750/*
12751 * For completion notice
12752 */
12753struct percent_tbl {
12754 int max_pass;
12755 int table[32];
12756};
12757static const struct percent_tbl e2fsck_tbl = {
12758 5, { 0, 70, 90, 92, 95, 100 }
12759};
12760
12761static char bar[128], spaces[128];
12762
12763static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12764 int max)
12765{
12766 float percent;
12767
12768 if (pass <= 0)
12769 return 0.0;
12770 if (pass > tbl->max_pass || max == 0)
12771 return 100.0;
12772 percent = ((float) curr) / ((float) max);
12773 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12774 + tbl->table[pass-1]);
12775}
12776
12777void e2fsck_clear_progbar(e2fsck_t ctx)
12778{
12779 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12780 return;
12781
12782 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12783 ctx->stop_meta);
12784 fflush(stdout);
12785 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12786}
12787
12788int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12789 unsigned int dpynum)
12790{
12791 static const char spinner[] = "\\|/-";
12792 int i;
12793 unsigned int tick;
12794 struct timeval tv;
12795 int dpywidth;
12796 int fixed_percent;
12797
12798 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12799 return 0;
12800
12801 /*
12802 * Calculate the new progress position. If the
12803 * percentage hasn't changed, then we skip out right
12804 * away.
12805 */
12806 fixed_percent = (int) ((10 * percent) + 0.5);
12807 if (ctx->progress_last_percent == fixed_percent)
12808 return 0;
12809 ctx->progress_last_percent = fixed_percent;
12810
12811 /*
12812 * If we've already updated the spinner once within
12813 * the last 1/8th of a second, no point doing it
12814 * again.
12815 */
12816 gettimeofday(&tv, NULL);
12817 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12818 if ((tick == ctx->progress_last_time) &&
12819 (fixed_percent != 0) && (fixed_percent != 1000))
12820 return 0;
12821 ctx->progress_last_time = tick;
12822
12823 /*
12824 * Advance the spinner, and note that the progress bar
12825 * will be on the screen
12826 */
12827 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12828 ctx->flags |= E2F_FLAG_PROG_BAR;
12829
12830 dpywidth = 66 - strlen(label);
12831 dpywidth = 8 * (dpywidth / 8);
12832 if (dpynum)
12833 dpywidth -= 8;
12834
12835 i = ((percent * dpywidth) + 50) / 100;
12836 printf("%s%s: |%s%s", ctx->start_meta, label,
12837 bar + (sizeof(bar) - (i+1)),
12838 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12839 if (fixed_percent == 1000)
Denis Vlasenko4daad902007-09-27 10:20:47 +000012840 bb_putchar('|');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012841 else
Denis Vlasenko4daad902007-09-27 10:20:47 +000012842 bb_putchar(spinner[ctx->progress_pos & 3]);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012843 printf(" %4.1f%% ", percent);
12844 if (dpynum)
12845 printf("%u\r", dpynum);
12846 else
12847 fputs(" \r", stdout);
12848 fputs(ctx->stop_meta, stdout);
12849
12850 if (fixed_percent == 1000)
12851 e2fsck_clear_progbar(ctx);
12852 fflush(stdout);
12853
12854 return 0;
12855}
12856
12857static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12858 unsigned long cur, unsigned long max)
12859{
12860 char buf[80];
12861 float percent;
12862
12863 if (pass == 0)
12864 return 0;
12865
12866 if (ctx->progress_fd) {
12867 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
Denis Vlasenko73c571a2009-03-09 00:12:37 +000012868 xwrite_str(ctx->progress_fd, buf);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012869 } else {
12870 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12871 e2fsck_simple_progress(ctx, ctx->device_name,
12872 percent, 0);
12873 }
12874 return 0;
12875}
12876
12877static void reserve_stdio_fds(void)
12878{
12879 int fd;
12880
12881 while (1) {
12882 fd = open(bb_dev_null, O_RDWR);
12883 if (fd > 2)
12884 break;
12885 if (fd < 0) {
12886 fprintf(stderr, _("ERROR: Cannot open "
12887 "/dev/null (%s)\n"),
12888 strerror(errno));
12889 break;
12890 }
12891 }
12892 close(fd);
12893}
12894
12895static void signal_progress_on(int sig FSCK_ATTR((unused)))
12896{
12897 e2fsck_t ctx = e2fsck_global_ctx;
12898
12899 if (!ctx)
12900 return;
12901
12902 ctx->progress = e2fsck_update_progress;
12903 ctx->progress_fd = 0;
12904}
12905
12906static void signal_progress_off(int sig FSCK_ATTR((unused)))
12907{
12908 e2fsck_t ctx = e2fsck_global_ctx;
12909
12910 if (!ctx)
12911 return;
12912
12913 e2fsck_clear_progbar(ctx);
12914 ctx->progress = 0;
12915}
12916
12917static void signal_cancel(int sig FSCK_ATTR((unused)))
12918{
12919 e2fsck_t ctx = e2fsck_global_ctx;
12920
12921 if (!ctx)
12922 exit(FSCK_CANCELED);
12923
12924 ctx->flags |= E2F_FLAG_CANCEL;
12925}
12926
12927static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12928{
12929 char *buf, *token, *next, *p, *arg;
12930 int ea_ver;
12931 int extended_usage = 0;
12932
12933 buf = string_copy(opts, 0);
12934 for (token = buf; token && *token; token = next) {
12935 p = strchr(token, ',');
12936 next = 0;
12937 if (p) {
12938 *p = 0;
12939 next = p+1;
12940 }
12941 arg = strchr(token, '=');
12942 if (arg) {
12943 *arg = 0;
12944 arg++;
12945 }
12946 if (strcmp(token, "ea_ver") == 0) {
12947 if (!arg) {
12948 extended_usage++;
12949 continue;
12950 }
12951 ea_ver = strtoul(arg, &p, 0);
12952 if (*p ||
12953 ((ea_ver != 1) && (ea_ver != 2))) {
12954 fprintf(stderr,
12955 _("Invalid EA version.\n"));
12956 extended_usage++;
12957 continue;
12958 }
12959 ctx->ext_attr_ver = ea_ver;
12960 } else {
12961 fprintf(stderr, _("Unknown extended option: %s\n"),
12962 token);
12963 extended_usage++;
12964 }
12965 }
12966 if (extended_usage) {
12967 bb_error_msg_and_die(
12968 "Extended options are separated by commas, "
12969 "and may take an argument which\n"
12970 "is set off by an equals ('=') sign. "
12971 "Valid extended options are:\n"
12972 "\tea_ver=<ea_version (1 or 2)>\n\n");
12973 }
12974}
12975
12976
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000012977static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012978{
12979 int flush = 0;
12980 int c, fd;
12981 e2fsck_t ctx;
12982 errcode_t retval;
12983 struct sigaction sa;
Denys Vlasenko4b1100e2010-03-05 14:10:54 +010012984 char *extended_opts = NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012985
12986 retval = e2fsck_allocate_context(&ctx);
12987 if (retval)
12988 return retval;
12989
12990 *ret_ctx = ctx;
12991
12992 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12993 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12994 if (isatty(0) && isatty(1)) {
12995 ctx->interactive = 1;
12996 } else {
12997 ctx->start_meta[0] = '\001';
12998 ctx->stop_meta[0] = '\002';
12999 }
13000 memset(bar, '=', sizeof(bar)-1);
13001 memset(spaces, ' ', sizeof(spaces)-1);
13002 blkid_get_cache(&ctx->blkid, NULL);
13003
13004 if (argc && *argv)
13005 ctx->program_name = *argv;
13006 else
13007 ctx->program_name = "e2fsck";
13008 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13009 switch (c) {
13010 case 'C':
13011 ctx->progress = e2fsck_update_progress;
13012 ctx->progress_fd = atoi(optarg);
13013 if (!ctx->progress_fd)
13014 break;
13015 /* Validate the file descriptor to avoid disasters */
13016 fd = dup(ctx->progress_fd);
13017 if (fd < 0) {
13018 fprintf(stderr,
13019 _("Error validating file descriptor %d: %s\n"),
13020 ctx->progress_fd,
13021 error_message(errno));
13022 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13023 } else
13024 close(fd);
13025 break;
13026 case 'D':
13027 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13028 break;
13029 case 'E':
13030 extended_opts = optarg;
13031 break;
13032 case 'p':
13033 case 'a':
13034 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13035 conflict_opt:
Denis Vlasenko54d10052008-12-24 03:11:43 +000013036 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013037 }
13038 ctx->options |= E2F_OPT_PREEN;
13039 break;
13040 case 'n':
13041 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13042 goto conflict_opt;
13043 ctx->options |= E2F_OPT_NO;
13044 break;
13045 case 'y':
13046 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13047 goto conflict_opt;
13048 ctx->options |= E2F_OPT_YES;
13049 break;
13050 case 't':
13051 /* FIXME - This needs to go away in a future path - will change binary */
13052 fprintf(stderr, _("The -t option is not "
13053 "supported on this version of e2fsck.\n"));
13054 break;
13055 case 'c':
13056 if (cflag++)
13057 ctx->options |= E2F_OPT_WRITECHECK;
13058 ctx->options |= E2F_OPT_CHECKBLOCKS;
13059 break;
13060 case 'r':
13061 /* What we do by default, anyway! */
13062 break;
13063 case 'b':
13064 ctx->use_superblock = atoi(optarg);
13065 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13066 break;
13067 case 'B':
13068 ctx->blocksize = atoi(optarg);
13069 break;
13070 case 'I':
13071 ctx->inode_buffer_blocks = atoi(optarg);
13072 break;
13073 case 'j':
13074 ctx->journal_name = string_copy(optarg, 0);
13075 break;
13076 case 'P':
13077 ctx->process_inode_size = atoi(optarg);
13078 break;
13079 case 'd':
13080 ctx->options |= E2F_OPT_DEBUG;
13081 break;
13082 case 'f':
13083 ctx->options |= E2F_OPT_FORCE;
13084 break;
13085 case 'F':
13086 flush = 1;
13087 break;
13088 case 'v':
13089 verbose = 1;
13090 break;
13091 case 'V':
13092 show_version_only = 1;
13093 break;
13094 case 'N':
13095 ctx->device_name = optarg;
13096 break;
13097#ifdef ENABLE_SWAPFS
13098 case 's':
13099 normalize_swapfs = 1;
13100 case 'S':
13101 swapfs = 1;
13102 break;
13103#else
13104 case 's':
13105 case 'S':
13106 fprintf(stderr, _("Byte-swapping filesystems "
13107 "not compiled in this version "
13108 "of e2fsck\n"));
13109 exit(1);
13110#endif
13111 default:
13112 bb_show_usage();
13113 }
13114 if (show_version_only)
13115 return 0;
13116 if (optind != argc - 1)
13117 bb_show_usage();
13118 if ((ctx->options & E2F_OPT_NO) &&
13119 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13120 ctx->options |= E2F_OPT_READONLY;
13121 ctx->io_options = strchr(argv[optind], '?');
13122 if (ctx->io_options)
13123 *ctx->io_options++ = 0;
13124 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13125 if (!ctx->filesystem_name) {
13126 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13127 bb_error_msg_and_die(0);
13128 }
13129 if (extended_opts)
13130 parse_extended_opts(ctx, extended_opts);
13131
13132 if (flush) {
13133 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13134 if (fd < 0) {
13135 bb_error_msg(_("while opening %s for flushing"),
13136 ctx->filesystem_name);
13137 bb_error_msg_and_die(0);
13138 }
13139 if ((retval = ext2fs_sync_device(fd, 1))) {
13140 bb_error_msg(_("while trying to flush %s"),
13141 ctx->filesystem_name);
13142 bb_error_msg_and_die(0);
13143 }
13144 close(fd);
13145 }
13146#ifdef ENABLE_SWAPFS
13147 if (swapfs && cflag) {
13148 fprintf(stderr, _("Incompatible options not "
13149 "allowed when byte-swapping.\n"));
13150 exit(EXIT_USAGE);
13151 }
13152#endif
13153 /*
13154 * Set up signal action
13155 */
13156 memset(&sa, 0, sizeof(struct sigaction));
13157 sa.sa_handler = signal_cancel;
13158 sigaction(SIGINT, &sa, 0);
13159 sigaction(SIGTERM, &sa, 0);
13160#ifdef SA_RESTART
13161 sa.sa_flags = SA_RESTART;
13162#endif
13163 e2fsck_global_ctx = ctx;
13164 sa.sa_handler = signal_progress_on;
13165 sigaction(SIGUSR1, &sa, 0);
13166 sa.sa_handler = signal_progress_off;
13167 sigaction(SIGUSR2, &sa, 0);
13168
13169 /* Update our PATH to include /sbin if we need to run badblocks */
13170 if (cflag)
13171 e2fs_set_sbin_path();
13172 return 0;
13173}
13174
13175static const char my_ver_string[] = E2FSPROGS_VERSION;
13176static const char my_ver_date[] = E2FSPROGS_DATE;
13177
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013178int e2fsck_main (int argc, char **argv);
13179int e2fsck_main (int argc, char **argv)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013180{
13181 errcode_t retval;
13182 int exit_value = EXIT_OK;
13183 ext2_filsys fs = 0;
13184 io_manager io_ptr;
13185 struct ext2_super_block *sb;
13186 const char *lib_ver_date;
13187 int my_ver, lib_ver;
13188 e2fsck_t ctx;
13189 struct problem_context pctx;
13190 int flags, run_result;
13191
13192 clear_problem_context(&pctx);
13193
13194 my_ver = ext2fs_parse_version_string(my_ver_string);
13195 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13196 if (my_ver > lib_ver) {
13197 fprintf( stderr, _("Error: ext2fs library version "
13198 "out of date!\n"));
13199 show_version_only++;
13200 }
13201
13202 retval = PRS(argc, argv, &ctx);
13203 if (retval) {
13204 bb_error_msg(_("while trying to initialize program"));
13205 exit(EXIT_ERROR);
13206 }
13207 reserve_stdio_fds();
13208
13209 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13210 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13211 my_ver_date);
13212
13213 if (show_version_only) {
13214 fprintf(stderr, _("\tUsing %s, %s\n"),
13215 error_message(EXT2_ET_BASE), lib_ver_date);
13216 exit(EXIT_OK);
13217 }
13218
13219 check_mount(ctx);
13220
13221 if (!(ctx->options & E2F_OPT_PREEN) &&
13222 !(ctx->options & E2F_OPT_NO) &&
13223 !(ctx->options & E2F_OPT_YES)) {
13224 if (!ctx->interactive)
13225 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13226 }
13227 ctx->superblock = ctx->use_superblock;
13228restart:
13229#ifdef CONFIG_TESTIO_DEBUG
13230 io_ptr = test_io_manager;
13231 test_io_backing_manager = unix_io_manager;
13232#else
13233 io_ptr = unix_io_manager;
13234#endif
13235 flags = 0;
13236 if ((ctx->options & E2F_OPT_READONLY) == 0)
13237 flags |= EXT2_FLAG_RW;
13238
13239 if (ctx->superblock && ctx->blocksize) {
13240 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13241 flags, ctx->superblock, ctx->blocksize,
13242 io_ptr, &fs);
13243 } else if (ctx->superblock) {
13244 int blocksize;
13245 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13246 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13247 retval = ext2fs_open2(ctx->filesystem_name,
13248 ctx->io_options, flags,
13249 ctx->superblock, blocksize,
13250 io_ptr, &fs);
13251 if (!retval)
13252 break;
13253 }
13254 } else
13255 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13256 flags, 0, 0, io_ptr, &fs);
13257 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13258 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13259 ((retval == EXT2_ET_BAD_MAGIC) ||
13260 ((retval == 0) && ext2fs_check_desc(fs)))) {
13261 if (!fs || (fs->group_desc_count > 1)) {
13262 printf(_("%s trying backup blocks...\n"),
13263 retval ? _("Couldn't find ext2 superblock,") :
13264 _("Group descriptors look bad..."));
13265 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13266 if (fs)
13267 ext2fs_close(fs);
13268 goto restart;
13269 }
13270 }
13271 if (retval) {
13272 bb_error_msg(_("while trying to open %s"),
13273 ctx->filesystem_name);
13274 if (retval == EXT2_ET_REV_TOO_HIGH) {
13275 printf(_("The filesystem revision is apparently "
13276 "too high for this version of e2fsck.\n"
13277 "(Or the filesystem superblock "
13278 "is corrupt)\n\n"));
13279 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13280 } else if (retval == EXT2_ET_SHORT_READ)
13281 printf(_("Could this be a zero-length partition?\n"));
13282 else if ((retval == EPERM) || (retval == EACCES))
13283 printf(_("You must have %s access to the "
13284 "filesystem or be root\n"),
13285 (ctx->options & E2F_OPT_READONLY) ?
13286 "r/o" : "r/w");
13287 else if (retval == ENXIO)
13288 printf(_("Possibly non-existent or swap device?\n"));
13289#ifdef EROFS
13290 else if (retval == EROFS)
13291 printf(_("Disk write-protected; use the -n option "
13292 "to do a read-only\n"
13293 "check of the device.\n"));
13294#endif
13295 else
13296 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13297 bb_error_msg_and_die(0);
13298 }
13299 ctx->fs = fs;
13300 fs->priv_data = ctx;
13301 sb = fs->super;
13302 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13303 bb_error_msg(_("while trying to open %s"),
13304 ctx->filesystem_name);
13305 get_newer:
13306 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13307 }
13308
13309 /*
13310 * Set the device name, which is used whenever we print error
13311 * or informational messages to the user.
13312 */
13313 if (ctx->device_name == 0 &&
13314 (sb->s_volume_name[0] != 0)) {
13315 ctx->device_name = string_copy(sb->s_volume_name,
13316 sizeof(sb->s_volume_name));
13317 }
13318 if (ctx->device_name == 0)
13319 ctx->device_name = ctx->filesystem_name;
13320
13321 /*
13322 * Make sure the ext3 superblock fields are consistent.
13323 */
13324 retval = e2fsck_check_ext3_journal(ctx);
13325 if (retval) {
13326 bb_error_msg(_("while checking ext3 journal for %s"),
13327 ctx->device_name);
13328 bb_error_msg_and_die(0);
13329 }
13330
13331 /*
13332 * Check to see if we need to do ext3-style recovery. If so,
13333 * do it, and then restart the fsck.
13334 */
13335 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13336 if (ctx->options & E2F_OPT_READONLY) {
13337 printf(_("Warning: skipping journal recovery "
13338 "because doing a read-only filesystem "
13339 "check.\n"));
13340 io_channel_flush(ctx->fs->io);
13341 } else {
13342 if (ctx->flags & E2F_FLAG_RESTARTED) {
13343 /*
13344 * Whoops, we attempted to run the
13345 * journal twice. This should never
13346 * happen, unless the hardware or
13347 * device driver is being bogus.
13348 */
Denys Vlasenko6331cf02009-11-13 09:08:27 +010013349 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013350 bb_error_msg_and_die(0);
13351 }
13352 retval = e2fsck_run_ext3_journal(ctx);
13353 if (retval) {
13354 bb_error_msg(_("while recovering ext3 journal of %s"),
13355 ctx->device_name);
13356 bb_error_msg_and_die(0);
13357 }
13358 ext2fs_close(ctx->fs);
13359 ctx->fs = 0;
13360 ctx->flags |= E2F_FLAG_RESTARTED;
13361 goto restart;
13362 }
13363 }
13364
13365 /*
13366 * Check for compatibility with the feature sets. We need to
13367 * be more stringent than ext2fs_open().
13368 */
13369 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13370 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13371 bb_error_msg("(%s)", ctx->device_name);
13372 goto get_newer;
13373 }
13374 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13375 bb_error_msg("(%s)", ctx->device_name);
13376 goto get_newer;
13377 }
13378#ifdef ENABLE_COMPRESSION
13379 /* FIXME - do we support this at all? */
13380 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
Denis Vlasenko54d10052008-12-24 03:11:43 +000013381 bb_error_msg(_("warning: compression support is experimental"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013382#endif
13383#ifndef ENABLE_HTREE
13384 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13385 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13386 "but filesystem %s has HTREE directories."),
13387 ctx->device_name);
13388 goto get_newer;
13389 }
13390#endif
13391
13392 /*
13393 * If the user specified a specific superblock, presumably the
13394 * master superblock has been trashed. So we mark the
13395 * superblock as dirty, so it can be written out.
13396 */
13397 if (ctx->superblock &&
13398 !(ctx->options & E2F_OPT_READONLY))
13399 ext2fs_mark_super_dirty(fs);
13400
13401 /*
13402 * We only update the master superblock because (a) paranoia;
13403 * we don't want to corrupt the backup superblocks, and (b) we
13404 * don't need to update the mount count and last checked
13405 * fields in the backup superblock (the kernel doesn't
13406 * update the backup superblocks anyway).
13407 */
13408 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13409
13410 ehandler_init(fs->io);
13411
13412 if (ctx->superblock)
13413 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13414 ext2fs_mark_valid(fs);
13415 check_super_block(ctx);
13416 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13417 bb_error_msg_and_die(0);
13418 check_if_skip(ctx);
13419 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13420 bb_error_msg_and_die(0);
13421#ifdef ENABLE_SWAPFS
13422
13423#ifdef WORDS_BIGENDIAN
13424#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13425#else
13426#define NATIVE_FLAG 0
13427#endif
13428
13429
13430 if (normalize_swapfs) {
13431 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13432 fprintf(stderr, _("%s: Filesystem byte order "
13433 "already normalized.\n"), ctx->device_name);
13434 bb_error_msg_and_die(0);
13435 }
13436 }
13437 if (swapfs) {
13438 swap_filesys(ctx);
13439 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13440 bb_error_msg_and_die(0);
13441 }
13442#endif
13443
13444 /*
13445 * Mark the system as valid, 'til proven otherwise
13446 */
13447 ext2fs_mark_valid(fs);
13448
13449 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13450 if (retval) {
13451 bb_error_msg(_("while reading bad blocks inode"));
13452 preenhalt(ctx);
13453 printf(_("This doesn't bode well,"
13454 " but we'll try to go on...\n"));
13455 }
13456
13457 run_result = e2fsck_run(ctx);
13458 e2fsck_clear_progbar(ctx);
13459 if (run_result == E2F_FLAG_RESTART) {
13460 printf(_("Restarting e2fsck from the beginning...\n"));
13461 retval = e2fsck_reset_context(ctx);
13462 if (retval) {
13463 bb_error_msg(_("while resetting context"));
13464 bb_error_msg_and_die(0);
13465 }
13466 ext2fs_close(fs);
13467 goto restart;
13468 }
13469 if (run_result & E2F_FLAG_CANCEL) {
13470 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13471 ctx->device_name : ctx->filesystem_name);
13472 exit_value |= FSCK_CANCELED;
13473 }
13474 if (run_result & E2F_FLAG_ABORT)
13475 bb_error_msg_and_die(_("aborted"));
13476
13477 /* Cleanup */
13478 if (ext2fs_test_changed(fs)) {
13479 exit_value |= EXIT_NONDESTRUCT;
13480 if (!(ctx->options & E2F_OPT_PREEN))
13481 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13482 ctx->device_name);
13483 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13484 printf(_("%s: ***** REBOOT LINUX *****\n"),
13485 ctx->device_name);
13486 exit_value |= EXIT_DESTRUCT;
13487 }
13488 }
13489 if (!ext2fs_test_valid(fs)) {
13490 printf(_("\n%s: ********** WARNING: Filesystem still has "
13491 "errors **********\n\n"), ctx->device_name);
13492 exit_value |= EXIT_UNCORRECTED;
13493 exit_value &= ~EXIT_NONDESTRUCT;
13494 }
13495 if (exit_value & FSCK_CANCELED)
13496 exit_value &= ~EXIT_NONDESTRUCT;
13497 else {
13498 show_stats(ctx);
13499 if (!(ctx->options & E2F_OPT_READONLY)) {
13500 if (ext2fs_test_valid(fs)) {
13501 if (!(sb->s_state & EXT2_VALID_FS))
13502 exit_value |= EXIT_NONDESTRUCT;
13503 sb->s_state = EXT2_VALID_FS;
13504 } else
13505 sb->s_state &= ~EXT2_VALID_FS;
13506 sb->s_mnt_count = 0;
13507 sb->s_lastcheck = time(NULL);
13508 ext2fs_mark_super_dirty(fs);
13509 }
13510 }
13511
13512 e2fsck_write_bitmaps(ctx);
13513
13514 ext2fs_close(fs);
13515 ctx->fs = NULL;
13516 free(ctx->filesystem_name);
13517 free(ctx->journal_name);
13518 e2fsck_free_context(ctx);
13519
13520 return exit_value;
13521}