blob: 7e0996956eefaac909d5c769e564d7bbf67c3be3 [file] [log] [blame]
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001/* vi: set sw=4 ts=4: */
2/*
3 * e2fsck
4 *
5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
6 * Copyright (C) 2006 Garrett Kajmowicz
7 *
8 * Dictionary Abstract Data Type
9 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
10 * Free Software License:
11 * All rights are reserved by the author, with the following exceptions:
12 * Permission is granted to freely reproduce and distribute this software,
13 * possibly in exchange for a fee, provided that this copyright notice appears
14 * intact. Permission is also granted to adapt this software to produce
15 * derivative works, as long as the modified versions carry this copyright
16 * notice and additional notices stating that the work has been modified.
17 * This source code may be translated into executable form and incorporated
18 * into proprietary software; there is no requirement for such software to
19 * contain a copyright notice related to this source.
20 *
21 * linux/fs/recovery and linux/fs/revoke
22 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
23 *
24 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
25 *
26 * Journal recovery routines for the generic filesystem journaling code;
27 * part of the ext2fs journaling system.
28 *
29 * Licensed under GPLv2 or later, see file License in this tarball for details.
30 */
31
32#ifndef _GNU_SOURCE
33#define _GNU_SOURCE 1 /* get strnlen() */
34#endif
35
36#include "e2fsck.h" /*Put all of our defines here to clean things up*/
37
38#define _(x) x
39#define N_(x) x
40
41/*
42 * Procedure declarations
43 */
44
45static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
46
47/* pass1.c */
48static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
49
50/* pass2.c */
51static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
52 ext2_ino_t ino, char *buf);
53
54/* pass3.c */
55static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
56static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
57 int num, int gauranteed_size);
58static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
59static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
60 int adj);
61
62/* rehash.c */
63static void e2fsck_rehash_directories(e2fsck_t ctx);
64
65/* util.c */
66static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
67 const char *description);
68static int ask(e2fsck_t ctx, const char * string, int def);
69static void e2fsck_read_bitmaps(e2fsck_t ctx);
70static void preenhalt(e2fsck_t ctx);
71static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
72 struct ext2_inode * inode, const char * proc);
73static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
74 struct ext2_inode * inode, const char * proc);
75static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
76 const char *name, io_manager manager);
77
78/* unix.c */
79static void e2fsck_clear_progbar(e2fsck_t ctx);
80static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
81 float percent, unsigned int dpynum);
82
83
84/*
85 * problem.h --- e2fsck problem error codes
86 */
87
88typedef __u32 problem_t;
89
90struct problem_context {
91 errcode_t errcode;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010092 ext2_ino_t ino, ino2, dir;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000093 struct ext2_inode *inode;
94 struct ext2_dir_entry *dirent;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010095 blk_t blk, blk2;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000096 e2_blkcnt_t blkcount;
97 int group;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010098 __u64 num;
99 const char *str;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000100};
101
102
103/*
104 * Function declarations
105 */
106static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
107static int end_problem_latch(e2fsck_t ctx, int mask);
108static int set_latch_flags(int mask, int setflags, int clearflags);
109static void clear_problem_context(struct problem_context *ctx);
110
111/*
112 * Dictionary Abstract Data Type
113 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
114 *
115 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
116 * kazlib_1_20
117 */
118
119#ifndef DICT_H
120#define DICT_H
121
122/*
123 * Blurb for inclusion into C++ translation units
124 */
125
126typedef unsigned long dictcount_t;
127#define DICTCOUNT_T_MAX ULONG_MAX
128
129/*
130 * The dictionary is implemented as a red-black tree
131 */
132
133typedef enum { dnode_red, dnode_black } dnode_color_t;
134
135typedef struct dnode_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100136 struct dnode_t *dict_left;
137 struct dnode_t *dict_right;
138 struct dnode_t *dict_parent;
139 dnode_color_t dict_color;
140 const void *dict_key;
141 void *dict_data;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000142} dnode_t;
143
144typedef int (*dict_comp_t)(const void *, const void *);
145typedef void (*dnode_free_t)(dnode_t *);
146
147typedef struct dict_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100148 dnode_t dict_nilnode;
149 dictcount_t dict_nodecount;
150 dictcount_t dict_maxcount;
151 dict_comp_t dict_compare;
152 dnode_free_t dict_freenode;
153 int dict_dupes;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000154} dict_t;
155
156typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
157
158typedef struct dict_load_t {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100159 dict_t *dict_dictptr;
160 dnode_t dict_nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000161} dict_load_t;
162
163#define dict_count(D) ((D)->dict_nodecount)
164#define dnode_get(N) ((N)->dict_data)
165#define dnode_getkey(N) ((N)->dict_key)
166
167#endif
168
169/*
170 * Compatibility header file for e2fsck which should be included
171 * instead of linux/jfs.h
172 *
173 * Copyright (C) 2000 Stephen C. Tweedie
174 */
175
176/*
177 * Pull in the definition of the e2fsck context structure
178 */
179
180struct buffer_head {
181 char b_data[8192];
182 e2fsck_t b_ctx;
183 io_channel b_io;
184 int b_size;
185 blk_t b_blocknr;
186 int b_dirty;
187 int b_uptodate;
188 int b_err;
189};
190
191
192#define K_DEV_FS 1
193#define K_DEV_JOURNAL 2
194
Denis Vlasenkobb045062008-09-27 14:06:06 +0000195#define lock_buffer(bh) do {} while (0)
196#define unlock_buffer(bh) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000197#define buffer_req(bh) 1
Denis Vlasenkobb045062008-09-27 14:06:06 +0000198#define do_readahead(journal, start) do {} while (0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000199
200static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
201
202typedef struct {
203 int object_length;
204} kmem_cache_t;
205
206#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
207
208/*
209 * We use the standard libext2fs portability tricks for inline
210 * functions.
211 */
212
213static kmem_cache_t * do_cache_create(int len)
214{
215 kmem_cache_t *new_cache;
216
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100217 new_cache = xmalloc(sizeof(*new_cache));
218 new_cache->object_length = len;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000219 return new_cache;
220}
221
222static void do_cache_destroy(kmem_cache_t *cache)
223{
224 free(cache);
225}
226
227
228/*
229 * Dictionary Abstract Data Type
230 */
231
232
233/*
234 * These macros provide short convenient names for structure members,
235 * which are embellished with dict_ prefixes so that they are
236 * properly confined to the documented namespace. It's legal for a
237 * program which uses dict to define, for instance, a macro called ``parent''.
238 * Such a macro would interfere with the dnode_t struct definition.
239 * In general, highly portable and reusable C modules which expose their
240 * structures need to confine structure member names to well-defined spaces.
241 * The resulting identifiers aren't necessarily convenient to use, nor
242 * readable, in the implementation, however!
243 */
244
245#define left dict_left
246#define right dict_right
247#define parent dict_parent
248#define color dict_color
249#define key dict_key
250#define data dict_data
251
252#define nilnode dict_nilnode
253#define maxcount dict_maxcount
254#define compare dict_compare
255#define dupes dict_dupes
256
257#define dict_root(D) ((D)->nilnode.left)
258#define dict_nil(D) (&(D)->nilnode)
259
260static void dnode_free(dnode_t *node);
261
262/*
263 * Perform a ``left rotation'' adjustment on the tree. The given node P and
264 * its right child C are rearranged so that the P instead becomes the left
265 * child of C. The left subtree of C is inherited as the new right subtree
266 * for P. The ordering of the keys within the tree is thus preserved.
267 */
268
269static void rotate_left(dnode_t *upper)
270{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100271 dnode_t *lower, *lowleft, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000272
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100273 lower = upper->right;
274 upper->right = lowleft = lower->left;
275 lowleft->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000276
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100277 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000278
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100279 /* don't need to check for root node here because root->parent is
280 the sentinel nil node, and root->parent->left points back to root */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000281
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100282 if (upper == upparent->left) {
283 upparent->left = lower;
284 } else {
285 assert (upper == upparent->right);
286 upparent->right = lower;
287 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000288
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100289 lower->left = upper;
290 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000291}
292
293/*
294 * This operation is the ``mirror'' image of rotate_left. It is
295 * the same procedure, but with left and right interchanged.
296 */
297
298static void rotate_right(dnode_t *upper)
299{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100300 dnode_t *lower, *lowright, *upparent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000301
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100302 lower = upper->left;
303 upper->left = lowright = lower->right;
304 lowright->parent = upper;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000305
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100306 lower->parent = upparent = upper->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000307
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100308 if (upper == upparent->right) {
309 upparent->right = lower;
310 } else {
311 assert (upper == upparent->left);
312 upparent->left = lower;
313 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000314
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100315 lower->right = upper;
316 upper->parent = lower;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000317}
318
319/*
320 * Do a postorder traversal of the tree rooted at the specified
321 * node and free everything under it. Used by dict_free().
322 */
323
324static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
325{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100326 if (node == nil)
327 return;
328 free_nodes(dict, node->left, nil);
329 free_nodes(dict, node->right, nil);
330 dict->dict_freenode(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000331}
332
333/*
334 * Verify that the tree contains the given node. This is done by
335 * traversing all of the nodes and comparing their pointers to the
336 * given pointer. Returns 1 if the node is found, otherwise
337 * returns zero. It is intended for debugging purposes.
338 */
339
340static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
341{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100342 if (root != nil) {
343 return root == node
344 || verify_dict_has_node(nil, root->left, node)
345 || verify_dict_has_node(nil, root->right, node);
346 }
347 return 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000348}
349
350
351/*
352 * Select a different set of node allocator routines.
353 */
354
355static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
356{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100357 assert(dict_count(dict) == 0);
358 dict->dict_freenode = fr;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000359}
360
361/*
362 * Free all the nodes in the dictionary by using the dictionary's
363 * installed free routine. The dictionary is emptied.
364 */
365
366static void dict_free_nodes(dict_t *dict)
367{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100368 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
369 free_nodes(dict, root, nil);
370 dict->dict_nodecount = 0;
371 dict->nilnode.left = &dict->nilnode;
372 dict->nilnode.right = &dict->nilnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000373}
374
375/*
376 * Initialize a user-supplied dictionary object.
377 */
378
379static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
380{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100381 dict->compare = comp;
382 dict->dict_freenode = dnode_free;
383 dict->dict_nodecount = 0;
384 dict->maxcount = maxcount;
385 dict->nilnode.left = &dict->nilnode;
386 dict->nilnode.right = &dict->nilnode;
387 dict->nilnode.parent = &dict->nilnode;
388 dict->nilnode.color = dnode_black;
389 dict->dupes = 0;
390 return dict;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000391}
392
393/*
394 * Locate a node in the dictionary having the given key.
395 * If the node is not found, a null a pointer is returned (rather than
396 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
397 * located node is returned.
398 */
399
400static dnode_t *dict_lookup(dict_t *dict, const void *key)
401{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100402 dnode_t *root = dict_root(dict);
403 dnode_t *nil = dict_nil(dict);
404 dnode_t *saved;
405 int result;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000406
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100407 /* simple binary search adapted for trees that contain duplicate keys */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000408
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100409 while (root != nil) {
410 result = dict->compare(key, root->key);
411 if (result < 0)
412 root = root->left;
413 else if (result > 0)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000414 root = root->right;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100415 else {
416 if (!dict->dupes) { /* no duplicates, return match */
417 return root;
418 } else { /* could be dupes, find leftmost one */
419 do {
420 saved = root;
421 root = root->left;
422 while (root != nil && dict->compare(key, root->key))
423 root = root->right;
424 } while (root != nil);
425 return saved;
426 }
427 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000428 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000429
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100430 return NULL;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000431}
432
433/*
434 * Insert a node into the dictionary. The node should have been
435 * initialized with a data field. All other fields are ignored.
436 * The behavior is undefined if the user attempts to insert into
437 * a dictionary that is already full (for which the dict_isfull()
438 * function returns true).
439 */
440
441static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
442{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100443 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
444 dnode_t *parent = nil, *uncle, *grandpa;
445 int result = -1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000446
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100447 node->key = key;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000448
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100449 /* basic binary tree insert */
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000450
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100451 while (where != nil) {
452 parent = where;
453 result = dict->compare(key, where->key);
454 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
455 assert(dict->dupes || result != 0);
456 if (result < 0)
457 where = where->left;
458 else
459 where = where->right;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000460 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000461
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100462 assert(where == nil);
463
464 if (result < 0)
465 parent->left = node;
466 else
467 parent->right = node;
468
469 node->parent = parent;
470 node->left = nil;
471 node->right = nil;
472
473 dict->dict_nodecount++;
474
475 /* red black adjustments */
476
477 node->color = dnode_red;
478
479 while (parent->color == dnode_red) {
480 grandpa = parent->parent;
481 if (parent == grandpa->left) {
482 uncle = grandpa->right;
483 if (uncle->color == dnode_red) { /* red parent, red uncle */
484 parent->color = dnode_black;
485 uncle->color = dnode_black;
486 grandpa->color = dnode_red;
487 node = grandpa;
488 parent = grandpa->parent;
489 } else { /* red parent, black uncle */
490 if (node == parent->right) {
491 rotate_left(parent);
492 parent = node;
493 assert (grandpa == parent->parent);
494 /* rotation between parent and child preserves grandpa */
495 }
496 parent->color = dnode_black;
497 grandpa->color = dnode_red;
498 rotate_right(grandpa);
499 break;
500 }
501 } else { /* symmetric cases: parent == parent->parent->right */
502 uncle = grandpa->left;
503 if (uncle->color == dnode_red) {
504 parent->color = dnode_black;
505 uncle->color = dnode_black;
506 grandpa->color = dnode_red;
507 node = grandpa;
508 parent = grandpa->parent;
509 } else {
510 if (node == parent->left) {
511 rotate_right(parent);
512 parent = node;
513 assert (grandpa == parent->parent);
514 }
515 parent->color = dnode_black;
516 grandpa->color = dnode_red;
517 rotate_left(grandpa);
518 break;
519 }
520 }
521 }
522
523 dict_root(dict)->color = dnode_black;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000524
525}
526
527/*
528 * Allocate a node using the dictionary's allocator routine, give it
529 * the data item.
530 */
531
532static dnode_t *dnode_init(dnode_t *dnode, void *data)
533{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100534 dnode->data = data;
535 dnode->parent = NULL;
536 dnode->left = NULL;
537 dnode->right = NULL;
538 return dnode;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000539}
540
541static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
542{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100543 dnode_t *node = xmalloc(sizeof(dnode_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000544
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000545 dnode_init(node, data);
546 dict_insert(dict, node, key);
547 return 1;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000548}
549
550/*
551 * Return the node with the lowest (leftmost) key. If the dictionary is empty
552 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
553 */
554
555static dnode_t *dict_first(dict_t *dict)
556{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100557 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000558
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100559 if (root != nil)
560 while ((left = root->left) != nil)
561 root = left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000562
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100563 return (root == nil) ? NULL : root;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000564}
565
566/*
567 * Return the given node's successor node---the node which has the
568 * next key in the the left to right ordering. If the node has
569 * no successor, a null pointer is returned rather than a pointer to
570 * the nil node.
571 */
572
573static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
574{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100575 dnode_t *nil = dict_nil(dict), *parent, *left;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000576
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100577 if (curr->right != nil) {
578 curr = curr->right;
579 while ((left = curr->left) != nil)
580 curr = left;
581 return curr;
582 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000583
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000584 parent = curr->parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000585
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100586 while (parent != nil && curr == parent->right) {
587 curr = parent;
588 parent = curr->parent;
589 }
590
591 return (parent == nil) ? NULL : parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000592}
593
594
595static void dnode_free(dnode_t *node)
596{
Denys Vlasenkoef3817c2010-01-08 09:07:25 +0100597 free(node);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +0000598}
599
600
601#undef left
602#undef right
603#undef parent
604#undef color
605#undef key
606#undef data
607
608#undef nilnode
609#undef maxcount
610#undef compare
611#undef dupes
612
613
614/*
615 * dirinfo.c --- maintains the directory information table for e2fsck.
616 */
617
618/*
619 * This subroutine is called during pass1 to create a directory info
620 * entry. During pass1, the passed-in parent is 0; it will get filled
621 * in during pass2.
622 */
623static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
624{
625 struct dir_info *dir;
626 int i, j;
627 ext2_ino_t num_dirs;
628 errcode_t retval;
629 unsigned long old_size;
630
631 if (!ctx->dir_info) {
632 ctx->dir_info_count = 0;
633 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
634 if (retval)
635 num_dirs = 1024; /* Guess */
636 ctx->dir_info_size = num_dirs + 10;
637 ctx->dir_info = (struct dir_info *)
638 e2fsck_allocate_memory(ctx, ctx->dir_info_size
639 * sizeof (struct dir_info),
640 "directory map");
641 }
642
643 if (ctx->dir_info_count >= ctx->dir_info_size) {
644 old_size = ctx->dir_info_size * sizeof(struct dir_info);
645 ctx->dir_info_size += 10;
646 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
647 sizeof(struct dir_info),
648 &ctx->dir_info);
649 if (retval) {
650 ctx->dir_info_size -= 10;
651 return;
652 }
653 }
654
655 /*
656 * Normally, add_dir_info is called with each inode in
657 * sequential order; but once in a while (like when pass 3
658 * needs to recreate the root directory or lost+found
659 * directory) it is called out of order. In those cases, we
660 * need to move the dir_info entries down to make room, since
661 * the dir_info array needs to be sorted by inode number for
662 * get_dir_info()'s sake.
663 */
664 if (ctx->dir_info_count &&
665 ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
666 for (i = ctx->dir_info_count-1; i > 0; i--)
667 if (ctx->dir_info[i-1].ino < ino)
668 break;
669 dir = &ctx->dir_info[i];
670 if (dir->ino != ino)
671 for (j = ctx->dir_info_count++; j > i; j--)
672 ctx->dir_info[j] = ctx->dir_info[j-1];
673 } else
674 dir = &ctx->dir_info[ctx->dir_info_count++];
675
676 dir->ino = ino;
677 dir->dotdot = parent;
678 dir->parent = parent;
679}
680
681/*
682 * get_dir_info() --- given an inode number, try to find the directory
683 * information entry for it.
684 */
685static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
686{
687 int low, high, mid;
688
689 low = 0;
690 high = ctx->dir_info_count-1;
691 if (!ctx->dir_info)
692 return 0;
693 if (ino == ctx->dir_info[low].ino)
694 return &ctx->dir_info[low];
695 if (ino == ctx->dir_info[high].ino)
696 return &ctx->dir_info[high];
697
698 while (low < high) {
699 mid = (low+high)/2;
700 if (mid == low || mid == high)
701 break;
702 if (ino == ctx->dir_info[mid].ino)
703 return &ctx->dir_info[mid];
704 if (ino < ctx->dir_info[mid].ino)
705 high = mid;
706 else
707 low = mid;
708 }
709 return 0;
710}
711
712/*
713 * Free the dir_info structure when it isn't needed any more.
714 */
715static void e2fsck_free_dir_info(e2fsck_t ctx)
716{
717 ext2fs_free_mem(&ctx->dir_info);
718 ctx->dir_info_size = 0;
719 ctx->dir_info_count = 0;
720}
721
722/*
723 * Return the count of number of directories in the dir_info structure
724 */
725static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
726{
727 return ctx->dir_info_count;
728}
729
730/*
731 * A simple interator function
732 */
733static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
734{
735 if (*control >= ctx->dir_info_count)
736 return 0;
737
738 return ctx->dir_info + (*control)++;
739}
740
741/*
742 * dirinfo.c --- maintains the directory information table for e2fsck.
743 *
744 */
745
746#ifdef ENABLE_HTREE
747
748/*
749 * This subroutine is called during pass1 to create a directory info
750 * entry. During pass1, the passed-in parent is 0; it will get filled
751 * in during pass2.
752 */
753static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
754{
755 struct dx_dir_info *dir;
756 int i, j;
757 errcode_t retval;
758 unsigned long old_size;
759
760 if (!ctx->dx_dir_info) {
761 ctx->dx_dir_info_count = 0;
762 ctx->dx_dir_info_size = 100; /* Guess */
763 ctx->dx_dir_info = (struct dx_dir_info *)
764 e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
765 * sizeof (struct dx_dir_info),
766 "directory map");
767 }
768
769 if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
770 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
771 ctx->dx_dir_info_size += 10;
772 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
773 sizeof(struct dx_dir_info),
774 &ctx->dx_dir_info);
775 if (retval) {
776 ctx->dx_dir_info_size -= 10;
777 return;
778 }
779 }
780
781 /*
782 * Normally, add_dx_dir_info is called with each inode in
783 * sequential order; but once in a while (like when pass 3
784 * needs to recreate the root directory or lost+found
785 * directory) it is called out of order. In those cases, we
786 * need to move the dx_dir_info entries down to make room, since
787 * the dx_dir_info array needs to be sorted by inode number for
788 * get_dx_dir_info()'s sake.
789 */
790 if (ctx->dx_dir_info_count &&
791 ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
792 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
793 if (ctx->dx_dir_info[i-1].ino < ino)
794 break;
795 dir = &ctx->dx_dir_info[i];
796 if (dir->ino != ino)
797 for (j = ctx->dx_dir_info_count++; j > i; j--)
798 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
799 } else
800 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
801
802 dir->ino = ino;
803 dir->numblocks = num_blocks;
804 dir->hashversion = 0;
805 dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
806 * sizeof (struct dx_dirblock_info),
807 "dx_block info array");
808
809}
810
811/*
812 * get_dx_dir_info() --- given an inode number, try to find the directory
813 * information entry for it.
814 */
815static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
816{
817 int low, high, mid;
818
819 low = 0;
820 high = ctx->dx_dir_info_count-1;
821 if (!ctx->dx_dir_info)
822 return 0;
823 if (ino == ctx->dx_dir_info[low].ino)
824 return &ctx->dx_dir_info[low];
825 if (ino == ctx->dx_dir_info[high].ino)
826 return &ctx->dx_dir_info[high];
827
828 while (low < high) {
829 mid = (low+high)/2;
830 if (mid == low || mid == high)
831 break;
832 if (ino == ctx->dx_dir_info[mid].ino)
833 return &ctx->dx_dir_info[mid];
834 if (ino < ctx->dx_dir_info[mid].ino)
835 high = mid;
836 else
837 low = mid;
838 }
839 return 0;
840}
841
842/*
843 * Free the dx_dir_info structure when it isn't needed any more.
844 */
845static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
846{
847 int i;
848 struct dx_dir_info *dir;
849
850 if (ctx->dx_dir_info) {
851 dir = ctx->dx_dir_info;
852 for (i=0; i < ctx->dx_dir_info_count; i++) {
853 ext2fs_free_mem(&dir->dx_block);
854 }
855 ext2fs_free_mem(&ctx->dx_dir_info);
856 }
857 ctx->dx_dir_info_size = 0;
858 ctx->dx_dir_info_count = 0;
859}
860
861/*
862 * A simple interator function
863 */
864static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
865{
866 if (*control >= ctx->dx_dir_info_count)
867 return 0;
868
869 return ctx->dx_dir_info + (*control)++;
870}
871
872#endif /* ENABLE_HTREE */
873/*
874 * e2fsck.c - a consistency checker for the new extended file system.
875 *
876 */
877
878/*
879 * This function allocates an e2fsck context
880 */
881static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
882{
883 e2fsck_t context;
884 errcode_t retval;
885
886 retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
887 if (retval)
888 return retval;
889
890 memset(context, 0, sizeof(struct e2fsck_struct));
891
892 context->process_inode_size = 256;
893 context->ext_attr_ver = 2;
894
895 *ret = context;
896 return 0;
897}
898
899struct ea_refcount_el {
900 blk_t ea_blk;
901 int ea_count;
902};
903
904struct ea_refcount {
905 blk_t count;
906 blk_t size;
907 blk_t cursor;
908 struct ea_refcount_el *list;
909};
910
911static void ea_refcount_free(ext2_refcount_t refcount)
912{
913 if (!refcount)
914 return;
915
916 ext2fs_free_mem(&refcount->list);
917 ext2fs_free_mem(&refcount);
918}
919
920/*
921 * This function resets an e2fsck context; it is called when e2fsck
922 * needs to be restarted.
923 */
924static errcode_t e2fsck_reset_context(e2fsck_t ctx)
925{
926 ctx->flags = 0;
927 ctx->lost_and_found = 0;
928 ctx->bad_lost_and_found = 0;
929 ext2fs_free_inode_bitmap(ctx->inode_used_map);
930 ctx->inode_used_map = 0;
931 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
932 ctx->inode_dir_map = 0;
933 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
934 ctx->inode_reg_map = 0;
935 ext2fs_free_block_bitmap(ctx->block_found_map);
936 ctx->block_found_map = 0;
937 ext2fs_free_icount(ctx->inode_link_info);
938 ctx->inode_link_info = 0;
939 if (ctx->journal_io) {
940 if (ctx->fs && ctx->fs->io != ctx->journal_io)
941 io_channel_close(ctx->journal_io);
942 ctx->journal_io = 0;
943 }
944 if (ctx->fs) {
945 ext2fs_free_dblist(ctx->fs->dblist);
946 ctx->fs->dblist = 0;
947 }
948 e2fsck_free_dir_info(ctx);
949#ifdef ENABLE_HTREE
950 e2fsck_free_dx_dir_info(ctx);
951#endif
952 ea_refcount_free(ctx->refcount);
953 ctx->refcount = 0;
954 ea_refcount_free(ctx->refcount_extra);
955 ctx->refcount_extra = 0;
956 ext2fs_free_block_bitmap(ctx->block_dup_map);
957 ctx->block_dup_map = 0;
958 ext2fs_free_block_bitmap(ctx->block_ea_map);
959 ctx->block_ea_map = 0;
960 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
961 ctx->inode_bad_map = 0;
962 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
963 ctx->inode_imagic_map = 0;
964 ext2fs_u32_list_free(ctx->dirs_to_hash);
965 ctx->dirs_to_hash = 0;
966
967 /*
968 * Clear the array of invalid meta-data flags
969 */
970 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
971 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
972 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
973
974 /* Clear statistic counters */
975 ctx->fs_directory_count = 0;
976 ctx->fs_regular_count = 0;
977 ctx->fs_blockdev_count = 0;
978 ctx->fs_chardev_count = 0;
979 ctx->fs_links_count = 0;
980 ctx->fs_symlinks_count = 0;
981 ctx->fs_fast_symlinks_count = 0;
982 ctx->fs_fifo_count = 0;
983 ctx->fs_total_count = 0;
984 ctx->fs_sockets_count = 0;
985 ctx->fs_ind_count = 0;
986 ctx->fs_dind_count = 0;
987 ctx->fs_tind_count = 0;
988 ctx->fs_fragmented = 0;
989 ctx->large_files = 0;
990
991 /* Reset the superblock to the user's requested value */
992 ctx->superblock = ctx->use_superblock;
993
994 return 0;
995}
996
997static void e2fsck_free_context(e2fsck_t ctx)
998{
999 if (!ctx)
1000 return;
1001
1002 e2fsck_reset_context(ctx);
1003 if (ctx->blkid)
1004 blkid_put_cache(ctx->blkid);
1005
1006 ext2fs_free_mem(&ctx);
1007}
1008
1009/*
1010 * ea_refcount.c
1011 */
1012
1013/*
1014 * The strategy we use for keeping track of EA refcounts is as
1015 * follows. We keep a sorted array of first EA blocks and its
1016 * reference counts. Once the refcount has dropped to zero, it is
1017 * removed from the array to save memory space. Once the EA block is
1018 * checked, its bit is set in the block_ea_map bitmap.
1019 */
1020
1021
1022static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1023{
1024 ext2_refcount_t refcount;
1025 errcode_t retval;
1026 size_t bytes;
1027
1028 retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1029 if (retval)
1030 return retval;
1031 memset(refcount, 0, sizeof(struct ea_refcount));
1032
1033 if (!size)
1034 size = 500;
1035 refcount->size = size;
1036 bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1037#ifdef DEBUG
1038 printf("Refcount allocated %d entries, %d bytes.\n",
1039 refcount->size, bytes);
1040#endif
1041 retval = ext2fs_get_mem(bytes, &refcount->list);
1042 if (retval)
1043 goto errout;
1044 memset(refcount->list, 0, bytes);
1045
1046 refcount->count = 0;
1047 refcount->cursor = 0;
1048
1049 *ret = refcount;
1050 return 0;
1051
1052errout:
1053 ea_refcount_free(refcount);
1054 return retval;
1055}
1056
1057/*
1058 * collapse_refcount() --- go through the refcount array, and get rid
1059 * of any count == zero entries
1060 */
1061static void refcount_collapse(ext2_refcount_t refcount)
1062{
1063 unsigned int i, j;
1064 struct ea_refcount_el *list;
1065
1066 list = refcount->list;
1067 for (i = 0, j = 0; i < refcount->count; i++) {
1068 if (list[i].ea_count) {
1069 if (i != j)
1070 list[j] = list[i];
1071 j++;
1072 }
1073 }
1074#if defined(DEBUG) || defined(TEST_PROGRAM)
1075 printf("Refcount_collapse: size was %d, now %d\n",
1076 refcount->count, j);
1077#endif
1078 refcount->count = j;
1079}
1080
1081
1082/*
1083 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1084 * specified position.
1085 */
1086static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1087 blk_t blk, int pos)
1088{
1089 struct ea_refcount_el *el;
1090 errcode_t retval;
1091 blk_t new_size = 0;
1092 int num;
1093
1094 if (refcount->count >= refcount->size) {
1095 new_size = refcount->size + 100;
1096#ifdef DEBUG
1097 printf("Reallocating refcount %d entries...\n", new_size);
1098#endif
1099 retval = ext2fs_resize_mem((size_t) refcount->size *
1100 sizeof(struct ea_refcount_el),
1101 (size_t) new_size *
1102 sizeof(struct ea_refcount_el),
1103 &refcount->list);
1104 if (retval)
1105 return 0;
1106 refcount->size = new_size;
1107 }
1108 num = (int) refcount->count - pos;
1109 if (num < 0)
1110 return 0; /* should never happen */
1111 if (num) {
1112 memmove(&refcount->list[pos+1], &refcount->list[pos],
1113 sizeof(struct ea_refcount_el) * num);
1114 }
1115 refcount->count++;
1116 el = &refcount->list[pos];
1117 el->ea_count = 0;
1118 el->ea_blk = blk;
1119 return el;
1120}
1121
1122
1123/*
1124 * get_refcount_el() --- given an block number, try to find refcount
1125 * information in the sorted list. If the create flag is set,
1126 * and we can't find an entry, create one in the sorted list.
1127 */
1128static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1129 blk_t blk, int create)
1130{
1131 float range;
1132 int low, high, mid;
1133 blk_t lowval, highval;
1134
1135 if (!refcount || !refcount->list)
1136 return 0;
1137retry:
1138 low = 0;
1139 high = (int) refcount->count-1;
1140 if (create && ((refcount->count == 0) ||
1141 (blk > refcount->list[high].ea_blk))) {
1142 if (refcount->count >= refcount->size)
1143 refcount_collapse(refcount);
1144
1145 return insert_refcount_el(refcount, blk,
1146 (unsigned) refcount->count);
1147 }
1148 if (refcount->count == 0)
1149 return 0;
1150
1151 if (refcount->cursor >= refcount->count)
1152 refcount->cursor = 0;
1153 if (blk == refcount->list[refcount->cursor].ea_blk)
1154 return &refcount->list[refcount->cursor++];
1155#ifdef DEBUG
1156 printf("Non-cursor get_refcount_el: %u\n", blk);
1157#endif
1158 while (low <= high) {
1159 if (low == high)
1160 mid = low;
1161 else {
1162 /* Interpolate for efficiency */
1163 lowval = refcount->list[low].ea_blk;
1164 highval = refcount->list[high].ea_blk;
1165
1166 if (blk < lowval)
1167 range = 0;
1168 else if (blk > highval)
1169 range = 1;
1170 else
1171 range = ((float) (blk - lowval)) /
1172 (highval - lowval);
1173 mid = low + ((int) (range * (high-low)));
1174 }
1175
1176 if (blk == refcount->list[mid].ea_blk) {
1177 refcount->cursor = mid+1;
1178 return &refcount->list[mid];
1179 }
1180 if (blk < refcount->list[mid].ea_blk)
1181 high = mid-1;
1182 else
1183 low = mid+1;
1184 }
1185 /*
1186 * If we need to create a new entry, it should be right at
1187 * low (where high will be left at low-1).
1188 */
1189 if (create) {
1190 if (refcount->count >= refcount->size) {
1191 refcount_collapse(refcount);
1192 if (refcount->count < refcount->size)
1193 goto retry;
1194 }
1195 return insert_refcount_el(refcount, blk, low);
1196 }
1197 return 0;
1198}
1199
1200static errcode_t
1201ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1202{
1203 struct ea_refcount_el *el;
1204
1205 el = get_refcount_el(refcount, blk, 1);
1206 if (!el)
1207 return EXT2_ET_NO_MEMORY;
1208 el->ea_count++;
1209
1210 if (ret)
1211 *ret = el->ea_count;
1212 return 0;
1213}
1214
1215static errcode_t
1216ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1217{
1218 struct ea_refcount_el *el;
1219
1220 el = get_refcount_el(refcount, blk, 0);
1221 if (!el || el->ea_count == 0)
1222 return EXT2_ET_INVALID_ARGUMENT;
1223
1224 el->ea_count--;
1225
1226 if (ret)
1227 *ret = el->ea_count;
1228 return 0;
1229}
1230
1231static errcode_t
1232ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1233{
1234 struct ea_refcount_el *el;
1235
1236 /*
1237 * Get the refcount element
1238 */
1239 el = get_refcount_el(refcount, blk, count ? 1 : 0);
1240 if (!el)
1241 return count ? EXT2_ET_NO_MEMORY : 0;
1242 el->ea_count = count;
1243 return 0;
1244}
1245
1246static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1247{
1248 refcount->cursor = 0;
1249}
1250
1251
1252static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1253{
1254 struct ea_refcount_el *list;
1255
1256 while (1) {
1257 if (refcount->cursor >= refcount->count)
1258 return 0;
1259 list = refcount->list;
1260 if (list[refcount->cursor].ea_count) {
1261 if (ret)
1262 *ret = list[refcount->cursor].ea_count;
1263 return list[refcount->cursor++].ea_blk;
1264 }
1265 refcount->cursor++;
1266 }
1267}
1268
1269
1270/*
1271 * ehandler.c --- handle bad block errors which come up during the
1272 * course of an e2fsck session.
1273 */
1274
1275
1276static const char *operation;
1277
1278static errcode_t
1279e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1280 void *data, size_t size FSCK_ATTR((unused)),
1281 int actual FSCK_ATTR((unused)), errcode_t error)
1282{
1283 int i;
1284 char *p;
1285 ext2_filsys fs = (ext2_filsys) channel->app_data;
1286 e2fsck_t ctx;
1287
1288 ctx = (e2fsck_t) fs->priv_data;
1289
1290 /*
1291 * If more than one block was read, try reading each block
1292 * separately. We could use the actual bytes read to figure
1293 * out where to start, but we don't bother.
1294 */
1295 if (count > 1) {
1296 p = (char *) data;
1297 for (i=0; i < count; i++, p += channel->block_size, block++) {
1298 error = io_channel_read_blk(channel, block,
1299 1, p);
1300 if (error)
1301 return error;
1302 }
1303 return 0;
1304 }
1305 if (operation)
1306 printf(_("Error reading block %lu (%s) while %s. "), block,
1307 error_message(error), operation);
1308 else
1309 printf(_("Error reading block %lu (%s). "), block,
1310 error_message(error));
1311 preenhalt(ctx);
1312 if (ask(ctx, _("Ignore error"), 1)) {
1313 if (ask(ctx, _("Force rewrite"), 1))
1314 io_channel_write_blk(channel, block, 1, data);
1315 return 0;
1316 }
1317
1318 return error;
1319}
1320
1321static errcode_t
1322e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1323 const void *data, size_t size FSCK_ATTR((unused)),
1324 int actual FSCK_ATTR((unused)), errcode_t error)
1325{
1326 int i;
1327 const char *p;
1328 ext2_filsys fs = (ext2_filsys) channel->app_data;
1329 e2fsck_t ctx;
1330
1331 ctx = (e2fsck_t) fs->priv_data;
1332
1333 /*
1334 * If more than one block was written, try writing each block
1335 * separately. We could use the actual bytes read to figure
1336 * out where to start, but we don't bother.
1337 */
1338 if (count > 1) {
1339 p = (const char *) data;
1340 for (i=0; i < count; i++, p += channel->block_size, block++) {
1341 error = io_channel_write_blk(channel, block,
1342 1, p);
1343 if (error)
1344 return error;
1345 }
1346 return 0;
1347 }
1348
1349 if (operation)
1350 printf(_("Error writing block %lu (%s) while %s. "), block,
1351 error_message(error), operation);
1352 else
1353 printf(_("Error writing block %lu (%s). "), block,
1354 error_message(error));
1355 preenhalt(ctx);
1356 if (ask(ctx, _("Ignore error"), 1))
1357 return 0;
1358
1359 return error;
1360}
1361
1362static const char *ehandler_operation(const char *op)
1363{
1364 const char *ret = operation;
1365
1366 operation = op;
1367 return ret;
1368}
1369
1370static void ehandler_init(io_channel channel)
1371{
1372 channel->read_error = e2fsck_handle_read_error;
1373 channel->write_error = e2fsck_handle_write_error;
1374}
1375
1376/*
1377 * journal.c --- code for handling the "ext3" journal
1378 *
1379 * Copyright (C) 2000 Andreas Dilger
1380 * Copyright (C) 2000 Theodore Ts'o
1381 *
1382 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1383 * Copyright (C) 1999 Red Hat Software
1384 *
1385 * This file may be redistributed under the terms of the
1386 * GNU General Public License version 2 or at your discretion
1387 * any later version.
1388 */
1389
1390/*
1391 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1392 * This creates a larger static binary, and a smaller binary using
1393 * shared libraries. It's also probably slightly less CPU-efficient,
1394 * which is why it's not on by default. But, it's a good way of
1395 * testing the functions in inode_io.c and fileio.c.
1396 */
1397#undef USE_INODE_IO
1398
1399/* Kernel compatibility functions for handling the journal. These allow us
1400 * to use the recovery.c file virtually unchanged from the kernel, so we
1401 * don't have to do much to keep kernel and user recovery in sync.
1402 */
1403static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1404{
1405#ifdef USE_INODE_IO
1406 *phys = block;
1407 return 0;
1408#else
1409 struct inode *inode = journal->j_inode;
1410 errcode_t retval;
1411 blk_t pblk;
1412
1413 if (!inode) {
1414 *phys = block;
1415 return 0;
1416 }
1417
1418 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1419 &inode->i_ext2, NULL, 0, block, &pblk);
1420 *phys = pblk;
1421 return retval;
1422#endif
1423}
1424
1425static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1426{
1427 struct buffer_head *bh;
1428
1429 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1430 if (!bh)
1431 return NULL;
1432
1433 bh->b_ctx = kdev->k_ctx;
1434 if (kdev->k_dev == K_DEV_FS)
1435 bh->b_io = kdev->k_ctx->fs->io;
1436 else
1437 bh->b_io = kdev->k_ctx->journal_io;
1438 bh->b_size = blocksize;
1439 bh->b_blocknr = blocknr;
1440
1441 return bh;
1442}
1443
1444static void sync_blockdev(kdev_t kdev)
1445{
1446 io_channel io;
1447
1448 if (kdev->k_dev == K_DEV_FS)
1449 io = kdev->k_ctx->fs->io;
1450 else
1451 io = kdev->k_ctx->journal_io;
1452
1453 io_channel_flush(io);
1454}
1455
1456static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1457{
1458 int retval;
1459 struct buffer_head *bh;
1460
1461 for (; nr > 0; --nr) {
1462 bh = *bhp++;
1463 if (rw == READ && !bh->b_uptodate) {
1464 retval = io_channel_read_blk(bh->b_io,
1465 bh->b_blocknr,
1466 1, bh->b_data);
1467 if (retval) {
1468 bb_error_msg("while reading block %lu",
1469 (unsigned long) bh->b_blocknr);
1470 bh->b_err = retval;
1471 continue;
1472 }
1473 bh->b_uptodate = 1;
1474 } else if (rw == WRITE && bh->b_dirty) {
1475 retval = io_channel_write_blk(bh->b_io,
1476 bh->b_blocknr,
1477 1, bh->b_data);
1478 if (retval) {
1479 bb_error_msg("while writing block %lu",
1480 (unsigned long) bh->b_blocknr);
1481 bh->b_err = retval;
1482 continue;
1483 }
1484 bh->b_dirty = 0;
1485 bh->b_uptodate = 1;
1486 }
1487 }
1488}
1489
1490static void mark_buffer_dirty(struct buffer_head *bh)
1491{
1492 bh->b_dirty = 1;
1493}
1494
1495static inline void mark_buffer_clean(struct buffer_head * bh)
1496{
1497 bh->b_dirty = 0;
1498}
1499
1500static void brelse(struct buffer_head *bh)
1501{
1502 if (bh->b_dirty)
1503 ll_rw_block(WRITE, 1, &bh);
1504 ext2fs_free_mem(&bh);
1505}
1506
1507static int buffer_uptodate(struct buffer_head *bh)
1508{
1509 return bh->b_uptodate;
1510}
1511
1512static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1513{
1514 bh->b_uptodate = val;
1515}
1516
1517static void wait_on_buffer(struct buffer_head *bh)
1518{
1519 if (!bh->b_uptodate)
1520 ll_rw_block(READ, 1, &bh);
1521}
1522
1523
1524static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1525{
1526 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1527
1528 /* if we had an error doing journal recovery, we need a full fsck */
1529 if (error)
1530 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1531 ext2fs_mark_super_dirty(ctx->fs);
1532}
1533
1534static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1535{
1536 struct ext2_super_block *sb = ctx->fs->super;
1537 struct ext2_super_block jsuper;
1538 struct problem_context pctx;
1539 struct buffer_head *bh;
1540 struct inode *j_inode = NULL;
1541 struct kdev_s *dev_fs = NULL, *dev_journal;
1542 const char *journal_name = 0;
1543 journal_t *journal = NULL;
1544 errcode_t retval = 0;
1545 io_manager io_ptr = 0;
1546 unsigned long start = 0;
1547 blk_t blk;
1548 int ext_journal = 0;
1549 int tried_backup_jnl = 0;
1550 int i;
1551
1552 clear_problem_context(&pctx);
1553
1554 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1555 if (!journal) {
1556 return EXT2_ET_NO_MEMORY;
1557 }
1558
1559 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1560 if (!dev_fs) {
1561 retval = EXT2_ET_NO_MEMORY;
1562 goto errout;
1563 }
1564 dev_journal = dev_fs+1;
1565
1566 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1567 dev_fs->k_dev = K_DEV_FS;
1568 dev_journal->k_dev = K_DEV_JOURNAL;
1569
1570 journal->j_dev = dev_journal;
1571 journal->j_fs_dev = dev_fs;
1572 journal->j_inode = NULL;
1573 journal->j_blocksize = ctx->fs->blocksize;
1574
1575 if (uuid_is_null(sb->s_journal_uuid)) {
1576 if (!sb->s_journal_inum)
1577 return EXT2_ET_BAD_INODE_NUM;
1578 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1579 "journal inode");
1580 if (!j_inode) {
1581 retval = EXT2_ET_NO_MEMORY;
1582 goto errout;
1583 }
1584
1585 j_inode->i_ctx = ctx;
1586 j_inode->i_ino = sb->s_journal_inum;
1587
1588 if ((retval = ext2fs_read_inode(ctx->fs,
1589 sb->s_journal_inum,
1590 &j_inode->i_ext2))) {
1591 try_backup_journal:
1592 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1593 tried_backup_jnl)
1594 goto errout;
1595 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1596 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1597 EXT2_N_BLOCKS*4);
1598 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1599 j_inode->i_ext2.i_links_count = 1;
1600 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1601 tried_backup_jnl++;
1602 }
1603 if (!j_inode->i_ext2.i_links_count ||
1604 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1605 retval = EXT2_ET_NO_JOURNAL;
1606 goto try_backup_journal;
1607 }
1608 if (j_inode->i_ext2.i_size / journal->j_blocksize <
1609 JFS_MIN_JOURNAL_BLOCKS) {
1610 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1611 goto try_backup_journal;
1612 }
1613 for (i=0; i < EXT2_N_BLOCKS; i++) {
1614 blk = j_inode->i_ext2.i_block[i];
1615 if (!blk) {
1616 if (i < EXT2_NDIR_BLOCKS) {
1617 retval = EXT2_ET_JOURNAL_TOO_SMALL;
1618 goto try_backup_journal;
1619 }
1620 continue;
1621 }
1622 if (blk < sb->s_first_data_block ||
1623 blk >= sb->s_blocks_count) {
1624 retval = EXT2_ET_BAD_BLOCK_NUM;
1625 goto try_backup_journal;
1626 }
1627 }
1628 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1629
1630#ifdef USE_INODE_IO
1631 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1632 &j_inode->i_ext2,
1633 &journal_name);
1634 if (retval)
1635 goto errout;
1636
1637 io_ptr = inode_io_manager;
1638#else
1639 journal->j_inode = j_inode;
1640 ctx->journal_io = ctx->fs->io;
1641 if ((retval = journal_bmap(journal, 0, &start)) != 0)
1642 goto errout;
1643#endif
1644 } else {
1645 ext_journal = 1;
1646 if (!ctx->journal_name) {
1647 char uuid[37];
1648
1649 uuid_unparse(sb->s_journal_uuid, uuid);
1650 ctx->journal_name = blkid_get_devname(ctx->blkid,
1651 "UUID", uuid);
1652 if (!ctx->journal_name)
1653 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1654 }
1655 journal_name = ctx->journal_name;
1656
1657 if (!journal_name) {
1658 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1659 return EXT2_ET_LOAD_EXT_JOURNAL;
1660 }
1661
1662 io_ptr = unix_io_manager;
1663 }
1664
1665#ifndef USE_INODE_IO
1666 if (ext_journal)
1667#endif
1668 retval = io_ptr->open(journal_name, IO_FLAG_RW,
1669 &ctx->journal_io);
1670 if (retval)
1671 goto errout;
1672
1673 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1674
1675 if (ext_journal) {
1676 if (ctx->fs->blocksize == 1024)
1677 start = 1;
1678 bh = getblk(dev_journal, start, ctx->fs->blocksize);
1679 if (!bh) {
1680 retval = EXT2_ET_NO_MEMORY;
1681 goto errout;
1682 }
1683 ll_rw_block(READ, 1, &bh);
1684 if ((retval = bh->b_err) != 0)
1685 goto errout;
1686 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
1687 sizeof(jsuper));
1688 brelse(bh);
1689#if BB_BIG_ENDIAN
1690 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1691 ext2fs_swap_super(&jsuper);
1692#endif
1693 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1694 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1695 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1696 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1697 goto errout;
1698 }
1699 /* Make sure the journal UUID is correct */
1700 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1701 sizeof(jsuper.s_uuid))) {
1702 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1703 retval = EXT2_ET_LOAD_EXT_JOURNAL;
1704 goto errout;
1705 }
1706
1707 journal->j_maxlen = jsuper.s_blocks_count;
1708 start++;
1709 }
1710
1711 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1712 retval = EXT2_ET_NO_MEMORY;
1713 goto errout;
1714 }
1715
1716 journal->j_sb_buffer = bh;
1717 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1718
1719#ifdef USE_INODE_IO
1720 ext2fs_free_mem(&j_inode);
1721#endif
1722
1723 *ret_journal = journal;
1724 return 0;
1725
1726errout:
1727 ext2fs_free_mem(&dev_fs);
1728 ext2fs_free_mem(&j_inode);
1729 ext2fs_free_mem(&journal);
1730 return retval;
1731
1732}
1733
1734static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1735 struct problem_context *pctx)
1736{
1737 struct ext2_super_block *sb = ctx->fs->super;
1738 int recover = ctx->fs->super->s_feature_incompat &
1739 EXT3_FEATURE_INCOMPAT_RECOVER;
1740 int has_journal = ctx->fs->super->s_feature_compat &
1741 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1742
1743 if (has_journal || sb->s_journal_inum) {
1744 /* The journal inode is bogus, remove and force full fsck */
1745 pctx->ino = sb->s_journal_inum;
1746 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1747 if (has_journal && sb->s_journal_inum)
1748 printf("*** ext3 journal has been deleted - "
1749 "filesystem is now ext2 only ***\n\n");
1750 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1751 sb->s_journal_inum = 0;
1752 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1753 e2fsck_clear_recover(ctx, 1);
1754 return 0;
1755 }
1756 return EXT2_ET_BAD_INODE_NUM;
1757 } else if (recover) {
1758 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1759 e2fsck_clear_recover(ctx, 1);
1760 return 0;
1761 }
1762 return EXT2_ET_UNSUPP_FEATURE;
1763 }
1764 return 0;
1765}
1766
1767#define V1_SB_SIZE 0x0024
1768static void clear_v2_journal_fields(journal_t *journal)
1769{
1770 e2fsck_t ctx = journal->j_dev->k_ctx;
1771 struct problem_context pctx;
1772
1773 clear_problem_context(&pctx);
1774
1775 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1776 return;
1777
1778 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1779 ctx->fs->blocksize-V1_SB_SIZE);
1780 mark_buffer_dirty(journal->j_sb_buffer);
1781}
1782
1783
1784static errcode_t e2fsck_journal_load(journal_t *journal)
1785{
1786 e2fsck_t ctx = journal->j_dev->k_ctx;
1787 journal_superblock_t *jsb;
1788 struct buffer_head *jbh = journal->j_sb_buffer;
1789 struct problem_context pctx;
1790
1791 clear_problem_context(&pctx);
1792
1793 ll_rw_block(READ, 1, &jbh);
1794 if (jbh->b_err) {
1795 bb_error_msg(_("reading journal superblock"));
1796 return jbh->b_err;
1797 }
1798
1799 jsb = journal->j_superblock;
1800 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1801 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1802 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1803
1804 switch (ntohl(jsb->s_header.h_blocktype)) {
1805 case JFS_SUPERBLOCK_V1:
1806 journal->j_format_version = 1;
1807 if (jsb->s_feature_compat ||
1808 jsb->s_feature_incompat ||
1809 jsb->s_feature_ro_compat ||
1810 jsb->s_nr_users)
1811 clear_v2_journal_fields(journal);
1812 break;
1813
1814 case JFS_SUPERBLOCK_V2:
1815 journal->j_format_version = 2;
1816 if (ntohl(jsb->s_nr_users) > 1 &&
1817 uuid_is_null(ctx->fs->super->s_journal_uuid))
1818 clear_v2_journal_fields(journal);
1819 if (ntohl(jsb->s_nr_users) > 1) {
1820 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1821 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1822 }
1823 break;
1824
1825 /*
1826 * These should never appear in a journal super block, so if
1827 * they do, the journal is badly corrupted.
1828 */
1829 case JFS_DESCRIPTOR_BLOCK:
1830 case JFS_COMMIT_BLOCK:
1831 case JFS_REVOKE_BLOCK:
1832 return EXT2_ET_CORRUPT_SUPERBLOCK;
1833
1834 /* If we don't understand the superblock major type, but there
1835 * is a magic number, then it is likely to be a new format we
1836 * just don't understand, so leave it alone. */
1837 default:
1838 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1839 }
1840
1841 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1842 return EXT2_ET_UNSUPP_FEATURE;
1843
1844 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1845 return EXT2_ET_RO_UNSUPP_FEATURE;
1846
1847 /* We have now checked whether we know enough about the journal
1848 * format to be able to proceed safely, so any other checks that
1849 * fail we should attempt to recover from. */
1850 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1851 bb_error_msg(_("%s: no valid journal superblock found"),
1852 ctx->device_name);
1853 return EXT2_ET_CORRUPT_SUPERBLOCK;
1854 }
1855
1856 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1857 journal->j_maxlen = ntohl(jsb->s_maxlen);
1858 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1859 bb_error_msg(_("%s: journal too short"),
1860 ctx->device_name);
1861 return EXT2_ET_CORRUPT_SUPERBLOCK;
1862 }
1863
1864 journal->j_tail_sequence = ntohl(jsb->s_sequence);
1865 journal->j_transaction_sequence = journal->j_tail_sequence;
1866 journal->j_tail = ntohl(jsb->s_start);
1867 journal->j_first = ntohl(jsb->s_first);
1868 journal->j_last = ntohl(jsb->s_maxlen);
1869
1870 return 0;
1871}
1872
1873static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1874 journal_t *journal)
1875{
1876 char *p;
1877 union {
1878 uuid_t uuid;
1879 __u32 val[4];
1880 } u;
1881 __u32 new_seq = 0;
1882 int i;
1883
1884 /* Leave a valid existing V1 superblock signature alone.
Denys Vlasenkob22bbff2009-07-04 16:50:43 +02001885 * Anything unrecognizable we overwrite with a new V2
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00001886 * signature. */
1887
1888 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1889 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1890 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1891 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1892 }
1893
1894 /* Zero out everything else beyond the superblock header */
1895
1896 p = ((char *) jsb) + sizeof(journal_header_t);
1897 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1898
1899 jsb->s_blocksize = htonl(ctx->fs->blocksize);
1900 jsb->s_maxlen = htonl(journal->j_maxlen);
1901 jsb->s_first = htonl(1);
1902
1903 /* Initialize the journal sequence number so that there is "no"
1904 * chance we will find old "valid" transactions in the journal.
1905 * This avoids the need to zero the whole journal (slow to do,
1906 * and risky when we are just recovering the filesystem).
1907 */
1908 uuid_generate(u.uuid);
1909 for (i = 0; i < 4; i ++)
1910 new_seq ^= u.val[i];
1911 jsb->s_sequence = htonl(new_seq);
1912
1913 mark_buffer_dirty(journal->j_sb_buffer);
1914 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1915}
1916
1917static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1918 journal_t *journal,
1919 struct problem_context *pctx)
1920{
1921 struct ext2_super_block *sb = ctx->fs->super;
1922 int recover = ctx->fs->super->s_feature_incompat &
1923 EXT3_FEATURE_INCOMPAT_RECOVER;
1924
1925 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1926 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1927 e2fsck_journal_reset_super(ctx, journal->j_superblock,
1928 journal);
1929 journal->j_transaction_sequence = 1;
1930 e2fsck_clear_recover(ctx, recover);
1931 return 0;
1932 }
1933 return EXT2_ET_CORRUPT_SUPERBLOCK;
1934 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1935 return EXT2_ET_CORRUPT_SUPERBLOCK;
1936
1937 return 0;
1938}
1939
1940static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1941 int reset, int drop)
1942{
1943 journal_superblock_t *jsb;
1944
1945 if (drop)
1946 mark_buffer_clean(journal->j_sb_buffer);
1947 else if (!(ctx->options & E2F_OPT_READONLY)) {
1948 jsb = journal->j_superblock;
1949 jsb->s_sequence = htonl(journal->j_transaction_sequence);
1950 if (reset)
1951 jsb->s_start = 0; /* this marks the journal as empty */
1952 mark_buffer_dirty(journal->j_sb_buffer);
1953 }
1954 brelse(journal->j_sb_buffer);
1955
1956 if (ctx->journal_io) {
1957 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1958 io_channel_close(ctx->journal_io);
1959 ctx->journal_io = 0;
1960 }
1961
1962#ifndef USE_INODE_IO
1963 ext2fs_free_mem(&journal->j_inode);
1964#endif
1965 ext2fs_free_mem(&journal->j_fs_dev);
1966 ext2fs_free_mem(&journal);
1967}
1968
1969/*
1970 * This function makes sure that the superblock fields regarding the
1971 * journal are consistent.
1972 */
1973static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1974{
1975 struct ext2_super_block *sb = ctx->fs->super;
1976 journal_t *journal;
1977 int recover = ctx->fs->super->s_feature_incompat &
1978 EXT3_FEATURE_INCOMPAT_RECOVER;
1979 struct problem_context pctx;
1980 problem_t problem;
1981 int reset = 0, force_fsck = 0;
1982 int retval;
1983
1984 /* If we don't have any journal features, don't do anything more */
1985 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1986 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1987 uuid_is_null(sb->s_journal_uuid))
1988 return 0;
1989
1990 clear_problem_context(&pctx);
1991 pctx.num = sb->s_journal_inum;
1992
1993 retval = e2fsck_get_journal(ctx, &journal);
1994 if (retval) {
1995 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1996 (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1997 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1998 (retval == EXT2_ET_NO_JOURNAL))
1999 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2000 return retval;
2001 }
2002
2003 retval = e2fsck_journal_load(journal);
2004 if (retval) {
2005 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2006 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2007 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2008 &pctx))) ||
2009 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2010 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2011 &pctx))) ||
2012 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2013 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2014 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2015 &pctx);
2016 e2fsck_journal_release(ctx, journal, 0, 1);
2017 return retval;
2018 }
2019
2020 /*
2021 * We want to make the flags consistent here. We will not leave with
2022 * needs_recovery set but has_journal clear. We can't get in a loop
2023 * with -y, -n, or -p, only if a user isn't making up their mind.
2024 */
2025no_has_journal:
2026 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2027 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2028 pctx.str = "inode";
2029 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2030 if (recover &&
2031 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2032 goto no_has_journal;
2033 /*
2034 * Need a full fsck if we are releasing a
2035 * journal stored on a reserved inode.
2036 */
2037 force_fsck = recover ||
2038 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2039 /* Clear all of the journal fields */
2040 sb->s_journal_inum = 0;
2041 sb->s_journal_dev = 0;
2042 memset(sb->s_journal_uuid, 0,
2043 sizeof(sb->s_journal_uuid));
2044 e2fsck_clear_recover(ctx, force_fsck);
2045 } else if (!(ctx->options & E2F_OPT_READONLY)) {
2046 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2047 ext2fs_mark_super_dirty(ctx->fs);
2048 }
2049 }
2050
2051 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2052 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2053 journal->j_superblock->s_start != 0) {
2054 /* Print status information */
2055 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2056 if (ctx->superblock)
2057 problem = PR_0_JOURNAL_RUN_DEFAULT;
2058 else
2059 problem = PR_0_JOURNAL_RUN;
2060 if (fix_problem(ctx, problem, &pctx)) {
2061 ctx->options |= E2F_OPT_FORCE;
2062 sb->s_feature_incompat |=
2063 EXT3_FEATURE_INCOMPAT_RECOVER;
2064 ext2fs_mark_super_dirty(ctx->fs);
2065 } else if (fix_problem(ctx,
2066 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2067 reset = 1;
2068 sb->s_state &= ~EXT2_VALID_FS;
2069 ext2fs_mark_super_dirty(ctx->fs);
2070 }
2071 /*
2072 * If the user answers no to the above question, we
2073 * ignore the fact that journal apparently has data;
2074 * accidentally replaying over valid data would be far
2075 * worse than skipping a questionable recovery.
2076 *
2077 * XXX should we abort with a fatal error here? What
2078 * will the ext3 kernel code do if a filesystem with
2079 * !NEEDS_RECOVERY but with a non-zero
2080 * journal->j_superblock->s_start is mounted?
2081 */
2082 }
2083
2084 e2fsck_journal_release(ctx, journal, reset, 0);
2085 return retval;
2086}
2087
2088static errcode_t recover_ext3_journal(e2fsck_t ctx)
2089{
2090 journal_t *journal;
2091 int retval;
2092
2093 journal_init_revoke_caches();
2094 retval = e2fsck_get_journal(ctx, &journal);
2095 if (retval)
2096 return retval;
2097
2098 retval = e2fsck_journal_load(journal);
2099 if (retval)
2100 goto errout;
2101
2102 retval = journal_init_revoke(journal, 1024);
2103 if (retval)
2104 goto errout;
2105
2106 retval = -journal_recover(journal);
2107 if (retval)
2108 goto errout;
2109
2110 if (journal->j_superblock->s_errno) {
2111 ctx->fs->super->s_state |= EXT2_ERROR_FS;
2112 ext2fs_mark_super_dirty(ctx->fs);
2113 journal->j_superblock->s_errno = 0;
2114 mark_buffer_dirty(journal->j_sb_buffer);
2115 }
2116
2117errout:
2118 journal_destroy_revoke(journal);
2119 journal_destroy_revoke_caches();
2120 e2fsck_journal_release(ctx, journal, 1, 0);
2121 return retval;
2122}
2123
2124static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2125{
2126 io_manager io_ptr = ctx->fs->io->manager;
2127 int blocksize = ctx->fs->blocksize;
2128 errcode_t retval, recover_retval;
2129
2130 printf(_("%s: recovering journal\n"), ctx->device_name);
2131 if (ctx->options & E2F_OPT_READONLY) {
2132 printf(_("%s: won't do journal recovery while read-only\n"),
2133 ctx->device_name);
2134 return EXT2_ET_FILE_RO;
2135 }
2136
2137 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2138 ext2fs_flush(ctx->fs); /* Force out any modifications */
2139
2140 recover_retval = recover_ext3_journal(ctx);
2141
2142 /*
2143 * Reload the filesystem context to get up-to-date data from disk
2144 * because journal recovery will change the filesystem under us.
2145 */
2146 ext2fs_close(ctx->fs);
2147 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2148 ctx->superblock, blocksize, io_ptr,
2149 &ctx->fs);
2150
2151 if (retval) {
2152 bb_error_msg(_("while trying to re-open %s"),
2153 ctx->device_name);
2154 bb_error_msg_and_die(0);
2155 }
2156 ctx->fs->priv_data = ctx;
2157
2158 /* Set the superblock flags */
2159 e2fsck_clear_recover(ctx, recover_retval);
2160 return recover_retval;
2161}
2162
2163/*
2164 * This function will move the journal inode from a visible file in
2165 * the filesystem directory hierarchy to the reserved inode if necessary.
2166 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002167static const char *const journal_names[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002168 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2169
2170static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2171{
2172 struct ext2_super_block *sb = ctx->fs->super;
2173 struct problem_context pctx;
2174 struct ext2_inode inode;
2175 ext2_filsys fs = ctx->fs;
2176 ext2_ino_t ino;
2177 errcode_t retval;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002178 const char *const * cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002179 int group, mount_flags;
2180
2181 clear_problem_context(&pctx);
2182
2183 /*
2184 * If the filesystem is opened read-only, or there is no
2185 * journal, then do nothing.
2186 */
2187 if ((ctx->options & E2F_OPT_READONLY) ||
2188 (sb->s_journal_inum == 0) ||
2189 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2190 return;
2191
2192 /*
2193 * Read in the journal inode
2194 */
2195 if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2196 return;
2197
2198 /*
2199 * If it's necessary to backup the journal inode, do so.
2200 */
2201 if ((sb->s_jnl_backup_type == 0) ||
2202 ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2203 memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2204 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2205 memcpy(sb->s_jnl_blocks, inode.i_block,
2206 EXT2_N_BLOCKS*4);
2207 sb->s_jnl_blocks[16] = inode.i_size;
2208 sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2209 ext2fs_mark_super_dirty(fs);
2210 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2211 }
2212 }
2213
2214 /*
2215 * If the journal is already the hidden inode, then do nothing
2216 */
2217 if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2218 return;
2219
2220 /*
2221 * The journal inode had better have only one link and not be readable.
2222 */
2223 if (inode.i_links_count != 1)
2224 return;
2225
2226 /*
2227 * If the filesystem is mounted, or we can't tell whether
2228 * or not it's mounted, do nothing.
2229 */
2230 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2231 if (retval || (mount_flags & EXT2_MF_MOUNTED))
2232 return;
2233
2234 /*
2235 * If we can't find the name of the journal inode, then do
2236 * nothing.
2237 */
2238 for (cpp = journal_names; *cpp; cpp++) {
2239 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2240 strlen(*cpp), 0, &ino);
2241 if ((retval == 0) && (ino == sb->s_journal_inum))
2242 break;
2243 }
2244 if (*cpp == 0)
2245 return;
2246
2247 /* We need the inode bitmap to be loaded */
2248 retval = ext2fs_read_bitmaps(fs);
2249 if (retval)
2250 return;
2251
2252 pctx.str = *cpp;
2253 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2254 return;
2255
2256 /*
2257 * OK, we've done all the checks, let's actually move the
2258 * journal inode. Errors at this point mean we need to force
2259 * an ext2 filesystem check.
2260 */
2261 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2262 goto err_out;
2263 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2264 goto err_out;
2265 sb->s_journal_inum = EXT2_JOURNAL_INO;
2266 ext2fs_mark_super_dirty(fs);
2267 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2268 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00002269 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002270 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2271 goto err_out;
2272
2273 group = ext2fs_group_of_ino(fs, ino);
2274 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2275 ext2fs_mark_ib_dirty(fs);
2276 fs->group_desc[group].bg_free_inodes_count++;
2277 fs->super->s_free_inodes_count++;
2278 return;
2279
2280err_out:
2281 pctx.errcode = retval;
2282 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2283 fs->super->s_state &= ~EXT2_VALID_FS;
2284 ext2fs_mark_super_dirty(fs);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002285}
2286
2287/*
2288 * message.c --- print e2fsck messages (with compression)
2289 *
2290 * print_e2fsck_message() prints a message to the user, using
2291 * compression techniques and expansions of abbreviations.
2292 *
2293 * The following % expansions are supported:
2294 *
2295 * %b <blk> block number
2296 * %B <blkcount> integer
2297 * %c <blk2> block number
2298 * %Di <dirent>->ino inode number
2299 * %Dn <dirent>->name string
2300 * %Dr <dirent>->rec_len
2301 * %Dl <dirent>->name_len
2302 * %Dt <dirent>->filetype
2303 * %d <dir> inode number
2304 * %g <group> integer
2305 * %i <ino> inode number
2306 * %Is <inode> -> i_size
2307 * %IS <inode> -> i_extra_isize
2308 * %Ib <inode> -> i_blocks
2309 * %Il <inode> -> i_links_count
2310 * %Im <inode> -> i_mode
2311 * %IM <inode> -> i_mtime
2312 * %IF <inode> -> i_faddr
2313 * %If <inode> -> i_file_acl
2314 * %Id <inode> -> i_dir_acl
2315 * %Iu <inode> -> i_uid
2316 * %Ig <inode> -> i_gid
2317 * %j <ino2> inode number
2318 * %m <com_err error message>
2319 * %N <num>
2320 * %p ext2fs_get_pathname of directory <ino>
2321 * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
2322 * the containing directory. (If dirent is NULL
2323 * then return the pathname of directory <ino2>)
2324 * %q ext2fs_get_pathname of directory <dir>
2325 * %Q ext2fs_get_pathname of directory <ino> with <dir> as
2326 * the containing directory.
2327 * %s <str> miscellaneous string
2328 * %S backup superblock
2329 * %X <num> hexadecimal format
2330 *
2331 * The following '@' expansions are supported:
2332 *
2333 * @a extended attribute
2334 * @A error allocating
2335 * @b block
2336 * @B bitmap
2337 * @c compress
2338 * @C conflicts with some other fs block
2339 * @D deleted
2340 * @d directory
2341 * @e entry
2342 * @E Entry '%Dn' in %p (%i)
2343 * @f filesystem
2344 * @F for @i %i (%Q) is
2345 * @g group
2346 * @h HTREE directory inode
2347 * @i inode
2348 * @I illegal
2349 * @j journal
2350 * @l lost+found
2351 * @L is a link
2352 * @m multiply-claimed
2353 * @n invalid
2354 * @o orphaned
2355 * @p problem in
2356 * @r root inode
2357 * @s should be
2358 * @S superblock
2359 * @u unattached
2360 * @v device
2361 * @z zero-length
2362 */
2363
2364
2365/*
2366 * This structure defines the abbreviations used by the text strings
2367 * below. The first character in the string is the index letter. An
2368 * abbreviation of the form '@<i>' is expanded by looking up the index
2369 * letter <i> in the table below.
2370 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002371static const char *const abbrevs[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002372 N_("aextended attribute"),
2373 N_("Aerror allocating"),
2374 N_("bblock"),
2375 N_("Bbitmap"),
2376 N_("ccompress"),
2377 N_("Cconflicts with some other fs @b"),
2378 N_("iinode"),
2379 N_("Iillegal"),
2380 N_("jjournal"),
2381 N_("Ddeleted"),
2382 N_("ddirectory"),
2383 N_("eentry"),
2384 N_("E@e '%Dn' in %p (%i)"),
2385 N_("ffilesystem"),
2386 N_("Ffor @i %i (%Q) is"),
2387 N_("ggroup"),
2388 N_("hHTREE @d @i"),
2389 N_("llost+found"),
2390 N_("Lis a link"),
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002391 N_("mmultiply-claimed"),
2392 N_("ninvalid"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002393 N_("oorphaned"),
2394 N_("pproblem in"),
2395 N_("rroot @i"),
2396 N_("sshould be"),
2397 N_("Ssuper@b"),
2398 N_("uunattached"),
2399 N_("vdevice"),
2400 N_("zzero-length"),
2401 "@@",
2402 0
2403 };
2404
2405/*
2406 * Give more user friendly names to the "special" inodes.
2407 */
2408#define num_special_inodes 11
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002409static const char *const special_inode_name[] =
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002410{
2411 N_("<The NULL inode>"), /* 0 */
2412 N_("<The bad blocks inode>"), /* 1 */
2413 "/", /* 2 */
2414 N_("<The ACL index inode>"), /* 3 */
2415 N_("<The ACL data inode>"), /* 4 */
2416 N_("<The boot loader inode>"), /* 5 */
2417 N_("<The undelete directory inode>"), /* 6 */
2418 N_("<The group descriptor inode>"), /* 7 */
2419 N_("<The journal inode>"), /* 8 */
2420 N_("<Reserved inode 9>"), /* 9 */
2421 N_("<Reserved inode 10>"), /* 10 */
2422};
2423
2424/*
2425 * This function does "safe" printing. It will convert non-printable
2426 * ASCII characters using '^' and M- notation.
2427 */
2428static void safe_print(const char *cp, int len)
2429{
2430 unsigned char ch;
2431
2432 if (len < 0)
2433 len = strlen(cp);
2434
2435 while (len--) {
2436 ch = *cp++;
2437 if (ch > 128) {
2438 fputs("M-", stdout);
2439 ch -= 128;
2440 }
2441 if ((ch < 32) || (ch == 0x7f)) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002442 bb_putchar('^');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002443 ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2444 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00002445 bb_putchar(ch);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002446 }
2447}
2448
2449
2450/*
2451 * This function prints a pathname, using the ext2fs_get_pathname
2452 * function
2453 */
2454static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2455{
2456 errcode_t retval;
2457 char *path;
2458
2459 if (!dir && (ino < num_special_inodes)) {
2460 fputs(_(special_inode_name[ino]), stdout);
2461 return;
2462 }
2463
2464 retval = ext2fs_get_pathname(fs, dir, ino, &path);
2465 if (retval)
2466 fputs("???", stdout);
2467 else {
2468 safe_print(path, -1);
2469 ext2fs_free_mem(&path);
2470 }
2471}
2472
2473static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2474 struct problem_context *pctx, int first);
2475/*
2476 * This function handles the '@' expansion. We allow recursive
2477 * expansion; an @ expression can contain further '@' and '%'
2478 * expressions.
2479 */
2480static void expand_at_expression(e2fsck_t ctx, char ch,
2481 struct problem_context *pctx,
2482 int *first)
2483{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002484 const char *const *cpp;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002485 const char *str;
2486
2487 /* Search for the abbreviation */
2488 for (cpp = abbrevs; *cpp; cpp++) {
2489 if (ch == *cpp[0])
2490 break;
2491 }
2492 if (*cpp) {
2493 str = _(*cpp) + 1;
2494 if (*first && islower(*str)) {
2495 *first = 0;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002496 bb_putchar(toupper(*str++));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002497 }
2498 print_e2fsck_message(ctx, str, pctx, *first);
2499 } else
2500 printf("@%c", ch);
2501}
2502
2503/*
2504 * This function expands '%IX' expressions
2505 */
2506static void expand_inode_expression(char ch,
2507 struct problem_context *ctx)
2508{
2509 struct ext2_inode *inode;
2510 struct ext2_inode_large *large_inode;
2511 char * time_str;
2512 time_t t;
2513 int do_gmt = -1;
2514
2515 if (!ctx || !ctx->inode)
2516 goto no_inode;
2517
2518 inode = ctx->inode;
2519 large_inode = (struct ext2_inode_large *) inode;
2520
2521 switch (ch) {
2522 case 's':
2523 if (LINUX_S_ISDIR(inode->i_mode))
2524 printf("%u", inode->i_size);
2525 else {
2526 printf("%"PRIu64, (inode->i_size |
2527 ((uint64_t) inode->i_size_high << 32)));
2528 }
2529 break;
2530 case 'S':
2531 printf("%u", large_inode->i_extra_isize);
2532 break;
2533 case 'b':
2534 printf("%u", inode->i_blocks);
2535 break;
2536 case 'l':
2537 printf("%d", inode->i_links_count);
2538 break;
2539 case 'm':
2540 printf("0%o", inode->i_mode);
2541 break;
2542 case 'M':
2543 /* The diet libc doesn't respect the TZ environemnt variable */
2544 if (do_gmt == -1) {
2545 time_str = getenv("TZ");
2546 if (!time_str)
2547 time_str = "";
2548 do_gmt = !strcmp(time_str, "GMT");
2549 }
2550 t = inode->i_mtime;
2551 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2552 printf("%.24s", time_str);
2553 break;
2554 case 'F':
2555 printf("%u", inode->i_faddr);
2556 break;
2557 case 'f':
2558 printf("%u", inode->i_file_acl);
2559 break;
2560 case 'd':
2561 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2562 inode->i_dir_acl : 0));
2563 break;
2564 case 'u':
2565 printf("%d", (inode->i_uid |
2566 (inode->osd2.linux2.l_i_uid_high << 16)));
2567 break;
2568 case 'g':
2569 printf("%d", (inode->i_gid |
2570 (inode->osd2.linux2.l_i_gid_high << 16)));
2571 break;
2572 default:
2573 no_inode:
2574 printf("%%I%c", ch);
2575 break;
2576 }
2577}
2578
2579/*
2580 * This function expands '%dX' expressions
2581 */
2582static void expand_dirent_expression(char ch,
2583 struct problem_context *ctx)
2584{
2585 struct ext2_dir_entry *dirent;
2586 int len;
2587
2588 if (!ctx || !ctx->dirent)
2589 goto no_dirent;
2590
2591 dirent = ctx->dirent;
2592
2593 switch (ch) {
2594 case 'i':
2595 printf("%u", dirent->inode);
2596 break;
2597 case 'n':
2598 len = dirent->name_len & 0xFF;
2599 if (len > EXT2_NAME_LEN)
2600 len = EXT2_NAME_LEN;
2601 if (len > dirent->rec_len)
2602 len = dirent->rec_len;
2603 safe_print(dirent->name, len);
2604 break;
2605 case 'r':
2606 printf("%u", dirent->rec_len);
2607 break;
2608 case 'l':
2609 printf("%u", dirent->name_len & 0xFF);
2610 break;
2611 case 't':
2612 printf("%u", dirent->name_len >> 8);
2613 break;
2614 default:
2615 no_dirent:
2616 printf("%%D%c", ch);
2617 break;
2618 }
2619}
2620
2621static void expand_percent_expression(ext2_filsys fs, char ch,
2622 struct problem_context *ctx)
2623{
2624 if (!ctx)
2625 goto no_context;
2626
2627 switch (ch) {
2628 case '%':
Denis Vlasenko4daad902007-09-27 10:20:47 +00002629 bb_putchar('%');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002630 break;
2631 case 'b':
2632 printf("%u", ctx->blk);
2633 break;
2634 case 'B':
2635 printf("%"PRIi64, ctx->blkcount);
2636 break;
2637 case 'c':
2638 printf("%u", ctx->blk2);
2639 break;
2640 case 'd':
2641 printf("%u", ctx->dir);
2642 break;
2643 case 'g':
2644 printf("%d", ctx->group);
2645 break;
2646 case 'i':
2647 printf("%u", ctx->ino);
2648 break;
2649 case 'j':
2650 printf("%u", ctx->ino2);
2651 break;
2652 case 'm':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002653 fputs(error_message(ctx->errcode), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002654 break;
2655 case 'N':
2656 printf("%"PRIi64, ctx->num);
2657 break;
2658 case 'p':
2659 print_pathname(fs, ctx->ino, 0);
2660 break;
2661 case 'P':
2662 print_pathname(fs, ctx->ino2,
2663 ctx->dirent ? ctx->dirent->inode : 0);
2664 break;
2665 case 'q':
2666 print_pathname(fs, ctx->dir, 0);
2667 break;
2668 case 'Q':
2669 print_pathname(fs, ctx->dir, ctx->ino);
2670 break;
2671 case 'S':
2672 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2673 break;
2674 case 's':
Denis Vlasenko605b20e2007-09-30 16:22:36 +00002675 fputs((ctx->str ? ctx->str : "NULL"), stdout);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002676 break;
2677 case 'X':
2678 printf("0x%"PRIi64, ctx->num);
2679 break;
2680 default:
2681 no_context:
2682 printf("%%%c", ch);
2683 break;
2684 }
2685}
2686
2687
2688static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2689 struct problem_context *pctx, int first)
2690{
2691 ext2_filsys fs = ctx->fs;
2692 const char * cp;
2693 int i;
2694
2695 e2fsck_clear_progbar(ctx);
2696 for (cp = msg; *cp; cp++) {
2697 if (cp[0] == '@') {
2698 cp++;
2699 expand_at_expression(ctx, *cp, pctx, &first);
2700 } else if (cp[0] == '%' && cp[1] == 'I') {
2701 cp += 2;
2702 expand_inode_expression(*cp, pctx);
2703 } else if (cp[0] == '%' && cp[1] == 'D') {
2704 cp += 2;
2705 expand_dirent_expression(*cp, pctx);
2706 } else if ((cp[0] == '%')) {
2707 cp++;
2708 expand_percent_expression(fs, *cp, pctx);
2709 } else {
2710 for (i=0; cp[i]; i++)
2711 if ((cp[i] == '@') || cp[i] == '%')
2712 break;
2713 printf("%.*s", i, cp);
2714 cp += i-1;
2715 }
2716 first = 0;
2717 }
2718}
2719
2720
2721/*
2722 * region.c --- code which manages allocations within a region.
2723 */
2724
2725struct region_el {
2726 region_addr_t start;
2727 region_addr_t end;
2728 struct region_el *next;
2729};
2730
2731struct region_struct {
2732 region_addr_t min;
2733 region_addr_t max;
2734 struct region_el *allocated;
2735};
2736
2737static region_t region_create(region_addr_t min, region_addr_t max)
2738{
2739 region_t region;
2740
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002741 region = xzalloc(sizeof(struct region_struct));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002742 region->min = min;
2743 region->max = max;
2744 return region;
2745}
2746
2747static void region_free(region_t region)
2748{
2749 struct region_el *r, *next;
2750
2751 for (r = region->allocated; r; r = next) {
2752 next = r->next;
2753 free(r);
2754 }
2755 memset(region, 0, sizeof(struct region_struct));
2756 free(region);
2757}
2758
2759static int region_allocate(region_t region, region_addr_t start, int n)
2760{
2761 struct region_el *r, *new_region, *prev, *next;
2762 region_addr_t end;
2763
2764 end = start+n;
2765 if ((start < region->min) || (end > region->max))
2766 return -1;
2767 if (n == 0)
2768 return 1;
2769
2770 /*
2771 * Search through the linked list. If we find that it
2772 * conflicts witih something that's already allocated, return
2773 * 1; if we can find an existing region which we can grow, do
2774 * so. Otherwise, stop when we find the appropriate place
2775 * insert a new region element into the linked list.
2776 */
2777 for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2778 if (((start >= r->start) && (start < r->end)) ||
2779 ((end > r->start) && (end <= r->end)) ||
2780 ((start <= r->start) && (end >= r->end)))
2781 return 1;
2782 if (end == r->start) {
2783 r->start = start;
2784 return 0;
2785 }
2786 if (start == r->end) {
2787 if ((next = r->next)) {
2788 if (end > next->start)
2789 return 1;
2790 if (end == next->start) {
2791 r->end = next->end;
2792 r->next = next->next;
2793 free(next);
2794 return 0;
2795 }
2796 }
2797 r->end = end;
2798 return 0;
2799 }
2800 if (start < r->start)
2801 break;
2802 }
2803 /*
2804 * Insert a new region element structure into the linked list
2805 */
Denys Vlasenkoef3817c2010-01-08 09:07:25 +01002806 new_region = xmalloc(sizeof(struct region_el));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00002807 new_region->start = start;
2808 new_region->end = start + n;
2809 new_region->next = r;
2810 if (prev)
2811 prev->next = new_region;
2812 else
2813 region->allocated = new_region;
2814 return 0;
2815}
2816
2817/*
2818 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2819 *
2820 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2821 * and applies the following tests to each inode:
2822 *
2823 * - The mode field of the inode must be legal.
2824 * - The size and block count fields of the inode are correct.
2825 * - A data block must not be used by another inode
2826 *
2827 * Pass 1 also gathers the collects the following information:
2828 *
2829 * - A bitmap of which inodes are in use. (inode_used_map)
2830 * - A bitmap of which inodes are directories. (inode_dir_map)
2831 * - A bitmap of which inodes are regular files. (inode_reg_map)
2832 * - A bitmap of which inodes have bad fields. (inode_bad_map)
2833 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
2834 * - A bitmap of which blocks are in use. (block_found_map)
2835 * - A bitmap of which blocks are in use by two inodes (block_dup_map)
2836 * - The data blocks of the directory inodes. (dir_map)
2837 *
2838 * Pass 1 is designed to stash away enough information so that the
2839 * other passes should not need to read in the inode information
2840 * during the normal course of a filesystem check. (Althogh if an
2841 * inconsistency is detected, other passes may need to read in an
2842 * inode to fix it.)
2843 *
2844 * Note that pass 1B will be invoked if there are any duplicate blocks
2845 * found.
2846 */
2847
2848
2849static int process_block(ext2_filsys fs, blk_t *blocknr,
2850 e2_blkcnt_t blockcnt, blk_t ref_blk,
2851 int ref_offset, void *priv_data);
2852static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2853 e2_blkcnt_t blockcnt, blk_t ref_blk,
2854 int ref_offset, void *priv_data);
2855static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2856 char *block_buf);
2857static void mark_table_blocks(e2fsck_t ctx);
2858static void alloc_imagic_map(e2fsck_t ctx);
2859static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2860static void handle_fs_bad_blocks(e2fsck_t ctx);
2861static void process_inodes(e2fsck_t ctx, char *block_buf);
2862static int process_inode_cmp(const void *a, const void *b);
2863static errcode_t scan_callback(ext2_filsys fs,
2864 dgrp_t group, void * priv_data);
2865static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2866 char *block_buf, int adjust_sign);
2867/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2868
2869static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2870 struct ext2_inode * inode, int bufsize,
2871 const char *proc);
2872
2873struct process_block_struct_1 {
2874 ext2_ino_t ino;
2875 unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
2876 fragmented:1, compressed:1, bbcheck:1;
2877 blk_t num_blocks;
2878 blk_t max_blocks;
2879 e2_blkcnt_t last_block;
2880 int num_illegal_blocks;
2881 blk_t previous_block;
2882 struct ext2_inode *inode;
2883 struct problem_context *pctx;
2884 ext2fs_block_bitmap fs_meta_blocks;
2885 e2fsck_t ctx;
2886};
2887
2888struct process_inode_block {
2889 ext2_ino_t ino;
2890 struct ext2_inode inode;
2891};
2892
2893struct scan_callback_struct {
2894 e2fsck_t ctx;
2895 char *block_buf;
2896};
2897
2898/*
2899 * For the inodes to process list.
2900 */
2901static struct process_inode_block *inodes_to_process;
2902static int process_inode_count;
2903
2904static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2905 EXT2_MIN_BLOCK_LOG_SIZE + 1];
2906
2907/*
2908 * Free all memory allocated by pass1 in preparation for restarting
2909 * things.
2910 */
2911static void unwind_pass1(void)
2912{
2913 ext2fs_free_mem(&inodes_to_process);
2914}
2915
2916/*
2917 * Check to make sure a device inode is real. Returns 1 if the device
2918 * checks out, 0 if not.
2919 *
2920 * Note: this routine is now also used to check FIFO's and Sockets,
2921 * since they have the same requirement; the i_block fields should be
2922 * zero.
2923 */
2924static int
2925e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2926{
2927 int i;
2928
2929 /*
2930 * If i_blocks is non-zero, or the index flag is set, then
2931 * this is a bogus device/fifo/socket
2932 */
2933 if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2934 (inode->i_flags & EXT2_INDEX_FL))
2935 return 0;
2936
2937 /*
2938 * We should be able to do the test below all the time, but
2939 * because the kernel doesn't forcibly clear the device
2940 * inode's additional i_block fields, there are some rare
2941 * occasions when a legitimate device inode will have non-zero
2942 * additional i_block fields. So for now, we only complain
2943 * when the immutable flag is set, which should never happen
2944 * for devices. (And that's when the problem is caused, since
2945 * you can't set or clear immutable flags for devices.) Once
2946 * the kernel has been fixed we can change this...
2947 */
2948 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2949 for (i=4; i < EXT2_N_BLOCKS; i++)
2950 if (inode->i_block[i])
2951 return 0;
2952 }
2953 return 1;
2954}
2955
2956/*
2957 * Check to make sure a symlink inode is real. Returns 1 if the symlink
2958 * checks out, 0 if not.
2959 */
2960static int
2961e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2962{
2963 unsigned int len;
2964 int i;
2965 blk_t blocks;
2966
2967 if ((inode->i_size_high || inode->i_size == 0) ||
2968 (inode->i_flags & EXT2_INDEX_FL))
2969 return 0;
2970
2971 blocks = ext2fs_inode_data_blocks(fs, inode);
2972 if (blocks) {
2973 if ((inode->i_size >= fs->blocksize) ||
2974 (blocks != fs->blocksize >> 9) ||
2975 (inode->i_block[0] < fs->super->s_first_data_block) ||
2976 (inode->i_block[0] >= fs->super->s_blocks_count))
2977 return 0;
2978
2979 for (i = 1; i < EXT2_N_BLOCKS; i++)
2980 if (inode->i_block[i])
2981 return 0;
2982
2983 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2984 return 0;
2985
2986 len = strnlen(buf, fs->blocksize);
2987 if (len == fs->blocksize)
2988 return 0;
2989 } else {
2990 if (inode->i_size >= sizeof(inode->i_block))
2991 return 0;
2992
2993 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2994 if (len == sizeof(inode->i_block))
2995 return 0;
2996 }
2997 if (len != inode->i_size)
2998 return 0;
2999 return 1;
3000}
3001
3002/*
3003 * If the immutable (or append-only) flag is set on the inode, offer
3004 * to clear it.
3005 */
3006#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3007static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3008{
3009 if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3010 return;
3011
3012 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3013 return;
3014
3015 pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3016 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3017}
3018
3019/*
3020 * If device, fifo or socket, check size is zero -- if not offer to
3021 * clear it
3022 */
3023static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3024{
3025 struct ext2_inode *inode = pctx->inode;
3026
3027 if ((inode->i_size == 0) && (inode->i_size_high == 0))
3028 return;
3029
3030 if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3031 return;
3032
3033 inode->i_size = 0;
3034 inode->i_size_high = 0;
3035 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3036}
3037
3038static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3039{
3040 struct ext2_super_block *sb = ctx->fs->super;
3041 struct ext2_inode_large *inode;
3042 struct ext2_ext_attr_entry *entry;
3043 char *start, *end;
3044 int storage_size, remain, offs;
3045 int problem = 0;
3046
3047 inode = (struct ext2_inode_large *) pctx->inode;
3048 storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3049 inode->i_extra_isize;
3050 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3051 inode->i_extra_isize + sizeof(__u32);
3052 end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3053 entry = (struct ext2_ext_attr_entry *) start;
3054
3055 /* scan all entry's headers first */
3056
3057 /* take finish entry 0UL into account */
3058 remain = storage_size - sizeof(__u32);
3059 offs = end - start;
3060
3061 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3062
3063 /* header eats this space */
3064 remain -= sizeof(struct ext2_ext_attr_entry);
3065
3066 /* is attribute name valid? */
3067 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3068 pctx->num = entry->e_name_len;
3069 problem = PR_1_ATTR_NAME_LEN;
3070 goto fix;
3071 }
3072
3073 /* attribute len eats this space */
3074 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3075
3076 /* check value size */
3077 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3078 pctx->num = entry->e_value_size;
3079 problem = PR_1_ATTR_VALUE_SIZE;
3080 goto fix;
3081 }
3082
3083 /* check value placement */
3084 if (entry->e_value_offs +
3085 EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3086 printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3087 pctx->num = entry->e_value_offs;
3088 problem = PR_1_ATTR_VALUE_OFFSET;
3089 goto fix;
3090 }
3091
3092 /* e_value_block must be 0 in inode's ea */
3093 if (entry->e_value_block != 0) {
3094 pctx->num = entry->e_value_block;
3095 problem = PR_1_ATTR_VALUE_BLOCK;
3096 goto fix;
3097 }
3098
3099 /* e_hash must be 0 in inode's ea */
3100 if (entry->e_hash != 0) {
3101 pctx->num = entry->e_hash;
3102 problem = PR_1_ATTR_HASH;
3103 goto fix;
3104 }
3105
3106 remain -= entry->e_value_size;
3107 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3108
3109 entry = EXT2_EXT_ATTR_NEXT(entry);
3110 }
3111fix:
3112 /*
3113 * it seems like a corruption. it's very unlikely we could repair
3114 * EA(s) in automatic fashion -bzzz
3115 */
3116 if (problem == 0 || !fix_problem(ctx, problem, pctx))
3117 return;
3118
3119 /* simple remove all possible EA(s) */
3120 *((__u32 *)start) = 0UL;
3121 e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3122 EXT2_INODE_SIZE(sb), "pass1");
3123}
3124
3125static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3126{
3127 struct ext2_super_block *sb = ctx->fs->super;
3128 struct ext2_inode_large *inode;
3129 __u32 *eamagic;
3130 int min, max;
3131
3132 inode = (struct ext2_inode_large *) pctx->inode;
3133 if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3134 /* this isn't large inode. so, nothing to check */
3135 return;
3136 }
3137
3138 /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3139 min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3140 max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3141 /*
3142 * For now we will allow i_extra_isize to be 0, but really
3143 * implementations should never allow i_extra_isize to be 0
3144 */
3145 if (inode->i_extra_isize &&
3146 (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3147 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3148 return;
3149 inode->i_extra_isize = min;
3150 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3151 EXT2_INODE_SIZE(sb), "pass1");
3152 return;
3153 }
3154
3155 eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3156 inode->i_extra_isize);
3157 if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3158 /* it seems inode has an extended attribute(s) in body */
3159 check_ea_in_inode(ctx, pctx);
3160 }
3161}
3162
3163static void e2fsck_pass1(e2fsck_t ctx)
3164{
3165 int i;
3166 __u64 max_sizes;
3167 ext2_filsys fs = ctx->fs;
3168 ext2_ino_t ino;
3169 struct ext2_inode *inode;
3170 ext2_inode_scan scan;
3171 char *block_buf;
3172 unsigned char frag, fsize;
3173 struct problem_context pctx;
3174 struct scan_callback_struct scan_struct;
3175 struct ext2_super_block *sb = ctx->fs->super;
3176 int imagic_fs;
3177 int busted_fs_time = 0;
3178 int inode_size;
3179
3180 clear_problem_context(&pctx);
3181
3182 if (!(ctx->options & E2F_OPT_PREEN))
3183 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3184
3185 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3186 !(ctx->options & E2F_OPT_NO)) {
3187 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3188 ctx->dirs_to_hash = 0;
3189 }
3190
3191 /* Pass 1 */
3192
3193#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3194
3195 for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3196 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3197 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3198 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3199 max_sizes = (max_sizes * (1UL << i)) - 1;
3200 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3201 }
3202#undef EXT2_BPP
3203
3204 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3205
3206 /*
3207 * Allocate bitmaps structures
3208 */
3209 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3210 &ctx->inode_used_map);
3211 if (pctx.errcode) {
3212 pctx.num = 1;
3213 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3214 ctx->flags |= E2F_FLAG_ABORT;
3215 return;
3216 }
3217 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3218 _("directory inode map"), &ctx->inode_dir_map);
3219 if (pctx.errcode) {
3220 pctx.num = 2;
3221 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3222 ctx->flags |= E2F_FLAG_ABORT;
3223 return;
3224 }
3225 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3226 _("regular file inode map"), &ctx->inode_reg_map);
3227 if (pctx.errcode) {
3228 pctx.num = 6;
3229 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3230 ctx->flags |= E2F_FLAG_ABORT;
3231 return;
3232 }
3233 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3234 &ctx->block_found_map);
3235 if (pctx.errcode) {
3236 pctx.num = 1;
3237 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3238 ctx->flags |= E2F_FLAG_ABORT;
3239 return;
3240 }
3241 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3242 &ctx->inode_link_info);
3243 if (pctx.errcode) {
3244 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3245 ctx->flags |= E2F_FLAG_ABORT;
3246 return;
3247 }
3248 inode_size = EXT2_INODE_SIZE(fs->super);
3249 inode = (struct ext2_inode *)
3250 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3251
3252 inodes_to_process = (struct process_inode_block *)
3253 e2fsck_allocate_memory(ctx,
3254 (ctx->process_inode_size *
3255 sizeof(struct process_inode_block)),
3256 "array of inodes to process");
3257 process_inode_count = 0;
3258
3259 pctx.errcode = ext2fs_init_dblist(fs, 0);
3260 if (pctx.errcode) {
3261 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3262 ctx->flags |= E2F_FLAG_ABORT;
3263 return;
3264 }
3265
3266 /*
3267 * If the last orphan field is set, clear it, since the pass1
3268 * processing will automatically find and clear the orphans.
3269 * In the future, we may want to try using the last_orphan
3270 * linked list ourselves, but for now, we clear it so that the
3271 * ext3 mount code won't get confused.
3272 */
3273 if (!(ctx->options & E2F_OPT_READONLY)) {
3274 if (fs->super->s_last_orphan) {
3275 fs->super->s_last_orphan = 0;
3276 ext2fs_mark_super_dirty(fs);
3277 }
3278 }
3279
3280 mark_table_blocks(ctx);
3281 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3282 "block interate buffer");
3283 e2fsck_use_inode_shortcuts(ctx, 1);
3284 ehandler_operation(_("doing inode scan"));
3285 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3286 &scan);
3287 if (pctx.errcode) {
3288 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3289 ctx->flags |= E2F_FLAG_ABORT;
3290 return;
3291 }
3292 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3293 ctx->stashed_inode = inode;
3294 scan_struct.ctx = ctx;
3295 scan_struct.block_buf = block_buf;
3296 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3297 if (ctx->progress)
3298 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3299 return;
3300 if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3301 (fs->super->s_mtime < fs->super->s_inodes_count))
3302 busted_fs_time = 1;
3303
3304 while (1) {
3305 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3306 inode, inode_size);
3307 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3308 return;
3309 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3310 continue;
3311 }
3312 if (pctx.errcode) {
3313 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3314 ctx->flags |= E2F_FLAG_ABORT;
3315 return;
3316 }
3317 if (!ino)
3318 break;
3319 pctx.ino = ino;
3320 pctx.inode = inode;
3321 ctx->stashed_ino = ino;
3322 if (inode->i_links_count) {
3323 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3324 ino, inode->i_links_count);
3325 if (pctx.errcode) {
3326 pctx.num = inode->i_links_count;
3327 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3328 ctx->flags |= E2F_FLAG_ABORT;
3329 return;
3330 }
3331 }
3332 if (ino == EXT2_BAD_INO) {
3333 struct process_block_struct_1 pb;
3334
3335 pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3336 &pb.fs_meta_blocks);
3337 if (pctx.errcode) {
3338 pctx.num = 4;
3339 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3340 ctx->flags |= E2F_FLAG_ABORT;
3341 return;
3342 }
3343 pb.ino = EXT2_BAD_INO;
3344 pb.num_blocks = pb.last_block = 0;
3345 pb.num_illegal_blocks = 0;
3346 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3347 pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3348 pb.inode = inode;
3349 pb.pctx = &pctx;
3350 pb.ctx = ctx;
3351 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3352 block_buf, process_bad_block, &pb);
3353 ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3354 if (pctx.errcode) {
3355 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3356 ctx->flags |= E2F_FLAG_ABORT;
3357 return;
3358 }
3359 if (pb.bbcheck)
3360 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3361 ctx->flags |= E2F_FLAG_ABORT;
3362 return;
3363 }
3364 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3365 clear_problem_context(&pctx);
3366 continue;
3367 } else if (ino == EXT2_ROOT_INO) {
3368 /*
3369 * Make sure the root inode is a directory; if
3370 * not, offer to clear it. It will be
3371 * regnerated in pass #3.
3372 */
3373 if (!LINUX_S_ISDIR(inode->i_mode)) {
3374 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003375 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003376 inode->i_links_count = 0;
3377 ext2fs_icount_store(ctx->inode_link_info,
3378 ino, 0);
3379 e2fsck_write_inode(ctx, ino, inode,
3380 "pass1");
3381 }
3382
3383 }
3384 /*
3385 * If dtime is set, offer to clear it. mke2fs
3386 * version 0.2b created filesystems with the
3387 * dtime field set for the root and lost+found
3388 * directories. We won't worry about
3389 * /lost+found, since that can be regenerated
3390 * easily. But we will fix the root directory
3391 * as a special case.
3392 */
3393 if (inode->i_dtime && inode->i_links_count) {
3394 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3395 inode->i_dtime = 0;
3396 e2fsck_write_inode(ctx, ino, inode,
3397 "pass1");
3398 }
3399 }
3400 } else if (ino == EXT2_JOURNAL_INO) {
3401 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3402 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3403 if (!LINUX_S_ISREG(inode->i_mode) &&
3404 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3405 &pctx)) {
3406 inode->i_mode = LINUX_S_IFREG;
3407 e2fsck_write_inode(ctx, ino, inode,
3408 "pass1");
3409 }
3410 check_blocks(ctx, &pctx, block_buf);
3411 continue;
3412 }
3413 if ((inode->i_links_count || inode->i_blocks ||
3414 inode->i_blocks || inode->i_block[0]) &&
3415 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3416 &pctx)) {
3417 memset(inode, 0, inode_size);
3418 ext2fs_icount_store(ctx->inode_link_info,
3419 ino, 0);
3420 e2fsck_write_inode_full(ctx, ino, inode,
3421 inode_size, "pass1");
3422 }
3423 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3424 int problem = 0;
3425
3426 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3427 if (ino == EXT2_BOOT_LOADER_INO) {
3428 if (LINUX_S_ISDIR(inode->i_mode))
3429 problem = PR_1_RESERVED_BAD_MODE;
3430 } else if (ino == EXT2_RESIZE_INO) {
3431 if (inode->i_mode &&
3432 !LINUX_S_ISREG(inode->i_mode))
3433 problem = PR_1_RESERVED_BAD_MODE;
3434 } else {
3435 if (inode->i_mode != 0)
3436 problem = PR_1_RESERVED_BAD_MODE;
3437 }
3438 if (problem) {
3439 if (fix_problem(ctx, problem, &pctx)) {
3440 inode->i_mode = 0;
3441 e2fsck_write_inode(ctx, ino, inode,
3442 "pass1");
3443 }
3444 }
3445 check_blocks(ctx, &pctx, block_buf);
3446 continue;
3447 }
3448 /*
3449 * Check for inodes who might have been part of the
3450 * orphaned list linked list. They should have gotten
3451 * dealt with by now, unless the list had somehow been
3452 * corrupted.
3453 *
3454 * FIXME: In the future, inodes which are still in use
3455 * (and which are therefore) pending truncation should
3456 * be handled specially. Right now we just clear the
3457 * dtime field, and the normal e2fsck handling of
3458 * inodes where i_size and the inode blocks are
3459 * inconsistent is to fix i_size, instead of releasing
3460 * the extra blocks. This won't catch the inodes that
3461 * was at the end of the orphan list, but it's better
3462 * than nothing. The right answer is that there
3463 * shouldn't be any bugs in the orphan list handling. :-)
3464 */
3465 if (inode->i_dtime && !busted_fs_time &&
3466 inode->i_dtime < ctx->fs->super->s_inodes_count) {
3467 if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3468 inode->i_dtime = inode->i_links_count ?
Denis Vlasenko04158e02009-02-02 10:48:06 +00003469 0 : time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003470 e2fsck_write_inode(ctx, ino, inode,
3471 "pass1");
3472 }
3473 }
3474
3475 /*
3476 * This code assumes that deleted inodes have
3477 * i_links_count set to 0.
3478 */
3479 if (!inode->i_links_count) {
3480 if (!inode->i_dtime && inode->i_mode) {
3481 if (fix_problem(ctx,
3482 PR_1_ZERO_DTIME, &pctx)) {
Denis Vlasenko04158e02009-02-02 10:48:06 +00003483 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003484 e2fsck_write_inode(ctx, ino, inode,
3485 "pass1");
3486 }
3487 }
3488 continue;
3489 }
3490 /*
3491 * n.b. 0.3c ext2fs code didn't clear i_links_count for
3492 * deleted files. Oops.
3493 *
3494 * Since all new ext2 implementations get this right,
3495 * we now assume that the case of non-zero
3496 * i_links_count and non-zero dtime means that we
3497 * should keep the file, not delete it.
3498 *
3499 */
3500 if (inode->i_dtime) {
3501 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3502 inode->i_dtime = 0;
3503 e2fsck_write_inode(ctx, ino, inode, "pass1");
3504 }
3505 }
3506
3507 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3508 switch (fs->super->s_creator_os) {
3509 case EXT2_OS_LINUX:
3510 frag = inode->osd2.linux2.l_i_frag;
3511 fsize = inode->osd2.linux2.l_i_fsize;
3512 break;
3513 case EXT2_OS_HURD:
3514 frag = inode->osd2.hurd2.h_i_frag;
3515 fsize = inode->osd2.hurd2.h_i_fsize;
3516 break;
3517 case EXT2_OS_MASIX:
3518 frag = inode->osd2.masix2.m_i_frag;
3519 fsize = inode->osd2.masix2.m_i_fsize;
3520 break;
3521 default:
3522 frag = fsize = 0;
3523 }
3524
3525 if (inode->i_faddr || frag || fsize ||
3526 (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3527 mark_inode_bad(ctx, ino);
3528 if (inode->i_flags & EXT2_IMAGIC_FL) {
3529 if (imagic_fs) {
3530 if (!ctx->inode_imagic_map)
3531 alloc_imagic_map(ctx);
3532 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3533 ino);
3534 } else {
3535 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3536 inode->i_flags &= ~EXT2_IMAGIC_FL;
3537 e2fsck_write_inode(ctx, ino,
3538 inode, "pass1");
3539 }
3540 }
3541 }
3542
3543 check_inode_extra_space(ctx, &pctx);
3544
3545 if (LINUX_S_ISDIR(inode->i_mode)) {
3546 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3547 e2fsck_add_dir_info(ctx, ino, 0);
3548 ctx->fs_directory_count++;
3549 } else if (LINUX_S_ISREG (inode->i_mode)) {
3550 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3551 ctx->fs_regular_count++;
3552 } else if (LINUX_S_ISCHR (inode->i_mode) &&
3553 e2fsck_pass1_check_device_inode(fs, inode)) {
3554 check_immutable(ctx, &pctx);
3555 check_size(ctx, &pctx);
3556 ctx->fs_chardev_count++;
3557 } else if (LINUX_S_ISBLK (inode->i_mode) &&
3558 e2fsck_pass1_check_device_inode(fs, inode)) {
3559 check_immutable(ctx, &pctx);
3560 check_size(ctx, &pctx);
3561 ctx->fs_blockdev_count++;
3562 } else if (LINUX_S_ISLNK (inode->i_mode) &&
3563 e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3564 check_immutable(ctx, &pctx);
3565 ctx->fs_symlinks_count++;
3566 if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3567 ctx->fs_fast_symlinks_count++;
3568 check_blocks(ctx, &pctx, block_buf);
3569 continue;
3570 }
3571 }
3572 else if (LINUX_S_ISFIFO (inode->i_mode) &&
3573 e2fsck_pass1_check_device_inode(fs, inode)) {
3574 check_immutable(ctx, &pctx);
3575 check_size(ctx, &pctx);
3576 ctx->fs_fifo_count++;
3577 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3578 e2fsck_pass1_check_device_inode(fs, inode)) {
3579 check_immutable(ctx, &pctx);
3580 check_size(ctx, &pctx);
3581 ctx->fs_sockets_count++;
3582 } else
3583 mark_inode_bad(ctx, ino);
3584 if (inode->i_block[EXT2_IND_BLOCK])
3585 ctx->fs_ind_count++;
3586 if (inode->i_block[EXT2_DIND_BLOCK])
3587 ctx->fs_dind_count++;
3588 if (inode->i_block[EXT2_TIND_BLOCK])
3589 ctx->fs_tind_count++;
3590 if (inode->i_block[EXT2_IND_BLOCK] ||
3591 inode->i_block[EXT2_DIND_BLOCK] ||
3592 inode->i_block[EXT2_TIND_BLOCK] ||
3593 inode->i_file_acl) {
3594 inodes_to_process[process_inode_count].ino = ino;
3595 inodes_to_process[process_inode_count].inode = *inode;
3596 process_inode_count++;
3597 } else
3598 check_blocks(ctx, &pctx, block_buf);
3599
3600 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3601 return;
3602
3603 if (process_inode_count >= ctx->process_inode_size) {
3604 process_inodes(ctx, block_buf);
3605
3606 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3607 return;
3608 }
3609 }
3610 process_inodes(ctx, block_buf);
3611 ext2fs_close_inode_scan(scan);
3612 ehandler_operation(0);
3613
3614 /*
3615 * If any extended attribute blocks' reference counts need to
3616 * be adjusted, either up (ctx->refcount_extra), or down
3617 * (ctx->refcount), then fix them.
3618 */
3619 if (ctx->refcount) {
3620 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3621 ea_refcount_free(ctx->refcount);
3622 ctx->refcount = 0;
3623 }
3624 if (ctx->refcount_extra) {
3625 adjust_extattr_refcount(ctx, ctx->refcount_extra,
3626 block_buf, +1);
3627 ea_refcount_free(ctx->refcount_extra);
3628 ctx->refcount_extra = 0;
3629 }
3630
3631 if (ctx->invalid_bitmaps)
3632 handle_fs_bad_blocks(ctx);
3633
3634 /* We don't need the block_ea_map any more */
3635 ext2fs_free_block_bitmap(ctx->block_ea_map);
3636 ctx->block_ea_map = 0;
3637
3638 if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3639 ext2fs_block_bitmap save_bmap;
3640
3641 save_bmap = fs->block_map;
3642 fs->block_map = ctx->block_found_map;
3643 clear_problem_context(&pctx);
3644 pctx.errcode = ext2fs_create_resize_inode(fs);
3645 if (pctx.errcode) {
3646 fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3647 /* Should never get here */
3648 ctx->flags |= E2F_FLAG_ABORT;
3649 return;
3650 }
3651 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3652 "recreate inode");
Denis Vlasenko04158e02009-02-02 10:48:06 +00003653 inode->i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00003654 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3655 "recreate inode");
3656 fs->block_map = save_bmap;
3657 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3658 }
3659
3660 if (ctx->flags & E2F_FLAG_RESTART) {
3661 /*
3662 * Only the master copy of the superblock and block
3663 * group descriptors are going to be written during a
3664 * restart, so set the superblock to be used to be the
3665 * master superblock.
3666 */
3667 ctx->use_superblock = 0;
3668 unwind_pass1();
3669 goto endit;
3670 }
3671
3672 if (ctx->block_dup_map) {
3673 if (ctx->options & E2F_OPT_PREEN) {
3674 clear_problem_context(&pctx);
3675 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3676 }
3677 e2fsck_pass1_dupblocks(ctx, block_buf);
3678 }
3679 ext2fs_free_mem(&inodes_to_process);
3680endit:
3681 e2fsck_use_inode_shortcuts(ctx, 0);
3682
3683 ext2fs_free_mem(&block_buf);
3684 ext2fs_free_mem(&inode);
3685
3686}
3687
3688/*
3689 * When the inode_scan routines call this callback at the end of the
3690 * glock group, call process_inodes.
3691 */
3692static errcode_t scan_callback(ext2_filsys fs,
3693 dgrp_t group, void * priv_data)
3694{
3695 struct scan_callback_struct *scan_struct;
3696 e2fsck_t ctx;
3697
3698 scan_struct = (struct scan_callback_struct *) priv_data;
3699 ctx = scan_struct->ctx;
3700
3701 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3702
3703 if (ctx->progress)
3704 if ((ctx->progress)(ctx, 1, group+1,
3705 ctx->fs->group_desc_count))
3706 return EXT2_ET_CANCEL_REQUESTED;
3707
3708 return 0;
3709}
3710
3711/*
3712 * Process the inodes in the "inodes to process" list.
3713 */
3714static void process_inodes(e2fsck_t ctx, char *block_buf)
3715{
3716 int i;
3717 struct ext2_inode *old_stashed_inode;
3718 ext2_ino_t old_stashed_ino;
3719 const char *old_operation;
3720 char buf[80];
3721 struct problem_context pctx;
3722
3723 /* begin process_inodes */
3724 if (process_inode_count == 0)
3725 return;
3726 old_operation = ehandler_operation(0);
3727 old_stashed_inode = ctx->stashed_inode;
3728 old_stashed_ino = ctx->stashed_ino;
3729 qsort(inodes_to_process, process_inode_count,
3730 sizeof(struct process_inode_block), process_inode_cmp);
3731 clear_problem_context(&pctx);
3732 for (i=0; i < process_inode_count; i++) {
3733 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3734 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3735 sprintf(buf, _("reading indirect blocks of inode %u"),
3736 pctx.ino);
3737 ehandler_operation(buf);
3738 check_blocks(ctx, &pctx, block_buf);
3739 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3740 break;
3741 }
3742 ctx->stashed_inode = old_stashed_inode;
3743 ctx->stashed_ino = old_stashed_ino;
3744 process_inode_count = 0;
3745 /* end process inodes */
3746
3747 ehandler_operation(old_operation);
3748}
3749
3750static int process_inode_cmp(const void *a, const void *b)
3751{
3752 const struct process_inode_block *ib_a =
3753 (const struct process_inode_block *) a;
3754 const struct process_inode_block *ib_b =
3755 (const struct process_inode_block *) b;
3756 int ret;
3757
3758 ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3759 ib_b->inode.i_block[EXT2_IND_BLOCK]);
3760 if (ret == 0)
3761 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3762 return ret;
3763}
3764
3765/*
3766 * Mark an inode as being bad in some what
3767 */
3768static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3769{
3770 struct problem_context pctx;
3771
3772 if (!ctx->inode_bad_map) {
3773 clear_problem_context(&pctx);
3774
3775 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3776 _("bad inode map"), &ctx->inode_bad_map);
3777 if (pctx.errcode) {
3778 pctx.num = 3;
3779 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3780 /* Should never get here */
3781 ctx->flags |= E2F_FLAG_ABORT;
3782 return;
3783 }
3784 }
3785 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3786}
3787
3788
3789/*
3790 * This procedure will allocate the inode imagic table
3791 */
3792static void alloc_imagic_map(e2fsck_t ctx)
3793{
3794 struct problem_context pctx;
3795
3796 clear_problem_context(&pctx);
3797 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3798 _("imagic inode map"),
3799 &ctx->inode_imagic_map);
3800 if (pctx.errcode) {
3801 pctx.num = 5;
3802 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3803 /* Should never get here */
3804 ctx->flags |= E2F_FLAG_ABORT;
3805 return;
3806 }
3807}
3808
3809/*
3810 * Marks a block as in use, setting the dup_map if it's been set
3811 * already. Called by process_block and process_bad_block.
3812 *
3813 * WARNING: Assumes checks have already been done to make sure block
3814 * is valid. This is true in both process_block and process_bad_block.
3815 */
3816static void mark_block_used(e2fsck_t ctx, blk_t block)
3817{
3818 struct problem_context pctx;
3819
3820 clear_problem_context(&pctx);
3821
3822 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3823 if (!ctx->block_dup_map) {
3824 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3825 _("multiply claimed block map"),
3826 &ctx->block_dup_map);
3827 if (pctx.errcode) {
3828 pctx.num = 3;
3829 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3830 &pctx);
3831 /* Should never get here */
3832 ctx->flags |= E2F_FLAG_ABORT;
3833 return;
3834 }
3835 }
3836 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3837 } else {
3838 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3839 }
3840}
3841
3842/*
3843 * Adjust the extended attribute block's reference counts at the end
3844 * of pass 1, either by subtracting out references for EA blocks that
3845 * are still referenced in ctx->refcount, or by adding references for
3846 * EA blocks that had extra references as accounted for in
3847 * ctx->refcount_extra.
3848 */
3849static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3850 char *block_buf, int adjust_sign)
3851{
3852 struct ext2_ext_attr_header *header;
3853 struct problem_context pctx;
3854 ext2_filsys fs = ctx->fs;
3855 blk_t blk;
3856 __u32 should_be;
3857 int count;
3858
3859 clear_problem_context(&pctx);
3860
3861 ea_refcount_intr_begin(refcount);
3862 while (1) {
3863 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3864 break;
3865 pctx.blk = blk;
3866 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3867 if (pctx.errcode) {
3868 fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3869 return;
3870 }
3871 header = (struct ext2_ext_attr_header *) block_buf;
3872 pctx.blkcount = header->h_refcount;
3873 should_be = header->h_refcount + adjust_sign * count;
3874 pctx.num = should_be;
3875 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3876 header->h_refcount = should_be;
3877 pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3878 block_buf);
3879 if (pctx.errcode) {
3880 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3881 continue;
3882 }
3883 }
3884 }
3885}
3886
3887/*
3888 * Handle processing the extended attribute blocks
3889 */
3890static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3891 char *block_buf)
3892{
3893 ext2_filsys fs = ctx->fs;
3894 ext2_ino_t ino = pctx->ino;
3895 struct ext2_inode *inode = pctx->inode;
3896 blk_t blk;
3897 char * end;
3898 struct ext2_ext_attr_header *header;
3899 struct ext2_ext_attr_entry *entry;
3900 int count;
3901 region_t region;
3902
3903 blk = inode->i_file_acl;
3904 if (blk == 0)
3905 return 0;
3906
3907 /*
3908 * If the Extended attribute flag isn't set, then a non-zero
3909 * file acl means that the inode is corrupted.
3910 *
3911 * Or if the extended attribute block is an invalid block,
3912 * then the inode is also corrupted.
3913 */
3914 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3915 (blk < fs->super->s_first_data_block) ||
3916 (blk >= fs->super->s_blocks_count)) {
3917 mark_inode_bad(ctx, ino);
3918 return 0;
3919 }
3920
3921 /* If ea bitmap hasn't been allocated, create it */
3922 if (!ctx->block_ea_map) {
3923 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3924 _("ext attr block map"),
3925 &ctx->block_ea_map);
3926 if (pctx->errcode) {
3927 pctx->num = 2;
3928 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3929 ctx->flags |= E2F_FLAG_ABORT;
3930 return 0;
3931 }
3932 }
3933
3934 /* Create the EA refcount structure if necessary */
3935 if (!ctx->refcount) {
3936 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3937 if (pctx->errcode) {
3938 pctx->num = 1;
3939 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3940 ctx->flags |= E2F_FLAG_ABORT;
3941 return 0;
3942 }
3943 }
3944
3945 /* Have we seen this EA block before? */
3946 if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3947 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3948 return 1;
3949 /* Ooops, this EA was referenced more than it stated */
3950 if (!ctx->refcount_extra) {
3951 pctx->errcode = ea_refcount_create(0,
3952 &ctx->refcount_extra);
3953 if (pctx->errcode) {
3954 pctx->num = 2;
3955 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3956 ctx->flags |= E2F_FLAG_ABORT;
3957 return 0;
3958 }
3959 }
3960 ea_refcount_increment(ctx->refcount_extra, blk, 0);
3961 return 1;
3962 }
3963
3964 /*
3965 * OK, we haven't seen this EA block yet. So we need to
3966 * validate it
3967 */
3968 pctx->blk = blk;
3969 pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3970 if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3971 goto clear_extattr;
3972 header = (struct ext2_ext_attr_header *) block_buf;
3973 pctx->blk = inode->i_file_acl;
3974 if (((ctx->ext_attr_ver == 1) &&
3975 (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3976 ((ctx->ext_attr_ver == 2) &&
3977 (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3978 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3979 goto clear_extattr;
3980 }
3981
3982 if (header->h_blocks != 1) {
3983 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3984 goto clear_extattr;
3985 }
3986
3987 region = region_create(0, fs->blocksize);
3988 if (!region) {
3989 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3990 ctx->flags |= E2F_FLAG_ABORT;
3991 return 0;
3992 }
3993 if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3994 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3995 goto clear_extattr;
3996 }
3997
3998 entry = (struct ext2_ext_attr_entry *)(header+1);
3999 end = block_buf + fs->blocksize;
4000 while ((char *)entry < end && *(__u32 *)entry) {
4001 if (region_allocate(region, (char *)entry - (char *)header,
4002 EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4003 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4004 goto clear_extattr;
4005 }
4006 if ((ctx->ext_attr_ver == 1 &&
4007 (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4008 (ctx->ext_attr_ver == 2 &&
4009 entry->e_name_index == 0)) {
4010 if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4011 goto clear_extattr;
4012 }
4013 if (entry->e_value_block != 0) {
4014 if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4015 goto clear_extattr;
4016 }
4017 if (entry->e_value_size &&
4018 region_allocate(region, entry->e_value_offs,
4019 EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4020 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4021 goto clear_extattr;
4022 }
4023 entry = EXT2_EXT_ATTR_NEXT(entry);
4024 }
4025 if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4026 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4027 goto clear_extattr;
4028 }
4029 region_free(region);
4030
4031 count = header->h_refcount - 1;
4032 if (count)
4033 ea_refcount_store(ctx->refcount, blk, count);
4034 mark_block_used(ctx, blk);
4035 ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4036
4037 return 1;
4038
4039clear_extattr:
4040 inode->i_file_acl = 0;
4041 e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4042 return 0;
4043}
4044
4045/* Returns 1 if bad htree, 0 if OK */
4046static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4047 ext2_ino_t ino FSCK_ATTR((unused)),
4048 struct ext2_inode *inode,
4049 char *block_buf)
4050{
4051 struct ext2_dx_root_info *root;
4052 ext2_filsys fs = ctx->fs;
4053 errcode_t retval;
4054 blk_t blk;
4055
4056 if ((!LINUX_S_ISDIR(inode->i_mode) &&
4057 fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4058 (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4059 fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4060 return 1;
4061
4062 blk = inode->i_block[0];
4063 if (((blk == 0) ||
4064 (blk < fs->super->s_first_data_block) ||
4065 (blk >= fs->super->s_blocks_count)) &&
4066 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4067 return 1;
4068
4069 retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4070 if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4071 return 1;
4072
4073 /* XXX should check that beginning matches a directory */
4074 root = (struct ext2_dx_root_info *) (block_buf + 24);
4075
4076 if ((root->reserved_zero || root->info_length < 8) &&
4077 fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4078 return 1;
4079
4080 pctx->num = root->hash_version;
4081 if ((root->hash_version != EXT2_HASH_LEGACY) &&
4082 (root->hash_version != EXT2_HASH_HALF_MD4) &&
4083 (root->hash_version != EXT2_HASH_TEA) &&
4084 fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4085 return 1;
4086
4087 if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4088 fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4089 return 1;
4090
4091 pctx->num = root->indirect_levels;
4092 if ((root->indirect_levels > 1) &&
4093 fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4094 return 1;
4095
4096 return 0;
4097}
4098
4099/*
4100 * This subroutine is called on each inode to account for all of the
4101 * blocks used by that inode.
4102 */
4103static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4104 char *block_buf)
4105{
4106 ext2_filsys fs = ctx->fs;
4107 struct process_block_struct_1 pb;
4108 ext2_ino_t ino = pctx->ino;
4109 struct ext2_inode *inode = pctx->inode;
4110 int bad_size = 0;
4111 int dirty_inode = 0;
4112 __u64 size;
4113
4114 pb.ino = ino;
4115 pb.num_blocks = 0;
4116 pb.last_block = -1;
4117 pb.num_illegal_blocks = 0;
4118 pb.suppress = 0; pb.clear = 0;
4119 pb.fragmented = 0;
4120 pb.compressed = 0;
4121 pb.previous_block = 0;
4122 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4123 pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4124 pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4125 pb.inode = inode;
4126 pb.pctx = pctx;
4127 pb.ctx = ctx;
4128 pctx->ino = ino;
4129 pctx->errcode = 0;
4130
4131 if (inode->i_flags & EXT2_COMPRBLK_FL) {
4132 if (fs->super->s_feature_incompat &
4133 EXT2_FEATURE_INCOMPAT_COMPRESSION)
4134 pb.compressed = 1;
4135 else {
4136 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4137 inode->i_flags &= ~EXT2_COMPRBLK_FL;
4138 dirty_inode++;
4139 }
4140 }
4141 }
4142
4143 if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4144 pb.num_blocks++;
4145
4146 if (ext2fs_inode_has_valid_blocks(inode))
4147 pctx->errcode = ext2fs_block_iterate2(fs, ino,
4148 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4149 block_buf, process_block, &pb);
4150 end_problem_latch(ctx, PR_LATCH_BLOCK);
4151 end_problem_latch(ctx, PR_LATCH_TOOBIG);
4152 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4153 goto out;
4154 if (pctx->errcode)
4155 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4156
4157 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4158 ctx->fs_fragmented++;
4159
4160 if (pb.clear) {
4161 inode->i_links_count = 0;
4162 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004163 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004164 dirty_inode++;
4165 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4166 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4167 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4168 /*
4169 * The inode was probably partially accounted for
4170 * before processing was aborted, so we need to
4171 * restart the pass 1 scan.
4172 */
4173 ctx->flags |= E2F_FLAG_RESTART;
4174 goto out;
4175 }
4176
4177 if (inode->i_flags & EXT2_INDEX_FL) {
4178 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4179 inode->i_flags &= ~EXT2_INDEX_FL;
4180 dirty_inode++;
4181 } else {
4182#ifdef ENABLE_HTREE
4183 e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4184#endif
4185 }
4186 }
4187 if (ctx->dirs_to_hash && pb.is_dir &&
4188 !(inode->i_flags & EXT2_INDEX_FL) &&
4189 ((inode->i_size / fs->blocksize) >= 3))
4190 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4191
4192 if (!pb.num_blocks && pb.is_dir) {
4193 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4194 inode->i_links_count = 0;
4195 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Denis Vlasenko04158e02009-02-02 10:48:06 +00004196 inode->i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004197 dirty_inode++;
4198 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4199 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4200 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4201 ctx->fs_directory_count--;
4202 goto out;
4203 }
4204 }
4205
4206 pb.num_blocks *= (fs->blocksize / 512);
4207
4208 if (pb.is_dir) {
4209 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4210 if (nblock > (pb.last_block + 1))
4211 bad_size = 1;
4212 else if (nblock < (pb.last_block + 1)) {
4213 if (((pb.last_block + 1) - nblock) >
4214 fs->super->s_prealloc_dir_blocks)
4215 bad_size = 2;
4216 }
4217 } else {
4218 size = EXT2_I_SIZE(inode);
4219 if ((pb.last_block >= 0) &&
4220 (size < (__u64) pb.last_block * fs->blocksize))
4221 bad_size = 3;
4222 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4223 bad_size = 4;
4224 }
4225 /* i_size for symlinks is checked elsewhere */
4226 if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4227 pctx->num = (pb.last_block+1) * fs->blocksize;
4228 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4229 inode->i_size = pctx->num;
4230 if (!LINUX_S_ISDIR(inode->i_mode))
4231 inode->i_size_high = pctx->num >> 32;
4232 dirty_inode++;
4233 }
4234 pctx->num = 0;
4235 }
4236 if (LINUX_S_ISREG(inode->i_mode) &&
4237 (inode->i_size_high || inode->i_size & 0x80000000UL))
4238 ctx->large_files++;
4239 if (pb.num_blocks != inode->i_blocks) {
4240 pctx->num = pb.num_blocks;
4241 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4242 inode->i_blocks = pb.num_blocks;
4243 dirty_inode++;
4244 }
4245 pctx->num = 0;
4246 }
4247out:
4248 if (dirty_inode)
4249 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4250}
4251
4252
4253/*
4254 * This is a helper function for check_blocks().
4255 */
4256static int process_block(ext2_filsys fs,
4257 blk_t *block_nr,
4258 e2_blkcnt_t blockcnt,
4259 blk_t ref_block FSCK_ATTR((unused)),
4260 int ref_offset FSCK_ATTR((unused)),
4261 void *priv_data)
4262{
4263 struct process_block_struct_1 *p;
4264 struct problem_context *pctx;
4265 blk_t blk = *block_nr;
4266 int ret_code = 0;
4267 int problem = 0;
4268 e2fsck_t ctx;
4269
4270 p = (struct process_block_struct_1 *) priv_data;
4271 pctx = p->pctx;
4272 ctx = p->ctx;
4273
4274 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4275 /* todo: Check that the comprblk_fl is high, that the
4276 blkaddr pattern looks right (all non-holes up to
4277 first EXT2FS_COMPRESSED_BLKADDR, then all
4278 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4279 that the feature_incompat bit is high, and that the
4280 inode is a regular file. If we're doing a "full
4281 check" (a concept introduced to e2fsck by e2compr,
4282 meaning that we look at data blocks as well as
4283 metadata) then call some library routine that
4284 checks the compressed data. I'll have to think
4285 about this, because one particularly important
4286 problem to be able to fix is to recalculate the
4287 cluster size if necessary. I think that perhaps
4288 we'd better do most/all e2compr-specific checks
4289 separately, after the non-e2compr checks. If not
4290 doing a full check, it may be useful to test that
4291 the personality is linux; e.g. if it isn't then
4292 perhaps this really is just an illegal block. */
4293 return 0;
4294 }
4295
4296 if (blk == 0) {
4297 if (p->is_dir == 0) {
4298 /*
4299 * Should never happen, since only directories
4300 * get called with BLOCK_FLAG_HOLE
4301 */
4302#ifdef DEBUG_E2FSCK
4303 printf("process_block() called with blk == 0, "
4304 "blockcnt=%d, inode %lu???\n",
4305 blockcnt, p->ino);
4306#endif
4307 return 0;
4308 }
4309 if (blockcnt < 0)
4310 return 0;
4311 if (blockcnt * fs->blocksize < p->inode->i_size) {
4312 goto mark_dir;
4313 }
4314 return 0;
4315 }
4316
4317 /*
4318 * Simplistic fragmentation check. We merely require that the
4319 * file be contiguous. (Which can never be true for really
4320 * big files that are greater than a block group.)
4321 */
4322 if (!HOLE_BLKADDR(p->previous_block)) {
4323 if (p->previous_block+1 != blk)
4324 p->fragmented = 1;
4325 }
4326 p->previous_block = blk;
4327
4328 if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4329 problem = PR_1_TOOBIG_DIR;
4330 if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4331 problem = PR_1_TOOBIG_REG;
4332 if (!p->is_dir && !p->is_reg && blockcnt > 0)
4333 problem = PR_1_TOOBIG_SYMLINK;
4334
4335 if (blk < fs->super->s_first_data_block ||
4336 blk >= fs->super->s_blocks_count)
4337 problem = PR_1_ILLEGAL_BLOCK_NUM;
4338
4339 if (problem) {
4340 p->num_illegal_blocks++;
4341 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4342 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4343 p->clear = 1;
4344 return BLOCK_ABORT;
4345 }
4346 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4347 p->suppress = 1;
4348 set_latch_flags(PR_LATCH_BLOCK,
4349 PRL_SUPPRESS, 0);
4350 }
4351 }
4352 pctx->blk = blk;
4353 pctx->blkcount = blockcnt;
4354 if (fix_problem(ctx, problem, pctx)) {
4355 blk = *block_nr = 0;
4356 ret_code = BLOCK_CHANGED;
4357 goto mark_dir;
4358 } else
4359 return 0;
4360 }
4361
4362 if (p->ino == EXT2_RESIZE_INO) {
4363 /*
4364 * The resize inode has already be sanity checked
4365 * during pass #0 (the superblock checks). All we
4366 * have to do is mark the double indirect block as
4367 * being in use; all of the other blocks are handled
4368 * by mark_table_blocks()).
4369 */
4370 if (blockcnt == BLOCK_COUNT_DIND)
4371 mark_block_used(ctx, blk);
4372 } else
4373 mark_block_used(ctx, blk);
4374 p->num_blocks++;
4375 if (blockcnt >= 0)
4376 p->last_block = blockcnt;
4377mark_dir:
4378 if (p->is_dir && (blockcnt >= 0)) {
4379 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4380 blk, blockcnt);
4381 if (pctx->errcode) {
4382 pctx->blk = blk;
4383 pctx->num = blockcnt;
4384 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4385 /* Should never get here */
4386 ctx->flags |= E2F_FLAG_ABORT;
4387 return BLOCK_ABORT;
4388 }
4389 }
4390 return ret_code;
4391}
4392
4393static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4394 blk_t *block_nr,
4395 e2_blkcnt_t blockcnt,
4396 blk_t ref_block FSCK_ATTR((unused)),
4397 int ref_offset FSCK_ATTR((unused)),
4398 void *priv_data EXT2FS_ATTR((unused)))
4399{
4400 /*
4401 * Note: This function processes blocks for the bad blocks
4402 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
4403 */
4404
4405 printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4406 return BLOCK_ERROR;
4407}
4408
4409/*
4410 * This routine gets called at the end of pass 1 if bad blocks are
4411 * detected in the superblock, group descriptors, inode_bitmaps, or
4412 * block bitmaps. At this point, all of the blocks have been mapped
4413 * out, so we can try to allocate new block(s) to replace the bad
4414 * blocks.
4415 */
4416static void handle_fs_bad_blocks(e2fsck_t ctx)
4417{
4418 printf("Bad blocks detected on your filesystem\n"
4419 "You should get your data off as the device will soon die\n");
4420}
4421
4422/*
4423 * This routine marks all blocks which are used by the superblock,
4424 * group descriptors, inode bitmaps, and block bitmaps.
4425 */
4426static void mark_table_blocks(e2fsck_t ctx)
4427{
4428 ext2_filsys fs = ctx->fs;
4429 blk_t block, b;
4430 dgrp_t i;
4431 int j;
4432 struct problem_context pctx;
4433
4434 clear_problem_context(&pctx);
4435
4436 block = fs->super->s_first_data_block;
4437 for (i = 0; i < fs->group_desc_count; i++) {
4438 pctx.group = i;
4439
4440 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4441
4442 /*
4443 * Mark the blocks used for the inode table
4444 */
4445 if (fs->group_desc[i].bg_inode_table) {
4446 for (j = 0, b = fs->group_desc[i].bg_inode_table;
4447 j < fs->inode_blocks_per_group;
4448 j++, b++) {
4449 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4450 b)) {
4451 pctx.blk = b;
4452 if (fix_problem(ctx,
4453 PR_1_ITABLE_CONFLICT, &pctx)) {
4454 ctx->invalid_inode_table_flag[i]++;
4455 ctx->invalid_bitmaps++;
4456 }
4457 } else {
4458 ext2fs_mark_block_bitmap(ctx->block_found_map,
4459 b);
4460 }
4461 }
4462 }
4463
4464 /*
4465 * Mark block used for the block bitmap
4466 */
4467 if (fs->group_desc[i].bg_block_bitmap) {
4468 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4469 fs->group_desc[i].bg_block_bitmap)) {
4470 pctx.blk = fs->group_desc[i].bg_block_bitmap;
4471 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4472 ctx->invalid_block_bitmap_flag[i]++;
4473 ctx->invalid_bitmaps++;
4474 }
4475 } else {
4476 ext2fs_mark_block_bitmap(ctx->block_found_map,
4477 fs->group_desc[i].bg_block_bitmap);
4478 }
4479
4480 }
4481 /*
4482 * Mark block used for the inode bitmap
4483 */
4484 if (fs->group_desc[i].bg_inode_bitmap) {
4485 if (ext2fs_test_block_bitmap(ctx->block_found_map,
4486 fs->group_desc[i].bg_inode_bitmap)) {
4487 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4488 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4489 ctx->invalid_inode_bitmap_flag[i]++;
4490 ctx->invalid_bitmaps++;
4491 }
4492 } else {
4493 ext2fs_mark_block_bitmap(ctx->block_found_map,
4494 fs->group_desc[i].bg_inode_bitmap);
4495 }
4496 }
4497 block += fs->super->s_blocks_per_group;
4498 }
4499}
4500
4501/*
4502 * Thes subroutines short circuits ext2fs_get_blocks and
4503 * ext2fs_check_directory; we use them since we already have the inode
4504 * structure, so there's no point in letting the ext2fs library read
4505 * the inode again.
4506 */
4507static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4508 blk_t *blocks)
4509{
4510 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4511 int i;
4512
4513 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4514 return EXT2_ET_CALLBACK_NOTHANDLED;
4515
4516 for (i=0; i < EXT2_N_BLOCKS; i++)
4517 blocks[i] = ctx->stashed_inode->i_block[i];
4518 return 0;
4519}
4520
4521static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4522 struct ext2_inode *inode)
4523{
4524 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4525
4526 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4527 return EXT2_ET_CALLBACK_NOTHANDLED;
4528 *inode = *ctx->stashed_inode;
4529 return 0;
4530}
4531
4532static errcode_t pass1_write_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 *ctx->stashed_inode = *inode;
4539 return EXT2_ET_CALLBACK_NOTHANDLED;
4540}
4541
4542static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4543{
4544 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545
4546 if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4547 return EXT2_ET_CALLBACK_NOTHANDLED;
4548
4549 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4550 return EXT2_ET_NO_DIRECTORY;
4551 return 0;
4552}
4553
4554void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4555{
4556 ext2_filsys fs = ctx->fs;
4557
4558 if (bool) {
4559 fs->get_blocks = pass1_get_blocks;
4560 fs->check_directory = pass1_check_directory;
4561 fs->read_inode = pass1_read_inode;
4562 fs->write_inode = pass1_write_inode;
4563 ctx->stashed_ino = 0;
4564 } else {
4565 fs->get_blocks = 0;
4566 fs->check_directory = 0;
4567 fs->read_inode = 0;
4568 fs->write_inode = 0;
4569 }
4570}
4571
4572/*
4573 * pass1b.c --- Pass #1b of e2fsck
4574 *
4575 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
4576 * only invoked if pass 1 discovered blocks which are in use by more
4577 * than one inode.
4578 *
4579 * Pass1B scans the data blocks of all the inodes again, generating a
4580 * complete list of duplicate blocks and which inodes have claimed
4581 * them.
4582 *
4583 * Pass1C does a tree-traversal of the filesystem, to determine the
4584 * parent directories of these inodes. This step is necessary so that
4585 * e2fsck can print out the pathnames of affected inodes.
4586 *
4587 * Pass1D is a reconciliation pass. For each inode with duplicate
4588 * blocks, the user is prompted if s/he would like to clone the file
4589 * (so that the file gets a fresh copy of the duplicated blocks) or
4590 * simply to delete the file.
4591 *
4592 */
4593
4594
4595/* Needed for architectures where sizeof(int) != sizeof(void *) */
4596#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
4597#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
4598
4599/* Define an extension to the ext2 library's block count information */
4600#define BLOCK_COUNT_EXTATTR (-5)
4601
4602struct block_el {
4603 blk_t block;
4604 struct block_el *next;
4605};
4606
4607struct inode_el {
4608 ext2_ino_t inode;
4609 struct inode_el *next;
4610};
4611
4612struct dup_block {
4613 int num_bad;
4614 struct inode_el *inode_list;
4615};
4616
4617/*
4618 * This structure stores information about a particular inode which
4619 * is sharing blocks with other inodes. This information is collected
4620 * to display to the user, so that the user knows what files he or she
4621 * is dealing with, when trying to decide how to resolve the conflict
4622 * of multiply-claimed blocks.
4623 */
4624struct dup_inode {
4625 ext2_ino_t dir;
4626 int num_dupblocks;
4627 struct ext2_inode inode;
4628 struct block_el *block_list;
4629};
4630
4631static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
4632 e2_blkcnt_t blockcnt, blk_t ref_blk,
4633 int ref_offset, void *priv_data);
4634static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4635 struct dup_inode *dp, char *block_buf);
4636static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4637 struct dup_inode *dp, char* block_buf);
4638static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4639
4640static void pass1b(e2fsck_t ctx, char *block_buf);
4641static void pass1c(e2fsck_t ctx, char *block_buf);
4642static void pass1d(e2fsck_t ctx, char *block_buf);
4643
4644static int dup_inode_count = 0;
4645
4646static dict_t blk_dict, ino_dict;
4647
4648static ext2fs_inode_bitmap inode_dup_map;
4649
4650static int dict_int_cmp(const void *a, const void *b)
4651{
4652 intptr_t ia, ib;
4653
4654 ia = (intptr_t)a;
4655 ib = (intptr_t)b;
4656
4657 return (ia-ib);
4658}
4659
4660/*
4661 * Add a duplicate block record
4662 */
4663static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4664 struct ext2_inode *inode)
4665{
4666 dnode_t *n;
4667 struct dup_block *db;
4668 struct dup_inode *di;
4669 struct block_el *blk_el;
4670 struct inode_el *ino_el;
4671
4672 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4673 if (n)
4674 db = (struct dup_block *) dnode_get(n);
4675 else {
4676 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4677 sizeof(struct dup_block), "duplicate block header");
4678 db->num_bad = 0;
4679 db->inode_list = 0;
4680 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4681 }
4682 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4683 sizeof(struct inode_el), "inode element");
4684 ino_el->inode = ino;
4685 ino_el->next = db->inode_list;
4686 db->inode_list = ino_el;
4687 db->num_bad++;
4688
4689 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4690 if (n)
4691 di = (struct dup_inode *) dnode_get(n);
4692 else {
4693 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4694 sizeof(struct dup_inode), "duplicate inode header");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00004695 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00004696 di->num_dupblocks = 0;
4697 di->block_list = 0;
4698 di->inode = *inode;
4699 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4700 }
4701 blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4702 sizeof(struct block_el), "block element");
4703 blk_el->block = blk;
4704 blk_el->next = di->block_list;
4705 di->block_list = blk_el;
4706 di->num_dupblocks++;
4707}
4708
4709/*
4710 * Free a duplicate inode record
4711 */
4712static void inode_dnode_free(dnode_t *node)
4713{
4714 struct dup_inode *di;
4715 struct block_el *p, *next;
4716
4717 di = (struct dup_inode *) dnode_get(node);
4718 for (p = di->block_list; p; p = next) {
4719 next = p->next;
4720 free(p);
4721 }
4722 free(node);
4723}
4724
4725/*
4726 * Free a duplicate block record
4727 */
4728static void block_dnode_free(dnode_t *node)
4729{
4730 struct dup_block *db;
4731 struct inode_el *p, *next;
4732
4733 db = (struct dup_block *) dnode_get(node);
4734 for (p = db->inode_list; p; p = next) {
4735 next = p->next;
4736 free(p);
4737 }
4738 free(node);
4739}
4740
4741
4742/*
4743 * Main procedure for handling duplicate blocks
4744 */
4745void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4746{
4747 ext2_filsys fs = ctx->fs;
4748 struct problem_context pctx;
4749
4750 clear_problem_context(&pctx);
4751
4752 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4753 _("multiply claimed inode map"), &inode_dup_map);
4754 if (pctx.errcode) {
4755 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4756 ctx->flags |= E2F_FLAG_ABORT;
4757 return;
4758 }
4759
4760 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4761 dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4762 dict_set_allocator(&ino_dict, inode_dnode_free);
4763 dict_set_allocator(&blk_dict, block_dnode_free);
4764
4765 pass1b(ctx, block_buf);
4766 pass1c(ctx, block_buf);
4767 pass1d(ctx, block_buf);
4768
4769 /*
4770 * Time to free all of the accumulated data structures that we
4771 * don't need anymore.
4772 */
4773 dict_free_nodes(&ino_dict);
4774 dict_free_nodes(&blk_dict);
4775}
4776
4777/*
4778 * Scan the inodes looking for inodes that contain duplicate blocks.
4779 */
4780struct process_block_struct_1b {
4781 e2fsck_t ctx;
4782 ext2_ino_t ino;
4783 int dup_blocks;
4784 struct ext2_inode *inode;
4785 struct problem_context *pctx;
4786};
4787
4788static void pass1b(e2fsck_t ctx, char *block_buf)
4789{
4790 ext2_filsys fs = ctx->fs;
4791 ext2_ino_t ino;
4792 struct ext2_inode inode;
4793 ext2_inode_scan scan;
4794 struct process_block_struct_1b pb;
4795 struct problem_context pctx;
4796
4797 clear_problem_context(&pctx);
4798
4799 if (!(ctx->options & E2F_OPT_PREEN))
4800 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4801 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4802 &scan);
4803 if (pctx.errcode) {
4804 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4805 ctx->flags |= E2F_FLAG_ABORT;
4806 return;
4807 }
4808 ctx->stashed_inode = &inode;
4809 pb.ctx = ctx;
4810 pb.pctx = &pctx;
4811 pctx.str = "pass1b";
4812 while (1) {
4813 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4814 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4815 continue;
4816 if (pctx.errcode) {
4817 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4818 ctx->flags |= E2F_FLAG_ABORT;
4819 return;
4820 }
4821 if (!ino)
4822 break;
4823 pctx.ino = ctx->stashed_ino = ino;
4824 if ((ino != EXT2_BAD_INO) &&
4825 !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4826 continue;
4827
4828 pb.ino = ino;
4829 pb.dup_blocks = 0;
4830 pb.inode = &inode;
4831
4832 if (ext2fs_inode_has_valid_blocks(&inode) ||
4833 (ino == EXT2_BAD_INO))
4834 pctx.errcode = ext2fs_block_iterate2(fs, ino,
4835 0, block_buf, process_pass1b_block, &pb);
4836 if (inode.i_file_acl)
4837 process_pass1b_block(fs, &inode.i_file_acl,
4838 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4839 if (pb.dup_blocks) {
4840 end_problem_latch(ctx, PR_LATCH_DBLOCK);
4841 if (ino >= EXT2_FIRST_INODE(fs->super) ||
4842 ino == EXT2_ROOT_INO)
4843 dup_inode_count++;
4844 }
4845 if (pctx.errcode)
4846 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4847 }
4848 ext2fs_close_inode_scan(scan);
4849 e2fsck_use_inode_shortcuts(ctx, 0);
4850}
4851
4852static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4853 blk_t *block_nr,
4854 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4855 blk_t ref_blk FSCK_ATTR((unused)),
4856 int ref_offset FSCK_ATTR((unused)),
4857 void *priv_data)
4858{
4859 struct process_block_struct_1b *p;
4860 e2fsck_t ctx;
4861
4862 if (HOLE_BLKADDR(*block_nr))
4863 return 0;
4864 p = (struct process_block_struct_1b *) priv_data;
4865 ctx = p->ctx;
4866
4867 if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4868 return 0;
4869
4870 /* OK, this is a duplicate block */
4871 if (p->ino != EXT2_BAD_INO) {
4872 p->pctx->blk = *block_nr;
4873 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4874 }
4875 p->dup_blocks++;
4876 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4877
4878 add_dupe(ctx, p->ino, *block_nr, p->inode);
4879
4880 return 0;
4881}
4882
4883/*
4884 * Pass 1c: Scan directories for inodes with duplicate blocks. This
4885 * is used so that we can print pathnames when prompting the user for
4886 * what to do.
4887 */
4888struct search_dir_struct {
4889 int count;
4890 ext2_ino_t first_inode;
4891 ext2_ino_t max_inode;
4892};
4893
4894static int search_dirent_proc(ext2_ino_t dir, int entry,
4895 struct ext2_dir_entry *dirent,
4896 int offset FSCK_ATTR((unused)),
4897 int blocksize FSCK_ATTR((unused)),
4898 char *buf FSCK_ATTR((unused)),
4899 void *priv_data)
4900{
4901 struct search_dir_struct *sd;
4902 struct dup_inode *p;
4903 dnode_t *n;
4904
4905 sd = (struct search_dir_struct *) priv_data;
4906
4907 if (dirent->inode > sd->max_inode)
4908 /* Should abort this inode, but not everything */
4909 return 0;
4910
4911 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4912 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4913 return 0;
4914
4915 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4916 if (!n)
4917 return 0;
4918 p = (struct dup_inode *) dnode_get(n);
4919 p->dir = dir;
4920 sd->count--;
4921
4922 return sd->count ? 0 : DIRENT_ABORT;
4923}
4924
4925
4926static void pass1c(e2fsck_t ctx, char *block_buf)
4927{
4928 ext2_filsys fs = ctx->fs;
4929 struct search_dir_struct sd;
4930 struct problem_context pctx;
4931
4932 clear_problem_context(&pctx);
4933
4934 if (!(ctx->options & E2F_OPT_PREEN))
4935 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4936
4937 /*
4938 * Search through all directories to translate inodes to names
4939 * (by searching for the containing directory for that inode.)
4940 */
4941 sd.count = dup_inode_count;
4942 sd.first_inode = EXT2_FIRST_INODE(fs->super);
4943 sd.max_inode = fs->super->s_inodes_count;
4944 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4945 search_dirent_proc, &sd);
4946}
4947
4948static void pass1d(e2fsck_t ctx, char *block_buf)
4949{
4950 ext2_filsys fs = ctx->fs;
4951 struct dup_inode *p, *t;
4952 struct dup_block *q;
4953 ext2_ino_t *shared, ino;
4954 int shared_len;
4955 int i;
4956 int file_ok;
4957 int meta_data = 0;
4958 struct problem_context pctx;
4959 dnode_t *n, *m;
4960 struct block_el *s;
4961 struct inode_el *r;
4962
4963 clear_problem_context(&pctx);
4964
4965 if (!(ctx->options & E2F_OPT_PREEN))
4966 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4967 e2fsck_read_bitmaps(ctx);
4968
4969 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4970 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4971 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4972 sizeof(ext2_ino_t) * dict_count(&ino_dict),
4973 "Shared inode list");
4974 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4975 p = (struct dup_inode *) dnode_get(n);
4976 shared_len = 0;
4977 file_ok = 1;
4978 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4979 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4980 continue;
4981
4982 /*
4983 * Find all of the inodes which share blocks with this
4984 * one. First we find all of the duplicate blocks
4985 * belonging to this inode, and then search each block
4986 * get the list of inodes, and merge them together.
4987 */
4988 for (s = p->block_list; s; s = s->next) {
4989 m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4990 if (!m)
4991 continue; /* Should never happen... */
4992 q = (struct dup_block *) dnode_get(m);
4993 if (q->num_bad > 1)
4994 file_ok = 0;
4995 if (check_if_fs_block(ctx, s->block)) {
4996 file_ok = 0;
4997 meta_data = 1;
4998 }
4999
5000 /*
5001 * Add all inodes used by this block to the
5002 * shared[] --- which is a unique list, so
5003 * if an inode is already in shared[], don't
5004 * add it again.
5005 */
5006 for (r = q->inode_list; r; r = r->next) {
5007 if (r->inode == ino)
5008 continue;
5009 for (i = 0; i < shared_len; i++)
5010 if (shared[i] == r->inode)
5011 break;
5012 if (i == shared_len) {
5013 shared[shared_len++] = r->inode;
5014 }
5015 }
5016 }
5017
5018 /*
5019 * Report the inode that we are working on
5020 */
5021 pctx.inode = &p->inode;
5022 pctx.ino = ino;
5023 pctx.dir = p->dir;
5024 pctx.blkcount = p->num_dupblocks;
5025 pctx.num = meta_data ? shared_len+1 : shared_len;
5026 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5027 pctx.blkcount = 0;
5028 pctx.num = 0;
5029
5030 if (meta_data)
5031 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5032
5033 for (i = 0; i < shared_len; i++) {
5034 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5035 if (!m)
5036 continue; /* should never happen */
5037 t = (struct dup_inode *) dnode_get(m);
5038 /*
5039 * Report the inode that we are sharing with
5040 */
5041 pctx.inode = &t->inode;
5042 pctx.ino = shared[i];
5043 pctx.dir = t->dir;
5044 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5045 }
5046 if (file_ok) {
5047 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5048 continue;
5049 }
5050 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5051 pctx.errcode = clone_file(ctx, ino, p, block_buf);
5052 if (pctx.errcode)
5053 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5054 else
5055 continue;
5056 }
5057 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5058 delete_file(ctx, ino, p, block_buf);
5059 else
5060 ext2fs_unmark_valid(fs);
5061 }
5062 ext2fs_free_mem(&shared);
5063}
5064
5065/*
5066 * Drop the refcount on the dup_block structure, and clear the entry
5067 * in the block_dup_map if appropriate.
5068 */
5069static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5070{
5071 p->num_bad--;
5072 if (p->num_bad <= 0 ||
5073 (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5074 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5075}
5076
5077static int delete_file_block(ext2_filsys fs,
5078 blk_t *block_nr,
5079 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5080 blk_t ref_block FSCK_ATTR((unused)),
5081 int ref_offset FSCK_ATTR((unused)),
5082 void *priv_data)
5083{
5084 struct process_block_struct_1b *pb;
5085 struct dup_block *p;
5086 dnode_t *n;
5087 e2fsck_t ctx;
5088
5089 pb = (struct process_block_struct_1b *) priv_data;
5090 ctx = pb->ctx;
5091
5092 if (HOLE_BLKADDR(*block_nr))
5093 return 0;
5094
5095 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5096 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5097 if (n) {
5098 p = (struct dup_block *) dnode_get(n);
5099 decrement_badcount(ctx, *block_nr, p);
5100 } else
5101 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5102 *block_nr);
5103 } else {
5104 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5105 ext2fs_block_alloc_stats(fs, *block_nr, -1);
5106 }
5107
5108 return 0;
5109}
5110
5111static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5112 struct dup_inode *dp, char* block_buf)
5113{
5114 ext2_filsys fs = ctx->fs;
5115 struct process_block_struct_1b pb;
5116 struct ext2_inode inode;
5117 struct problem_context pctx;
5118 unsigned int count;
5119
5120 clear_problem_context(&pctx);
5121 pctx.ino = pb.ino = ino;
5122 pb.dup_blocks = dp->num_dupblocks;
5123 pb.ctx = ctx;
5124 pctx.str = "delete_file";
5125
5126 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5127 if (ext2fs_inode_has_valid_blocks(&inode))
5128 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5129 delete_file_block, &pb);
5130 if (pctx.errcode)
5131 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5132 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5133 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5134 if (ctx->inode_bad_map)
5135 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5136 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5137
5138 /* Inode may have changed by block_iterate, so reread it */
5139 e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5140 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00005141 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00005142 if (inode.i_file_acl &&
5143 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5144 count = 1;
5145 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5146 block_buf, -1, &count);
5147 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5148 pctx.errcode = 0;
5149 count = 1;
5150 }
5151 if (pctx.errcode) {
5152 pctx.blk = inode.i_file_acl;
5153 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5154 }
5155 /*
5156 * If the count is zero, then arrange to have the
5157 * block deleted. If the block is in the block_dup_map,
5158 * also call delete_file_block since it will take care
5159 * of keeping the accounting straight.
5160 */
5161 if ((count == 0) ||
5162 ext2fs_test_block_bitmap(ctx->block_dup_map,
5163 inode.i_file_acl))
5164 delete_file_block(fs, &inode.i_file_acl,
5165 BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5166 }
5167 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5168}
5169
5170struct clone_struct {
5171 errcode_t errcode;
5172 ext2_ino_t dir;
5173 char *buf;
5174 e2fsck_t ctx;
5175};
5176
5177static int clone_file_block(ext2_filsys fs,
5178 blk_t *block_nr,
5179 e2_blkcnt_t blockcnt,
5180 blk_t ref_block FSCK_ATTR((unused)),
5181 int ref_offset FSCK_ATTR((unused)),
5182 void *priv_data)
5183{
5184 struct dup_block *p;
5185 blk_t new_block;
5186 errcode_t retval;
5187 struct clone_struct *cs = (struct clone_struct *) priv_data;
5188 dnode_t *n;
5189 e2fsck_t ctx;
5190
5191 ctx = cs->ctx;
5192
5193 if (HOLE_BLKADDR(*block_nr))
5194 return 0;
5195
5196 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5197 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5198 if (n) {
5199 p = (struct dup_block *) dnode_get(n);
5200 retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5201 &new_block);
5202 if (retval) {
5203 cs->errcode = retval;
5204 return BLOCK_ABORT;
5205 }
5206 if (cs->dir && (blockcnt >= 0)) {
5207 retval = ext2fs_set_dir_block(fs->dblist,
5208 cs->dir, new_block, blockcnt);
5209 if (retval) {
5210 cs->errcode = retval;
5211 return BLOCK_ABORT;
5212 }
5213 }
5214
5215 retval = io_channel_read_blk(fs->io, *block_nr, 1,
5216 cs->buf);
5217 if (retval) {
5218 cs->errcode = retval;
5219 return BLOCK_ABORT;
5220 }
5221 retval = io_channel_write_blk(fs->io, new_block, 1,
5222 cs->buf);
5223 if (retval) {
5224 cs->errcode = retval;
5225 return BLOCK_ABORT;
5226 }
5227 decrement_badcount(ctx, *block_nr, p);
5228 *block_nr = new_block;
5229 ext2fs_mark_block_bitmap(ctx->block_found_map,
5230 new_block);
5231 ext2fs_mark_block_bitmap(fs->block_map, new_block);
5232 return BLOCK_CHANGED;
5233 } else
5234 bb_error_msg(_("internal error; can't find dup_blk for %d"),
5235 *block_nr);
5236 }
5237 return 0;
5238}
5239
5240static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5241 struct dup_inode *dp, char* block_buf)
5242{
5243 ext2_filsys fs = ctx->fs;
5244 errcode_t retval;
5245 struct clone_struct cs;
5246 struct problem_context pctx;
5247 blk_t blk;
5248 dnode_t *n;
5249 struct inode_el *ino_el;
5250 struct dup_block *db;
5251 struct dup_inode *di;
5252
5253 clear_problem_context(&pctx);
5254 cs.errcode = 0;
5255 cs.dir = 0;
5256 cs.ctx = ctx;
5257 retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5258 if (retval)
5259 return retval;
5260
5261 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5262 cs.dir = ino;
5263
5264 pctx.ino = ino;
5265 pctx.str = "clone_file";
5266 if (ext2fs_inode_has_valid_blocks(&dp->inode))
5267 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5268 clone_file_block, &cs);
5269 ext2fs_mark_bb_dirty(fs);
5270 if (pctx.errcode) {
5271 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5272 retval = pctx.errcode;
5273 goto errout;
5274 }
5275 if (cs.errcode) {
5276 bb_error_msg(_("returned from clone_file_block"));
5277 retval = cs.errcode;
5278 goto errout;
5279 }
5280 /* The inode may have changed on disk, so we have to re-read it */
5281 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5282 blk = dp->inode.i_file_acl;
5283 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5284 BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5285 BLOCK_CHANGED)) {
5286 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5287 /*
5288 * If we cloned the EA block, find all other inodes
5289 * which refered to that EA block, and modify
5290 * them to point to the new EA block.
5291 */
5292 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5293 db = (struct dup_block *) dnode_get(n);
5294 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5295 if (ino_el->inode == ino)
5296 continue;
5297 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5298 di = (struct dup_inode *) dnode_get(n);
5299 if (di->inode.i_file_acl == blk) {
5300 di->inode.i_file_acl = dp->inode.i_file_acl;
5301 e2fsck_write_inode(ctx, ino_el->inode,
5302 &di->inode, "clone file EA");
5303 decrement_badcount(ctx, blk, db);
5304 }
5305 }
5306 }
5307 retval = 0;
5308errout:
5309 ext2fs_free_mem(&cs.buf);
5310 return retval;
5311}
5312
5313/*
5314 * This routine returns 1 if a block overlaps with one of the superblocks,
5315 * group descriptors, inode bitmaps, or block bitmaps.
5316 */
5317static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5318{
5319 ext2_filsys fs = ctx->fs;
5320 blk_t block;
5321 dgrp_t i;
5322
5323 block = fs->super->s_first_data_block;
5324 for (i = 0; i < fs->group_desc_count; i++) {
5325
5326 /* Check superblocks/block group descriptros */
5327 if (ext2fs_bg_has_super(fs, i)) {
5328 if (test_block >= block &&
5329 (test_block <= block + fs->desc_blocks))
5330 return 1;
5331 }
5332
5333 /* Check the inode table */
5334 if ((fs->group_desc[i].bg_inode_table) &&
5335 (test_block >= fs->group_desc[i].bg_inode_table) &&
5336 (test_block < (fs->group_desc[i].bg_inode_table +
5337 fs->inode_blocks_per_group)))
5338 return 1;
5339
5340 /* Check the bitmap blocks */
5341 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5342 (test_block == fs->group_desc[i].bg_inode_bitmap))
5343 return 1;
5344
5345 block += fs->super->s_blocks_per_group;
5346 }
5347 return 0;
5348}
5349/*
5350 * pass2.c --- check directory structure
5351 *
5352 * Pass 2 of e2fsck iterates through all active directory inodes, and
5353 * applies to following tests to each directory entry in the directory
5354 * blocks in the inodes:
5355 *
5356 * - The length of the directory entry (rec_len) should be at
5357 * least 8 bytes, and no more than the remaining space
5358 * left in the directory block.
5359 * - The length of the name in the directory entry (name_len)
5360 * should be less than (rec_len - 8).
5361 * - The inode number in the directory entry should be within
5362 * legal bounds.
5363 * - The inode number should refer to a in-use inode.
5364 * - The first entry should be '.', and its inode should be
5365 * the inode of the directory.
5366 * - The second entry should be '..'.
5367 *
5368 * To minimize disk seek time, the directory blocks are processed in
5369 * sorted order of block numbers.
5370 *
5371 * Pass 2 also collects the following information:
5372 * - The inode numbers of the subdirectories for each directory.
5373 *
5374 * Pass 2 relies on the following information from previous passes:
5375 * - The directory information collected in pass 1.
5376 * - The inode_used_map bitmap
5377 * - The inode_bad_map bitmap
5378 * - The inode_dir_map bitmap
5379 *
5380 * Pass 2 frees the following data structures
5381 * - The inode_bad_map bitmap
5382 * - The inode_reg_map bitmap
5383 */
5384
5385/*
5386 * Keeps track of how many times an inode is referenced.
5387 */
5388static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5389static int check_dir_block(ext2_filsys fs,
5390 struct ext2_db_entry *dir_blocks_info,
5391 void *priv_data);
5392static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5393 struct problem_context *pctx);
5394static int update_dir_block(ext2_filsys fs,
5395 blk_t *block_nr,
5396 e2_blkcnt_t blockcnt,
5397 blk_t ref_block,
5398 int ref_offset,
5399 void *priv_data);
5400static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5401static int htree_depth(struct dx_dir_info *dx_dir,
5402 struct dx_dirblock_info *dx_db);
5403static int special_dir_block_cmp(const void *a, const void *b);
5404
5405struct check_dir_struct {
5406 char *buf;
5407 struct problem_context pctx;
5408 int count, max;
5409 e2fsck_t ctx;
5410};
5411
5412static void e2fsck_pass2(e2fsck_t ctx)
5413{
5414 struct ext2_super_block *sb = ctx->fs->super;
5415 struct problem_context pctx;
5416 ext2_filsys fs = ctx->fs;
5417 char *buf;
5418 struct dir_info *dir;
5419 struct check_dir_struct cd;
5420 struct dx_dir_info *dx_dir;
5421 struct dx_dirblock_info *dx_db, *dx_parent;
5422 int b;
5423 int i, depth;
5424 problem_t code;
5425 int bad_dir;
5426
5427 clear_problem_context(&cd.pctx);
5428
5429 /* Pass 2 */
5430
5431 if (!(ctx->options & E2F_OPT_PREEN))
5432 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5433
5434 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5435 0, ctx->inode_link_info,
5436 &ctx->inode_count);
5437 if (cd.pctx.errcode) {
5438 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5439 ctx->flags |= E2F_FLAG_ABORT;
5440 return;
5441 }
5442 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5443 "directory scan buffer");
5444
5445 /*
5446 * Set up the parent pointer for the root directory, if
5447 * present. (If the root directory is not present, we will
5448 * create it in pass 3.)
5449 */
5450 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5451 if (dir)
5452 dir->parent = EXT2_ROOT_INO;
5453
5454 cd.buf = buf;
5455 cd.ctx = ctx;
5456 cd.count = 1;
5457 cd.max = ext2fs_dblist_count(fs->dblist);
5458
5459 if (ctx->progress)
5460 (void) (ctx->progress)(ctx, 2, 0, cd.max);
5461
5462 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5463 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5464
5465 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5466 &cd);
5467 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5468 return;
5469 if (cd.pctx.errcode) {
5470 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5471 ctx->flags |= E2F_FLAG_ABORT;
5472 return;
5473 }
5474
5475#ifdef ENABLE_HTREE
5476 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5477 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478 return;
5479 if (dx_dir->numblocks == 0)
5480 continue;
5481 clear_problem_context(&pctx);
5482 bad_dir = 0;
5483 pctx.dir = dx_dir->ino;
5484 dx_db = dx_dir->dx_block;
5485 if (dx_db->flags & DX_FLAG_REFERENCED)
5486 dx_db->flags |= DX_FLAG_DUP_REF;
5487 else
5488 dx_db->flags |= DX_FLAG_REFERENCED;
5489 /*
5490 * Find all of the first and last leaf blocks, and
5491 * update their parent's min and max hash values
5492 */
5493 for (b=0, dx_db = dx_dir->dx_block;
5494 b < dx_dir->numblocks;
5495 b++, dx_db++) {
5496 if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5497 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5498 continue;
5499 dx_parent = &dx_dir->dx_block[dx_db->parent];
5500 /*
5501 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5502 */
5503 if (dx_db->flags & DX_FLAG_FIRST)
5504 dx_parent->min_hash = dx_db->min_hash;
5505 /*
5506 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5507 */
5508 if (dx_db->flags & DX_FLAG_LAST)
5509 dx_parent->max_hash = dx_db->max_hash;
5510 }
5511
5512 for (b=0, dx_db = dx_dir->dx_block;
5513 b < dx_dir->numblocks;
5514 b++, dx_db++) {
5515 pctx.blkcount = b;
5516 pctx.group = dx_db->parent;
5517 code = 0;
5518 if (!(dx_db->flags & DX_FLAG_FIRST) &&
5519 (dx_db->min_hash < dx_db->node_min_hash)) {
5520 pctx.blk = dx_db->min_hash;
5521 pctx.blk2 = dx_db->node_min_hash;
5522 code = PR_2_HTREE_MIN_HASH;
5523 fix_problem(ctx, code, &pctx);
5524 bad_dir++;
5525 }
5526 if (dx_db->type == DX_DIRBLOCK_LEAF) {
5527 depth = htree_depth(dx_dir, dx_db);
5528 if (depth != dx_dir->depth) {
5529 code = PR_2_HTREE_BAD_DEPTH;
5530 fix_problem(ctx, code, &pctx);
5531 bad_dir++;
5532 }
5533 }
5534 /*
5535 * This test doesn't apply for the root block
5536 * at block #0
5537 */
5538 if (b &&
5539 (dx_db->max_hash > dx_db->node_max_hash)) {
5540 pctx.blk = dx_db->max_hash;
5541 pctx.blk2 = dx_db->node_max_hash;
5542 code = PR_2_HTREE_MAX_HASH;
5543 fix_problem(ctx, code, &pctx);
5544 bad_dir++;
5545 }
5546 if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5547 code = PR_2_HTREE_NOTREF;
5548 fix_problem(ctx, code, &pctx);
5549 bad_dir++;
5550 } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5551 code = PR_2_HTREE_DUPREF;
5552 fix_problem(ctx, code, &pctx);
5553 bad_dir++;
5554 }
5555 if (code == 0)
5556 continue;
5557 }
5558 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5559 clear_htree(ctx, dx_dir->ino);
5560 dx_dir->numblocks = 0;
5561 }
5562 }
5563#endif
5564 ext2fs_free_mem(&buf);
5565 ext2fs_free_dblist(fs->dblist);
5566
5567 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5568 ctx->inode_bad_map = 0;
5569 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5570 ctx->inode_reg_map = 0;
5571
5572 clear_problem_context(&pctx);
5573 if (ctx->large_files) {
5574 if (!(sb->s_feature_ro_compat &
5575 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5576 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5577 sb->s_feature_ro_compat |=
5578 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5579 ext2fs_mark_super_dirty(fs);
5580 }
5581 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5582 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5583 ext2fs_update_dynamic_rev(fs);
5584 ext2fs_mark_super_dirty(fs);
5585 }
5586 } else if (!ctx->large_files &&
5587 (sb->s_feature_ro_compat &
5588 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5589 if (fs->flags & EXT2_FLAG_RW) {
5590 sb->s_feature_ro_compat &=
5591 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5592 ext2fs_mark_super_dirty(fs);
5593 }
5594 }
5595
5596}
5597
5598#define MAX_DEPTH 32000
5599static int htree_depth(struct dx_dir_info *dx_dir,
5600 struct dx_dirblock_info *dx_db)
5601{
5602 int depth = 0;
5603
5604 while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5605 dx_db = &dx_dir->dx_block[dx_db->parent];
5606 depth++;
5607 }
5608 return depth;
5609}
5610
5611static int dict_de_cmp(const void *a, const void *b)
5612{
5613 const struct ext2_dir_entry *de_a, *de_b;
5614 int a_len, b_len;
5615
5616 de_a = (const struct ext2_dir_entry *) a;
5617 a_len = de_a->name_len & 0xFF;
5618 de_b = (const struct ext2_dir_entry *) b;
5619 b_len = de_b->name_len & 0xFF;
5620
5621 if (a_len != b_len)
5622 return (a_len - b_len);
5623
5624 return strncmp(de_a->name, de_b->name, a_len);
5625}
5626
5627/*
5628 * This is special sort function that makes sure that directory blocks
5629 * with a dirblock of zero are sorted to the beginning of the list.
5630 * This guarantees that the root node of the htree directories are
5631 * processed first, so we know what hash version to use.
5632 */
5633static int special_dir_block_cmp(const void *a, const void *b)
5634{
5635 const struct ext2_db_entry *db_a =
5636 (const struct ext2_db_entry *) a;
5637 const struct ext2_db_entry *db_b =
5638 (const struct ext2_db_entry *) b;
5639
5640 if (db_a->blockcnt && !db_b->blockcnt)
5641 return 1;
5642
5643 if (!db_a->blockcnt && db_b->blockcnt)
5644 return -1;
5645
5646 if (db_a->blk != db_b->blk)
5647 return (int) (db_a->blk - db_b->blk);
5648
5649 if (db_a->ino != db_b->ino)
5650 return (int) (db_a->ino - db_b->ino);
5651
5652 return (int) (db_a->blockcnt - db_b->blockcnt);
5653}
5654
5655
5656/*
5657 * Make sure the first entry in the directory is '.', and that the
5658 * directory entry is sane.
5659 */
5660static int check_dot(e2fsck_t ctx,
5661 struct ext2_dir_entry *dirent,
5662 ext2_ino_t ino, struct problem_context *pctx)
5663{
5664 struct ext2_dir_entry *nextdir;
5665 int status = 0;
5666 int created = 0;
5667 int new_len;
5668 int problem = 0;
5669
5670 if (!dirent->inode)
5671 problem = PR_2_MISSING_DOT;
5672 else if (((dirent->name_len & 0xFF) != 1) ||
5673 (dirent->name[0] != '.'))
5674 problem = PR_2_1ST_NOT_DOT;
5675 else if (dirent->name[1] != '\0')
5676 problem = PR_2_DOT_NULL_TERM;
5677
5678 if (problem) {
5679 if (fix_problem(ctx, problem, pctx)) {
5680 if (dirent->rec_len < 12)
5681 dirent->rec_len = 12;
5682 dirent->inode = ino;
5683 dirent->name_len = 1;
5684 dirent->name[0] = '.';
5685 dirent->name[1] = '\0';
5686 status = 1;
5687 created = 1;
5688 }
5689 }
5690 if (dirent->inode != ino) {
5691 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5692 dirent->inode = ino;
5693 status = 1;
5694 }
5695 }
5696 if (dirent->rec_len > 12) {
5697 new_len = dirent->rec_len - 12;
5698 if (new_len > 12) {
5699 if (created ||
5700 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5701 nextdir = (struct ext2_dir_entry *)
5702 ((char *) dirent + 12);
5703 dirent->rec_len = 12;
5704 nextdir->rec_len = new_len;
5705 nextdir->inode = 0;
5706 nextdir->name_len = 0;
5707 status = 1;
5708 }
5709 }
5710 }
5711 return status;
5712}
5713
5714/*
5715 * Make sure the second entry in the directory is '..', and that the
5716 * directory entry is sane. We do not check the inode number of '..'
5717 * here; this gets done in pass 3.
5718 */
5719static int check_dotdot(e2fsck_t ctx,
5720 struct ext2_dir_entry *dirent,
5721 struct dir_info *dir, struct problem_context *pctx)
5722{
5723 int problem = 0;
5724
5725 if (!dirent->inode)
5726 problem = PR_2_MISSING_DOT_DOT;
5727 else if (((dirent->name_len & 0xFF) != 2) ||
5728 (dirent->name[0] != '.') ||
5729 (dirent->name[1] != '.'))
5730 problem = PR_2_2ND_NOT_DOT_DOT;
5731 else if (dirent->name[2] != '\0')
5732 problem = PR_2_DOT_DOT_NULL_TERM;
5733
5734 if (problem) {
5735 if (fix_problem(ctx, problem, pctx)) {
5736 if (dirent->rec_len < 12)
5737 dirent->rec_len = 12;
5738 /*
5739 * Note: we don't have the parent inode just
5740 * yet, so we will fill it in with the root
5741 * inode. This will get fixed in pass 3.
5742 */
5743 dirent->inode = EXT2_ROOT_INO;
5744 dirent->name_len = 2;
5745 dirent->name[0] = '.';
5746 dirent->name[1] = '.';
5747 dirent->name[2] = '\0';
5748 return 1;
5749 }
5750 return 0;
5751 }
5752 dir->dotdot = dirent->inode;
5753 return 0;
5754}
5755
5756/*
5757 * Check to make sure a directory entry doesn't contain any illegal
5758 * characters.
5759 */
5760static int check_name(e2fsck_t ctx,
5761 struct ext2_dir_entry *dirent,
5762 struct problem_context *pctx)
5763{
5764 int i;
5765 int fixup = -1;
5766 int ret = 0;
5767
5768 for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5769 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5770 if (fixup < 0) {
5771 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5772 }
5773 if (fixup) {
5774 dirent->name[i] = '.';
5775 ret = 1;
5776 }
5777 }
5778 }
5779 return ret;
5780}
5781
5782/*
5783 * Check the directory filetype (if present)
5784 */
5785
5786/*
5787 * Given a mode, return the ext2 file type
5788 */
5789static int ext2_file_type(unsigned int mode)
5790{
5791 if (LINUX_S_ISREG(mode))
5792 return EXT2_FT_REG_FILE;
5793
5794 if (LINUX_S_ISDIR(mode))
5795 return EXT2_FT_DIR;
5796
5797 if (LINUX_S_ISCHR(mode))
5798 return EXT2_FT_CHRDEV;
5799
5800 if (LINUX_S_ISBLK(mode))
5801 return EXT2_FT_BLKDEV;
5802
5803 if (LINUX_S_ISLNK(mode))
5804 return EXT2_FT_SYMLINK;
5805
5806 if (LINUX_S_ISFIFO(mode))
5807 return EXT2_FT_FIFO;
5808
5809 if (LINUX_S_ISSOCK(mode))
5810 return EXT2_FT_SOCK;
5811
5812 return 0;
5813}
5814
5815static int check_filetype(e2fsck_t ctx,
5816 struct ext2_dir_entry *dirent,
5817 struct problem_context *pctx)
5818{
5819 int filetype = dirent->name_len >> 8;
5820 int should_be = EXT2_FT_UNKNOWN;
5821 struct ext2_inode inode;
5822
5823 if (!(ctx->fs->super->s_feature_incompat &
5824 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5825 if (filetype == 0 ||
5826 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5827 return 0;
5828 dirent->name_len = dirent->name_len & 0xFF;
5829 return 1;
5830 }
5831
5832 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5833 should_be = EXT2_FT_DIR;
5834 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5835 dirent->inode)) {
5836 should_be = EXT2_FT_REG_FILE;
5837 } else if (ctx->inode_bad_map &&
5838 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5839 dirent->inode))
5840 should_be = 0;
5841 else {
5842 e2fsck_read_inode(ctx, dirent->inode, &inode,
5843 "check_filetype");
5844 should_be = ext2_file_type(inode.i_mode);
5845 }
5846 if (filetype == should_be)
5847 return 0;
5848 pctx->num = should_be;
5849
5850 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5851 pctx) == 0)
5852 return 0;
5853
5854 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5855 return 1;
5856}
5857
5858#ifdef ENABLE_HTREE
5859static void parse_int_node(ext2_filsys fs,
5860 struct ext2_db_entry *db,
5861 struct check_dir_struct *cd,
5862 struct dx_dir_info *dx_dir,
5863 char *block_buf)
5864{
5865 struct ext2_dx_root_info *root;
5866 struct ext2_dx_entry *ent;
5867 struct ext2_dx_countlimit *limit;
5868 struct dx_dirblock_info *dx_db;
5869 int i, expect_limit, count;
5870 blk_t blk;
5871 ext2_dirhash_t min_hash = 0xffffffff;
5872 ext2_dirhash_t max_hash = 0;
5873 ext2_dirhash_t hash = 0, prev_hash;
5874
5875 if (db->blockcnt == 0) {
5876 root = (struct ext2_dx_root_info *) (block_buf + 24);
5877 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5878 } else {
5879 ent = (struct ext2_dx_entry *) (block_buf+8);
5880 }
5881 limit = (struct ext2_dx_countlimit *) ent;
5882
5883 count = ext2fs_le16_to_cpu(limit->count);
5884 expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5885 sizeof(struct ext2_dx_entry);
5886 if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5887 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5888 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5889 goto clear_and_exit;
5890 }
5891 if (count > expect_limit) {
5892 cd->pctx.num = count;
5893 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5894 goto clear_and_exit;
5895 count = expect_limit;
5896 }
5897
5898 for (i=0; i < count; i++) {
5899 prev_hash = hash;
5900 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5901 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5902 /* Check to make sure the block is valid */
5903 if (blk > (blk_t) dx_dir->numblocks) {
5904 cd->pctx.blk = blk;
5905 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5906 &cd->pctx))
5907 goto clear_and_exit;
5908 }
5909 if (hash < prev_hash &&
5910 fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5911 goto clear_and_exit;
5912 dx_db = &dx_dir->dx_block[blk];
5913 if (dx_db->flags & DX_FLAG_REFERENCED) {
5914 dx_db->flags |= DX_FLAG_DUP_REF;
5915 } else {
5916 dx_db->flags |= DX_FLAG_REFERENCED;
5917 dx_db->parent = db->blockcnt;
5918 }
5919 if (hash < min_hash)
5920 min_hash = hash;
5921 if (hash > max_hash)
5922 max_hash = hash;
5923 dx_db->node_min_hash = hash;
5924 if ((i+1) < count)
5925 dx_db->node_max_hash =
5926 ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5927 else {
5928 dx_db->node_max_hash = 0xfffffffe;
5929 dx_db->flags |= DX_FLAG_LAST;
5930 }
5931 if (i == 0)
5932 dx_db->flags |= DX_FLAG_FIRST;
5933 }
5934 dx_db = &dx_dir->dx_block[db->blockcnt];
5935 dx_db->min_hash = min_hash;
5936 dx_db->max_hash = max_hash;
5937 return;
5938
5939clear_and_exit:
5940 clear_htree(cd->ctx, cd->pctx.ino);
5941 dx_dir->numblocks = 0;
5942}
5943#endif /* ENABLE_HTREE */
5944
5945/*
5946 * Given a busted directory, try to salvage it somehow.
5947 *
5948 */
5949static void salvage_directory(ext2_filsys fs,
5950 struct ext2_dir_entry *dirent,
5951 struct ext2_dir_entry *prev,
5952 unsigned int *offset)
5953{
5954 char *cp = (char *) dirent;
5955 int left = fs->blocksize - *offset - dirent->rec_len;
5956 int name_len = dirent->name_len & 0xFF;
5957
5958 /*
5959 * Special case of directory entry of size 8: copy what's left
5960 * of the directory block up to cover up the invalid hole.
5961 */
5962 if ((left >= 12) && (dirent->rec_len == 8)) {
5963 memmove(cp, cp+8, left);
5964 memset(cp + left, 0, 8);
5965 return;
5966 }
5967 /*
5968 * If the directory entry overruns the end of the directory
5969 * block, and the name is small enough to fit, then adjust the
5970 * record length.
5971 */
5972 if ((left < 0) &&
5973 (name_len + 8 <= dirent->rec_len + left) &&
5974 dirent->inode <= fs->super->s_inodes_count &&
5975 strnlen(dirent->name, name_len) == name_len) {
5976 dirent->rec_len += left;
5977 return;
5978 }
5979 /*
5980 * If the directory entry is a multiple of four, so it is
5981 * valid, let the previous directory entry absorb the invalid
5982 * one.
5983 */
5984 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5985 prev->rec_len += dirent->rec_len;
5986 *offset += dirent->rec_len;
5987 return;
5988 }
5989 /*
5990 * Default salvage method --- kill all of the directory
5991 * entries for the rest of the block. We will either try to
5992 * absorb it into the previous directory entry, or create a
5993 * new empty directory entry the rest of the directory block.
5994 */
5995 if (prev) {
5996 prev->rec_len += fs->blocksize - *offset;
5997 *offset = fs->blocksize;
5998 } else {
5999 dirent->rec_len = fs->blocksize - *offset;
6000 dirent->name_len = 0;
6001 dirent->inode = 0;
6002 }
6003}
6004
6005static int check_dir_block(ext2_filsys fs,
6006 struct ext2_db_entry *db,
6007 void *priv_data)
6008{
6009 struct dir_info *subdir, *dir;
6010 struct dx_dir_info *dx_dir;
6011#ifdef ENABLE_HTREE
6012 struct dx_dirblock_info *dx_db = 0;
6013#endif /* ENABLE_HTREE */
6014 struct ext2_dir_entry *dirent, *prev;
6015 ext2_dirhash_t hash;
6016 unsigned int offset = 0;
6017 int dir_modified = 0;
6018 int dot_state;
6019 blk_t block_nr = db->blk;
6020 ext2_ino_t ino = db->ino;
6021 __u16 links;
6022 struct check_dir_struct *cd;
6023 char *buf;
6024 e2fsck_t ctx;
6025 int problem;
6026 struct ext2_dx_root_info *root;
6027 struct ext2_dx_countlimit *limit;
6028 static dict_t de_dict;
6029 struct problem_context pctx;
6030 int dups_found = 0;
6031
6032 cd = (struct check_dir_struct *) priv_data;
6033 buf = cd->buf;
6034 ctx = cd->ctx;
6035
6036 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6037 return DIRENT_ABORT;
6038
6039 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6040 return DIRENT_ABORT;
6041
6042 /*
6043 * Make sure the inode is still in use (could have been
6044 * deleted in the duplicate/bad blocks pass.
6045 */
6046 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6047 return 0;
6048
6049 cd->pctx.ino = ino;
6050 cd->pctx.blk = block_nr;
6051 cd->pctx.blkcount = db->blockcnt;
6052 cd->pctx.ino2 = 0;
6053 cd->pctx.dirent = 0;
6054 cd->pctx.num = 0;
6055
6056 if (db->blk == 0) {
6057 if (allocate_dir_block(ctx, db, &cd->pctx))
6058 return 0;
6059 block_nr = db->blk;
6060 }
6061
6062 if (db->blockcnt)
6063 dot_state = 2;
6064 else
6065 dot_state = 0;
6066
6067 if (ctx->dirs_to_hash &&
6068 ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6069 dups_found++;
6070
6071 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6072 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6073 cd->pctx.errcode = 0; /* We'll handle this ourselves */
6074 if (cd->pctx.errcode) {
6075 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6076 ctx->flags |= E2F_FLAG_ABORT;
6077 return DIRENT_ABORT;
6078 }
6079 memset(buf, 0, fs->blocksize);
6080 }
6081#ifdef ENABLE_HTREE
6082 dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6083 if (dx_dir && dx_dir->numblocks) {
6084 if (db->blockcnt >= dx_dir->numblocks) {
6085 printf("XXX should never happen!!!\n");
6086 abort();
6087 }
6088 dx_db = &dx_dir->dx_block[db->blockcnt];
6089 dx_db->type = DX_DIRBLOCK_LEAF;
6090 dx_db->phys = block_nr;
6091 dx_db->min_hash = ~0;
6092 dx_db->max_hash = 0;
6093
6094 dirent = (struct ext2_dir_entry *) buf;
6095 limit = (struct ext2_dx_countlimit *) (buf+8);
6096 if (db->blockcnt == 0) {
6097 root = (struct ext2_dx_root_info *) (buf + 24);
6098 dx_db->type = DX_DIRBLOCK_ROOT;
6099 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6100 if ((root->reserved_zero ||
6101 root->info_length < 8 ||
6102 root->indirect_levels > 1) &&
6103 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6104 clear_htree(ctx, ino);
6105 dx_dir->numblocks = 0;
6106 dx_db = 0;
6107 }
6108 dx_dir->hashversion = root->hash_version;
6109 dx_dir->depth = root->indirect_levels + 1;
6110 } else if ((dirent->inode == 0) &&
6111 (dirent->rec_len == fs->blocksize) &&
6112 (dirent->name_len == 0) &&
6113 (ext2fs_le16_to_cpu(limit->limit) ==
6114 ((fs->blocksize-8) /
6115 sizeof(struct ext2_dx_entry))))
6116 dx_db->type = DX_DIRBLOCK_NODE;
6117 }
6118#endif /* ENABLE_HTREE */
6119
6120 dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6121 prev = 0;
6122 do {
6123 problem = 0;
6124 dirent = (struct ext2_dir_entry *) (buf + offset);
6125 cd->pctx.dirent = dirent;
6126 cd->pctx.num = offset;
6127 if (((offset + dirent->rec_len) > fs->blocksize) ||
6128 (dirent->rec_len < 12) ||
6129 ((dirent->rec_len % 4) != 0) ||
6130 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6131 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6132 salvage_directory(fs, dirent, prev, &offset);
6133 dir_modified++;
6134 continue;
6135 } else
6136 goto abort_free_dict;
6137 }
6138 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6139 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6140 dirent->name_len = EXT2_NAME_LEN;
6141 dir_modified++;
6142 }
6143 }
6144
6145 if (dot_state == 0) {
6146 if (check_dot(ctx, dirent, ino, &cd->pctx))
6147 dir_modified++;
6148 } else if (dot_state == 1) {
6149 dir = e2fsck_get_dir_info(ctx, ino);
6150 if (!dir) {
6151 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6152 goto abort_free_dict;
6153 }
6154 if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6155 dir_modified++;
6156 } else if (dirent->inode == ino) {
6157 problem = PR_2_LINK_DOT;
6158 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6159 dirent->inode = 0;
6160 dir_modified++;
6161 goto next;
6162 }
6163 }
6164 if (!dirent->inode)
6165 goto next;
6166
6167 /*
6168 * Make sure the inode listed is a legal one.
6169 */
6170 if (((dirent->inode != EXT2_ROOT_INO) &&
6171 (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6172 (dirent->inode > fs->super->s_inodes_count)) {
6173 problem = PR_2_BAD_INO;
6174 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6175 dirent->inode))) {
6176 /*
6177 * If the inode is unused, offer to clear it.
6178 */
6179 problem = PR_2_UNUSED_INODE;
6180 } else if ((dot_state > 1) &&
6181 ((dirent->name_len & 0xFF) == 1) &&
6182 (dirent->name[0] == '.')) {
6183 /*
6184 * If there's a '.' entry in anything other
6185 * than the first directory entry, it's a
6186 * duplicate entry that should be removed.
6187 */
6188 problem = PR_2_DUP_DOT;
6189 } else if ((dot_state > 1) &&
6190 ((dirent->name_len & 0xFF) == 2) &&
6191 (dirent->name[0] == '.') &&
6192 (dirent->name[1] == '.')) {
6193 /*
6194 * If there's a '..' entry in anything other
6195 * than the second directory entry, it's a
6196 * duplicate entry that should be removed.
6197 */
6198 problem = PR_2_DUP_DOT_DOT;
6199 } else if ((dot_state > 1) &&
6200 (dirent->inode == EXT2_ROOT_INO)) {
6201 /*
6202 * Don't allow links to the root directory.
6203 * We check this specially to make sure we
6204 * catch this error case even if the root
6205 * directory hasn't been created yet.
6206 */
6207 problem = PR_2_LINK_ROOT;
6208 } else if ((dot_state > 1) &&
6209 (dirent->name_len & 0xFF) == 0) {
6210 /*
6211 * Don't allow zero-length directory names.
6212 */
6213 problem = PR_2_NULL_NAME;
6214 }
6215
6216 if (problem) {
6217 if (fix_problem(ctx, problem, &cd->pctx)) {
6218 dirent->inode = 0;
6219 dir_modified++;
6220 goto next;
6221 } else {
6222 ext2fs_unmark_valid(fs);
6223 if (problem == PR_2_BAD_INO)
6224 goto next;
6225 }
6226 }
6227
6228 /*
6229 * If the inode was marked as having bad fields in
6230 * pass1, process it and offer to fix/clear it.
6231 * (We wait until now so that we can display the
6232 * pathname to the user.)
6233 */
6234 if (ctx->inode_bad_map &&
6235 ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6236 dirent->inode)) {
6237 if (e2fsck_process_bad_inode(ctx, ino,
6238 dirent->inode,
6239 buf + fs->blocksize)) {
6240 dirent->inode = 0;
6241 dir_modified++;
6242 goto next;
6243 }
6244 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6245 return DIRENT_ABORT;
6246 }
6247
6248 if (check_name(ctx, dirent, &cd->pctx))
6249 dir_modified++;
6250
6251 if (check_filetype(ctx, dirent, &cd->pctx))
6252 dir_modified++;
6253
6254#ifdef ENABLE_HTREE
6255 if (dx_db) {
6256 ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6257 (dirent->name_len & 0xFF),
6258 fs->super->s_hash_seed, &hash, 0);
6259 if (hash < dx_db->min_hash)
6260 dx_db->min_hash = hash;
6261 if (hash > dx_db->max_hash)
6262 dx_db->max_hash = hash;
6263 }
6264#endif
6265
6266 /*
6267 * If this is a directory, then mark its parent in its
6268 * dir_info structure. If the parent field is already
6269 * filled in, then this directory has more than one
6270 * hard link. We assume the first link is correct,
6271 * and ask the user if he/she wants to clear this one.
6272 */
6273 if ((dot_state > 1) &&
6274 (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6275 dirent->inode))) {
6276 subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6277 if (!subdir) {
6278 cd->pctx.ino = dirent->inode;
6279 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6280 goto abort_free_dict;
6281 }
6282 if (subdir->parent) {
6283 cd->pctx.ino2 = subdir->parent;
6284 if (fix_problem(ctx, PR_2_LINK_DIR,
6285 &cd->pctx)) {
6286 dirent->inode = 0;
6287 dir_modified++;
6288 goto next;
6289 }
6290 cd->pctx.ino2 = 0;
6291 } else
6292 subdir->parent = ino;
6293 }
6294
6295 if (dups_found) {
6296 ;
6297 } else if (dict_lookup(&de_dict, dirent)) {
6298 clear_problem_context(&pctx);
6299 pctx.ino = ino;
6300 pctx.dirent = dirent;
6301 fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6302 if (!ctx->dirs_to_hash)
6303 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6304 if (ctx->dirs_to_hash)
6305 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6306 dups_found++;
6307 } else
6308 dict_alloc_insert(&de_dict, dirent, dirent);
6309
6310 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6311 &links);
6312 if (links > 1)
6313 ctx->fs_links_count++;
6314 ctx->fs_total_count++;
6315 next:
6316 prev = dirent;
6317 offset += dirent->rec_len;
6318 dot_state++;
6319 } while (offset < fs->blocksize);
6320#ifdef ENABLE_HTREE
6321 if (dx_db) {
6322 cd->pctx.dir = cd->pctx.ino;
6323 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6324 (dx_db->type == DX_DIRBLOCK_NODE))
6325 parse_int_node(fs, db, cd, dx_dir, buf);
6326 }
6327#endif /* ENABLE_HTREE */
6328 if (offset != fs->blocksize) {
6329 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6330 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6331 dirent->rec_len = cd->pctx.num;
6332 dir_modified++;
6333 }
6334 }
6335 if (dir_modified) {
6336 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6337 if (cd->pctx.errcode) {
6338 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6339 &cd->pctx))
6340 goto abort_free_dict;
6341 }
6342 ext2fs_mark_changed(fs);
6343 }
6344 dict_free_nodes(&de_dict);
6345 return 0;
6346abort_free_dict:
6347 dict_free_nodes(&de_dict);
6348 ctx->flags |= E2F_FLAG_ABORT;
6349 return DIRENT_ABORT;
6350}
6351
6352/*
6353 * This function is called to deallocate a block, and is an interator
6354 * functioned called by deallocate inode via ext2fs_iterate_block().
6355 */
6356static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6357 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6358 blk_t ref_block FSCK_ATTR((unused)),
6359 int ref_offset FSCK_ATTR((unused)),
6360 void *priv_data)
6361{
6362 e2fsck_t ctx = (e2fsck_t) priv_data;
6363
6364 if (HOLE_BLKADDR(*block_nr))
6365 return 0;
6366 if ((*block_nr < fs->super->s_first_data_block) ||
6367 (*block_nr >= fs->super->s_blocks_count))
6368 return 0;
6369 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6370 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6371 return 0;
6372}
6373
6374/*
6375 * This fuction deallocates an inode
6376 */
6377static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6378{
6379 ext2_filsys fs = ctx->fs;
6380 struct ext2_inode inode;
6381 struct problem_context pctx;
6382 __u32 count;
6383
6384 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6385 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6386 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006387 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006388 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6389 clear_problem_context(&pctx);
6390 pctx.ino = ino;
6391
6392 /*
6393 * Fix up the bitmaps...
6394 */
6395 e2fsck_read_bitmaps(ctx);
6396 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6397 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6398 if (ctx->inode_bad_map)
6399 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6400 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6401
6402 if (inode.i_file_acl &&
6403 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6404 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6405 block_buf, -1, &count);
6406 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6407 pctx.errcode = 0;
6408 count = 1;
6409 }
6410 if (pctx.errcode) {
6411 pctx.blk = inode.i_file_acl;
6412 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6413 ctx->flags |= E2F_FLAG_ABORT;
6414 return;
6415 }
6416 if (count == 0) {
6417 ext2fs_unmark_block_bitmap(ctx->block_found_map,
6418 inode.i_file_acl);
6419 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6420 }
6421 inode.i_file_acl = 0;
6422 }
6423
6424 if (!ext2fs_inode_has_valid_blocks(&inode))
6425 return;
6426
6427 if (LINUX_S_ISREG(inode.i_mode) &&
6428 (inode.i_size_high || inode.i_size & 0x80000000UL))
6429 ctx->large_files--;
6430
6431 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6432 deallocate_inode_block, ctx);
6433 if (pctx.errcode) {
6434 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6435 ctx->flags |= E2F_FLAG_ABORT;
6436 return;
6437 }
6438}
6439
6440/*
6441 * This fuction clears the htree flag on an inode
6442 */
6443static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6444{
6445 struct ext2_inode inode;
6446
6447 e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6448 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6449 e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6450 if (ctx->dirs_to_hash)
6451 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6452}
6453
6454
6455static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6456 ext2_ino_t ino, char *buf)
6457{
6458 ext2_filsys fs = ctx->fs;
6459 struct ext2_inode inode;
6460 int inode_modified = 0;
6461 int not_fixed = 0;
6462 unsigned char *frag, *fsize;
6463 struct problem_context pctx;
6464 int problem = 0;
6465
6466 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6467
6468 clear_problem_context(&pctx);
6469 pctx.ino = ino;
6470 pctx.dir = dir;
6471 pctx.inode = &inode;
6472
6473 if (inode.i_file_acl &&
6474 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6475 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6476 inode.i_file_acl = 0;
6477#if BB_BIG_ENDIAN
6478 /*
6479 * This is a special kludge to deal with long symlinks
6480 * on big endian systems. i_blocks had already been
6481 * decremented earlier in pass 1, but since i_file_acl
6482 * hadn't yet been cleared, ext2fs_read_inode()
6483 * assumed that the file was short symlink and would
6484 * not have byte swapped i_block[0]. Hence, we have
6485 * to byte-swap it here.
6486 */
6487 if (LINUX_S_ISLNK(inode.i_mode) &&
6488 (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6489 (inode.i_blocks == fs->blocksize >> 9))
6490 inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6491#endif
6492 inode_modified++;
6493 } else
6494 not_fixed++;
6495
6496 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6497 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6498 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6499 !(LINUX_S_ISSOCK(inode.i_mode)))
6500 problem = PR_2_BAD_MODE;
6501 else if (LINUX_S_ISCHR(inode.i_mode)
6502 && !e2fsck_pass1_check_device_inode(fs, &inode))
6503 problem = PR_2_BAD_CHAR_DEV;
6504 else if (LINUX_S_ISBLK(inode.i_mode)
6505 && !e2fsck_pass1_check_device_inode(fs, &inode))
6506 problem = PR_2_BAD_BLOCK_DEV;
6507 else if (LINUX_S_ISFIFO(inode.i_mode)
6508 && !e2fsck_pass1_check_device_inode(fs, &inode))
6509 problem = PR_2_BAD_FIFO;
6510 else if (LINUX_S_ISSOCK(inode.i_mode)
6511 && !e2fsck_pass1_check_device_inode(fs, &inode))
6512 problem = PR_2_BAD_SOCKET;
6513 else if (LINUX_S_ISLNK(inode.i_mode)
6514 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6515 problem = PR_2_INVALID_SYMLINK;
6516 }
6517
6518 if (problem) {
6519 if (fix_problem(ctx, problem, &pctx)) {
6520 deallocate_inode(ctx, ino, 0);
6521 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6522 return 0;
6523 return 1;
6524 } else
6525 not_fixed++;
6526 problem = 0;
6527 }
6528
6529 if (inode.i_faddr) {
6530 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6531 inode.i_faddr = 0;
6532 inode_modified++;
6533 } else
6534 not_fixed++;
6535 }
6536
6537 switch (fs->super->s_creator_os) {
6538 case EXT2_OS_LINUX:
6539 frag = &inode.osd2.linux2.l_i_frag;
6540 fsize = &inode.osd2.linux2.l_i_fsize;
6541 break;
6542 case EXT2_OS_HURD:
6543 frag = &inode.osd2.hurd2.h_i_frag;
6544 fsize = &inode.osd2.hurd2.h_i_fsize;
6545 break;
6546 case EXT2_OS_MASIX:
6547 frag = &inode.osd2.masix2.m_i_frag;
6548 fsize = &inode.osd2.masix2.m_i_fsize;
6549 break;
6550 default:
6551 frag = fsize = 0;
6552 }
6553 if (frag && *frag) {
6554 pctx.num = *frag;
6555 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6556 *frag = 0;
6557 inode_modified++;
6558 } else
6559 not_fixed++;
6560 pctx.num = 0;
6561 }
6562 if (fsize && *fsize) {
6563 pctx.num = *fsize;
6564 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6565 *fsize = 0;
6566 inode_modified++;
6567 } else
6568 not_fixed++;
6569 pctx.num = 0;
6570 }
6571
6572 if (inode.i_file_acl &&
6573 ((inode.i_file_acl < fs->super->s_first_data_block) ||
6574 (inode.i_file_acl >= fs->super->s_blocks_count))) {
6575 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6576 inode.i_file_acl = 0;
6577 inode_modified++;
6578 } else
6579 not_fixed++;
6580 }
6581 if (inode.i_dir_acl &&
6582 LINUX_S_ISDIR(inode.i_mode)) {
6583 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6584 inode.i_dir_acl = 0;
6585 inode_modified++;
6586 } else
6587 not_fixed++;
6588 }
6589
6590 if (inode_modified)
6591 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6592 if (!not_fixed)
6593 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6594 return 0;
6595}
6596
6597
6598/*
6599 * allocate_dir_block --- this function allocates a new directory
6600 * block for a particular inode; this is done if a directory has
6601 * a "hole" in it, or if a directory has a illegal block number
6602 * that was zeroed out and now needs to be replaced.
6603 */
6604static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6605 struct problem_context *pctx)
6606{
6607 ext2_filsys fs = ctx->fs;
6608 blk_t blk;
6609 char *block;
6610 struct ext2_inode inode;
6611
6612 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6613 return 1;
6614
6615 /*
6616 * Read the inode and block bitmaps in; we'll be messing with
6617 * them.
6618 */
6619 e2fsck_read_bitmaps(ctx);
6620
6621 /*
6622 * First, find a free block
6623 */
6624 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6625 if (pctx->errcode) {
6626 pctx->str = "ext2fs_new_block";
6627 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6628 return 1;
6629 }
6630 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6631 ext2fs_mark_block_bitmap(fs->block_map, blk);
6632 ext2fs_mark_bb_dirty(fs);
6633
6634 /*
6635 * Now let's create the actual data block for the inode
6636 */
6637 if (db->blockcnt)
6638 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6639 else
6640 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6641 EXT2_ROOT_INO, &block);
6642
6643 if (pctx->errcode) {
6644 pctx->str = "ext2fs_new_dir_block";
6645 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6646 return 1;
6647 }
6648
6649 pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6650 ext2fs_free_mem(&block);
6651 if (pctx->errcode) {
6652 pctx->str = "ext2fs_write_dir_block";
6653 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6654 return 1;
6655 }
6656
6657 /*
6658 * Update the inode block count
6659 */
6660 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6661 inode.i_blocks += fs->blocksize / 512;
6662 if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6663 inode.i_size = (db->blockcnt+1) * fs->blocksize;
6664 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6665
6666 /*
6667 * Finally, update the block pointers for the inode
6668 */
6669 db->blk = blk;
6670 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6671 0, update_dir_block, db);
6672 if (pctx->errcode) {
6673 pctx->str = "ext2fs_block_iterate";
6674 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6675 return 1;
6676 }
6677
6678 return 0;
6679}
6680
6681/*
6682 * This is a helper function for allocate_dir_block().
6683 */
6684static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6685 blk_t *block_nr,
6686 e2_blkcnt_t blockcnt,
6687 blk_t ref_block FSCK_ATTR((unused)),
6688 int ref_offset FSCK_ATTR((unused)),
6689 void *priv_data)
6690{
6691 struct ext2_db_entry *db;
6692
6693 db = (struct ext2_db_entry *) priv_data;
6694 if (db->blockcnt == (int) blockcnt) {
6695 *block_nr = db->blk;
6696 return BLOCK_CHANGED;
6697 }
6698 return 0;
6699}
6700
6701/*
6702 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6703 *
6704 * Pass #3 assures that all directories are connected to the
6705 * filesystem tree, using the following algorithm:
6706 *
6707 * First, the root directory is checked to make sure it exists; if
6708 * not, e2fsck will offer to create a new one. It is then marked as
6709 * "done".
6710 *
6711 * Then, pass3 interates over all directory inodes; for each directory
6712 * it attempts to trace up the filesystem tree, using dirinfo.parent
6713 * until it reaches a directory which has been marked "done". If it
6714 * cannot do so, then the directory must be disconnected, and e2fsck
6715 * will offer to reconnect it to /lost+found. While it is chasing
6716 * parent pointers up the filesystem tree, if pass3 sees a directory
6717 * twice, then it has detected a filesystem loop, and it will again
6718 * offer to reconnect the directory to /lost+found in to break the
6719 * filesystem loop.
6720 *
6721 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6722 * reconnect inodes to /lost+found; this subroutine is also used by
6723 * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
6724 * is responsible for creating /lost+found if it does not exist.
6725 *
6726 * Pass 3 frees the following data structures:
6727 * - The dirinfo directory information cache.
6728 */
6729
6730static void check_root(e2fsck_t ctx);
6731static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6732 struct problem_context *pctx);
6733static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6734
6735static ext2fs_inode_bitmap inode_loop_detect;
6736static ext2fs_inode_bitmap inode_done_map;
6737
6738static void e2fsck_pass3(e2fsck_t ctx)
6739{
6740 ext2_filsys fs = ctx->fs;
6741 int i;
6742 struct problem_context pctx;
6743 struct dir_info *dir;
6744 unsigned long maxdirs, count;
6745
6746 clear_problem_context(&pctx);
6747
6748 /* Pass 3 */
6749
6750 if (!(ctx->options & E2F_OPT_PREEN))
6751 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6752
6753 /*
6754 * Allocate some bitmaps to do loop detection.
6755 */
6756 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6757 &inode_done_map);
6758 if (pctx.errcode) {
6759 pctx.num = 2;
6760 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6761 ctx->flags |= E2F_FLAG_ABORT;
6762 goto abort_exit;
6763 }
6764 check_root(ctx);
6765 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6766 goto abort_exit;
6767
6768 ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6769
6770 maxdirs = e2fsck_get_num_dirinfo(ctx);
6771 count = 1;
6772
6773 if (ctx->progress)
6774 if ((ctx->progress)(ctx, 3, 0, maxdirs))
6775 goto abort_exit;
6776
6777 for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6778 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6779 goto abort_exit;
6780 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6781 goto abort_exit;
6782 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6783 if (check_directory(ctx, dir, &pctx))
6784 goto abort_exit;
6785 }
6786
6787 /*
6788 * Force the creation of /lost+found if not present
6789 */
6790 if ((ctx->flags & E2F_OPT_READONLY) == 0)
6791 e2fsck_get_lost_and_found(ctx, 1);
6792
6793 /*
6794 * If there are any directories that need to be indexed or
6795 * optimized, do it here.
6796 */
6797 e2fsck_rehash_directories(ctx);
6798
6799abort_exit:
6800 e2fsck_free_dir_info(ctx);
6801 ext2fs_free_inode_bitmap(inode_loop_detect);
6802 inode_loop_detect = 0;
6803 ext2fs_free_inode_bitmap(inode_done_map);
6804 inode_done_map = 0;
6805}
6806
6807/*
6808 * This makes sure the root inode is present; if not, we ask if the
6809 * user wants us to create it. Not creating it is a fatal error.
6810 */
6811static void check_root(e2fsck_t ctx)
6812{
6813 ext2_filsys fs = ctx->fs;
6814 blk_t blk;
6815 struct ext2_inode inode;
6816 char * block;
6817 struct problem_context pctx;
6818
6819 clear_problem_context(&pctx);
6820
6821 if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6822 /*
6823 * If the root inode is not a directory, die here. The
6824 * user must have answered 'no' in pass1 when we
6825 * offered to clear it.
6826 */
6827 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6828 EXT2_ROOT_INO))) {
6829 fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6830 ctx->flags |= E2F_FLAG_ABORT;
6831 }
6832 return;
6833 }
6834
6835 if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6836 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6837 ctx->flags |= E2F_FLAG_ABORT;
6838 return;
6839 }
6840
6841 e2fsck_read_bitmaps(ctx);
6842
6843 /*
6844 * First, find a free block
6845 */
6846 pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6847 if (pctx.errcode) {
6848 pctx.str = "ext2fs_new_block";
6849 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6850 ctx->flags |= E2F_FLAG_ABORT;
6851 return;
6852 }
6853 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6854 ext2fs_mark_block_bitmap(fs->block_map, blk);
6855 ext2fs_mark_bb_dirty(fs);
6856
6857 /*
6858 * Now let's create the actual data block for the inode
6859 */
6860 pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6861 &block);
6862 if (pctx.errcode) {
6863 pctx.str = "ext2fs_new_dir_block";
6864 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6865 ctx->flags |= E2F_FLAG_ABORT;
6866 return;
6867 }
6868
6869 pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6870 if (pctx.errcode) {
6871 pctx.str = "ext2fs_write_dir_block";
6872 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6873 ctx->flags |= E2F_FLAG_ABORT;
6874 return;
6875 }
6876 ext2fs_free_mem(&block);
6877
6878 /*
6879 * Set up the inode structure
6880 */
6881 memset(&inode, 0, sizeof(inode));
6882 inode.i_mode = 040755;
6883 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00006884 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00006885 inode.i_links_count = 2;
6886 inode.i_blocks = fs->blocksize / 512;
6887 inode.i_block[0] = blk;
6888
6889 /*
6890 * Write out the inode.
6891 */
6892 pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6893 if (pctx.errcode) {
6894 pctx.str = "ext2fs_write_inode";
6895 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6896 ctx->flags |= E2F_FLAG_ABORT;
6897 return;
6898 }
6899
6900 /*
6901 * Miscellaneous bookkeeping...
6902 */
6903 e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6904 ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6905 ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6906
6907 ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6908 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6909 ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6910 ext2fs_mark_ib_dirty(fs);
6911}
6912
6913/*
6914 * This subroutine is responsible for making sure that a particular
6915 * directory is connected to the root; if it isn't we trace it up as
6916 * far as we can go, and then offer to connect the resulting parent to
6917 * the lost+found. We have to do loop detection; if we ever discover
6918 * a loop, we treat that as a disconnected directory and offer to
6919 * reparent it to lost+found.
6920 *
6921 * However, loop detection is expensive, because for very large
6922 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6923 * is non-trivial. Loops in filesystems are also a rare error case,
6924 * and we shouldn't optimize for error cases. So we try two passes of
6925 * the algorithm. The first time, we ignore loop detection and merely
6926 * increment a counter; if the counter exceeds some extreme threshold,
6927 * then we try again with the loop detection bitmap enabled.
6928 */
6929static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6930 struct problem_context *pctx)
6931{
6932 ext2_filsys fs = ctx->fs;
6933 struct dir_info *p = dir;
6934 int loop_pass = 0, parent_count = 0;
6935
6936 if (!p)
6937 return 0;
6938
6939 while (1) {
6940 /*
6941 * Mark this inode as being "done"; by the time we
6942 * return from this function, the inode we either be
6943 * verified as being connected to the directory tree,
6944 * or we will have offered to reconnect this to
6945 * lost+found.
6946 *
6947 * If it was marked done already, then we've reached a
6948 * parent we've already checked.
6949 */
6950 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6951 break;
6952
6953 /*
6954 * If this directory doesn't have a parent, or we've
6955 * seen the parent once already, then offer to
6956 * reparent it to lost+found
6957 */
6958 if (!p->parent ||
6959 (loop_pass &&
6960 (ext2fs_test_inode_bitmap(inode_loop_detect,
6961 p->parent)))) {
6962 pctx->ino = p->ino;
6963 if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6964 if (e2fsck_reconnect_file(ctx, pctx->ino))
6965 ext2fs_unmark_valid(fs);
6966 else {
6967 p = e2fsck_get_dir_info(ctx, pctx->ino);
6968 p->parent = ctx->lost_and_found;
6969 fix_dotdot(ctx, p, ctx->lost_and_found);
6970 }
6971 }
6972 break;
6973 }
6974 p = e2fsck_get_dir_info(ctx, p->parent);
6975 if (!p) {
6976 fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6977 return 0;
6978 }
6979 if (loop_pass) {
6980 ext2fs_mark_inode_bitmap(inode_loop_detect,
6981 p->ino);
6982 } else if (parent_count++ > 2048) {
6983 /*
6984 * If we've run into a path depth that's
6985 * greater than 2048, try again with the inode
6986 * loop bitmap turned on and start from the
6987 * top.
6988 */
6989 loop_pass = 1;
6990 if (inode_loop_detect)
6991 ext2fs_clear_inode_bitmap(inode_loop_detect);
6992 else {
6993 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6994 if (pctx->errcode) {
6995 pctx->num = 1;
6996 fix_problem(ctx,
6997 PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6998 ctx->flags |= E2F_FLAG_ABORT;
6999 return -1;
7000 }
7001 }
7002 p = dir;
7003 }
7004 }
7005
7006 /*
7007 * Make sure that .. and the parent directory are the same;
7008 * offer to fix it if not.
7009 */
7010 if (dir->parent != dir->dotdot) {
7011 pctx->ino = dir->ino;
7012 pctx->ino2 = dir->dotdot;
7013 pctx->dir = dir->parent;
7014 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7015 fix_dotdot(ctx, dir, dir->parent);
7016 }
7017 return 0;
7018}
7019
7020/*
7021 * This routine gets the lost_and_found inode, making it a directory
7022 * if necessary
7023 */
7024ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7025{
7026 ext2_filsys fs = ctx->fs;
7027 ext2_ino_t ino;
7028 blk_t blk;
7029 errcode_t retval;
7030 struct ext2_inode inode;
7031 char * block;
7032 static const char name[] = "lost+found";
7033 struct problem_context pctx;
7034 struct dir_info *dirinfo;
7035
7036 if (ctx->lost_and_found)
7037 return ctx->lost_and_found;
7038
7039 clear_problem_context(&pctx);
7040
7041 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7042 sizeof(name)-1, 0, &ino);
7043 if (retval && !fix)
7044 return 0;
7045 if (!retval) {
7046 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7047 ctx->lost_and_found = ino;
7048 return ino;
7049 }
7050
7051 /* Lost+found isn't a directory! */
7052 if (!fix)
7053 return 0;
7054 pctx.ino = ino;
7055 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7056 return 0;
7057
7058 /* OK, unlink the old /lost+found file. */
7059 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7060 if (pctx.errcode) {
7061 pctx.str = "ext2fs_unlink";
7062 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7063 return 0;
7064 }
7065 dirinfo = e2fsck_get_dir_info(ctx, ino);
7066 if (dirinfo)
7067 dirinfo->parent = 0;
7068 e2fsck_adjust_inode_count(ctx, ino, -1);
7069 } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7070 pctx.errcode = retval;
7071 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7072 }
7073 if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7074 return 0;
7075
7076 /*
7077 * Read the inode and block bitmaps in; we'll be messing with
7078 * them.
7079 */
7080 e2fsck_read_bitmaps(ctx);
7081
7082 /*
7083 * First, find a free block
7084 */
7085 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7086 if (retval) {
7087 pctx.errcode = retval;
7088 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7089 return 0;
7090 }
7091 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7092 ext2fs_block_alloc_stats(fs, blk, +1);
7093
7094 /*
7095 * Next find a free inode.
7096 */
7097 retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7098 ctx->inode_used_map, &ino);
7099 if (retval) {
7100 pctx.errcode = retval;
7101 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7102 return 0;
7103 }
7104 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7105 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7106 ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7107
7108 /*
7109 * Now let's create the actual data block for the inode
7110 */
7111 retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7112 if (retval) {
7113 pctx.errcode = retval;
7114 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7115 return 0;
7116 }
7117
7118 retval = ext2fs_write_dir_block(fs, blk, block);
7119 ext2fs_free_mem(&block);
7120 if (retval) {
7121 pctx.errcode = retval;
7122 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7123 return 0;
7124 }
7125
7126 /*
7127 * Set up the inode structure
7128 */
7129 memset(&inode, 0, sizeof(inode));
7130 inode.i_mode = 040700;
7131 inode.i_size = fs->blocksize;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007132 inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007133 inode.i_links_count = 2;
7134 inode.i_blocks = fs->blocksize / 512;
7135 inode.i_block[0] = blk;
7136
7137 /*
7138 * Next, write out the inode.
7139 */
7140 pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7141 if (pctx.errcode) {
7142 pctx.str = "ext2fs_write_inode";
7143 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7144 return 0;
7145 }
7146 /*
7147 * Finally, create the directory link
7148 */
7149 pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7150 if (pctx.errcode) {
7151 pctx.str = "ext2fs_link";
7152 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153 return 0;
7154 }
7155
7156 /*
7157 * Miscellaneous bookkeeping that needs to be kept straight.
7158 */
7159 e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7160 e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7161 ext2fs_icount_store(ctx->inode_count, ino, 2);
7162 ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7163 ctx->lost_and_found = ino;
7164 return ino;
7165}
7166
7167/*
7168 * This routine will connect a file to lost+found
7169 */
7170int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7171{
7172 ext2_filsys fs = ctx->fs;
7173 errcode_t retval;
7174 char name[80];
7175 struct problem_context pctx;
7176 struct ext2_inode inode;
7177 int file_type = 0;
7178
7179 clear_problem_context(&pctx);
7180 pctx.ino = ino;
7181
7182 if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7183 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7184 ctx->bad_lost_and_found++;
7185 }
7186 if (ctx->bad_lost_and_found) {
7187 fix_problem(ctx, PR_3_NO_LPF, &pctx);
7188 return 1;
7189 }
7190
7191 sprintf(name, "#%u", ino);
7192 if (ext2fs_read_inode(fs, ino, &inode) == 0)
7193 file_type = ext2_file_type(inode.i_mode);
7194 retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7195 if (retval == EXT2_ET_DIR_NO_SPACE) {
7196 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7197 return 1;
7198 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7199 1, 0);
7200 if (retval) {
7201 pctx.errcode = retval;
7202 fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7203 return 1;
7204 }
7205 retval = ext2fs_link(fs, ctx->lost_and_found, name,
7206 ino, file_type);
7207 }
7208 if (retval) {
7209 pctx.errcode = retval;
7210 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7211 return 1;
7212 }
7213 e2fsck_adjust_inode_count(ctx, ino, 1);
7214
7215 return 0;
7216}
7217
7218/*
7219 * Utility routine to adjust the inode counts on an inode.
7220 */
7221errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7222{
7223 ext2_filsys fs = ctx->fs;
7224 errcode_t retval;
7225 struct ext2_inode inode;
7226
7227 if (!ino)
7228 return 0;
7229
7230 retval = ext2fs_read_inode(fs, ino, &inode);
7231 if (retval)
7232 return retval;
7233
7234 if (adj == 1) {
7235 ext2fs_icount_increment(ctx->inode_count, ino, 0);
7236 if (inode.i_links_count == (__u16) ~0)
7237 return 0;
7238 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7239 inode.i_links_count++;
7240 } else if (adj == -1) {
7241 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7242 if (inode.i_links_count == 0)
7243 return 0;
7244 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7245 inode.i_links_count--;
7246 }
7247
7248 retval = ext2fs_write_inode(fs, ino, &inode);
7249 if (retval)
7250 return retval;
7251
7252 return 0;
7253}
7254
7255/*
7256 * Fix parent --- this routine fixes up the parent of a directory.
7257 */
7258struct fix_dotdot_struct {
7259 ext2_filsys fs;
7260 ext2_ino_t parent;
7261 int done;
7262 e2fsck_t ctx;
7263};
7264
7265static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7266 int offset FSCK_ATTR((unused)),
7267 int blocksize FSCK_ATTR((unused)),
7268 char *buf FSCK_ATTR((unused)),
7269 void *priv_data)
7270{
7271 struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7272 errcode_t retval;
7273 struct problem_context pctx;
7274
7275 if ((dirent->name_len & 0xFF) != 2)
7276 return 0;
7277 if (strncmp(dirent->name, "..", 2))
7278 return 0;
7279
7280 clear_problem_context(&pctx);
7281
7282 retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7283 if (retval) {
7284 pctx.errcode = retval;
7285 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7286 }
7287 retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7288 if (retval) {
7289 pctx.errcode = retval;
7290 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7291 }
7292 dirent->inode = fp->parent;
7293
7294 fp->done++;
7295 return DIRENT_ABORT | DIRENT_CHANGED;
7296}
7297
7298static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7299{
7300 ext2_filsys fs = ctx->fs;
7301 errcode_t retval;
7302 struct fix_dotdot_struct fp;
7303 struct problem_context pctx;
7304
7305 fp.fs = fs;
7306 fp.parent = parent;
7307 fp.done = 0;
7308 fp.ctx = ctx;
7309
7310 retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7311 0, fix_dotdot_proc, &fp);
7312 if (retval || !fp.done) {
7313 clear_problem_context(&pctx);
7314 pctx.ino = dir->ino;
7315 pctx.errcode = retval;
7316 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7317 PR_3_FIX_PARENT_NOFIND, &pctx);
7318 ext2fs_unmark_valid(fs);
7319 }
7320 dir->dotdot = parent;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007321}
7322
7323/*
7324 * These routines are responsible for expanding a /lost+found if it is
7325 * too small.
7326 */
7327
7328struct expand_dir_struct {
7329 int num;
7330 int guaranteed_size;
7331 int newblocks;
7332 int last_block;
7333 errcode_t err;
7334 e2fsck_t ctx;
7335};
7336
7337static int expand_dir_proc(ext2_filsys fs,
7338 blk_t *blocknr,
7339 e2_blkcnt_t blockcnt,
7340 blk_t ref_block FSCK_ATTR((unused)),
7341 int ref_offset FSCK_ATTR((unused)),
7342 void *priv_data)
7343{
7344 struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7345 blk_t new_blk;
7346 static blk_t last_blk = 0;
7347 char *block;
7348 errcode_t retval;
7349 e2fsck_t ctx;
7350
7351 ctx = es->ctx;
7352
7353 if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7354 return BLOCK_ABORT;
7355
7356 if (blockcnt > 0)
7357 es->last_block = blockcnt;
7358 if (*blocknr) {
7359 last_blk = *blocknr;
7360 return 0;
7361 }
7362 retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7363 &new_blk);
7364 if (retval) {
7365 es->err = retval;
7366 return BLOCK_ABORT;
7367 }
7368 if (blockcnt > 0) {
7369 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7370 if (retval) {
7371 es->err = retval;
7372 return BLOCK_ABORT;
7373 }
7374 es->num--;
7375 retval = ext2fs_write_dir_block(fs, new_blk, block);
7376 } else {
7377 retval = ext2fs_get_mem(fs->blocksize, &block);
7378 if (retval) {
7379 es->err = retval;
7380 return BLOCK_ABORT;
7381 }
7382 memset(block, 0, fs->blocksize);
7383 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7384 }
7385 if (retval) {
7386 es->err = retval;
7387 return BLOCK_ABORT;
7388 }
7389 ext2fs_free_mem(&block);
7390 *blocknr = new_blk;
7391 ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7392 ext2fs_block_alloc_stats(fs, new_blk, +1);
7393 es->newblocks++;
7394
7395 if (es->num == 0)
7396 return (BLOCK_CHANGED | BLOCK_ABORT);
7397 else
7398 return BLOCK_CHANGED;
7399}
7400
7401errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7402 int num, int guaranteed_size)
7403{
7404 ext2_filsys fs = ctx->fs;
7405 errcode_t retval;
7406 struct expand_dir_struct es;
7407 struct ext2_inode inode;
7408
7409 if (!(fs->flags & EXT2_FLAG_RW))
7410 return EXT2_ET_RO_FILSYS;
7411
7412 /*
7413 * Read the inode and block bitmaps in; we'll be messing with
7414 * them.
7415 */
7416 e2fsck_read_bitmaps(ctx);
7417
7418 retval = ext2fs_check_directory(fs, dir);
7419 if (retval)
7420 return retval;
7421
7422 es.num = num;
7423 es.guaranteed_size = guaranteed_size;
7424 es.last_block = 0;
7425 es.err = 0;
7426 es.newblocks = 0;
7427 es.ctx = ctx;
7428
7429 retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7430 0, expand_dir_proc, &es);
7431
7432 if (es.err)
7433 return es.err;
7434
7435 /*
7436 * Update the size and block count fields in the inode.
7437 */
7438 retval = ext2fs_read_inode(fs, dir, &inode);
7439 if (retval)
7440 return retval;
7441
7442 inode.i_size = (es.last_block + 1) * fs->blocksize;
7443 inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7444
7445 e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7446
7447 return 0;
7448}
7449
7450/*
7451 * pass4.c -- pass #4 of e2fsck: Check reference counts
7452 *
7453 * Pass 4 frees the following data structures:
7454 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
7455 */
7456
7457/*
7458 * This routine is called when an inode is not connected to the
7459 * directory tree.
7460 *
7461 * This subroutine returns 1 then the caller shouldn't bother with the
7462 * rest of the pass 4 tests.
7463 */
7464static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7465{
7466 ext2_filsys fs = ctx->fs;
7467 struct ext2_inode inode;
7468 struct problem_context pctx;
7469
7470 e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7471 clear_problem_context(&pctx);
7472 pctx.ino = i;
7473 pctx.inode = &inode;
7474
7475 /*
7476 * Offer to delete any zero-length files that does not have
7477 * blocks. If there is an EA block, it might have useful
7478 * information, so we won't prompt to delete it, but let it be
7479 * reconnected to lost+found.
7480 */
7481 if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7482 LINUX_S_ISDIR(inode.i_mode))) {
7483 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7484 ext2fs_icount_store(ctx->inode_link_info, i, 0);
7485 inode.i_links_count = 0;
Denis Vlasenko04158e02009-02-02 10:48:06 +00007486 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00007487 e2fsck_write_inode(ctx, i, &inode,
7488 "disconnect_inode");
7489 /*
7490 * Fix up the bitmaps...
7491 */
7492 e2fsck_read_bitmaps(ctx);
7493 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7494 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7495 ext2fs_inode_alloc_stats2(fs, i, -1,
7496 LINUX_S_ISDIR(inode.i_mode));
7497 return 0;
7498 }
7499 }
7500
7501 /*
7502 * Prompt to reconnect.
7503 */
7504 if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7505 if (e2fsck_reconnect_file(ctx, i))
7506 ext2fs_unmark_valid(fs);
7507 } else {
7508 /*
7509 * If we don't attach the inode, then skip the
7510 * i_links_test since there's no point in trying to
7511 * force i_links_count to zero.
7512 */
7513 ext2fs_unmark_valid(fs);
7514 return 1;
7515 }
7516 return 0;
7517}
7518
7519
7520static void e2fsck_pass4(e2fsck_t ctx)
7521{
7522 ext2_filsys fs = ctx->fs;
7523 ext2_ino_t i;
7524 struct ext2_inode inode;
7525 struct problem_context pctx;
7526 __u16 link_count, link_counted;
7527 char *buf = 0;
7528 int group, maxgroup;
7529
7530 /* Pass 4 */
7531
7532 clear_problem_context(&pctx);
7533
7534 if (!(ctx->options & E2F_OPT_PREEN))
7535 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7536
7537 group = 0;
7538 maxgroup = fs->group_desc_count;
7539 if (ctx->progress)
7540 if ((ctx->progress)(ctx, 4, 0, maxgroup))
7541 return;
7542
7543 for (i=1; i <= fs->super->s_inodes_count; i++) {
7544 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7545 return;
7546 if ((i % fs->super->s_inodes_per_group) == 0) {
7547 group++;
7548 if (ctx->progress)
7549 if ((ctx->progress)(ctx, 4, group, maxgroup))
7550 return;
7551 }
7552 if (i == EXT2_BAD_INO ||
7553 (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7554 continue;
7555 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7556 (ctx->inode_imagic_map &&
7557 ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7558 continue;
7559 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7560 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7561 if (link_counted == 0) {
7562 if (!buf)
7563 buf = e2fsck_allocate_memory(ctx,
7564 fs->blocksize, "bad_inode buffer");
7565 if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7566 continue;
7567 if (disconnect_inode(ctx, i))
7568 continue;
7569 ext2fs_icount_fetch(ctx->inode_link_info, i,
7570 &link_count);
7571 ext2fs_icount_fetch(ctx->inode_count, i,
7572 &link_counted);
7573 }
7574 if (link_counted != link_count) {
7575 e2fsck_read_inode(ctx, i, &inode, "pass4");
7576 pctx.ino = i;
7577 pctx.inode = &inode;
7578 if (link_count != inode.i_links_count) {
7579 pctx.num = link_count;
7580 fix_problem(ctx,
7581 PR_4_INCONSISTENT_COUNT, &pctx);
7582 }
7583 pctx.num = link_counted;
7584 if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7585 inode.i_links_count = link_counted;
7586 e2fsck_write_inode(ctx, i, &inode, "pass4");
7587 }
7588 }
7589 }
7590 ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7591 ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7592 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7593 ctx->inode_imagic_map = 0;
7594 ext2fs_free_mem(&buf);
7595}
7596
7597/*
7598 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7599 */
7600
7601#define NO_BLK ((blk_t) -1)
7602
7603static void print_bitmap_problem(e2fsck_t ctx, int problem,
7604 struct problem_context *pctx)
7605{
7606 switch (problem) {
7607 case PR_5_BLOCK_UNUSED:
7608 if (pctx->blk == pctx->blk2)
7609 pctx->blk2 = 0;
7610 else
7611 problem = PR_5_BLOCK_RANGE_UNUSED;
7612 break;
7613 case PR_5_BLOCK_USED:
7614 if (pctx->blk == pctx->blk2)
7615 pctx->blk2 = 0;
7616 else
7617 problem = PR_5_BLOCK_RANGE_USED;
7618 break;
7619 case PR_5_INODE_UNUSED:
7620 if (pctx->ino == pctx->ino2)
7621 pctx->ino2 = 0;
7622 else
7623 problem = PR_5_INODE_RANGE_UNUSED;
7624 break;
7625 case PR_5_INODE_USED:
7626 if (pctx->ino == pctx->ino2)
7627 pctx->ino2 = 0;
7628 else
7629 problem = PR_5_INODE_RANGE_USED;
7630 break;
7631 }
7632 fix_problem(ctx, problem, pctx);
7633 pctx->blk = pctx->blk2 = NO_BLK;
7634 pctx->ino = pctx->ino2 = 0;
7635}
7636
7637static void check_block_bitmaps(e2fsck_t ctx)
7638{
7639 ext2_filsys fs = ctx->fs;
7640 blk_t i;
7641 int *free_array;
7642 int group = 0;
7643 unsigned int blocks = 0;
7644 unsigned int free_blocks = 0;
7645 int group_free = 0;
7646 int actual, bitmap;
7647 struct problem_context pctx;
7648 int problem, save_problem, fixit, had_problem;
7649 errcode_t retval;
7650
7651 clear_problem_context(&pctx);
7652 free_array = (int *) e2fsck_allocate_memory(ctx,
7653 fs->group_desc_count * sizeof(int), "free block count array");
7654
7655 if ((fs->super->s_first_data_block <
7656 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7657 (fs->super->s_blocks_count-1 >
7658 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7659 pctx.num = 1;
7660 pctx.blk = fs->super->s_first_data_block;
7661 pctx.blk2 = fs->super->s_blocks_count -1;
7662 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7663 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7664 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7665
7666 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7667 return;
7668 }
7669
7670 if ((fs->super->s_first_data_block <
7671 ext2fs_get_block_bitmap_start(fs->block_map)) ||
7672 (fs->super->s_blocks_count-1 >
7673 ext2fs_get_block_bitmap_end(fs->block_map))) {
7674 pctx.num = 2;
7675 pctx.blk = fs->super->s_first_data_block;
7676 pctx.blk2 = fs->super->s_blocks_count -1;
7677 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7678 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7679 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7680
7681 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7682 return;
7683 }
7684
7685redo_counts:
7686 had_problem = 0;
7687 save_problem = 0;
7688 pctx.blk = pctx.blk2 = NO_BLK;
7689 for (i = fs->super->s_first_data_block;
7690 i < fs->super->s_blocks_count;
7691 i++) {
7692 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7693 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7694
7695 if (actual == bitmap)
7696 goto do_counts;
7697
7698 if (!actual && bitmap) {
7699 /*
7700 * Block not used, but marked in use in the bitmap.
7701 */
7702 problem = PR_5_BLOCK_UNUSED;
7703 } else {
7704 /*
7705 * Block used, but not marked in use in the bitmap.
7706 */
7707 problem = PR_5_BLOCK_USED;
7708 }
7709 if (pctx.blk == NO_BLK) {
7710 pctx.blk = pctx.blk2 = i;
7711 save_problem = problem;
7712 } else {
7713 if ((problem == save_problem) &&
7714 (pctx.blk2 == i-1))
7715 pctx.blk2++;
7716 else {
7717 print_bitmap_problem(ctx, save_problem, &pctx);
7718 pctx.blk = pctx.blk2 = i;
7719 save_problem = problem;
7720 }
7721 }
7722 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7723 had_problem++;
7724
7725 do_counts:
7726 if (!bitmap) {
7727 group_free++;
7728 free_blocks++;
7729 }
7730 blocks ++;
7731 if ((blocks == fs->super->s_blocks_per_group) ||
7732 (i == fs->super->s_blocks_count-1)) {
7733 free_array[group] = group_free;
7734 group ++;
7735 blocks = 0;
7736 group_free = 0;
7737 if (ctx->progress)
7738 if ((ctx->progress)(ctx, 5, group,
7739 fs->group_desc_count*2))
7740 return;
7741 }
7742 }
7743 if (pctx.blk != NO_BLK)
7744 print_bitmap_problem(ctx, save_problem, &pctx);
7745 if (had_problem)
7746 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7747 else
7748 fixit = -1;
7749 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7750
7751 if (fixit == 1) {
7752 ext2fs_free_block_bitmap(fs->block_map);
7753 retval = ext2fs_copy_bitmap(ctx->block_found_map,
7754 &fs->block_map);
7755 if (retval) {
7756 clear_problem_context(&pctx);
7757 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7758 ctx->flags |= E2F_FLAG_ABORT;
7759 return;
7760 }
7761 ext2fs_set_bitmap_padding(fs->block_map);
7762 ext2fs_mark_bb_dirty(fs);
7763
7764 /* Redo the counts */
7765 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7766 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7767 goto redo_counts;
7768 } else if (fixit == 0)
7769 ext2fs_unmark_valid(fs);
7770
7771 for (i = 0; i < fs->group_desc_count; i++) {
7772 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7773 pctx.group = i;
7774 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7775 pctx.blk2 = free_array[i];
7776
7777 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7778 &pctx)) {
7779 fs->group_desc[i].bg_free_blocks_count =
7780 free_array[i];
7781 ext2fs_mark_super_dirty(fs);
7782 } else
7783 ext2fs_unmark_valid(fs);
7784 }
7785 }
7786 if (free_blocks != fs->super->s_free_blocks_count) {
7787 pctx.group = 0;
7788 pctx.blk = fs->super->s_free_blocks_count;
7789 pctx.blk2 = free_blocks;
7790
7791 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7792 fs->super->s_free_blocks_count = free_blocks;
7793 ext2fs_mark_super_dirty(fs);
7794 } else
7795 ext2fs_unmark_valid(fs);
7796 }
7797 ext2fs_free_mem(&free_array);
7798}
7799
7800static void check_inode_bitmaps(e2fsck_t ctx)
7801{
7802 ext2_filsys fs = ctx->fs;
7803 ext2_ino_t i;
7804 unsigned int free_inodes = 0;
7805 int group_free = 0;
7806 int dirs_count = 0;
7807 int group = 0;
7808 unsigned int inodes = 0;
7809 int *free_array;
7810 int *dir_array;
7811 int actual, bitmap;
7812 errcode_t retval;
7813 struct problem_context pctx;
7814 int problem, save_problem, fixit, had_problem;
7815
7816 clear_problem_context(&pctx);
7817 free_array = (int *) e2fsck_allocate_memory(ctx,
7818 fs->group_desc_count * sizeof(int), "free inode count array");
7819
7820 dir_array = (int *) e2fsck_allocate_memory(ctx,
7821 fs->group_desc_count * sizeof(int), "directory count array");
7822
7823 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7824 (fs->super->s_inodes_count >
7825 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7826 pctx.num = 3;
7827 pctx.blk = 1;
7828 pctx.blk2 = fs->super->s_inodes_count;
7829 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7830 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7831 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7832
7833 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7834 return;
7835 }
7836 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7837 (fs->super->s_inodes_count >
7838 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7839 pctx.num = 4;
7840 pctx.blk = 1;
7841 pctx.blk2 = fs->super->s_inodes_count;
7842 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7843 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7844 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7845
7846 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7847 return;
7848 }
7849
7850redo_counts:
7851 had_problem = 0;
7852 save_problem = 0;
7853 pctx.ino = pctx.ino2 = 0;
7854 for (i = 1; i <= fs->super->s_inodes_count; i++) {
7855 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7856 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7857
7858 if (actual == bitmap)
7859 goto do_counts;
7860
7861 if (!actual && bitmap) {
7862 /*
7863 * Inode wasn't used, but marked in bitmap
7864 */
7865 problem = PR_5_INODE_UNUSED;
7866 } else /* if (actual && !bitmap) */ {
7867 /*
7868 * Inode used, but not in bitmap
7869 */
7870 problem = PR_5_INODE_USED;
7871 }
7872 if (pctx.ino == 0) {
7873 pctx.ino = pctx.ino2 = i;
7874 save_problem = problem;
7875 } else {
7876 if ((problem == save_problem) &&
7877 (pctx.ino2 == i-1))
7878 pctx.ino2++;
7879 else {
7880 print_bitmap_problem(ctx, save_problem, &pctx);
7881 pctx.ino = pctx.ino2 = i;
7882 save_problem = problem;
7883 }
7884 }
7885 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7886 had_problem++;
7887
7888do_counts:
7889 if (!bitmap) {
7890 group_free++;
7891 free_inodes++;
7892 } else {
7893 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7894 dirs_count++;
7895 }
7896 inodes++;
7897 if ((inodes == fs->super->s_inodes_per_group) ||
7898 (i == fs->super->s_inodes_count)) {
7899 free_array[group] = group_free;
7900 dir_array[group] = dirs_count;
7901 group ++;
7902 inodes = 0;
7903 group_free = 0;
7904 dirs_count = 0;
7905 if (ctx->progress)
7906 if ((ctx->progress)(ctx, 5,
7907 group + fs->group_desc_count,
7908 fs->group_desc_count*2))
7909 return;
7910 }
7911 }
7912 if (pctx.ino)
7913 print_bitmap_problem(ctx, save_problem, &pctx);
7914
7915 if (had_problem)
7916 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7917 else
7918 fixit = -1;
7919 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7920
7921 if (fixit == 1) {
7922 ext2fs_free_inode_bitmap(fs->inode_map);
7923 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7924 &fs->inode_map);
7925 if (retval) {
7926 clear_problem_context(&pctx);
7927 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7928 ctx->flags |= E2F_FLAG_ABORT;
7929 return;
7930 }
7931 ext2fs_set_bitmap_padding(fs->inode_map);
7932 ext2fs_mark_ib_dirty(fs);
7933
7934 /* redo counts */
7935 inodes = 0; free_inodes = 0; group_free = 0;
7936 dirs_count = 0; group = 0;
7937 memset(free_array, 0, fs->group_desc_count * sizeof(int));
7938 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7939 goto redo_counts;
7940 } else if (fixit == 0)
7941 ext2fs_unmark_valid(fs);
7942
7943 for (i = 0; i < fs->group_desc_count; i++) {
7944 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7945 pctx.group = i;
7946 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7947 pctx.ino2 = free_array[i];
7948 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7949 &pctx)) {
7950 fs->group_desc[i].bg_free_inodes_count =
7951 free_array[i];
7952 ext2fs_mark_super_dirty(fs);
7953 } else
7954 ext2fs_unmark_valid(fs);
7955 }
7956 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7957 pctx.group = i;
7958 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7959 pctx.ino2 = dir_array[i];
7960
7961 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7962 &pctx)) {
7963 fs->group_desc[i].bg_used_dirs_count =
7964 dir_array[i];
7965 ext2fs_mark_super_dirty(fs);
7966 } else
7967 ext2fs_unmark_valid(fs);
7968 }
7969 }
7970 if (free_inodes != fs->super->s_free_inodes_count) {
7971 pctx.group = -1;
7972 pctx.ino = fs->super->s_free_inodes_count;
7973 pctx.ino2 = free_inodes;
7974
7975 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7976 fs->super->s_free_inodes_count = free_inodes;
7977 ext2fs_mark_super_dirty(fs);
7978 } else
7979 ext2fs_unmark_valid(fs);
7980 }
7981 ext2fs_free_mem(&free_array);
7982 ext2fs_free_mem(&dir_array);
7983}
7984
7985static void check_inode_end(e2fsck_t ctx)
7986{
7987 ext2_filsys fs = ctx->fs;
7988 ext2_ino_t end, save_inodes_count, i;
7989 struct problem_context pctx;
7990
7991 clear_problem_context(&pctx);
7992
7993 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7994 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7995 &save_inodes_count);
7996 if (pctx.errcode) {
7997 pctx.num = 1;
7998 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7999 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8000 return;
8001 }
8002 if (save_inodes_count == end)
8003 return;
8004
8005 for (i = save_inodes_count + 1; i <= end; i++) {
8006 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8007 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8008 for (i = save_inodes_count + 1; i <= end; i++)
8009 ext2fs_mark_inode_bitmap(fs->inode_map,
8010 i);
8011 ext2fs_mark_ib_dirty(fs);
8012 } else
8013 ext2fs_unmark_valid(fs);
8014 break;
8015 }
8016 }
8017
8018 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8019 save_inodes_count, 0);
8020 if (pctx.errcode) {
8021 pctx.num = 2;
8022 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8023 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8024 return;
8025 }
8026}
8027
8028static void check_block_end(e2fsck_t ctx)
8029{
8030 ext2_filsys fs = ctx->fs;
8031 blk_t end, save_blocks_count, i;
8032 struct problem_context pctx;
8033
8034 clear_problem_context(&pctx);
8035
8036 end = fs->block_map->start +
8037 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8038 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8039 &save_blocks_count);
8040 if (pctx.errcode) {
8041 pctx.num = 3;
8042 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8043 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8044 return;
8045 }
8046 if (save_blocks_count == end)
8047 return;
8048
8049 for (i = save_blocks_count + 1; i <= end; i++) {
8050 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8051 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8052 for (i = save_blocks_count + 1; i <= end; i++)
8053 ext2fs_mark_block_bitmap(fs->block_map,
8054 i);
8055 ext2fs_mark_bb_dirty(fs);
8056 } else
8057 ext2fs_unmark_valid(fs);
8058 break;
8059 }
8060 }
8061
8062 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8063 save_blocks_count, 0);
8064 if (pctx.errcode) {
8065 pctx.num = 4;
8066 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8067 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8068 return;
8069 }
8070}
8071
8072static void e2fsck_pass5(e2fsck_t ctx)
8073{
8074 struct problem_context pctx;
8075
8076 /* Pass 5 */
8077
8078 clear_problem_context(&pctx);
8079
8080 if (!(ctx->options & E2F_OPT_PREEN))
8081 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8082
8083 if (ctx->progress)
8084 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8085 return;
8086
8087 e2fsck_read_bitmaps(ctx);
8088
8089 check_block_bitmaps(ctx);
8090 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8091 return;
8092 check_inode_bitmaps(ctx);
8093 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8094 return;
8095 check_inode_end(ctx);
8096 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8097 return;
8098 check_block_end(ctx);
8099 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100 return;
8101
8102 ext2fs_free_inode_bitmap(ctx->inode_used_map);
8103 ctx->inode_used_map = 0;
8104 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8105 ctx->inode_dir_map = 0;
8106 ext2fs_free_block_bitmap(ctx->block_found_map);
8107 ctx->block_found_map = 0;
8108}
8109
8110/*
8111 * problem.c --- report filesystem problems to the user
8112 */
8113
8114#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */
8115#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */
8116#define PR_NO_DEFAULT 0x000004 /* Default to no */
8117#define PR_MSG_ONLY 0x000008 /* Print message only */
8118
8119/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8120
8121#define PR_FATAL 0x001000 /* Fatal error */
8122#define PR_AFTER_CODE 0x002000 /* After asking the first question, */
8123 /* ask another */
8124#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */
8125#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */
8126#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */
8127#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */
8128#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */
8129
8130
8131#define PROMPT_NONE 0
8132#define PROMPT_FIX 1
8133#define PROMPT_CLEAR 2
8134#define PROMPT_RELOCATE 3
8135#define PROMPT_ALLOCATE 4
8136#define PROMPT_EXPAND 5
8137#define PROMPT_CONNECT 6
8138#define PROMPT_CREATE 7
8139#define PROMPT_SALVAGE 8
8140#define PROMPT_TRUNCATE 9
8141#define PROMPT_CLEAR_INODE 10
8142#define PROMPT_ABORT 11
8143#define PROMPT_SPLIT 12
8144#define PROMPT_CONTINUE 13
8145#define PROMPT_CLONE 14
8146#define PROMPT_DELETE 15
8147#define PROMPT_SUPPRESS 16
8148#define PROMPT_UNLINK 17
8149#define PROMPT_CLEAR_HTREE 18
8150#define PROMPT_RECREATE 19
8151#define PROMPT_NULL 20
8152
8153struct e2fsck_problem {
8154 problem_t e2p_code;
8155 const char * e2p_description;
8156 char prompt;
8157 int flags;
8158 problem_t second_code;
8159};
8160
8161struct latch_descr {
8162 int latch_code;
8163 problem_t question;
8164 problem_t end_message;
8165 int flags;
8166};
8167
8168/*
8169 * These are the prompts which are used to ask the user if they want
8170 * to fix a problem.
8171 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008172static const char *const prompt[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008173 N_("(no prompt)"), /* 0 */
8174 N_("Fix"), /* 1 */
8175 N_("Clear"), /* 2 */
8176 N_("Relocate"), /* 3 */
8177 N_("Allocate"), /* 4 */
8178 N_("Expand"), /* 5 */
8179 N_("Connect to /lost+found"), /* 6 */
8180 N_("Create"), /* 7 */
8181 N_("Salvage"), /* 8 */
8182 N_("Truncate"), /* 9 */
8183 N_("Clear inode"), /* 10 */
8184 N_("Abort"), /* 11 */
8185 N_("Split"), /* 12 */
8186 N_("Continue"), /* 13 */
8187 N_("Clone multiply-claimed blocks"), /* 14 */
8188 N_("Delete file"), /* 15 */
8189 N_("Suppress messages"),/* 16 */
8190 N_("Unlink"), /* 17 */
8191 N_("Clear HTree index"),/* 18 */
8192 N_("Recreate"), /* 19 */
8193 "", /* 20 */
8194};
8195
8196/*
8197 * These messages are printed when we are preen mode and we will be
8198 * automatically fixing the problem.
8199 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00008200static const char *const preen_msg[] = {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00008201 N_("(NONE)"), /* 0 */
8202 N_("FIXED"), /* 1 */
8203 N_("CLEARED"), /* 2 */
8204 N_("RELOCATED"), /* 3 */
8205 N_("ALLOCATED"), /* 4 */
8206 N_("EXPANDED"), /* 5 */
8207 N_("RECONNECTED"), /* 6 */
8208 N_("CREATED"), /* 7 */
8209 N_("SALVAGED"), /* 8 */
8210 N_("TRUNCATED"), /* 9 */
8211 N_("INODE CLEARED"), /* 10 */
8212 N_("ABORTED"), /* 11 */
8213 N_("SPLIT"), /* 12 */
8214 N_("CONTINUING"), /* 13 */
8215 N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8216 N_("FILE DELETED"), /* 15 */
8217 N_("SUPPRESSED"), /* 16 */
8218 N_("UNLINKED"), /* 17 */
8219 N_("HTREE INDEX CLEARED"),/* 18 */
8220 N_("WILL RECREATE"), /* 19 */
8221 "", /* 20 */
8222};
8223
8224static const struct e2fsck_problem problem_table[] = {
8225
8226 /* Pre-Pass 1 errors */
8227
8228 /* Block bitmap not in group */
8229 { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"),
8230 PROMPT_RELOCATE, PR_LATCH_RELOC },
8231
8232 /* Inode bitmap not in group */
8233 { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"),
8234 PROMPT_RELOCATE, PR_LATCH_RELOC },
8235
8236 /* Inode table not in group */
8237 { PR_0_ITABLE_NOT_GROUP,
8238 N_("@i table for @g %g is not in @g. (@b %b)\n"
8239 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8240 PROMPT_RELOCATE, PR_LATCH_RELOC },
8241
8242 /* Superblock corrupt */
8243 { PR_0_SB_CORRUPT,
8244 N_("\nThe @S could not be read or does not describe a correct ext2\n"
8245 "@f. If the @v is valid and it really contains an ext2\n"
8246 "@f (and not swap or ufs or something else), then the @S\n"
8247 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8248 " e2fsck -b %S <@v>\n\n"),
8249 PROMPT_NONE, PR_FATAL },
8250
8251 /* Filesystem size is wrong */
8252 { PR_0_FS_SIZE_WRONG,
8253 N_("The @f size (according to the @S) is %b @bs\n"
8254 "The physical size of the @v is %c @bs\n"
8255 "Either the @S or the partition table is likely to be corrupt!\n"),
8256 PROMPT_ABORT, 0 },
8257
8258 /* Fragments not supported */
8259 { PR_0_NO_FRAGMENTS,
8260 N_("@S @b_size = %b, fragsize = %c.\n"
8261 "This version of e2fsck does not support fragment sizes different\n"
8262 "from the @b size.\n"),
8263 PROMPT_NONE, PR_FATAL },
8264
8265 /* Bad blocks_per_group */
8266 { PR_0_BLOCKS_PER_GROUP,
8267 N_("@S @bs_per_group = %b, should have been %c\n"),
8268 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8269
8270 /* Bad first_data_block */
8271 { PR_0_FIRST_DATA_BLOCK,
8272 N_("@S first_data_@b = %b, should have been %c\n"),
8273 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8274
8275 /* Adding UUID to filesystem */
8276 { PR_0_ADD_UUID,
8277 N_("@f did not have a UUID; generating one.\n\n"),
8278 PROMPT_NONE, 0 },
8279
8280 /* Relocate hint */
8281 { PR_0_RELOCATE_HINT,
8282 N_("Note: if several inode or block bitmap blocks or part\n"
8283 "of the inode table require relocation, you may wish to try\n"
8284 "running e2fsck with the '-b %S' option first. The problem\n"
8285 "may lie only with the primary block group descriptors, and\n"
8286 "the backup block group descriptors may be OK.\n\n"),
8287 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8288
8289 /* Miscellaneous superblock corruption */
8290 { PR_0_MISC_CORRUPT_SUPER,
8291 N_("Corruption found in @S. (%s = %N).\n"),
8292 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8293
8294 /* Error determing physical device size of filesystem */
8295 { PR_0_GETSIZE_ERROR,
8296 N_("Error determining size of the physical @v: %m\n"),
8297 PROMPT_NONE, PR_FATAL },
8298
8299 /* Inode count in superblock is incorrect */
8300 { PR_0_INODE_COUNT_WRONG,
8301 N_("@i count in @S is %i, @s %j.\n"),
8302 PROMPT_FIX, 0 },
8303
8304 { PR_0_HURD_CLEAR_FILETYPE,
8305 N_("The Hurd does not support the filetype feature.\n"),
8306 PROMPT_CLEAR, 0 },
8307
8308 /* Journal inode is invalid */
8309 { PR_0_JOURNAL_BAD_INODE,
8310 N_("@S has an @n ext3 @j (@i %i).\n"),
8311 PROMPT_CLEAR, PR_PREEN_OK },
8312
8313 /* The external journal has (unsupported) multiple filesystems */
8314 { PR_0_JOURNAL_UNSUPP_MULTIFS,
8315 N_("External @j has multiple @f users (unsupported).\n"),
8316 PROMPT_NONE, PR_FATAL },
8317
8318 /* Can't find external journal */
8319 { PR_0_CANT_FIND_JOURNAL,
8320 N_("Can't find external @j\n"),
8321 PROMPT_NONE, PR_FATAL },
8322
8323 /* External journal has bad superblock */
8324 { PR_0_EXT_JOURNAL_BAD_SUPER,
8325 N_("External @j has bad @S\n"),
8326 PROMPT_NONE, PR_FATAL },
8327
8328 /* Superblock has a bad journal UUID */
8329 { PR_0_JOURNAL_BAD_UUID,
8330 N_("External @j does not support this @f\n"),
8331 PROMPT_NONE, PR_FATAL },
8332
8333 /* Journal has an unknown superblock type */
8334 { PR_0_JOURNAL_UNSUPP_SUPER,
8335 N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8336 "It is likely that your copy of e2fsck is old and/or doesn't "
8337 "support this @j format.\n"
8338 "It is also possible the @j @S is corrupt.\n"),
8339 PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8340
8341 /* Journal superblock is corrupt */
8342 { PR_0_JOURNAL_BAD_SUPER,
8343 N_("Ext3 @j @S is corrupt.\n"),
8344 PROMPT_FIX, PR_PREEN_OK },
8345
8346 /* Superblock flag should be cleared */
8347 { PR_0_JOURNAL_HAS_JOURNAL,
8348 N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8349 PROMPT_CLEAR, PR_PREEN_OK },
8350
8351 /* Superblock flag is incorrect */
8352 { PR_0_JOURNAL_RECOVER_SET,
8353 N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8354 PROMPT_CLEAR, PR_PREEN_OK },
8355
8356 /* Journal has data, but recovery flag is clear */
8357 { PR_0_JOURNAL_RECOVERY_CLEAR,
8358 N_("ext3 recovery flag is clear, but @j has data.\n"),
8359 PROMPT_NONE, 0 },
8360
8361 /* Ask if we should clear the journal */
8362 { PR_0_JOURNAL_RESET_JOURNAL,
8363 N_("Clear @j"),
8364 PROMPT_NULL, PR_PREEN_NOMSG },
8365
8366 /* Ask if we should run the journal anyway */
8367 { PR_0_JOURNAL_RUN,
8368 N_("Run @j anyway"),
8369 PROMPT_NULL, 0 },
8370
8371 /* Run the journal by default */
8372 { PR_0_JOURNAL_RUN_DEFAULT,
8373 N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8374 PROMPT_NONE, 0 },
8375
8376 /* Clearing orphan inode */
8377 { PR_0_ORPHAN_CLEAR_INODE,
8378 N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8379 PROMPT_NONE, 0 },
8380
8381 /* Illegal block found in orphaned inode */
8382 { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8383 N_("@I @b #%B (%b) found in @o @i %i.\n"),
8384 PROMPT_NONE, 0 },
8385
8386 /* Already cleared block found in orphaned inode */
8387 { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8388 N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8389 PROMPT_NONE, 0 },
8390
8391 /* Illegal orphan inode in superblock */
8392 { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8393 N_("@I @o @i %i in @S.\n"),
8394 PROMPT_NONE, 0 },
8395
8396 /* Illegal inode in orphaned inode list */
8397 { PR_0_ORPHAN_ILLEGAL_INODE,
8398 N_("@I @i %i in @o @i list.\n"),
8399 PROMPT_NONE, 0 },
8400
8401 /* Filesystem revision is 0, but feature flags are set */
8402 { PR_0_FS_REV_LEVEL,
8403 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8404 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8405
8406 /* Journal superblock has an unknown read-only feature flag set */
8407 { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8408 N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8409 PROMPT_ABORT, 0 },
8410
8411 /* Journal superblock has an unknown incompatible feature flag set */
8412 { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8413 N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8414 PROMPT_ABORT, 0 },
8415
8416 /* Journal has unsupported version number */
8417 { PR_0_JOURNAL_UNSUPP_VERSION,
8418 N_("@j version not supported by this e2fsck.\n"),
8419 PROMPT_ABORT, 0 },
8420
8421 /* Moving journal to hidden file */
8422 { PR_0_MOVE_JOURNAL,
8423 N_("Moving @j from /%s to hidden @i.\n\n"),
8424 PROMPT_NONE, 0 },
8425
8426 /* Error moving journal to hidden file */
8427 { PR_0_ERR_MOVE_JOURNAL,
8428 N_("Error moving @j: %m\n\n"),
8429 PROMPT_NONE, 0 },
8430
8431 /* Clearing V2 journal superblock */
8432 { PR_0_CLEAR_V2_JOURNAL,
8433 N_("Found @n V2 @j @S fields (from V1 @j).\n"
8434 "Clearing fields beyond the V1 @j @S...\n\n"),
8435 PROMPT_NONE, 0 },
8436
8437 /* Backup journal inode blocks */
8438 { PR_0_BACKUP_JNL,
8439 N_("Backing up @j @i @b information.\n\n"),
8440 PROMPT_NONE, 0 },
8441
8442 /* Reserved blocks w/o resize_inode */
8443 { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8444 N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8445 "is %N; @s zero. "),
8446 PROMPT_FIX, 0 },
8447
8448 /* Resize_inode not enabled, but resize inode is non-zero */
8449 { PR_0_CLEAR_RESIZE_INODE,
8450 N_("Resize_@i not enabled, but the resize @i is non-zero. "),
8451 PROMPT_CLEAR, 0 },
8452
8453 /* Resize inode invalid */
8454 { PR_0_RESIZE_INODE_INVALID,
8455 N_("Resize @i not valid. "),
8456 PROMPT_RECREATE, 0 },
8457
8458 /* Pass 1 errors */
8459
8460 /* Pass 1: Checking inodes, blocks, and sizes */
8461 { PR_1_PASS_HEADER,
8462 N_("Pass 1: Checking @is, @bs, and sizes\n"),
8463 PROMPT_NONE, 0 },
8464
8465 /* Root directory is not an inode */
8466 { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "),
8467 PROMPT_CLEAR, 0 },
8468
8469 /* Root directory has dtime set */
8470 { PR_1_ROOT_DTIME,
8471 N_("@r has dtime set (probably due to old mke2fs). "),
8472 PROMPT_FIX, PR_PREEN_OK },
8473
8474 /* Reserved inode has bad mode */
8475 { PR_1_RESERVED_BAD_MODE,
8476 N_("Reserved @i %i (%Q) has @n mode. "),
8477 PROMPT_CLEAR, PR_PREEN_OK },
8478
8479 /* Deleted inode has zero dtime */
8480 { PR_1_ZERO_DTIME,
8481 N_("@D @i %i has zero dtime. "),
8482 PROMPT_FIX, PR_PREEN_OK },
8483
8484 /* Inode in use, but dtime set */
8485 { PR_1_SET_DTIME,
8486 N_("@i %i is in use, but has dtime set. "),
8487 PROMPT_FIX, PR_PREEN_OK },
8488
8489 /* Zero-length directory */
8490 { PR_1_ZERO_LENGTH_DIR,
8491 N_("@i %i is a @z @d. "),
8492 PROMPT_CLEAR, PR_PREEN_OK },
8493
8494 /* Block bitmap conflicts with some other fs block */
8495 { PR_1_BB_CONFLICT,
8496 N_("@g %g's @b @B at %b @C.\n"),
8497 PROMPT_RELOCATE, 0 },
8498
8499 /* Inode bitmap conflicts with some other fs block */
8500 { PR_1_IB_CONFLICT,
8501 N_("@g %g's @i @B at %b @C.\n"),
8502 PROMPT_RELOCATE, 0 },
8503
8504 /* Inode table conflicts with some other fs block */
8505 { PR_1_ITABLE_CONFLICT,
8506 N_("@g %g's @i table at %b @C.\n"),
8507 PROMPT_RELOCATE, 0 },
8508
8509 /* Block bitmap is on a bad block */
8510 { PR_1_BB_BAD_BLOCK,
8511 N_("@g %g's @b @B (%b) is bad. "),
8512 PROMPT_RELOCATE, 0 },
8513
8514 /* Inode bitmap is on a bad block */
8515 { PR_1_IB_BAD_BLOCK,
8516 N_("@g %g's @i @B (%b) is bad. "),
8517 PROMPT_RELOCATE, 0 },
8518
8519 /* Inode has incorrect i_size */
8520 { PR_1_BAD_I_SIZE,
8521 N_("@i %i, i_size is %Is, @s %N. "),
8522 PROMPT_FIX, PR_PREEN_OK },
8523
8524 /* Inode has incorrect i_blocks */
8525 { PR_1_BAD_I_BLOCKS,
8526 N_("@i %i, i_@bs is %Ib, @s %N. "),
8527 PROMPT_FIX, PR_PREEN_OK },
8528
8529 /* Illegal blocknumber in inode */
8530 { PR_1_ILLEGAL_BLOCK_NUM,
8531 N_("@I @b #%B (%b) in @i %i. "),
8532 PROMPT_CLEAR, PR_LATCH_BLOCK },
8533
8534 /* Block number overlaps fs metadata */
8535 { PR_1_BLOCK_OVERLAPS_METADATA,
8536 N_("@b #%B (%b) overlaps @f metadata in @i %i. "),
8537 PROMPT_CLEAR, PR_LATCH_BLOCK },
8538
8539 /* Inode has illegal blocks (latch question) */
8540 { PR_1_INODE_BLOCK_LATCH,
8541 N_("@i %i has illegal @b(s). "),
8542 PROMPT_CLEAR, 0 },
8543
8544 /* Too many bad blocks in inode */
8545 { PR_1_TOO_MANY_BAD_BLOCKS,
8546 N_("Too many illegal @bs in @i %i.\n"),
8547 PROMPT_CLEAR_INODE, PR_NO_OK },
8548
8549 /* Illegal block number in bad block inode */
8550 { PR_1_BB_ILLEGAL_BLOCK_NUM,
8551 N_("@I @b #%B (%b) in bad @b @i. "),
8552 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8553
8554 /* Bad block inode has illegal blocks (latch question) */
8555 { PR_1_INODE_BBLOCK_LATCH,
8556 N_("Bad @b @i has illegal @b(s). "),
8557 PROMPT_CLEAR, 0 },
8558
8559 /* Duplicate or bad blocks in use! */
8560 { PR_1_DUP_BLOCKS_PREENSTOP,
8561 N_("Duplicate or bad @b in use!\n"),
8562 PROMPT_NONE, 0 },
8563
8564 /* Bad block used as bad block indirect block */
8565 { PR_1_BBINODE_BAD_METABLOCK,
8566 N_("Bad @b %b used as bad @b @i indirect @b. "),
8567 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8568
8569 /* Inconsistency can't be fixed prompt */
8570 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8571 N_("\nThe bad @b @i has probably been corrupted. You probably\n"
8572 "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8573 "in the @f.\n"),
8574 PROMPT_CONTINUE, PR_PREEN_NOMSG },
8575
8576 /* Bad primary block */
8577 { PR_1_BAD_PRIMARY_BLOCK,
8578 N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8579 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8580
8581 /* Bad primary block prompt */
8582 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8583 N_("You can remove this @b from the bad @b list and hope\n"
8584 "that the @b is really OK. But there are no guarantees.\n\n"),
8585 PROMPT_CLEAR, PR_PREEN_NOMSG },
8586
8587 /* Bad primary superblock */
8588 { PR_1_BAD_PRIMARY_SUPERBLOCK,
8589 N_("The primary @S (%b) is on the bad @b list.\n"),
8590 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8591
8592 /* Bad primary block group descriptors */
8593 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8594 N_("Block %b in the primary @g descriptors "
8595 "is on the bad @b list\n"),
8596 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8597
8598 /* Bad superblock in group */
8599 { PR_1_BAD_SUPERBLOCK,
8600 N_("Warning: Group %g's @S (%b) is bad.\n"),
8601 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8602
8603 /* Bad block group descriptors in group */
8604 { PR_1_BAD_GROUP_DESCRIPTORS,
8605 N_("Warning: Group %g's copy of the @g descriptors has a bad "
8606 "@b (%b).\n"),
8607 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8608
8609 /* Block claimed for no reason */
8610 { PR_1_PROGERR_CLAIMED_BLOCK,
8611 N_("Programming error? @b #%b claimed for no reason in "
8612 "process_bad_@b.\n"),
8613 PROMPT_NONE, PR_PREEN_OK },
8614
8615 /* Error allocating blocks for relocating metadata */
8616 { PR_1_RELOC_BLOCK_ALLOCATE,
8617 N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8618 PROMPT_NONE, PR_PREEN_OK },
8619
8620 /* Error allocating block buffer during relocation process */
8621 { PR_1_RELOC_MEMORY_ALLOCATE,
8622 N_("@A @b buffer for relocating %s\n"),
8623 PROMPT_NONE, PR_PREEN_OK },
8624
8625 /* Relocating metadata group information from X to Y */
8626 { PR_1_RELOC_FROM_TO,
8627 N_("Relocating @g %g's %s from %b to %c...\n"),
8628 PROMPT_NONE, PR_PREEN_OK },
8629
8630 /* Relocating metatdata group information to X */
8631 { PR_1_RELOC_TO,
8632 N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8633 PROMPT_NONE, PR_PREEN_OK },
8634
8635 /* Block read error during relocation process */
8636 { PR_1_RELOC_READ_ERR,
8637 N_("Warning: could not read @b %b of %s: %m\n"),
8638 PROMPT_NONE, PR_PREEN_OK },
8639
8640 /* Block write error during relocation process */
8641 { PR_1_RELOC_WRITE_ERR,
8642 N_("Warning: could not write @b %b for %s: %m\n"),
8643 PROMPT_NONE, PR_PREEN_OK },
8644
8645 /* Error allocating inode bitmap */
8646 { PR_1_ALLOCATE_IBITMAP_ERROR,
8647 N_("@A @i @B (%N): %m\n"),
8648 PROMPT_NONE, PR_FATAL },
8649
8650 /* Error allocating block bitmap */
8651 { PR_1_ALLOCATE_BBITMAP_ERROR,
8652 N_("@A @b @B (%N): %m\n"),
8653 PROMPT_NONE, PR_FATAL },
8654
8655 /* Error allocating icount structure */
8656 { PR_1_ALLOCATE_ICOUNT,
8657 N_("@A icount link information: %m\n"),
8658 PROMPT_NONE, PR_FATAL },
8659
8660 /* Error allocating dbcount */
8661 { PR_1_ALLOCATE_DBCOUNT,
8662 N_("@A @d @b array: %m\n"),
8663 PROMPT_NONE, PR_FATAL },
8664
8665 /* Error while scanning inodes */
8666 { PR_1_ISCAN_ERROR,
8667 N_("Error while scanning @is (%i): %m\n"),
8668 PROMPT_NONE, PR_FATAL },
8669
8670 /* Error while iterating over blocks */
8671 { PR_1_BLOCK_ITERATE,
8672 N_("Error while iterating over @bs in @i %i: %m\n"),
8673 PROMPT_NONE, PR_FATAL },
8674
8675 /* Error while storing inode count information */
8676 { PR_1_ICOUNT_STORE,
8677 N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8678 PROMPT_NONE, PR_FATAL },
8679
8680 /* Error while storing directory block information */
8681 { PR_1_ADD_DBLOCK,
8682 N_("Error storing @d @b information "
8683 "(@i=%i, @b=%b, num=%N): %m\n"),
8684 PROMPT_NONE, PR_FATAL },
8685
8686 /* Error while reading inode (for clearing) */
8687 { PR_1_READ_INODE,
8688 N_("Error reading @i %i: %m\n"),
8689 PROMPT_NONE, PR_FATAL },
8690
8691 /* Suppress messages prompt */
8692 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8693
8694 /* Imagic flag set on an inode when filesystem doesn't support it */
8695 { PR_1_SET_IMAGIC,
8696 N_("@i %i has imagic flag set. "),
8697 PROMPT_CLEAR, 0 },
8698
8699 /* Immutable flag set on a device or socket inode */
8700 { PR_1_SET_IMMUTABLE,
8701 N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8702 "or append-only flag set. "),
8703 PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8704
8705 /* Compression flag set on an inode when filesystem doesn't support it */
8706 { PR_1_COMPR_SET,
8707 N_("@i %i has @cion flag set on @f without @cion support. "),
8708 PROMPT_CLEAR, 0 },
8709
8710 /* Non-zero size for device, fifo or socket inode */
8711 { PR_1_SET_NONZSIZE,
8712 N_("Special (@v/socket/fifo) @i %i has non-zero size. "),
8713 PROMPT_FIX, PR_PREEN_OK },
8714
8715 /* Filesystem revision is 0, but feature flags are set */
8716 { PR_1_FS_REV_LEVEL,
8717 N_("@f has feature flag(s) set, but is a revision 0 @f. "),
8718 PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8719
8720 /* Journal inode is not in use, but contains data */
8721 { PR_1_JOURNAL_INODE_NOT_CLEAR,
8722 N_("@j @i is not in use, but contains data. "),
8723 PROMPT_CLEAR, PR_PREEN_OK },
8724
8725 /* Journal has bad mode */
8726 { PR_1_JOURNAL_BAD_MODE,
8727 N_("@j is not regular file. "),
8728 PROMPT_FIX, PR_PREEN_OK },
8729
8730 /* Deal with inodes that were part of orphan linked list */
8731 { PR_1_LOW_DTIME,
8732 N_("@i %i was part of the @o @i list. "),
8733 PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8734
8735 /* Deal with inodes that were part of corrupted orphan linked
8736 list (latch question) */
8737 { PR_1_ORPHAN_LIST_REFUGEES,
8738 N_("@is that were part of a corrupted orphan linked list found. "),
8739 PROMPT_FIX, 0 },
8740
8741 /* Error allocating refcount structure */
8742 { PR_1_ALLOCATE_REFCOUNT,
8743 N_("@A refcount structure (%N): %m\n"),
8744 PROMPT_NONE, PR_FATAL },
8745
8746 /* Error reading extended attribute block */
8747 { PR_1_READ_EA_BLOCK,
8748 N_("Error reading @a @b %b for @i %i. "),
8749 PROMPT_CLEAR, 0 },
8750
8751 /* Invalid extended attribute block */
8752 { PR_1_BAD_EA_BLOCK,
8753 N_("@i %i has a bad @a @b %b. "),
8754 PROMPT_CLEAR, 0 },
8755
8756 /* Error reading Extended Attribute block while fixing refcount */
8757 { PR_1_EXTATTR_READ_ABORT,
8758 N_("Error reading @a @b %b (%m). "),
8759 PROMPT_ABORT, 0 },
8760
8761 /* Extended attribute reference count incorrect */
8762 { PR_1_EXTATTR_REFCOUNT,
8763 N_("@a @b %b has reference count %B, @s %N. "),
8764 PROMPT_FIX, 0 },
8765
8766 /* Error writing Extended Attribute block while fixing refcount */
8767 { PR_1_EXTATTR_WRITE,
8768 N_("Error writing @a @b %b (%m). "),
8769 PROMPT_ABORT, 0 },
8770
8771 /* Multiple EA blocks not supported */
8772 { PR_1_EA_MULTI_BLOCK,
8773 N_("@a @b %b has h_@bs > 1. "),
8774 PROMPT_CLEAR, 0},
8775
8776 /* Error allocating EA region allocation structure */
8777 { PR_1_EA_ALLOC_REGION,
8778 N_("@A @a @b %b. "),
8779 PROMPT_ABORT, 0},
8780
8781 /* Error EA allocation collision */
8782 { PR_1_EA_ALLOC_COLLISION,
8783 N_("@a @b %b is corrupt (allocation collision). "),
8784 PROMPT_CLEAR, 0},
8785
8786 /* Bad extended attribute name */
8787 { PR_1_EA_BAD_NAME,
8788 N_("@a @b %b is corrupt (@n name). "),
8789 PROMPT_CLEAR, 0},
8790
8791 /* Bad extended attribute value */
8792 { PR_1_EA_BAD_VALUE,
8793 N_("@a @b %b is corrupt (@n value). "),
8794 PROMPT_CLEAR, 0},
8795
8796 /* Inode too big (latch question) */
8797 { PR_1_INODE_TOOBIG,
8798 N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
8799
8800 /* Directory too big */
8801 { PR_1_TOOBIG_DIR,
8802 N_("@b #%B (%b) causes @d to be too big. "),
8803 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8804
8805 /* Regular file too big */
8806 { PR_1_TOOBIG_REG,
8807 N_("@b #%B (%b) causes file to be too big. "),
8808 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8809
8810 /* Symlink too big */
8811 { PR_1_TOOBIG_SYMLINK,
8812 N_("@b #%B (%b) causes symlink to be too big. "),
8813 PROMPT_CLEAR, PR_LATCH_TOOBIG },
8814
8815 /* INDEX_FL flag set on a non-HTREE filesystem */
8816 { PR_1_HTREE_SET,
8817 N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8818 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8819
8820 /* INDEX_FL flag set on a non-directory */
8821 { PR_1_HTREE_NODIR,
8822 N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8823 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8824
8825 /* Invalid root node in HTREE directory */
8826 { PR_1_HTREE_BADROOT,
8827 N_("@h %i has an @n root node.\n"),
8828 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8829
8830 /* Unsupported hash version in HTREE directory */
8831 { PR_1_HTREE_HASHV,
8832 N_("@h %i has an unsupported hash version (%N)\n"),
8833 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8834
8835 /* Incompatible flag in HTREE root node */
8836 { PR_1_HTREE_INCOMPAT,
8837 N_("@h %i uses an incompatible htree root node flag.\n"),
8838 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8839
8840 /* HTREE too deep */
8841 { PR_1_HTREE_DEPTH,
8842 N_("@h %i has a tree depth (%N) which is too big\n"),
8843 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8844
8845 /* Bad block has indirect block that conflicts with filesystem block */
8846 { PR_1_BB_FS_BLOCK,
8847 N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8848 "@f metadata. "),
8849 PROMPT_CLEAR, PR_LATCH_BBLOCK },
8850
8851 /* Resize inode failed */
8852 { PR_1_RESIZE_INODE_CREATE,
8853 N_("Resize @i (re)creation failed: %m."),
8854 PROMPT_ABORT, 0 },
8855
8856 /* invalid inode->i_extra_isize */
8857 { PR_1_EXTRA_ISIZE,
8858 N_("@i %i has a extra size (%IS) which is @n\n"),
8859 PROMPT_FIX, PR_PREEN_OK },
8860
8861 /* invalid ea entry->e_name_len */
8862 { PR_1_ATTR_NAME_LEN,
8863 N_("@a in @i %i has a namelen (%N) which is @n\n"),
8864 PROMPT_CLEAR, PR_PREEN_OK },
8865
8866 /* invalid ea entry->e_value_size */
8867 { PR_1_ATTR_VALUE_SIZE,
8868 N_("@a in @i %i has a value size (%N) which is @n\n"),
8869 PROMPT_CLEAR, PR_PREEN_OK },
8870
8871 /* invalid ea entry->e_value_offs */
8872 { PR_1_ATTR_VALUE_OFFSET,
8873 N_("@a in @i %i has a value offset (%N) which is @n\n"),
8874 PROMPT_CLEAR, PR_PREEN_OK },
8875
8876 /* invalid ea entry->e_value_block */
8877 { PR_1_ATTR_VALUE_BLOCK,
8878 N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8879 PROMPT_CLEAR, PR_PREEN_OK },
8880
8881 /* invalid ea entry->e_hash */
8882 { PR_1_ATTR_HASH,
8883 N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8884 PROMPT_CLEAR, PR_PREEN_OK },
8885
8886 /* Pass 1b errors */
8887
8888 /* Pass 1B: Rescan for duplicate/bad blocks */
8889 { PR_1B_PASS_HEADER,
8890 N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8891 "Pass 1B: Rescanning for @m @bs\n"),
8892 PROMPT_NONE, 0 },
8893
8894 /* Duplicate/bad block(s) header */
8895 { PR_1B_DUP_BLOCK_HEADER,
8896 N_("@m @b(s) in @i %i:"),
8897 PROMPT_NONE, 0 },
8898
8899 /* Duplicate/bad block(s) in inode */
8900 { PR_1B_DUP_BLOCK,
8901 " %b",
8902 PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8903
8904 /* Duplicate/bad block(s) end */
8905 { PR_1B_DUP_BLOCK_END,
8906 "\n",
8907 PROMPT_NONE, PR_PREEN_NOHDR },
8908
8909 /* Error while scanning inodes */
8910 { PR_1B_ISCAN_ERROR,
8911 N_("Error while scanning inodes (%i): %m\n"),
8912 PROMPT_NONE, PR_FATAL },
8913
8914 /* Error allocating inode bitmap */
8915 { PR_1B_ALLOCATE_IBITMAP_ERROR,
8916 N_("@A @i @B (@i_dup_map): %m\n"),
8917 PROMPT_NONE, PR_FATAL },
8918
8919 /* Error while iterating over blocks */
8920 { PR_1B_BLOCK_ITERATE,
8921 N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8922 PROMPT_NONE, 0 },
8923
8924 /* Error adjusting EA refcount */
8925 { PR_1B_ADJ_EA_REFCOUNT,
8926 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8927 PROMPT_NONE, 0 },
8928
8929
8930 /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8931 { PR_1C_PASS_HEADER,
8932 N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8933 PROMPT_NONE, 0 },
8934
8935
8936 /* Pass 1D: Reconciling multiply-claimed blocks */
8937 { PR_1D_PASS_HEADER,
8938 N_("Pass 1D: Reconciling @m @bs\n"),
8939 PROMPT_NONE, 0 },
8940
8941 /* File has duplicate blocks */
8942 { PR_1D_DUP_FILE,
8943 N_("File %Q (@i #%i, mod time %IM)\n"
8944 " has %B @m @b(s), shared with %N file(s):\n"),
8945 PROMPT_NONE, 0 },
8946
8947 /* List of files sharing duplicate blocks */
8948 { PR_1D_DUP_FILE_LIST,
8949 N_("\t%Q (@i #%i, mod time %IM)\n"),
8950 PROMPT_NONE, 0 },
8951
8952 /* File sharing blocks with filesystem metadata */
8953 { PR_1D_SHARE_METADATA,
8954 N_("\t<@f metadata>\n"),
8955 PROMPT_NONE, 0 },
8956
8957 /* Report of how many duplicate/bad inodes */
8958 { PR_1D_NUM_DUP_INODES,
8959 N_("(There are %N @is containing @m @bs.)\n\n"),
8960 PROMPT_NONE, 0 },
8961
8962 /* Duplicated blocks already reassigned or cloned. */
8963 { PR_1D_DUP_BLOCKS_DEALT,
8964 N_("@m @bs already reassigned or cloned.\n\n"),
8965 PROMPT_NONE, 0 },
8966
8967 /* Clone duplicate/bad blocks? */
8968 { PR_1D_CLONE_QUESTION,
8969 "", PROMPT_CLONE, PR_NO_OK },
8970
8971 /* Delete file? */
8972 { PR_1D_DELETE_QUESTION,
8973 "", PROMPT_DELETE, 0 },
8974
8975 /* Couldn't clone file (error) */
8976 { PR_1D_CLONE_ERROR,
8977 N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8978
8979 /* Pass 2 errors */
8980
8981 /* Pass 2: Checking directory structure */
8982 { PR_2_PASS_HEADER,
8983 N_("Pass 2: Checking @d structure\n"),
8984 PROMPT_NONE, 0 },
8985
8986 /* Bad inode number for '.' */
8987 { PR_2_BAD_INODE_DOT,
8988 N_("@n @i number for '.' in @d @i %i.\n"),
8989 PROMPT_FIX, 0 },
8990
8991 /* Directory entry has bad inode number */
8992 { PR_2_BAD_INO,
8993 N_("@E has @n @i #: %Di.\n"),
8994 PROMPT_CLEAR, 0 },
8995
8996 /* Directory entry has deleted or unused inode */
8997 { PR_2_UNUSED_INODE,
8998 N_("@E has @D/unused @i %Di. "),
8999 PROMPT_CLEAR, PR_PREEN_OK },
9000
9001 /* Directry entry is link to '.' */
9002 { PR_2_LINK_DOT,
9003 N_("@E @L to '.' "),
9004 PROMPT_CLEAR, 0 },
9005
9006 /* Directory entry points to inode now located in a bad block */
9007 { PR_2_BB_INODE,
9008 N_("@E points to @i (%Di) located in a bad @b.\n"),
9009 PROMPT_CLEAR, 0 },
9010
9011 /* Directory entry contains a link to a directory */
9012 { PR_2_LINK_DIR,
9013 N_("@E @L to @d %P (%Di).\n"),
9014 PROMPT_CLEAR, 0 },
9015
9016 /* Directory entry contains a link to the root directry */
9017 { PR_2_LINK_ROOT,
9018 N_("@E @L to the @r.\n"),
9019 PROMPT_CLEAR, 0 },
9020
9021 /* Directory entry has illegal characters in its name */
9022 { PR_2_BAD_NAME,
9023 N_("@E has illegal characters in its name.\n"),
9024 PROMPT_FIX, 0 },
9025
9026 /* Missing '.' in directory inode */
9027 { PR_2_MISSING_DOT,
9028 N_("Missing '.' in @d @i %i.\n"),
9029 PROMPT_FIX, 0 },
9030
9031 /* Missing '..' in directory inode */
9032 { PR_2_MISSING_DOT_DOT,
9033 N_("Missing '..' in @d @i %i.\n"),
9034 PROMPT_FIX, 0 },
9035
9036 /* First entry in directory inode doesn't contain '.' */
9037 { PR_2_1ST_NOT_DOT,
9038 N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9039 PROMPT_FIX, 0 },
9040
9041 /* Second entry in directory inode doesn't contain '..' */
9042 { PR_2_2ND_NOT_DOT_DOT,
9043 N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9044 PROMPT_FIX, 0 },
9045
9046 /* i_faddr should be zero */
9047 { PR_2_FADDR_ZERO,
9048 N_("i_faddr @F %IF, @s zero.\n"),
9049 PROMPT_CLEAR, 0 },
9050
9051 /* i_file_acl should be zero */
9052 { PR_2_FILE_ACL_ZERO,
9053 N_("i_file_acl @F %If, @s zero.\n"),
9054 PROMPT_CLEAR, 0 },
9055
9056 /* i_dir_acl should be zero */
9057 { PR_2_DIR_ACL_ZERO,
9058 N_("i_dir_acl @F %Id, @s zero.\n"),
9059 PROMPT_CLEAR, 0 },
9060
9061 /* i_frag should be zero */
9062 { PR_2_FRAG_ZERO,
9063 N_("i_frag @F %N, @s zero.\n"),
9064 PROMPT_CLEAR, 0 },
9065
9066 /* i_fsize should be zero */
9067 { PR_2_FSIZE_ZERO,
9068 N_("i_fsize @F %N, @s zero.\n"),
9069 PROMPT_CLEAR, 0 },
9070
9071 /* inode has bad mode */
9072 { PR_2_BAD_MODE,
9073 N_("@i %i (%Q) has @n mode (%Im).\n"),
9074 PROMPT_CLEAR, 0 },
9075
9076 /* directory corrupted */
9077 { PR_2_DIR_CORRUPTED,
9078 N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9079 PROMPT_SALVAGE, 0 },
9080
9081 /* filename too long */
9082 { PR_2_FILENAME_LONG,
9083 N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9084 PROMPT_TRUNCATE, 0 },
9085
9086 /* Directory inode has a missing block (hole) */
9087 { PR_2_DIRECTORY_HOLE,
9088 N_("@d @i %i has an unallocated @b #%B. "),
9089 PROMPT_ALLOCATE, 0 },
9090
9091 /* '.' is not NULL terminated */
9092 { PR_2_DOT_NULL_TERM,
9093 N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9094 PROMPT_FIX, 0 },
9095
9096 /* '..' is not NULL terminated */
9097 { PR_2_DOT_DOT_NULL_TERM,
9098 N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9099 PROMPT_FIX, 0 },
9100
9101 /* Illegal character device inode */
9102 { PR_2_BAD_CHAR_DEV,
9103 N_("@i %i (%Q) is an @I character @v.\n"),
9104 PROMPT_CLEAR, 0 },
9105
9106 /* Illegal block device inode */
9107 { PR_2_BAD_BLOCK_DEV,
9108 N_("@i %i (%Q) is an @I @b @v.\n"),
9109 PROMPT_CLEAR, 0 },
9110
9111 /* Duplicate '.' entry */
9112 { PR_2_DUP_DOT,
9113 N_("@E is duplicate '.' @e.\n"),
9114 PROMPT_FIX, 0 },
9115
9116 /* Duplicate '..' entry */
9117 { PR_2_DUP_DOT_DOT,
9118 N_("@E is duplicate '..' @e.\n"),
9119 PROMPT_FIX, 0 },
9120
9121 /* Internal error: couldn't find dir_info */
9122 { PR_2_NO_DIRINFO,
9123 N_("Internal error: cannot find dir_info for %i.\n"),
9124 PROMPT_NONE, PR_FATAL },
9125
9126 /* Final rec_len is wrong */
9127 { PR_2_FINAL_RECLEN,
9128 N_("@E has rec_len of %Dr, @s %N.\n"),
9129 PROMPT_FIX, 0 },
9130
9131 /* Error allocating icount structure */
9132 { PR_2_ALLOCATE_ICOUNT,
9133 N_("@A icount structure: %m\n"),
9134 PROMPT_NONE, PR_FATAL },
9135
9136 /* Error iterating over directory blocks */
9137 { PR_2_DBLIST_ITERATE,
9138 N_("Error iterating over @d @bs: %m\n"),
9139 PROMPT_NONE, PR_FATAL },
9140
9141 /* Error reading directory block */
9142 { PR_2_READ_DIRBLOCK,
9143 N_("Error reading @d @b %b (@i %i): %m\n"),
9144 PROMPT_CONTINUE, 0 },
9145
9146 /* Error writing directory block */
9147 { PR_2_WRITE_DIRBLOCK,
9148 N_("Error writing @d @b %b (@i %i): %m\n"),
9149 PROMPT_CONTINUE, 0 },
9150
9151 /* Error allocating new directory block */
9152 { PR_2_ALLOC_DIRBOCK,
9153 N_("@A new @d @b for @i %i (%s): %m\n"),
9154 PROMPT_NONE, 0 },
9155
9156 /* Error deallocating inode */
9157 { PR_2_DEALLOC_INODE,
9158 N_("Error deallocating @i %i: %m\n"),
9159 PROMPT_NONE, PR_FATAL },
9160
9161 /* Directory entry for '.' is big. Split? */
9162 { PR_2_SPLIT_DOT,
9163 N_("@d @e for '.' is big. "),
9164 PROMPT_SPLIT, PR_NO_OK },
9165
9166 /* Illegal FIFO inode */
9167 { PR_2_BAD_FIFO,
9168 N_("@i %i (%Q) is an @I FIFO.\n"),
9169 PROMPT_CLEAR, 0 },
9170
9171 /* Illegal socket inode */
9172 { PR_2_BAD_SOCKET,
9173 N_("@i %i (%Q) is an @I socket.\n"),
9174 PROMPT_CLEAR, 0 },
9175
9176 /* Directory filetype not set */
9177 { PR_2_SET_FILETYPE,
9178 N_("Setting filetype for @E to %N.\n"),
9179 PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9180
9181 /* Directory filetype incorrect */
9182 { PR_2_BAD_FILETYPE,
9183 N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9184 PROMPT_FIX, 0 },
9185
9186 /* Directory filetype set on filesystem */
9187 { PR_2_CLEAR_FILETYPE,
9188 N_("@E has filetype set.\n"),
9189 PROMPT_CLEAR, PR_PREEN_OK },
9190
9191 /* Directory filename is null */
9192 { PR_2_NULL_NAME,
9193 N_("@E has a @z name.\n"),
9194 PROMPT_CLEAR, 0 },
9195
9196 /* Invalid symlink */
9197 { PR_2_INVALID_SYMLINK,
9198 N_("Symlink %Q (@i #%i) is @n.\n"),
9199 PROMPT_CLEAR, 0 },
9200
9201 /* i_file_acl (extended attribute block) is bad */
9202 { PR_2_FILE_ACL_BAD,
9203 N_("@a @b @F @n (%If).\n"),
9204 PROMPT_CLEAR, 0 },
9205
9206 /* Filesystem contains large files, but has no such flag in sb */
9207 { PR_2_FEATURE_LARGE_FILES,
9208 N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9209 PROMPT_FIX, 0 },
9210
9211 /* Node in HTREE directory not referenced */
9212 { PR_2_HTREE_NOTREF,
9213 N_("@p @h %d: node (%B) not referenced\n"),
9214 PROMPT_NONE, 0 },
9215
9216 /* Node in HTREE directory referenced twice */
9217 { PR_2_HTREE_DUPREF,
9218 N_("@p @h %d: node (%B) referenced twice\n"),
9219 PROMPT_NONE, 0 },
9220
9221 /* Node in HTREE directory has bad min hash */
9222 { PR_2_HTREE_MIN_HASH,
9223 N_("@p @h %d: node (%B) has bad min hash\n"),
9224 PROMPT_NONE, 0 },
9225
9226 /* Node in HTREE directory has bad max hash */
9227 { PR_2_HTREE_MAX_HASH,
9228 N_("@p @h %d: node (%B) has bad max hash\n"),
9229 PROMPT_NONE, 0 },
9230
9231 /* Clear invalid HTREE directory */
9232 { PR_2_HTREE_CLEAR,
9233 N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 },
9234
9235 /* Bad block in htree interior node */
9236 { PR_2_HTREE_BADBLK,
9237 N_("@p @h %d (%q): bad @b number %b.\n"),
9238 PROMPT_CLEAR_HTREE, 0 },
9239
9240 /* Error adjusting EA refcount */
9241 { PR_2_ADJ_EA_REFCOUNT,
9242 N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9243 PROMPT_NONE, PR_FATAL },
9244
9245 /* Invalid HTREE root node */
9246 { PR_2_HTREE_BAD_ROOT,
9247 N_("@p @h %d: root node is @n\n"),
9248 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9249
9250 /* Invalid HTREE limit */
9251 { PR_2_HTREE_BAD_LIMIT,
9252 N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9253 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9254
9255 /* Invalid HTREE count */
9256 { PR_2_HTREE_BAD_COUNT,
9257 N_("@p @h %d: node (%B) has @n count (%N)\n"),
9258 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9259
9260 /* HTREE interior node has out-of-order hashes in table */
9261 { PR_2_HTREE_HASH_ORDER,
9262 N_("@p @h %d: node (%B) has an unordered hash table\n"),
9263 PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9264
9265 /* Node in HTREE directory has invalid depth */
9266 { PR_2_HTREE_BAD_DEPTH,
9267 N_("@p @h %d: node (%B) has @n depth\n"),
9268 PROMPT_NONE, 0 },
9269
9270 /* Duplicate directory entry found */
9271 { PR_2_DUPLICATE_DIRENT,
9272 N_("Duplicate @E found. "),
9273 PROMPT_CLEAR, 0 },
9274
9275 /* Non-unique filename found */
9276 { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9277 N_("@E has a non-unique filename.\nRename to %s"),
9278 PROMPT_NULL, 0 },
9279
9280 /* Duplicate directory entry found */
9281 { PR_2_REPORT_DUP_DIRENT,
9282 N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9283 PROMPT_NONE, 0 },
9284
9285 /* Pass 3 errors */
9286
9287 /* Pass 3: Checking directory connectivity */
9288 { PR_3_PASS_HEADER,
9289 N_("Pass 3: Checking @d connectivity\n"),
9290 PROMPT_NONE, 0 },
9291
9292 /* Root inode not allocated */
9293 { PR_3_NO_ROOT_INODE,
9294 N_("@r not allocated. "),
9295 PROMPT_ALLOCATE, 0 },
9296
9297 /* No room in lost+found */
9298 { PR_3_EXPAND_LF_DIR,
9299 N_("No room in @l @d. "),
9300 PROMPT_EXPAND, 0 },
9301
9302 /* Unconnected directory inode */
9303 { PR_3_UNCONNECTED_DIR,
9304 N_("Unconnected @d @i %i (%p)\n"),
9305 PROMPT_CONNECT, 0 },
9306
9307 /* /lost+found not found */
9308 { PR_3_NO_LF_DIR,
9309 N_("/@l not found. "),
9310 PROMPT_CREATE, PR_PREEN_OK },
9311
9312 /* .. entry is incorrect */
9313 { PR_3_BAD_DOT_DOT,
9314 N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9315 PROMPT_FIX, 0 },
9316
9317 /* Bad or non-existent /lost+found. Cannot reconnect */
9318 { PR_3_NO_LPF,
9319 N_("Bad or non-existent /@l. Cannot reconnect.\n"),
9320 PROMPT_NONE, 0 },
9321
9322 /* Could not expand /lost+found */
9323 { PR_3_CANT_EXPAND_LPF,
9324 N_("Could not expand /@l: %m\n"),
9325 PROMPT_NONE, 0 },
9326
9327 /* Could not reconnect inode */
9328 { PR_3_CANT_RECONNECT,
9329 N_("Could not reconnect %i: %m\n"),
9330 PROMPT_NONE, 0 },
9331
9332 /* Error while trying to find /lost+found */
9333 { PR_3_ERR_FIND_LPF,
9334 N_("Error while trying to find /@l: %m\n"),
9335 PROMPT_NONE, 0 },
9336
9337 /* Error in ext2fs_new_block while creating /lost+found */
9338 { PR_3_ERR_LPF_NEW_BLOCK,
9339 N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9340 PROMPT_NONE, 0 },
9341
9342 /* Error in ext2fs_new_inode while creating /lost+found */
9343 { PR_3_ERR_LPF_NEW_INODE,
9344 N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9345 PROMPT_NONE, 0 },
9346
9347 /* Error in ext2fs_new_dir_block while creating /lost+found */
9348 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9349 N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9350 PROMPT_NONE, 0 },
9351
9352 /* Error while writing directory block for /lost+found */
9353 { PR_3_ERR_LPF_WRITE_BLOCK,
9354 N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9355 PROMPT_NONE, 0 },
9356
9357 /* Error while adjusting inode count */
9358 { PR_3_ADJUST_INODE,
9359 N_("Error while adjusting @i count on @i %i\n"),
9360 PROMPT_NONE, 0 },
9361
9362 /* Couldn't fix parent directory -- error */
9363 { PR_3_FIX_PARENT_ERR,
9364 N_("Couldn't fix parent of @i %i: %m\n\n"),
9365 PROMPT_NONE, 0 },
9366
9367 /* Couldn't fix parent directory -- couldn't find it */
9368 { PR_3_FIX_PARENT_NOFIND,
9369 N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9370 PROMPT_NONE, 0 },
9371
9372 /* Error allocating inode bitmap */
9373 { PR_3_ALLOCATE_IBITMAP_ERROR,
9374 N_("@A @i @B (%N): %m\n"),
9375 PROMPT_NONE, PR_FATAL },
9376
9377 /* Error creating root directory */
9378 { PR_3_CREATE_ROOT_ERROR,
9379 N_("Error creating root @d (%s): %m\n"),
9380 PROMPT_NONE, PR_FATAL },
9381
9382 /* Error creating lost and found directory */
9383 { PR_3_CREATE_LPF_ERROR,
9384 N_("Error creating /@l @d (%s): %m\n"),
9385 PROMPT_NONE, PR_FATAL },
9386
9387 /* Root inode is not directory; aborting */
9388 { PR_3_ROOT_NOT_DIR_ABORT,
9389 N_("@r is not a @d; aborting.\n"),
9390 PROMPT_NONE, PR_FATAL },
9391
9392 /* Cannot proceed without a root inode. */
9393 { PR_3_NO_ROOT_INODE_ABORT,
Denys Vlasenko6331cf02009-11-13 09:08:27 +01009394 N_("can't proceed without a @r.\n"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +00009395 PROMPT_NONE, PR_FATAL },
9396
9397 /* Internal error: couldn't find dir_info */
9398 { PR_3_NO_DIRINFO,
9399 N_("Internal error: cannot find dir_info for %i.\n"),
9400 PROMPT_NONE, PR_FATAL },
9401
9402 /* Lost+found not a directory */
9403 { PR_3_LPF_NOTDIR,
9404 N_("/@l is not a @d (ino=%i)\n"),
9405 PROMPT_UNLINK, 0 },
9406
9407 /* Pass 3A Directory Optimization */
9408
9409 /* Pass 3A: Optimizing directories */
9410 { PR_3A_PASS_HEADER,
9411 N_("Pass 3A: Optimizing directories\n"),
9412 PROMPT_NONE, PR_PREEN_NOMSG },
9413
9414 /* Error iterating over directories */
9415 { PR_3A_OPTIMIZE_ITER,
9416 N_("Failed to create dirs_to_hash iterator: %m"),
9417 PROMPT_NONE, 0 },
9418
9419 /* Error rehash directory */
9420 { PR_3A_OPTIMIZE_DIR_ERR,
9421 N_("Failed to optimize directory %q (%d): %m"),
9422 PROMPT_NONE, 0 },
9423
9424 /* Rehashing dir header */
9425 { PR_3A_OPTIMIZE_DIR_HEADER,
9426 N_("Optimizing directories: "),
9427 PROMPT_NONE, PR_MSG_ONLY },
9428
9429 /* Rehashing directory %d */
9430 { PR_3A_OPTIMIZE_DIR,
9431 " %d",
9432 PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9433
9434 /* Rehashing dir end */
9435 { PR_3A_OPTIMIZE_DIR_END,
9436 "\n",
9437 PROMPT_NONE, PR_PREEN_NOHDR },
9438
9439 /* Pass 4 errors */
9440
9441 /* Pass 4: Checking reference counts */
9442 { PR_4_PASS_HEADER,
9443 N_("Pass 4: Checking reference counts\n"),
9444 PROMPT_NONE, 0 },
9445
9446 /* Unattached zero-length inode */
9447 { PR_4_ZERO_LEN_INODE,
9448 N_("@u @z @i %i. "),
9449 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9450
9451 /* Unattached inode */
9452 { PR_4_UNATTACHED_INODE,
9453 N_("@u @i %i\n"),
9454 PROMPT_CONNECT, 0 },
9455
9456 /* Inode ref count wrong */
9457 { PR_4_BAD_REF_COUNT,
9458 N_("@i %i ref count is %Il, @s %N. "),
9459 PROMPT_FIX, PR_PREEN_OK },
9460
9461 { PR_4_INCONSISTENT_COUNT,
9462 N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9463 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9464 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
9465 "They @s the same!\n"),
9466 PROMPT_NONE, 0 },
9467
9468 /* Pass 5 errors */
9469
9470 /* Pass 5: Checking group summary information */
9471 { PR_5_PASS_HEADER,
9472 N_("Pass 5: Checking @g summary information\n"),
9473 PROMPT_NONE, 0 },
9474
9475 /* Padding at end of inode bitmap is not set. */
9476 { PR_5_INODE_BMAP_PADDING,
9477 N_("Padding at end of @i @B is not set. "),
9478 PROMPT_FIX, PR_PREEN_OK },
9479
9480 /* Padding at end of block bitmap is not set. */
9481 { PR_5_BLOCK_BMAP_PADDING,
9482 N_("Padding at end of @b @B is not set. "),
9483 PROMPT_FIX, PR_PREEN_OK },
9484
9485 /* Block bitmap differences header */
9486 { PR_5_BLOCK_BITMAP_HEADER,
9487 N_("@b @B differences: "),
9488 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9489
9490 /* Block not used, but marked in bitmap */
9491 { PR_5_BLOCK_UNUSED,
9492 " -%b",
9493 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9494
9495 /* Block used, but not marked used in bitmap */
9496 { PR_5_BLOCK_USED,
9497 " +%b",
9498 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9499
9500 /* Block bitmap differences end */
9501 { PR_5_BLOCK_BITMAP_END,
9502 "\n",
9503 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9504
9505 /* Inode bitmap differences header */
9506 { PR_5_INODE_BITMAP_HEADER,
9507 N_("@i @B differences: "),
9508 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9509
9510 /* Inode not used, but marked in bitmap */
9511 { PR_5_INODE_UNUSED,
9512 " -%i",
9513 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9514
9515 /* Inode used, but not marked used in bitmap */
9516 { PR_5_INODE_USED,
9517 " +%i",
9518 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9519
9520 /* Inode bitmap differences end */
9521 { PR_5_INODE_BITMAP_END,
9522 "\n",
9523 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9524
9525 /* Free inodes count for group wrong */
9526 { PR_5_FREE_INODE_COUNT_GROUP,
9527 N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9528 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9529
9530 /* Directories count for group wrong */
9531 { PR_5_FREE_DIR_COUNT_GROUP,
9532 N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9533 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9534
9535 /* Free inodes count wrong */
9536 { PR_5_FREE_INODE_COUNT,
9537 N_("Free @is count wrong (%i, counted=%j).\n"),
9538 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9539
9540 /* Free blocks count for group wrong */
9541 { PR_5_FREE_BLOCK_COUNT_GROUP,
9542 N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9543 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9544
9545 /* Free blocks count wrong */
9546 { PR_5_FREE_BLOCK_COUNT,
9547 N_("Free @bs count wrong (%b, counted=%c).\n"),
9548 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9549
9550 /* Programming error: bitmap endpoints don't match */
9551 { PR_5_BMAP_ENDPOINTS,
9552 N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9553 "match calculated @B endpoints (%i, %j)\n"),
9554 PROMPT_NONE, PR_FATAL },
9555
9556 /* Internal error: fudging end of bitmap */
9557 { PR_5_FUDGE_BITMAP_ERROR,
9558 N_("Internal error: fudging end of bitmap (%N)\n"),
9559 PROMPT_NONE, PR_FATAL },
9560
9561 /* Error copying in replacement inode bitmap */
9562 { PR_5_COPY_IBITMAP_ERROR,
9563 N_("Error copying in replacement @i @B: %m\n"),
9564 PROMPT_NONE, PR_FATAL },
9565
9566 /* Error copying in replacement block bitmap */
9567 { PR_5_COPY_BBITMAP_ERROR,
9568 N_("Error copying in replacement @b @B: %m\n"),
9569 PROMPT_NONE, PR_FATAL },
9570
9571 /* Block range not used, but marked in bitmap */
9572 { PR_5_BLOCK_RANGE_UNUSED,
9573 " -(%b--%c)",
9574 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9575
9576 /* Block range used, but not marked used in bitmap */
9577 { PR_5_BLOCK_RANGE_USED,
9578 " +(%b--%c)",
9579 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9580
9581 /* Inode range not used, but marked in bitmap */
9582 { PR_5_INODE_RANGE_UNUSED,
9583 " -(%i--%j)",
9584 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9585
9586 /* Inode range used, but not marked used in bitmap */
9587 { PR_5_INODE_RANGE_USED,
9588 " +(%i--%j)",
9589 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9590
9591 { 0 }
9592};
9593
9594/*
9595 * This is the latch flags register. It allows several problems to be
9596 * "latched" together. This means that the user has to answer but one
9597 * question for the set of problems, and all of the associated
9598 * problems will be either fixed or not fixed.
9599 */
9600static struct latch_descr pr_latch_info[] = {
9601 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9602 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9603 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9604 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9605 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9606 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9607 { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9608 { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9609 { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9610 { -1, 0, 0 },
9611};
9612
9613static const struct e2fsck_problem *find_problem(problem_t code)
9614{
9615 int i;
9616
9617 for (i=0; problem_table[i].e2p_code; i++) {
9618 if (problem_table[i].e2p_code == code)
9619 return &problem_table[i];
9620 }
9621 return 0;
9622}
9623
9624static struct latch_descr *find_latch(int code)
9625{
9626 int i;
9627
9628 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9629 if (pr_latch_info[i].latch_code == code)
9630 return &pr_latch_info[i];
9631 }
9632 return 0;
9633}
9634
9635int end_problem_latch(e2fsck_t ctx, int mask)
9636{
9637 struct latch_descr *ldesc;
9638 struct problem_context pctx;
9639 int answer = -1;
9640
9641 ldesc = find_latch(mask);
9642 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9643 clear_problem_context(&pctx);
9644 answer = fix_problem(ctx, ldesc->end_message, &pctx);
9645 }
9646 ldesc->flags &= ~(PRL_VARIABLE);
9647 return answer;
9648}
9649
9650int set_latch_flags(int mask, int setflags, int clearflags)
9651{
9652 struct latch_descr *ldesc;
9653
9654 ldesc = find_latch(mask);
9655 if (!ldesc)
9656 return -1;
9657 ldesc->flags |= setflags;
9658 ldesc->flags &= ~clearflags;
9659 return 0;
9660}
9661
9662void clear_problem_context(struct problem_context *ctx)
9663{
9664 memset(ctx, 0, sizeof(struct problem_context));
9665 ctx->blkcount = -1;
9666 ctx->group = -1;
9667}
9668
9669int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9670{
9671 ext2_filsys fs = ctx->fs;
9672 const struct e2fsck_problem *ptr;
9673 struct latch_descr *ldesc = 0;
9674 const char *message;
9675 int def_yn, answer, ans;
9676 int print_answer = 0;
9677 int suppress = 0;
9678
9679 ptr = find_problem(code);
9680 if (!ptr) {
9681 printf(_("Unhandled error code (0x%x)!\n"), code);
9682 return 0;
9683 }
9684 def_yn = 1;
9685 if ((ptr->flags & PR_NO_DEFAULT) ||
9686 ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9687 (ctx->options & E2F_OPT_NO))
9688 def_yn= 0;
9689
9690 /*
9691 * Do special latch processing. This is where we ask the
9692 * latch question, if it exists
9693 */
9694 if (ptr->flags & PR_LATCH_MASK) {
9695 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9696 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9697 ans = fix_problem(ctx, ldesc->question, pctx);
9698 if (ans == 1)
9699 ldesc->flags |= PRL_YES;
9700 if (ans == 0)
9701 ldesc->flags |= PRL_NO;
9702 ldesc->flags |= PRL_LATCHED;
9703 }
9704 if (ldesc->flags & PRL_SUPPRESS)
9705 suppress++;
9706 }
9707 if ((ptr->flags & PR_PREEN_NOMSG) &&
9708 (ctx->options & E2F_OPT_PREEN))
9709 suppress++;
9710 if ((ptr->flags & PR_NO_NOMSG) &&
9711 (ctx->options & E2F_OPT_NO))
9712 suppress++;
9713 if (!suppress) {
9714 message = ptr->e2p_description;
9715 if ((ctx->options & E2F_OPT_PREEN) &&
9716 !(ptr->flags & PR_PREEN_NOHDR)) {
9717 printf("%s: ", ctx->device_name ?
9718 ctx->device_name : ctx->filesystem_name);
9719 }
9720 if (*message)
9721 print_e2fsck_message(ctx, _(message), pctx, 1);
9722 }
9723 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9724 preenhalt(ctx);
9725
9726 if (ptr->flags & PR_FATAL)
9727 bb_error_msg_and_die(0);
9728
9729 if (ptr->prompt == PROMPT_NONE) {
9730 if (ptr->flags & PR_NOCOLLATE)
9731 answer = -1;
9732 else
9733 answer = def_yn;
9734 } else {
9735 if (ctx->options & E2F_OPT_PREEN) {
9736 answer = def_yn;
9737 if (!(ptr->flags & PR_PREEN_NOMSG))
9738 print_answer = 1;
9739 } else if ((ptr->flags & PR_LATCH_MASK) &&
9740 (ldesc->flags & (PRL_YES | PRL_NO))) {
9741 if (!suppress)
9742 print_answer = 1;
9743 if (ldesc->flags & PRL_YES)
9744 answer = 1;
9745 else
9746 answer = 0;
9747 } else
9748 answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9749 if (!answer && !(ptr->flags & PR_NO_OK))
9750 ext2fs_unmark_valid(fs);
9751
9752 if (print_answer)
9753 printf("%s.\n", answer ?
9754 _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9755
9756 }
9757
9758 if ((ptr->prompt == PROMPT_ABORT) && answer)
9759 bb_error_msg_and_die(0);
9760
9761 if (ptr->flags & PR_AFTER_CODE)
9762 answer = fix_problem(ctx, ptr->second_code, pctx);
9763
9764 return answer;
9765}
9766
9767/*
9768 * linux/fs/recovery.c
9769 *
9770 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9771 */
9772
9773/*
9774 * Maintain information about the progress of the recovery job, so that
9775 * the different passes can carry information between them.
9776 */
9777struct recovery_info
9778{
9779 tid_t start_transaction;
9780 tid_t end_transaction;
9781
9782 int nr_replays;
9783 int nr_revokes;
9784 int nr_revoke_hits;
9785};
9786
9787enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9788static int do_one_pass(journal_t *journal,
9789 struct recovery_info *info, enum passtype pass);
9790static int scan_revoke_records(journal_t *, struct buffer_head *,
9791 tid_t, struct recovery_info *);
9792
9793/*
9794 * Read a block from the journal
9795 */
9796
9797static int jread(struct buffer_head **bhp, journal_t *journal,
9798 unsigned int offset)
9799{
9800 int err;
9801 unsigned long blocknr;
9802 struct buffer_head *bh;
9803
9804 *bhp = NULL;
9805
9806 err = journal_bmap(journal, offset, &blocknr);
9807
9808 if (err) {
9809 printf("JBD: bad block at offset %u\n", offset);
9810 return err;
9811 }
9812
9813 bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9814 if (!bh)
9815 return -ENOMEM;
9816
9817 if (!buffer_uptodate(bh)) {
9818 /* If this is a brand new buffer, start readahead.
9819 Otherwise, we assume we are already reading it. */
9820 if (!buffer_req(bh))
9821 do_readahead(journal, offset);
9822 wait_on_buffer(bh);
9823 }
9824
9825 if (!buffer_uptodate(bh)) {
9826 printf("JBD: Failed to read block at offset %u\n", offset);
9827 brelse(bh);
9828 return -EIO;
9829 }
9830
9831 *bhp = bh;
9832 return 0;
9833}
9834
9835
9836/*
9837 * Count the number of in-use tags in a journal descriptor block.
9838 */
9839
9840static int count_tags(struct buffer_head *bh, int size)
9841{
9842 char * tagp;
9843 journal_block_tag_t * tag;
9844 int nr = 0;
9845
9846 tagp = &bh->b_data[sizeof(journal_header_t)];
9847
9848 while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9849 tag = (journal_block_tag_t *) tagp;
9850
9851 nr++;
9852 tagp += sizeof(journal_block_tag_t);
9853 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9854 tagp += 16;
9855
9856 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9857 break;
9858 }
9859
9860 return nr;
9861}
9862
9863
9864/* Make sure we wrap around the log correctly! */
9865#define wrap(journal, var) \
9866do { \
9867 if (var >= (journal)->j_last) \
9868 var -= ((journal)->j_last - (journal)->j_first); \
9869} while (0)
9870
9871/**
9872 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9873 * @journal: the journal to recover
9874 *
9875 * The primary function for recovering the log contents when mounting a
9876 * journaled device.
9877 *
9878 * Recovery is done in three passes. In the first pass, we look for the
9879 * end of the log. In the second, we assemble the list of revoke
9880 * blocks. In the third and final pass, we replay any un-revoked blocks
9881 * in the log.
9882 */
9883int journal_recover(journal_t *journal)
9884{
9885 int err;
9886 journal_superblock_t * sb;
9887
9888 struct recovery_info info;
9889
9890 memset(&info, 0, sizeof(info));
9891 sb = journal->j_superblock;
9892
9893 /*
9894 * The journal superblock's s_start field (the current log head)
9895 * is always zero if, and only if, the journal was cleanly
9896 * unmounted.
9897 */
9898
9899 if (!sb->s_start) {
9900 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9901 return 0;
9902 }
9903
9904 err = do_one_pass(journal, &info, PASS_SCAN);
9905 if (!err)
9906 err = do_one_pass(journal, &info, PASS_REVOKE);
9907 if (!err)
9908 err = do_one_pass(journal, &info, PASS_REPLAY);
9909
9910 /* Restart the log at the next transaction ID, thus invalidating
9911 * any existing commit records in the log. */
9912 journal->j_transaction_sequence = ++info.end_transaction;
9913
9914 journal_clear_revoke(journal);
9915 sync_blockdev(journal->j_fs_dev);
9916 return err;
9917}
9918
9919static int do_one_pass(journal_t *journal,
9920 struct recovery_info *info, enum passtype pass)
9921{
9922 unsigned int first_commit_ID, next_commit_ID;
9923 unsigned long next_log_block;
9924 int err, success = 0;
9925 journal_superblock_t * sb;
9926 journal_header_t * tmp;
9927 struct buffer_head * bh;
9928 unsigned int sequence;
9929 int blocktype;
9930
9931 /* Precompute the maximum metadata descriptors in a descriptor block */
9932 int MAX_BLOCKS_PER_DESC;
9933 MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9934 / sizeof(journal_block_tag_t));
9935
9936 /*
9937 * First thing is to establish what we expect to find in the log
9938 * (in terms of transaction IDs), and where (in terms of log
9939 * block offsets): query the superblock.
9940 */
9941
9942 sb = journal->j_superblock;
9943 next_commit_ID = ntohl(sb->s_sequence);
9944 next_log_block = ntohl(sb->s_start);
9945
9946 first_commit_ID = next_commit_ID;
9947 if (pass == PASS_SCAN)
9948 info->start_transaction = first_commit_ID;
9949
9950 /*
9951 * Now we walk through the log, transaction by transaction,
9952 * making sure that each transaction has a commit block in the
9953 * expected place. Each complete transaction gets replayed back
9954 * into the main filesystem.
9955 */
9956
9957 while (1) {
9958 int flags;
9959 char * tagp;
9960 journal_block_tag_t * tag;
9961 struct buffer_head * obh;
9962 struct buffer_head * nbh;
9963
9964 /* If we already know where to stop the log traversal,
9965 * check right now that we haven't gone past the end of
9966 * the log. */
9967
9968 if (pass != PASS_SCAN)
9969 if (tid_geq(next_commit_ID, info->end_transaction))
9970 break;
9971
9972 /* Skip over each chunk of the transaction looking
9973 * either the next descriptor block or the final commit
9974 * record. */
9975
9976 err = jread(&bh, journal, next_log_block);
9977 if (err)
9978 goto failed;
9979
9980 next_log_block++;
9981 wrap(journal, next_log_block);
9982
9983 /* What kind of buffer is it?
9984 *
9985 * If it is a descriptor block, check that it has the
9986 * expected sequence number. Otherwise, we're all done
9987 * here. */
9988
9989 tmp = (journal_header_t *)bh->b_data;
9990
9991 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9992 brelse(bh);
9993 break;
9994 }
9995
9996 blocktype = ntohl(tmp->h_blocktype);
9997 sequence = ntohl(tmp->h_sequence);
9998
9999 if (sequence != next_commit_ID) {
10000 brelse(bh);
10001 break;
10002 }
10003
10004 /* OK, we have a valid descriptor block which matches
10005 * all of the sequence number checks. What are we going
10006 * to do with it? That depends on the pass... */
10007
Denis Vlasenkobb045062008-09-27 14:06:06 +000010008 switch (blocktype) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010009 case JFS_DESCRIPTOR_BLOCK:
10010 /* If it is a valid descriptor block, replay it
10011 * in pass REPLAY; otherwise, just skip over the
10012 * blocks it describes. */
10013 if (pass != PASS_REPLAY) {
10014 next_log_block +=
10015 count_tags(bh, journal->j_blocksize);
10016 wrap(journal, next_log_block);
10017 brelse(bh);
10018 continue;
10019 }
10020
10021 /* A descriptor block: we can now write all of
10022 * the data blocks. Yay, useful work is finally
10023 * getting done here! */
10024
10025 tagp = &bh->b_data[sizeof(journal_header_t)];
10026 while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10027 <= journal->j_blocksize) {
10028 unsigned long io_block;
10029
10030 tag = (journal_block_tag_t *) tagp;
10031 flags = ntohl(tag->t_flags);
10032
10033 io_block = next_log_block++;
10034 wrap(journal, next_log_block);
10035 err = jread(&obh, journal, io_block);
10036 if (err) {
10037 /* Recover what we can, but
10038 * report failure at the end. */
10039 success = err;
10040 printf("JBD: IO error %d recovering "
10041 "block %ld in log\n",
10042 err, io_block);
10043 } else {
10044 unsigned long blocknr;
10045
10046 blocknr = ntohl(tag->t_blocknr);
10047
10048 /* If the block has been
10049 * revoked, then we're all done
10050 * here. */
10051 if (journal_test_revoke
10052 (journal, blocknr,
10053 next_commit_ID)) {
10054 brelse(obh);
10055 ++info->nr_revoke_hits;
10056 goto skip_write;
10057 }
10058
10059 /* Find a buffer for the new
10060 * data being restored */
10061 nbh = getblk(journal->j_fs_dev,
10062 blocknr,
10063 journal->j_blocksize);
10064 if (nbh == NULL) {
10065 printf("JBD: Out of memory "
10066 "during recovery.\n");
10067 err = -ENOMEM;
10068 brelse(bh);
10069 brelse(obh);
10070 goto failed;
10071 }
10072
10073 lock_buffer(nbh);
10074 memcpy(nbh->b_data, obh->b_data,
10075 journal->j_blocksize);
10076 if (flags & JFS_FLAG_ESCAPE) {
10077 *((unsigned int *)bh->b_data) =
10078 htonl(JFS_MAGIC_NUMBER);
10079 }
10080
10081 mark_buffer_uptodate(nbh, 1);
10082 mark_buffer_dirty(nbh);
10083 ++info->nr_replays;
10084 /* ll_rw_block(WRITE, 1, &nbh); */
10085 unlock_buffer(nbh);
10086 brelse(obh);
10087 brelse(nbh);
10088 }
10089
10090 skip_write:
10091 tagp += sizeof(journal_block_tag_t);
10092 if (!(flags & JFS_FLAG_SAME_UUID))
10093 tagp += 16;
10094
10095 if (flags & JFS_FLAG_LAST_TAG)
10096 break;
10097 }
10098
10099 brelse(bh);
10100 continue;
10101
10102 case JFS_COMMIT_BLOCK:
10103 /* Found an expected commit block: not much to
10104 * do other than move on to the next sequence
10105 * number. */
10106 brelse(bh);
10107 next_commit_ID++;
10108 continue;
10109
10110 case JFS_REVOKE_BLOCK:
10111 /* If we aren't in the REVOKE pass, then we can
10112 * just skip over this block. */
10113 if (pass != PASS_REVOKE) {
10114 brelse(bh);
10115 continue;
10116 }
10117
10118 err = scan_revoke_records(journal, bh,
10119 next_commit_ID, info);
10120 brelse(bh);
10121 if (err)
10122 goto failed;
10123 continue;
10124
10125 default:
10126 goto done;
10127 }
10128 }
10129
10130 done:
10131 /*
10132 * We broke out of the log scan loop: either we came to the
10133 * known end of the log or we found an unexpected block in the
10134 * log. If the latter happened, then we know that the "current"
10135 * transaction marks the end of the valid log.
10136 */
10137
10138 if (pass == PASS_SCAN)
10139 info->end_transaction = next_commit_ID;
10140 else {
10141 /* It's really bad news if different passes end up at
10142 * different places (but possible due to IO errors). */
10143 if (info->end_transaction != next_commit_ID) {
10144 printf("JBD: recovery pass %d ended at "
10145 "transaction %u, expected %u\n",
10146 pass, next_commit_ID, info->end_transaction);
10147 if (!success)
10148 success = -EIO;
10149 }
10150 }
10151
10152 return success;
10153
10154 failed:
10155 return err;
10156}
10157
10158
10159/* Scan a revoke record, marking all blocks mentioned as revoked. */
10160
10161static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10162 tid_t sequence, struct recovery_info *info)
10163{
10164 journal_revoke_header_t *header;
10165 int offset, max;
10166
10167 header = (journal_revoke_header_t *) bh->b_data;
10168 offset = sizeof(journal_revoke_header_t);
10169 max = ntohl(header->r_count);
10170
10171 while (offset < max) {
10172 unsigned long blocknr;
10173 int err;
10174
10175 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10176 offset += 4;
10177 err = journal_set_revoke(journal, blocknr, sequence);
10178 if (err)
10179 return err;
10180 ++info->nr_revokes;
10181 }
10182 return 0;
10183}
10184
10185
10186/*
10187 * rehash.c --- rebuild hash tree directories
10188 *
10189 * This algorithm is designed for simplicity of implementation and to
10190 * pack the directory as much as possible. It however requires twice
10191 * as much memory as the size of the directory. The maximum size
10192 * directory supported using a 4k blocksize is roughly a gigabyte, and
10193 * so there may very well be problems with machines that don't have
10194 * virtual memory, and obscenely large directories.
10195 *
10196 * An alternate algorithm which is much more disk intensive could be
10197 * written, and probably will need to be written in the future. The
10198 * design goals of such an algorithm are: (a) use (roughly) constant
10199 * amounts of memory, no matter how large the directory, (b) the
10200 * directory must be safe at all times, even if e2fsck is interrupted
10201 * in the middle, (c) we must use minimal amounts of extra disk
10202 * blocks. This pretty much requires an incremental approach, where
10203 * we are reading from one part of the directory, and inserting into
10204 * the front half. So the algorithm will have to keep track of a
10205 * moving block boundary between the new tree and the old tree, and
10206 * files will need to be moved from the old directory and inserted
10207 * into the new tree. If the new directory requires space which isn't
10208 * yet available, blocks from the beginning part of the old directory
10209 * may need to be moved to the end of the directory to make room for
10210 * the new tree:
10211 *
10212 * --------------------------------------------------------
10213 * | new tree | | old tree |
10214 * --------------------------------------------------------
10215 * ^ ptr ^ptr
10216 * tail new head old
10217 *
10218 * This is going to be a pain in the tuckus to implement, and will
10219 * require a lot more disk accesses. So I'm going to skip it for now;
10220 * it's only really going to be an issue for really, really big
10221 * filesystems (when we reach the level of tens of millions of files
10222 * in a single directory). It will probably be easier to simply
10223 * require that e2fsck use VM first.
10224 */
10225
10226struct fill_dir_struct {
10227 char *buf;
10228 struct ext2_inode *inode;
10229 int err;
10230 e2fsck_t ctx;
10231 struct hash_entry *harray;
10232 int max_array, num_array;
10233 int dir_size;
10234 int compress;
10235 ino_t parent;
10236};
10237
10238struct hash_entry {
10239 ext2_dirhash_t hash;
10240 ext2_dirhash_t minor_hash;
10241 struct ext2_dir_entry *dir;
10242};
10243
10244struct out_dir {
10245 int num;
10246 int max;
10247 char *buf;
10248 ext2_dirhash_t *hashes;
10249};
10250
10251static int fill_dir_block(ext2_filsys fs,
10252 blk_t *block_nr,
10253 e2_blkcnt_t blockcnt,
10254 blk_t ref_block FSCK_ATTR((unused)),
10255 int ref_offset FSCK_ATTR((unused)),
10256 void *priv_data)
10257{
10258 struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
10259 struct hash_entry *new_array, *ent;
10260 struct ext2_dir_entry *dirent;
10261 char *dir;
10262 unsigned int offset, dir_offset;
10263
10264 if (blockcnt < 0)
10265 return 0;
10266
10267 offset = blockcnt * fs->blocksize;
10268 if (offset + fs->blocksize > fd->inode->i_size) {
10269 fd->err = EXT2_ET_DIR_CORRUPTED;
10270 return BLOCK_ABORT;
10271 }
10272 dir = (fd->buf+offset);
10273 if (HOLE_BLKADDR(*block_nr)) {
10274 memset(dir, 0, fs->blocksize);
10275 dirent = (struct ext2_dir_entry *) dir;
10276 dirent->rec_len = fs->blocksize;
10277 } else {
10278 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10279 if (fd->err)
10280 return BLOCK_ABORT;
10281 }
10282 /* While the directory block is "hot", index it. */
10283 dir_offset = 0;
10284 while (dir_offset < fs->blocksize) {
10285 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10286 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10287 (dirent->rec_len < 8) ||
10288 ((dirent->rec_len % 4) != 0) ||
10289 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10290 fd->err = EXT2_ET_DIR_CORRUPTED;
10291 return BLOCK_ABORT;
10292 }
10293 dir_offset += dirent->rec_len;
10294 if (dirent->inode == 0)
10295 continue;
10296 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10297 (dirent->name[0] == '.'))
10298 continue;
10299 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10300 (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10301 fd->parent = dirent->inode;
10302 continue;
10303 }
10304 if (fd->num_array >= fd->max_array) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010305 new_array = xrealloc(fd->harray,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010306 sizeof(struct hash_entry) * (fd->max_array+500));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010307 fd->harray = new_array;
10308 fd->max_array += 500;
10309 }
10310 ent = fd->harray + fd->num_array++;
10311 ent->dir = dirent;
10312 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10313 if (fd->compress)
10314 ent->hash = ent->minor_hash = 0;
10315 else {
10316 fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10317 dirent->name,
10318 dirent->name_len & 0xFF,
10319 fs->super->s_hash_seed,
10320 &ent->hash, &ent->minor_hash);
10321 if (fd->err)
10322 return BLOCK_ABORT;
10323 }
10324 }
10325
10326 return 0;
10327}
10328
10329/* Used for sorting the hash entry */
10330static int name_cmp(const void *a, const void *b)
10331{
10332 const struct hash_entry *he_a = (const struct hash_entry *) a;
10333 const struct hash_entry *he_b = (const struct hash_entry *) b;
10334 int ret;
10335 int min_len;
10336
10337 min_len = he_a->dir->name_len;
10338 if (min_len > he_b->dir->name_len)
10339 min_len = he_b->dir->name_len;
10340
10341 ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10342 if (ret == 0) {
10343 if (he_a->dir->name_len > he_b->dir->name_len)
10344 ret = 1;
10345 else if (he_a->dir->name_len < he_b->dir->name_len)
10346 ret = -1;
10347 else
10348 ret = he_b->dir->inode - he_a->dir->inode;
10349 }
10350 return ret;
10351}
10352
10353/* Used for sorting the hash entry */
10354static int hash_cmp(const void *a, const void *b)
10355{
10356 const struct hash_entry *he_a = (const struct hash_entry *) a;
10357 const struct hash_entry *he_b = (const struct hash_entry *) b;
10358 int ret;
10359
10360 if (he_a->hash > he_b->hash)
10361 ret = 1;
10362 else if (he_a->hash < he_b->hash)
10363 ret = -1;
10364 else {
10365 if (he_a->minor_hash > he_b->minor_hash)
10366 ret = 1;
10367 else if (he_a->minor_hash < he_b->minor_hash)
10368 ret = -1;
10369 else
10370 ret = name_cmp(a, b);
10371 }
10372 return ret;
10373}
10374
10375static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10376 int blocks)
10377{
10378 void *new_mem;
10379
10380 if (outdir->max) {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010381 new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010382 outdir->buf = new_mem;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010383 new_mem = xrealloc(outdir->hashes,
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010384 blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010385 outdir->hashes = new_mem;
10386 } else {
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010387 outdir->buf = xmalloc(blocks * fs->blocksize);
10388 outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010389 outdir->num = 0;
10390 }
10391 outdir->max = blocks;
10392 return 0;
10393}
10394
10395static void free_out_dir(struct out_dir *outdir)
10396{
10397 free(outdir->buf);
10398 free(outdir->hashes);
10399 outdir->max = 0;
10400 outdir->num =0;
10401}
10402
10403static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10404 char ** ret)
10405{
10406 errcode_t retval;
10407
10408 if (outdir->num >= outdir->max) {
10409 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10410 if (retval)
10411 return retval;
10412 }
10413 *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10414 memset(*ret, 0, fs->blocksize);
10415 return 0;
10416}
10417
10418/*
10419 * This function is used to make a unique filename. We do this by
10420 * appending ~0, and then incrementing the number. However, we cannot
10421 * expand the length of the filename beyond the padding available in
10422 * the directory entry.
10423 */
10424static void mutate_name(char *str, __u16 *len)
10425{
10426 int i;
10427 __u16 l = *len & 0xFF, h = *len & 0xff00;
10428
10429 /*
10430 * First check to see if it looks the name has been mutated
10431 * already
10432 */
10433 for (i = l-1; i > 0; i--) {
10434 if (!isdigit(str[i]))
10435 break;
10436 }
10437 if ((i == l-1) || (str[i] != '~')) {
10438 if (((l-1) & 3) < 2)
10439 l += 2;
10440 else
10441 l = (l+3) & ~3;
10442 str[l-2] = '~';
10443 str[l-1] = '0';
10444 *len = l | h;
10445 return;
10446 }
10447 for (i = l-1; i >= 0; i--) {
10448 if (isdigit(str[i])) {
10449 if (str[i] == '9')
10450 str[i] = '0';
10451 else {
10452 str[i]++;
10453 return;
10454 }
10455 continue;
10456 }
10457 if (i == 1) {
10458 if (str[0] == 'z')
10459 str[0] = 'A';
10460 else if (str[0] == 'Z') {
10461 str[0] = '~';
10462 str[1] = '0';
10463 } else
10464 str[0]++;
10465 } else if (i > 0) {
10466 str[i] = '1';
10467 str[i-1] = '~';
10468 } else {
10469 if (str[0] == '~')
10470 str[0] = 'a';
10471 else
10472 str[0]++;
10473 }
10474 break;
10475 }
10476}
10477
10478static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10479 ext2_ino_t ino,
10480 struct fill_dir_struct *fd)
10481{
10482 struct problem_context pctx;
10483 struct hash_entry *ent, *prev;
10484 int i, j;
10485 int fixed = 0;
10486 char new_name[256];
10487 __u16 new_len;
10488
10489 clear_problem_context(&pctx);
10490 pctx.ino = ino;
10491
10492 for (i=1; i < fd->num_array; i++) {
10493 ent = fd->harray + i;
10494 prev = ent - 1;
10495 if (!ent->dir->inode ||
10496 ((ent->dir->name_len & 0xFF) !=
10497 (prev->dir->name_len & 0xFF)) ||
10498 (strncmp(ent->dir->name, prev->dir->name,
10499 ent->dir->name_len & 0xFF)))
10500 continue;
10501 pctx.dirent = ent->dir;
10502 if ((ent->dir->inode == prev->dir->inode) &&
10503 fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10504 e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10505 ent->dir->inode = 0;
10506 fixed++;
10507 continue;
10508 }
10509 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10510 new_len = ent->dir->name_len;
10511 mutate_name(new_name, &new_len);
10512 for (j=0; j < fd->num_array; j++) {
10513 if ((i==j) ||
10514 ((ent->dir->name_len & 0xFF) !=
10515 (fd->harray[j].dir->name_len & 0xFF)) ||
10516 (strncmp(new_name, fd->harray[j].dir->name,
10517 new_len & 0xFF)))
10518 continue;
10519 mutate_name(new_name, &new_len);
10520
10521 j = -1;
10522 }
10523 new_name[new_len & 0xFF] = 0;
10524 pctx.str = new_name;
10525 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10526 memcpy(ent->dir->name, new_name, new_len & 0xFF);
10527 ent->dir->name_len = new_len;
10528 ext2fs_dirhash(fs->super->s_def_hash_version,
10529 ent->dir->name,
10530 ent->dir->name_len & 0xFF,
10531 fs->super->s_hash_seed,
10532 &ent->hash, &ent->minor_hash);
10533 fixed++;
10534 }
10535 }
10536 return fixed;
10537}
10538
10539
10540static errcode_t copy_dir_entries(ext2_filsys fs,
10541 struct fill_dir_struct *fd,
10542 struct out_dir *outdir)
10543{
10544 errcode_t retval;
10545 char *block_start;
10546 struct hash_entry *ent;
10547 struct ext2_dir_entry *dirent;
10548 int i, rec_len, left;
10549 ext2_dirhash_t prev_hash;
10550 int offset;
10551
10552 outdir->max = 0;
10553 retval = alloc_size_dir(fs, outdir,
10554 (fd->dir_size / fs->blocksize) + 2);
10555 if (retval)
10556 return retval;
10557 outdir->num = fd->compress ? 0 : 1;
10558 offset = 0;
10559 outdir->hashes[0] = 0;
10560 prev_hash = 1;
10561 if ((retval = get_next_block(fs, outdir, &block_start)))
10562 return retval;
10563 dirent = (struct ext2_dir_entry *) block_start;
10564 left = fs->blocksize;
10565 for (i=0; i < fd->num_array; i++) {
10566 ent = fd->harray + i;
10567 if (ent->dir->inode == 0)
10568 continue;
10569 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10570 if (rec_len > left) {
10571 if (left)
10572 dirent->rec_len += left;
10573 if ((retval = get_next_block(fs, outdir,
10574 &block_start)))
10575 return retval;
10576 offset = 0;
10577 }
10578 left = fs->blocksize - offset;
10579 dirent = (struct ext2_dir_entry *) (block_start + offset);
10580 if (offset == 0) {
10581 if (ent->hash == prev_hash)
10582 outdir->hashes[outdir->num-1] = ent->hash | 1;
10583 else
10584 outdir->hashes[outdir->num-1] = ent->hash;
10585 }
10586 dirent->inode = ent->dir->inode;
10587 dirent->name_len = ent->dir->name_len;
10588 dirent->rec_len = rec_len;
10589 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10590 offset += rec_len;
10591 left -= rec_len;
10592 if (left < 12) {
10593 dirent->rec_len += left;
10594 offset += left;
10595 left = 0;
10596 }
10597 prev_hash = ent->hash;
10598 }
10599 if (left)
10600 dirent->rec_len += left;
10601
10602 return 0;
10603}
10604
10605
10606static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10607 ext2_ino_t ino, ext2_ino_t parent)
10608{
10609 struct ext2_dir_entry *dir;
10610 struct ext2_dx_root_info *root;
10611 struct ext2_dx_countlimit *limits;
10612 int filetype = 0;
10613
10614 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10615 filetype = EXT2_FT_DIR << 8;
10616
10617 memset(buf, 0, fs->blocksize);
10618 dir = (struct ext2_dir_entry *) buf;
10619 dir->inode = ino;
10620 dir->name[0] = '.';
10621 dir->name_len = 1 | filetype;
10622 dir->rec_len = 12;
10623 dir = (struct ext2_dir_entry *) (buf + 12);
10624 dir->inode = parent;
10625 dir->name[0] = '.';
10626 dir->name[1] = '.';
10627 dir->name_len = 2 | filetype;
10628 dir->rec_len = fs->blocksize - 12;
10629
10630 root = (struct ext2_dx_root_info *) (buf+24);
10631 root->reserved_zero = 0;
10632 root->hash_version = fs->super->s_def_hash_version;
10633 root->info_length = 8;
10634 root->indirect_levels = 0;
10635 root->unused_flags = 0;
10636
10637 limits = (struct ext2_dx_countlimit *) (buf+32);
10638 limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10639 limits->count = 0;
10640
10641 return root;
10642}
10643
10644
10645static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10646{
10647 struct ext2_dir_entry *dir;
10648 struct ext2_dx_countlimit *limits;
10649
10650 memset(buf, 0, fs->blocksize);
10651 dir = (struct ext2_dir_entry *) buf;
10652 dir->inode = 0;
10653 dir->rec_len = fs->blocksize;
10654
10655 limits = (struct ext2_dx_countlimit *) (buf+8);
10656 limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10657 limits->count = 0;
10658
10659 return (struct ext2_dx_entry *) limits;
10660}
10661
10662/*
10663 * This function takes the leaf nodes which have been written in
10664 * outdir, and populates the root node and any necessary interior nodes.
10665 */
10666static errcode_t calculate_tree(ext2_filsys fs,
10667 struct out_dir *outdir,
10668 ext2_ino_t ino,
10669 ext2_ino_t parent)
10670{
10671 struct ext2_dx_root_info *root_info;
10672 struct ext2_dx_entry *root, *dx_ent = 0;
10673 struct ext2_dx_countlimit *root_limit, *limit;
10674 errcode_t retval;
10675 char * block_start;
10676 int i, c1, c2, nblks;
10677 int limit_offset, root_offset;
10678
10679 root_info = set_root_node(fs, outdir->buf, ino, parent);
10680 root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10681 root_info->info_length;
10682 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10683 c1 = root_limit->limit;
10684 nblks = outdir->num;
10685
10686 /* Write out the pointer blocks */
10687 if (nblks-1 <= c1) {
10688 /* Just write out the root block, and we're done */
10689 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10690 for (i=1; i < nblks; i++) {
10691 root->block = ext2fs_cpu_to_le32(i);
10692 if (i != 1)
10693 root->hash =
10694 ext2fs_cpu_to_le32(outdir->hashes[i]);
10695 root++;
10696 c1--;
10697 }
10698 } else {
10699 c2 = 0;
10700 limit = 0;
10701 root_info->indirect_levels = 1;
10702 for (i=1; i < nblks; i++) {
10703 if (c1 == 0)
10704 return ENOSPC;
10705 if (c2 == 0) {
10706 if (limit)
10707 limit->limit = limit->count =
10708 ext2fs_cpu_to_le16(limit->limit);
10709 root = (struct ext2_dx_entry *)
10710 (outdir->buf + root_offset);
10711 root->block = ext2fs_cpu_to_le32(outdir->num);
10712 if (i != 1)
10713 root->hash =
10714 ext2fs_cpu_to_le32(outdir->hashes[i]);
10715 if ((retval = get_next_block(fs, outdir,
10716 &block_start)))
10717 return retval;
10718 dx_ent = set_int_node(fs, block_start);
10719 limit = (struct ext2_dx_countlimit *) dx_ent;
10720 c2 = limit->limit;
10721 root_offset += sizeof(struct ext2_dx_entry);
10722 c1--;
10723 }
10724 dx_ent->block = ext2fs_cpu_to_le32(i);
10725 if (c2 != limit->limit)
10726 dx_ent->hash =
10727 ext2fs_cpu_to_le32(outdir->hashes[i]);
10728 dx_ent++;
10729 c2--;
10730 }
10731 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10732 limit->limit = ext2fs_cpu_to_le16(limit->limit);
10733 }
10734 root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10735 root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10736 root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10737
10738 return 0;
10739}
10740
10741struct write_dir_struct {
10742 struct out_dir *outdir;
10743 errcode_t err;
10744 e2fsck_t ctx;
10745 int cleared;
10746};
10747
10748/*
10749 * Helper function which writes out a directory block.
10750 */
10751static int write_dir_block(ext2_filsys fs,
10752 blk_t *block_nr,
10753 e2_blkcnt_t blockcnt,
10754 blk_t ref_block FSCK_ATTR((unused)),
10755 int ref_offset FSCK_ATTR((unused)),
10756 void *priv_data)
10757{
10758 struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10759 blk_t blk;
10760 char *dir;
10761
10762 if (*block_nr == 0)
10763 return 0;
10764 if (blockcnt >= wd->outdir->num) {
10765 e2fsck_read_bitmaps(wd->ctx);
10766 blk = *block_nr;
10767 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10768 ext2fs_block_alloc_stats(fs, blk, -1);
10769 *block_nr = 0;
10770 wd->cleared++;
10771 return BLOCK_CHANGED;
10772 }
10773 if (blockcnt < 0)
10774 return 0;
10775
10776 dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10777 wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10778 if (wd->err)
10779 return BLOCK_ABORT;
10780 return 0;
10781}
10782
10783static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10784 struct out_dir *outdir,
10785 ext2_ino_t ino, int compress)
10786{
10787 struct write_dir_struct wd;
10788 errcode_t retval;
10789 struct ext2_inode inode;
10790
10791 retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10792 if (retval)
10793 return retval;
10794
10795 wd.outdir = outdir;
10796 wd.err = 0;
10797 wd.ctx = ctx;
10798 wd.cleared = 0;
10799
10800 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10801 write_dir_block, &wd);
10802 if (retval)
10803 return retval;
10804 if (wd.err)
10805 return wd.err;
10806
10807 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10808 if (compress)
10809 inode.i_flags &= ~EXT2_INDEX_FL;
10810 else
10811 inode.i_flags |= EXT2_INDEX_FL;
10812 inode.i_size = outdir->num * fs->blocksize;
10813 inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10814 e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10815
10816 return 0;
10817}
10818
10819static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10820{
10821 ext2_filsys fs = ctx->fs;
10822 errcode_t retval;
10823 struct ext2_inode inode;
10824 char *dir_buf = 0;
10825 struct fill_dir_struct fd;
10826 struct out_dir outdir;
10827
10828 outdir.max = outdir.num = 0;
10829 outdir.buf = 0;
10830 outdir.hashes = 0;
10831 e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10832
10833 retval = ENOMEM;
10834 fd.harray = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010835 dir_buf = xmalloc(inode.i_size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010836
10837 fd.max_array = inode.i_size / 32;
10838 fd.num_array = 0;
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010010839 fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000010840
10841 fd.ctx = ctx;
10842 fd.buf = dir_buf;
10843 fd.inode = &inode;
10844 fd.err = 0;
10845 fd.dir_size = 0;
10846 fd.compress = 0;
10847 if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10848 (inode.i_size / fs->blocksize) < 2)
10849 fd.compress = 1;
10850 fd.parent = 0;
10851
10852 /* Read in the entire directory into memory */
10853 retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10854 fill_dir_block, &fd);
10855 if (fd.err) {
10856 retval = fd.err;
10857 goto errout;
10858 }
10859
10860 /* Sort the list */
10861resort:
10862 if (fd.compress)
10863 qsort(fd.harray+2, fd.num_array-2,
10864 sizeof(struct hash_entry), name_cmp);
10865 else
10866 qsort(fd.harray, fd.num_array,
10867 sizeof(struct hash_entry), hash_cmp);
10868
10869 /*
10870 * Look for duplicates
10871 */
10872 if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10873 goto resort;
10874
10875 if (ctx->options & E2F_OPT_NO) {
10876 retval = 0;
10877 goto errout;
10878 }
10879
10880 /*
10881 * Copy the directory entries. In a htree directory these
10882 * will become the leaf nodes.
10883 */
10884 retval = copy_dir_entries(fs, &fd, &outdir);
10885 if (retval)
10886 goto errout;
10887
10888 free(dir_buf); dir_buf = 0;
10889
10890 if (!fd.compress) {
10891 /* Calculate the interior nodes */
10892 retval = calculate_tree(fs, &outdir, ino, fd.parent);
10893 if (retval)
10894 goto errout;
10895 }
10896
10897 retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10898
10899errout:
10900 free(dir_buf);
10901 free(fd.harray);
10902
10903 free_out_dir(&outdir);
10904 return retval;
10905}
10906
10907void e2fsck_rehash_directories(e2fsck_t ctx)
10908{
10909 struct problem_context pctx;
10910 struct dir_info *dir;
10911 ext2_u32_iterate iter;
10912 ext2_ino_t ino;
10913 errcode_t retval;
10914 int i, cur, max, all_dirs, dir_index, first = 1;
10915
10916 all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10917
10918 if (!ctx->dirs_to_hash && !all_dirs)
10919 return;
10920
10921 e2fsck_get_lost_and_found(ctx, 0);
10922
10923 clear_problem_context(&pctx);
10924
10925 dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10926 cur = 0;
10927 if (all_dirs) {
10928 i = 0;
10929 max = e2fsck_get_num_dirinfo(ctx);
10930 } else {
10931 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10932 &iter);
10933 if (retval) {
10934 pctx.errcode = retval;
10935 fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10936 return;
10937 }
10938 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10939 }
10940 while (1) {
10941 if (all_dirs) {
10942 if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10943 break;
10944 ino = dir->ino;
10945 } else {
10946 if (!ext2fs_u32_list_iterate(iter, &ino))
10947 break;
10948 }
10949 if (ino == ctx->lost_and_found)
10950 continue;
10951 pctx.dir = ino;
10952 if (first) {
10953 fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10954 first = 0;
10955 }
10956 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10957 if (pctx.errcode) {
10958 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10959 fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10960 }
10961 if (ctx->progress && !ctx->progress_fd)
10962 e2fsck_simple_progress(ctx, "Rebuilding directory",
10963 100.0 * (float) (++cur) / (float) max, ino);
10964 }
10965 end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10966 if (!all_dirs)
10967 ext2fs_u32_list_iterate_end(iter);
10968
10969 ext2fs_u32_list_free(ctx->dirs_to_hash);
10970 ctx->dirs_to_hash = 0;
10971}
10972
10973/*
10974 * linux/fs/revoke.c
10975 *
10976 * Journal revoke routines for the generic filesystem journaling code;
10977 * part of the ext2fs journaling system.
10978 *
10979 * Revoke is the mechanism used to prevent old log records for deleted
10980 * metadata from being replayed on top of newer data using the same
10981 * blocks. The revoke mechanism is used in two separate places:
10982 *
10983 * + Commit: during commit we write the entire list of the current
10984 * transaction's revoked blocks to the journal
10985 *
10986 * + Recovery: during recovery we record the transaction ID of all
10987 * revoked blocks. If there are multiple revoke records in the log
10988 * for a single block, only the last one counts, and if there is a log
10989 * entry for a block beyond the last revoke, then that log entry still
10990 * gets replayed.
10991 *
10992 * We can get interactions between revokes and new log data within a
10993 * single transaction:
10994 *
10995 * Block is revoked and then journaled:
10996 * The desired end result is the journaling of the new block, so we
10997 * cancel the revoke before the transaction commits.
10998 *
10999 * Block is journaled and then revoked:
11000 * The revoke must take precedence over the write of the block, so we
11001 * need either to cancel the journal entry or to write the revoke
11002 * later in the log than the log block. In this case, we choose the
11003 * latter: journaling a block cancels any revoke record for that block
11004 * in the current transaction, so any revoke for that block in the
11005 * transaction must have happened after the block was journaled and so
11006 * the revoke must take precedence.
11007 *
11008 * Block is revoked and then written as data:
11009 * The data write is allowed to succeed, but the revoke is _not_
11010 * cancelled. We still need to prevent old log records from
11011 * overwriting the new data. We don't even need to clear the revoke
11012 * bit here.
11013 *
11014 * Revoke information on buffers is a tri-state value:
11015 *
11016 * RevokeValid clear: no cached revoke status, need to look it up
11017 * RevokeValid set, Revoked clear:
11018 * buffer has not been revoked, and cancel_revoke
11019 * need do nothing.
11020 * RevokeValid set, Revoked set:
11021 * buffer has been revoked.
11022 */
11023
11024static kmem_cache_t *revoke_record_cache;
11025static kmem_cache_t *revoke_table_cache;
11026
11027/* Each revoke record represents one single revoked block. During
11028 journal replay, this involves recording the transaction ID of the
11029 last transaction to revoke this block. */
11030
11031struct jbd_revoke_record_s
11032{
11033 struct list_head hash;
11034 tid_t sequence; /* Used for recovery only */
11035 unsigned long blocknr;
11036};
11037
11038
11039/* The revoke table is just a simple hash table of revoke records. */
11040struct jbd_revoke_table_s
11041{
11042 /* It is conceivable that we might want a larger hash table
11043 * for recovery. Must be a power of two. */
11044 int hash_size;
11045 int hash_shift;
11046 struct list_head *hash_table;
11047};
11048
11049
11050/* Utility functions to maintain the revoke table */
11051
11052/* Borrowed from buffer.c: this is a tried and tested block hash function */
11053static int hash(journal_t *journal, unsigned long block)
11054{
11055 struct jbd_revoke_table_s *table = journal->j_revoke;
11056 int hash_shift = table->hash_shift;
11057
11058 return ((block << (hash_shift - 6)) ^
11059 (block >> 13) ^
11060 (block << (hash_shift - 12))) & (table->hash_size - 1);
11061}
11062
11063static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11064 tid_t seq)
11065{
11066 struct list_head *hash_list;
11067 struct jbd_revoke_record_s *record;
11068
11069 record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11070 if (!record)
11071 goto oom;
11072
11073 record->sequence = seq;
11074 record->blocknr = blocknr;
11075 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11076 list_add(&record->hash, hash_list);
11077 return 0;
11078
11079oom:
11080 return -ENOMEM;
11081}
11082
11083/* Find a revoke record in the journal's hash table. */
11084
11085static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11086 unsigned long blocknr)
11087{
11088 struct list_head *hash_list;
11089 struct jbd_revoke_record_s *record;
11090
11091 hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11092
11093 record = (struct jbd_revoke_record_s *) hash_list->next;
11094 while (&(record->hash) != hash_list) {
11095 if (record->blocknr == blocknr)
11096 return record;
11097 record = (struct jbd_revoke_record_s *) record->hash.next;
11098 }
11099 return NULL;
11100}
11101
11102int journal_init_revoke_caches(void)
11103{
11104 revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11105 if (revoke_record_cache == 0)
11106 return -ENOMEM;
11107
11108 revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11109 if (revoke_table_cache == 0) {
11110 do_cache_destroy(revoke_record_cache);
11111 revoke_record_cache = NULL;
11112 return -ENOMEM;
11113 }
11114 return 0;
11115}
11116
11117void journal_destroy_revoke_caches(void)
11118{
11119 do_cache_destroy(revoke_record_cache);
11120 revoke_record_cache = 0;
11121 do_cache_destroy(revoke_table_cache);
11122 revoke_table_cache = 0;
11123}
11124
11125/* Initialise the revoke table for a given journal to a given size. */
11126
11127int journal_init_revoke(journal_t *journal, int hash_size)
11128{
11129 int shift, tmp;
11130
11131 journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11132 if (!journal->j_revoke)
11133 return -ENOMEM;
11134
11135 /* Check that the hash_size is a power of two */
11136 journal->j_revoke->hash_size = hash_size;
11137
11138 shift = 0;
11139 tmp = hash_size;
Denis Vlasenkobb045062008-09-27 14:06:06 +000011140 while ((tmp >>= 1UL) != 0UL)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011141 shift++;
11142 journal->j_revoke->hash_shift = shift;
11143
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010011144 journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011145
11146 for (tmp = 0; tmp < hash_size; tmp++)
11147 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11148
11149 return 0;
11150}
11151
11152/* Destoy a journal's revoke table. The table must already be empty! */
11153
11154void journal_destroy_revoke(journal_t *journal)
11155{
11156 struct jbd_revoke_table_s *table;
11157 struct list_head *hash_list;
11158 int i;
11159
11160 table = journal->j_revoke;
11161 if (!table)
11162 return;
11163
11164 for (i=0; i<table->hash_size; i++) {
11165 hash_list = &table->hash_table[i];
11166 }
11167
11168 free(table->hash_table);
11169 free(table);
11170 journal->j_revoke = NULL;
11171}
11172
11173/*
11174 * Revoke support for recovery.
11175 *
11176 * Recovery needs to be able to:
11177 *
11178 * record all revoke records, including the tid of the latest instance
11179 * of each revoke in the journal
11180 *
11181 * check whether a given block in a given transaction should be replayed
11182 * (ie. has not been revoked by a revoke record in that or a subsequent
11183 * transaction)
11184 *
11185 * empty the revoke table after recovery.
11186 */
11187
11188/*
11189 * First, setting revoke records. We create a new revoke record for
11190 * every block ever revoked in the log as we scan it for recovery, and
11191 * we update the existing records if we find multiple revokes for a
11192 * single block.
11193 */
11194
11195int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11196 tid_t sequence)
11197{
11198 struct jbd_revoke_record_s *record;
11199
11200 record = find_revoke_record(journal, blocknr);
11201 if (record) {
11202 /* If we have multiple occurences, only record the
11203 * latest sequence number in the hashed record */
11204 if (tid_gt(sequence, record->sequence))
11205 record->sequence = sequence;
11206 return 0;
11207 }
11208 return insert_revoke_hash(journal, blocknr, sequence);
11209}
11210
11211/*
11212 * Test revoke records. For a given block referenced in the log, has
11213 * that block been revoked? A revoke record with a given transaction
11214 * sequence number revokes all blocks in that transaction and earlier
11215 * ones, but later transactions still need replayed.
11216 */
11217
11218int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11219 tid_t sequence)
11220{
11221 struct jbd_revoke_record_s *record;
11222
11223 record = find_revoke_record(journal, blocknr);
11224 if (!record)
11225 return 0;
11226 if (tid_gt(sequence, record->sequence))
11227 return 0;
11228 return 1;
11229}
11230
11231/*
11232 * Finally, once recovery is over, we need to clear the revoke table so
11233 * that it can be reused by the running filesystem.
11234 */
11235
11236void journal_clear_revoke(journal_t *journal)
11237{
11238 int i;
11239 struct list_head *hash_list;
11240 struct jbd_revoke_record_s *record;
11241 struct jbd_revoke_table_s *revoke_var;
11242
11243 revoke_var = journal->j_revoke;
11244
11245 for (i = 0; i < revoke_var->hash_size; i++) {
11246 hash_list = &revoke_var->hash_table[i];
11247 while (!list_empty(hash_list)) {
11248 record = (struct jbd_revoke_record_s*) hash_list->next;
11249 list_del(&record->hash);
11250 free(record);
11251 }
11252 }
11253}
11254
11255/*
11256 * e2fsck.c - superblock checks
11257 */
11258
11259#define MIN_CHECK 1
11260#define MAX_CHECK 2
11261
11262static void check_super_value(e2fsck_t ctx, const char *descr,
11263 unsigned long value, int flags,
11264 unsigned long min_val, unsigned long max_val)
11265{
11266 struct problem_context pctx;
11267
11268 if (((flags & MIN_CHECK) && (value < min_val)) ||
11269 ((flags & MAX_CHECK) && (value > max_val))) {
11270 clear_problem_context(&pctx);
11271 pctx.num = value;
11272 pctx.str = descr;
11273 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11274 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11275 }
11276}
11277
11278/*
11279 * This routine may get stubbed out in special compilations of the
11280 * e2fsck code..
11281 */
11282#ifndef EXT2_SPECIAL_DEVICE_SIZE
11283static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11284{
11285 return (ext2fs_get_device_size(ctx->filesystem_name,
11286 EXT2_BLOCK_SIZE(ctx->fs->super),
11287 &ctx->num_blocks));
11288}
11289#endif
11290
11291/*
11292 * helper function to release an inode
11293 */
11294struct process_block_struct {
11295 e2fsck_t ctx;
11296 char *buf;
11297 struct problem_context *pctx;
11298 int truncating;
11299 int truncate_offset;
11300 e2_blkcnt_t truncate_block;
11301 int truncated_blocks;
11302 int abort;
11303 errcode_t errcode;
11304};
11305
11306static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11307 e2_blkcnt_t blockcnt,
11308 blk_t ref_blk FSCK_ATTR((unused)),
11309 int ref_offset FSCK_ATTR((unused)),
11310 void *priv_data)
11311{
11312 struct process_block_struct *pb;
11313 e2fsck_t ctx;
11314 struct problem_context *pctx;
11315 blk_t blk = *block_nr;
11316 int retval = 0;
11317
11318 pb = (struct process_block_struct *) priv_data;
11319 ctx = pb->ctx;
11320 pctx = pb->pctx;
11321
11322 pctx->blk = blk;
11323 pctx->blkcount = blockcnt;
11324
11325 if (HOLE_BLKADDR(blk))
11326 return 0;
11327
11328 if ((blk < fs->super->s_first_data_block) ||
11329 (blk >= fs->super->s_blocks_count)) {
11330 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11331 return_abort:
11332 pb->abort = 1;
11333 return BLOCK_ABORT;
11334 }
11335
11336 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11337 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11338 goto return_abort;
11339 }
11340
11341 /*
11342 * If we are deleting an orphan, then we leave the fields alone.
11343 * If we are truncating an orphan, then update the inode fields
11344 * and clean up any partial block data.
11345 */
11346 if (pb->truncating) {
11347 /*
11348 * We only remove indirect blocks if they are
11349 * completely empty.
11350 */
11351 if (blockcnt < 0) {
11352 int i, limit;
11353 blk_t *bp;
11354
11355 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11356 pb->buf);
11357 if (pb->errcode)
11358 goto return_abort;
11359
11360 limit = fs->blocksize >> 2;
11361 for (i = 0, bp = (blk_t *) pb->buf;
11362 i < limit; i++, bp++)
11363 if (*bp)
11364 return 0;
11365 }
11366 /*
11367 * We don't remove direct blocks until we've reached
11368 * the truncation block.
11369 */
11370 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11371 return 0;
11372 /*
11373 * If part of the last block needs truncating, we do
11374 * it here.
11375 */
11376 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11377 pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11378 pb->buf);
11379 if (pb->errcode)
11380 goto return_abort;
11381 memset(pb->buf + pb->truncate_offset, 0,
11382 fs->blocksize - pb->truncate_offset);
11383 pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11384 pb->buf);
11385 if (pb->errcode)
11386 goto return_abort;
11387 }
11388 pb->truncated_blocks++;
11389 *block_nr = 0;
11390 retval |= BLOCK_CHANGED;
11391 }
11392
11393 ext2fs_block_alloc_stats(fs, blk, -1);
11394 return retval;
11395}
11396
11397/*
11398 * This function releases an inode. Returns 1 if an inconsistency was
11399 * found. If the inode has a link count, then it is being truncated and
11400 * not deleted.
11401 */
11402static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11403 struct ext2_inode *inode, char *block_buf,
11404 struct problem_context *pctx)
11405{
11406 struct process_block_struct pb;
11407 ext2_filsys fs = ctx->fs;
11408 errcode_t retval;
11409 __u32 count;
11410
11411 if (!ext2fs_inode_has_valid_blocks(inode))
11412 return 0;
11413
11414 pb.buf = block_buf + 3 * ctx->fs->blocksize;
11415 pb.ctx = ctx;
11416 pb.abort = 0;
11417 pb.errcode = 0;
11418 pb.pctx = pctx;
11419 if (inode->i_links_count) {
11420 pb.truncating = 1;
11421 pb.truncate_block = (e2_blkcnt_t)
11422 ((((long long)inode->i_size_high << 32) +
11423 inode->i_size + fs->blocksize - 1) /
11424 fs->blocksize);
11425 pb.truncate_offset = inode->i_size % fs->blocksize;
11426 } else {
11427 pb.truncating = 0;
11428 pb.truncate_block = 0;
11429 pb.truncate_offset = 0;
11430 }
11431 pb.truncated_blocks = 0;
11432 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11433 block_buf, release_inode_block, &pb);
11434 if (retval) {
11435 bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11436 ino);
11437 return 1;
11438 }
11439 if (pb.abort)
11440 return 1;
11441
11442 /* Refresh the inode since ext2fs_block_iterate may have changed it */
11443 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11444
11445 if (pb.truncated_blocks)
11446 inode->i_blocks -= pb.truncated_blocks *
11447 (fs->blocksize / 512);
11448
11449 if (inode->i_file_acl) {
11450 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11451 block_buf, -1, &count);
11452 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11453 retval = 0;
11454 count = 1;
11455 }
11456 if (retval) {
11457 bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11458 ino);
11459 return 1;
11460 }
11461 if (count == 0)
11462 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11463 inode->i_file_acl = 0;
11464 }
11465 return 0;
11466}
11467
11468/*
11469 * This function releases all of the orphan inodes. It returns 1 if
11470 * it hit some error, and 0 on success.
11471 */
11472static int release_orphan_inodes(e2fsck_t ctx)
11473{
11474 ext2_filsys fs = ctx->fs;
11475 ext2_ino_t ino, next_ino;
11476 struct ext2_inode inode;
11477 struct problem_context pctx;
11478 char *block_buf;
11479
11480 if ((ino = fs->super->s_last_orphan) == 0)
11481 return 0;
11482
11483 /*
11484 * Win or lose, we won't be using the head of the orphan inode
11485 * list again.
11486 */
11487 fs->super->s_last_orphan = 0;
11488 ext2fs_mark_super_dirty(fs);
11489
11490 /*
11491 * If the filesystem contains errors, don't run the orphan
11492 * list, since the orphan list can't be trusted; and we're
11493 * going to be running a full e2fsck run anyway...
11494 */
11495 if (fs->super->s_state & EXT2_ERROR_FS)
11496 return 0;
11497
11498 if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11499 (ino > fs->super->s_inodes_count)) {
11500 clear_problem_context(&pctx);
11501 pctx.ino = ino;
11502 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11503 return 1;
11504 }
11505
11506 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11507 "block iterate buffer");
11508 e2fsck_read_bitmaps(ctx);
11509
11510 while (ino) {
11511 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11512 clear_problem_context(&pctx);
11513 pctx.ino = ino;
11514 pctx.inode = &inode;
11515 pctx.str = inode.i_links_count ? _("Truncating") :
11516 _("Clearing");
11517
11518 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11519
11520 next_ino = inode.i_dtime;
11521 if (next_ino &&
11522 ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11523 (next_ino > fs->super->s_inodes_count))) {
11524 pctx.ino = next_ino;
11525 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11526 goto return_abort;
11527 }
11528
11529 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11530 goto return_abort;
11531
11532 if (!inode.i_links_count) {
11533 ext2fs_inode_alloc_stats2(fs, ino, -1,
11534 LINUX_S_ISDIR(inode.i_mode));
Denis Vlasenko04158e02009-02-02 10:48:06 +000011535 inode.i_dtime = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011536 } else {
11537 inode.i_dtime = 0;
11538 }
11539 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11540 ino = next_ino;
11541 }
11542 ext2fs_free_mem(&block_buf);
11543 return 0;
11544return_abort:
11545 ext2fs_free_mem(&block_buf);
11546 return 1;
11547}
11548
11549/*
11550 * Check the resize inode to make sure it is sane. We check both for
11551 * the case where on-line resizing is not enabled (in which case the
11552 * resize inode should be cleared) as well as the case where on-line
11553 * resizing is enabled.
11554 */
11555static void check_resize_inode(e2fsck_t ctx)
11556{
11557 ext2_filsys fs = ctx->fs;
11558 struct ext2_inode inode;
11559 struct problem_context pctx;
11560 int i, j, gdt_off, ind_off;
11561 blk_t blk, pblk, expect;
11562 __u32 *dind_buf = 0, *ind_buf;
11563 errcode_t retval;
11564
11565 clear_problem_context(&pctx);
11566
11567 /*
11568 * If the resize inode feature isn't set, then
11569 * s_reserved_gdt_blocks must be zero.
11570 */
11571 if (!(fs->super->s_feature_compat &
11572 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11573 if (fs->super->s_reserved_gdt_blocks) {
11574 pctx.num = fs->super->s_reserved_gdt_blocks;
11575 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11576 &pctx)) {
11577 fs->super->s_reserved_gdt_blocks = 0;
11578 ext2fs_mark_super_dirty(fs);
11579 }
11580 }
11581 }
11582
11583 /* Read the resize inode */
11584 pctx.ino = EXT2_RESIZE_INO;
11585 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11586 if (retval) {
11587 if (fs->super->s_feature_compat &
11588 EXT2_FEATURE_COMPAT_RESIZE_INODE)
11589 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11590 return;
11591 }
11592
11593 /*
11594 * If the resize inode feature isn't set, check to make sure
11595 * the resize inode is cleared; then we're done.
11596 */
11597 if (!(fs->super->s_feature_compat &
11598 EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11599 for (i=0; i < EXT2_N_BLOCKS; i++) {
11600 if (inode.i_block[i])
11601 break;
11602 }
11603 if ((i < EXT2_N_BLOCKS) &&
11604 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11605 memset(&inode, 0, sizeof(inode));
11606 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11607 "clear_resize");
11608 }
11609 return;
11610 }
11611
11612 /*
11613 * The resize inode feature is enabled; check to make sure the
11614 * only block in use is the double indirect block
11615 */
11616 blk = inode.i_block[EXT2_DIND_BLOCK];
11617 for (i=0; i < EXT2_N_BLOCKS; i++) {
11618 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11619 break;
11620 }
11621 if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11622 !(inode.i_mode & LINUX_S_IFREG) ||
11623 (blk < fs->super->s_first_data_block ||
11624 blk >= fs->super->s_blocks_count)) {
11625 resize_inode_invalid:
11626 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11627 memset(&inode, 0, sizeof(inode));
11628 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11629 "clear_resize");
11630 ctx->flags |= E2F_FLAG_RESIZE_INODE;
11631 }
11632 if (!(ctx->options & E2F_OPT_READONLY)) {
11633 fs->super->s_state &= ~EXT2_VALID_FS;
11634 ext2fs_mark_super_dirty(fs);
11635 }
11636 goto cleanup;
11637 }
11638 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11639 "resize dind buffer");
11640 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11641
11642 retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11643 if (retval)
11644 goto resize_inode_invalid;
11645
11646 gdt_off = fs->desc_blocks;
11647 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11648 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11649 i++, gdt_off++, pblk++) {
11650 gdt_off %= fs->blocksize/4;
11651 if (dind_buf[gdt_off] != pblk)
11652 goto resize_inode_invalid;
11653 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11654 if (retval)
11655 goto resize_inode_invalid;
11656 ind_off = 0;
11657 for (j = 1; j < fs->group_desc_count; j++) {
11658 if (!ext2fs_bg_has_super(fs, j))
11659 continue;
11660 expect = pblk + (j * fs->super->s_blocks_per_group);
11661 if (ind_buf[ind_off] != expect)
11662 goto resize_inode_invalid;
11663 ind_off++;
11664 }
11665 }
11666
11667cleanup:
11668 ext2fs_free_mem(&dind_buf);
11669
11670 }
11671
11672static void check_super_block(e2fsck_t ctx)
11673{
11674 ext2_filsys fs = ctx->fs;
11675 blk_t first_block, last_block;
11676 struct ext2_super_block *sb = fs->super;
11677 struct ext2_group_desc *gd;
11678 blk_t blocks_per_group = fs->super->s_blocks_per_group;
11679 blk_t bpg_max;
11680 int inodes_per_block;
11681 int ipg_max;
11682 int inode_size;
11683 dgrp_t i;
11684 blk_t should_be;
11685 struct problem_context pctx;
11686 __u32 free_blocks = 0, free_inodes = 0;
11687
11688 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11689 ipg_max = inodes_per_block * (blocks_per_group - 4);
11690 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11691 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11692 bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11693 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11694 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11695
11696 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11697 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11698 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11699 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11700 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11701 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11702
11703 clear_problem_context(&pctx);
11704
11705 /*
11706 * Verify the super block constants...
11707 */
11708 check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11709 MIN_CHECK, 1, 0);
11710 check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11711 MIN_CHECK, 1, 0);
11712 check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11713 MAX_CHECK, 0, sb->s_blocks_count);
11714 check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11715 MIN_CHECK | MAX_CHECK, 0,
11716 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11717 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11718 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11719 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11720 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11721 bpg_max);
11722 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11723 MIN_CHECK | MAX_CHECK, 8, bpg_max);
11724 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11725 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11726 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11727 MAX_CHECK, 0, sb->s_blocks_count / 2);
11728 check_super_value(ctx, "reserved_gdt_blocks",
11729 sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11730 fs->blocksize/4);
11731 inode_size = EXT2_INODE_SIZE(sb);
11732 check_super_value(ctx, "inode_size",
11733 inode_size, MIN_CHECK | MAX_CHECK,
11734 EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11735 if (inode_size & (inode_size - 1)) {
11736 pctx.num = inode_size;
11737 pctx.str = "inode_size";
11738 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11739 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11740 return;
11741 }
11742
11743 if (!ctx->num_blocks) {
11744 pctx.errcode = e2fsck_get_device_size(ctx);
11745 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11746 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11747 ctx->flags |= E2F_FLAG_ABORT;
11748 return;
11749 }
11750 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11751 (ctx->num_blocks < sb->s_blocks_count)) {
11752 pctx.blk = sb->s_blocks_count;
11753 pctx.blk2 = ctx->num_blocks;
11754 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11755 ctx->flags |= E2F_FLAG_ABORT;
11756 return;
11757 }
11758 }
11759 }
11760
11761 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11762 pctx.blk = EXT2_BLOCK_SIZE(sb);
11763 pctx.blk2 = EXT2_FRAG_SIZE(sb);
11764 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11765 ctx->flags |= E2F_FLAG_ABORT;
11766 return;
11767 }
11768
11769 should_be = sb->s_frags_per_group >>
11770 (sb->s_log_block_size - sb->s_log_frag_size);
11771 if (sb->s_blocks_per_group != should_be) {
11772 pctx.blk = sb->s_blocks_per_group;
11773 pctx.blk2 = should_be;
11774 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11775 ctx->flags |= E2F_FLAG_ABORT;
11776 return;
11777 }
11778
11779 should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11780 if (sb->s_first_data_block != should_be) {
11781 pctx.blk = sb->s_first_data_block;
11782 pctx.blk2 = should_be;
11783 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11784 ctx->flags |= E2F_FLAG_ABORT;
11785 return;
11786 }
11787
11788 should_be = sb->s_inodes_per_group * fs->group_desc_count;
11789 if (sb->s_inodes_count != should_be) {
11790 pctx.ino = sb->s_inodes_count;
11791 pctx.ino2 = should_be;
11792 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11793 sb->s_inodes_count = should_be;
11794 ext2fs_mark_super_dirty(fs);
11795 }
11796 }
11797
11798 /*
11799 * Verify the group descriptors....
11800 */
11801 first_block = sb->s_first_data_block;
11802 last_block = first_block + blocks_per_group;
11803
11804 for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11805 pctx.group = i;
11806
11807 if (i == fs->group_desc_count - 1)
11808 last_block = sb->s_blocks_count;
11809 if ((gd->bg_block_bitmap < first_block) ||
11810 (gd->bg_block_bitmap >= last_block)) {
11811 pctx.blk = gd->bg_block_bitmap;
11812 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11813 gd->bg_block_bitmap = 0;
11814 }
11815 if (gd->bg_block_bitmap == 0) {
11816 ctx->invalid_block_bitmap_flag[i]++;
11817 ctx->invalid_bitmaps++;
11818 }
11819 if ((gd->bg_inode_bitmap < first_block) ||
11820 (gd->bg_inode_bitmap >= last_block)) {
11821 pctx.blk = gd->bg_inode_bitmap;
11822 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11823 gd->bg_inode_bitmap = 0;
11824 }
11825 if (gd->bg_inode_bitmap == 0) {
11826 ctx->invalid_inode_bitmap_flag[i]++;
11827 ctx->invalid_bitmaps++;
11828 }
11829 if ((gd->bg_inode_table < first_block) ||
11830 ((gd->bg_inode_table +
11831 fs->inode_blocks_per_group - 1) >= last_block)) {
11832 pctx.blk = gd->bg_inode_table;
11833 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11834 gd->bg_inode_table = 0;
11835 }
11836 if (gd->bg_inode_table == 0) {
11837 ctx->invalid_inode_table_flag[i]++;
11838 ctx->invalid_bitmaps++;
11839 }
11840 free_blocks += gd->bg_free_blocks_count;
11841 free_inodes += gd->bg_free_inodes_count;
11842 first_block += sb->s_blocks_per_group;
11843 last_block += sb->s_blocks_per_group;
11844
11845 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11846 (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11847 (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11848 ext2fs_unmark_valid(fs);
11849
11850 }
11851
11852 /*
11853 * Update the global counts from the block group counts. This
11854 * is needed for an experimental patch which eliminates
11855 * locking the entire filesystem when allocating blocks or
11856 * inodes; if the filesystem is not unmounted cleanly, the
11857 * global counts may not be accurate.
11858 */
11859 if ((free_blocks != sb->s_free_blocks_count) ||
11860 (free_inodes != sb->s_free_inodes_count)) {
11861 if (ctx->options & E2F_OPT_READONLY)
11862 ext2fs_unmark_valid(fs);
11863 else {
11864 sb->s_free_blocks_count = free_blocks;
11865 sb->s_free_inodes_count = free_inodes;
11866 ext2fs_mark_super_dirty(fs);
11867 }
11868 }
11869
11870 if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11871 (sb->s_free_inodes_count > sb->s_inodes_count))
11872 ext2fs_unmark_valid(fs);
11873
11874
11875 /*
11876 * If we have invalid bitmaps, set the error state of the
11877 * filesystem.
11878 */
11879 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11880 sb->s_state &= ~EXT2_VALID_FS;
11881 ext2fs_mark_super_dirty(fs);
11882 }
11883
11884 clear_problem_context(&pctx);
11885
11886 /*
11887 * If the UUID field isn't assigned, assign it.
11888 */
11889 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11890 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11891 uuid_generate(sb->s_uuid);
11892 ext2fs_mark_super_dirty(fs);
11893 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11894 }
11895 }
11896
11897 /* FIXME - HURD support?
11898 * For the Hurd, check to see if the filetype option is set,
11899 * since it doesn't support it.
11900 */
11901 if (!(ctx->options & E2F_OPT_READONLY) &&
11902 fs->super->s_creator_os == EXT2_OS_HURD &&
11903 (fs->super->s_feature_incompat &
11904 EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11905 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11906 fs->super->s_feature_incompat &=
11907 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11908 ext2fs_mark_super_dirty(fs);
11909
11910 }
11911 }
11912
11913 /*
11914 * If we have any of the compatibility flags set, we need to have a
11915 * revision 1 filesystem. Most kernels will not check the flags on
11916 * a rev 0 filesystem and we may have corruption issues because of
11917 * the incompatible changes to the filesystem.
11918 */
11919 if (!(ctx->options & E2F_OPT_READONLY) &&
11920 fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11921 (fs->super->s_feature_compat ||
11922 fs->super->s_feature_ro_compat ||
11923 fs->super->s_feature_incompat) &&
11924 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11925 ext2fs_update_dynamic_rev(fs);
11926 ext2fs_mark_super_dirty(fs);
11927 }
11928
11929 check_resize_inode(ctx);
11930
11931 /*
11932 * Clean up any orphan inodes, if present.
11933 */
11934 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11935 fs->super->s_state &= ~EXT2_VALID_FS;
11936 ext2fs_mark_super_dirty(fs);
11937 }
11938
11939 /*
11940 * Move the ext3 journal file, if necessary.
11941 */
11942 e2fsck_move_ext3_journal(ctx);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000011943}
11944
11945/*
11946 * swapfs.c --- byte-swap an ext2 filesystem
11947 */
11948
11949#ifdef ENABLE_SWAPFS
11950
11951struct swap_block_struct {
11952 ext2_ino_t ino;
11953 int isdir;
11954 errcode_t errcode;
11955 char *dir_buf;
11956 struct ext2_inode *inode;
11957};
11958
11959/*
11960 * This is a helper function for block_iterate. We mark all of the
11961 * indirect and direct blocks as changed, so that block_iterate will
11962 * write them out.
11963 */
11964static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11965 void *priv_data)
11966{
11967 errcode_t retval;
11968
11969 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11970
11971 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11972 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11973 if (retval) {
11974 sb->errcode = retval;
11975 return BLOCK_ABORT;
11976 }
11977 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11978 if (retval) {
11979 sb->errcode = retval;
11980 return BLOCK_ABORT;
11981 }
11982 }
11983 if (blockcnt >= 0) {
11984 if (blockcnt < EXT2_NDIR_BLOCKS)
11985 return 0;
11986 return BLOCK_CHANGED;
11987 }
11988 if (blockcnt == BLOCK_COUNT_IND) {
11989 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11990 return 0;
11991 return BLOCK_CHANGED;
11992 }
11993 if (blockcnt == BLOCK_COUNT_DIND) {
11994 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11995 return 0;
11996 return BLOCK_CHANGED;
11997 }
11998 if (blockcnt == BLOCK_COUNT_TIND) {
11999 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12000 return 0;
12001 return BLOCK_CHANGED;
12002 }
12003 return BLOCK_CHANGED;
12004}
12005
12006/*
12007 * This function is responsible for byte-swapping all of the indirect,
12008 * block pointers. It is also responsible for byte-swapping directories.
12009 */
12010static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12011 struct ext2_inode *inode)
12012{
12013 errcode_t retval;
12014 struct swap_block_struct sb;
12015
12016 sb.ino = ino;
12017 sb.inode = inode;
12018 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12019 sb.errcode = 0;
12020 sb.isdir = 0;
12021 if (LINUX_S_ISDIR(inode->i_mode))
12022 sb.isdir = 1;
12023
12024 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12025 swap_block, &sb);
12026 if (retval) {
12027 bb_error_msg(_("while calling ext2fs_block_iterate"));
12028 ctx->flags |= E2F_FLAG_ABORT;
12029 return;
12030 }
12031 if (sb.errcode) {
12032 bb_error_msg(_("while calling iterator function"));
12033 ctx->flags |= E2F_FLAG_ABORT;
12034 return;
12035 }
12036}
12037
12038static void swap_inodes(e2fsck_t ctx)
12039{
12040 ext2_filsys fs = ctx->fs;
12041 dgrp_t group;
12042 unsigned int i;
12043 ext2_ino_t ino = 1;
12044 char *buf, *block_buf;
12045 errcode_t retval;
12046 struct ext2_inode * inode;
12047
12048 e2fsck_use_inode_shortcuts(ctx, 1);
12049
12050 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12051 &buf);
12052 if (retval) {
12053 bb_error_msg(_("while allocating inode buffer"));
12054 ctx->flags |= E2F_FLAG_ABORT;
12055 return;
12056 }
12057 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12058 "block interate buffer");
12059 for (group = 0; group < fs->group_desc_count; group++) {
12060 retval = io_channel_read_blk(fs->io,
12061 fs->group_desc[group].bg_inode_table,
12062 fs->inode_blocks_per_group, buf);
12063 if (retval) {
12064 bb_error_msg(_("while reading inode table (group %d)"),
12065 group);
12066 ctx->flags |= E2F_FLAG_ABORT;
12067 return;
12068 }
12069 inode = (struct ext2_inode *) buf;
12070 for (i=0; i < fs->super->s_inodes_per_group;
12071 i++, ino++, inode++) {
12072 ctx->stashed_ino = ino;
12073 ctx->stashed_inode = inode;
12074
12075 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12076 ext2fs_swap_inode(fs, inode, inode, 0);
12077
12078 /*
12079 * Skip deleted files.
12080 */
12081 if (inode->i_links_count == 0)
12082 continue;
12083
12084 if (LINUX_S_ISDIR(inode->i_mode) ||
12085 ((inode->i_block[EXT2_IND_BLOCK] ||
12086 inode->i_block[EXT2_DIND_BLOCK] ||
12087 inode->i_block[EXT2_TIND_BLOCK]) &&
12088 ext2fs_inode_has_valid_blocks(inode)))
12089 swap_inode_blocks(ctx, ino, block_buf, inode);
12090
12091 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12092 return;
12093
12094 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12095 ext2fs_swap_inode(fs, inode, inode, 1);
12096 }
12097 retval = io_channel_write_blk(fs->io,
12098 fs->group_desc[group].bg_inode_table,
12099 fs->inode_blocks_per_group, buf);
12100 if (retval) {
12101 bb_error_msg(_("while writing inode table (group %d)"),
12102 group);
12103 ctx->flags |= E2F_FLAG_ABORT;
12104 return;
12105 }
12106 }
12107 ext2fs_free_mem(&buf);
12108 ext2fs_free_mem(&block_buf);
12109 e2fsck_use_inode_shortcuts(ctx, 0);
12110 ext2fs_flush_icache(fs);
12111}
12112
12113#if defined(__powerpc__) && BB_BIG_ENDIAN
12114/*
12115 * On the PowerPC, the big-endian variant of the ext2 filesystem
12116 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12117 * of each word. Thus a bitmap with only bit 0 set would be, as
12118 * a string of bytes, 00 00 00 01 00 ...
12119 * To cope with this, we byte-reverse each word of a bitmap if
12120 * we have a big-endian filesystem, that is, if we are *not*
12121 * byte-swapping other word-sized numbers.
12122 */
12123#define EXT2_BIG_ENDIAN_BITMAPS
12124#endif
12125
12126#ifdef EXT2_BIG_ENDIAN_BITMAPS
12127static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12128{
12129 __u32 *p = (__u32 *) bmap->bitmap;
12130 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12131
12132 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12133 *p = ext2fs_swab32(*p);
12134}
12135#endif
12136
12137
12138#ifdef ENABLE_SWAPFS
12139static void swap_filesys(e2fsck_t ctx)
12140{
12141 ext2_filsys fs = ctx->fs;
12142 if (!(ctx->options & E2F_OPT_PREEN))
12143 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12144
12145 /* Byte swap */
12146
12147 if (fs->super->s_mnt_count) {
12148 fprintf(stderr, _("%s: the filesystem must be freshly "
12149 "checked using fsck\n"
12150 "and not mounted before trying to "
12151 "byte-swap it.\n"), ctx->device_name);
12152 ctx->flags |= E2F_FLAG_ABORT;
12153 return;
12154 }
12155 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12156 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12157 EXT2_FLAG_SWAP_BYTES_WRITE);
12158 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12159 } else {
12160 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12161 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12162 }
12163 swap_inodes(ctx);
12164 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12165 return;
12166 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12167 fs->flags |= EXT2_FLAG_SWAP_BYTES;
12168 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12169 EXT2_FLAG_SWAP_BYTES_WRITE);
12170
12171#ifdef EXT2_BIG_ENDIAN_BITMAPS
12172 e2fsck_read_bitmaps(ctx);
12173 ext2fs_swap_bitmap(fs->inode_map);
12174 ext2fs_swap_bitmap(fs->block_map);
12175 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12176#endif
12177 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12178 ext2fs_flush(fs);
12179 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12180}
12181#endif /* ENABLE_SWAPFS */
12182
12183#endif
12184
12185/*
12186 * util.c --- miscellaneous utilities
12187 */
12188
12189
12190void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12191 const char *description)
12192{
12193 void *ret;
12194 char buf[256];
12195
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012196 ret = xzalloc(size);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012197 return ret;
12198}
12199
12200static char *string_copy(const char *str, int len)
12201{
12202 char *ret;
12203
12204 if (!str)
12205 return NULL;
12206 if (!len)
12207 len = strlen(str);
Denys Vlasenkoef3817c2010-01-08 09:07:25 +010012208 ret = xmalloc(len+1);
12209 strncpy(ret, str, len);
12210 ret[len] = 0;
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012211 return ret;
12212}
12213
12214#ifndef HAVE_CONIO_H
12215static int read_a_char(void)
12216{
12217 char c;
12218 int r;
12219 int fail = 0;
12220
Denis Vlasenkobb045062008-09-27 14:06:06 +000012221 while (1) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012222 if (e2fsck_global_ctx &&
12223 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12224 return 3;
12225 }
12226 r = read(0, &c, 1);
12227 if (r == 1)
12228 return c;
12229 if (fail++ > 100)
12230 break;
12231 }
12232 return EOF;
12233}
12234#endif
12235
12236static int ask_yn(const char * string, int def)
12237{
12238 int c;
12239 const char *defstr;
12240 static const char short_yes[] = "yY";
12241 static const char short_no[] = "nN";
12242
12243#ifdef HAVE_TERMIOS_H
12244 struct termios termios, tmp;
12245
12246 tcgetattr (0, &termios);
12247 tmp = termios;
12248 tmp.c_lflag &= ~(ICANON | ECHO);
12249 tmp.c_cc[VMIN] = 1;
12250 tmp.c_cc[VTIME] = 0;
Denis Vlasenko202ac502008-11-05 13:20:58 +000012251 tcsetattr_stdin_TCSANOW(&tmp);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012252#endif
12253
12254 if (def == 1)
12255 defstr = "<y>";
12256 else if (def == 0)
12257 defstr = "<n>";
12258 else
12259 defstr = " (y/n)";
12260 printf("%s%s? ", string, defstr);
12261 while (1) {
12262 fflush (stdout);
12263 if ((c = read_a_char()) == EOF)
12264 break;
12265 if (c == 3) {
12266#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012267 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012268#endif
12269 if (e2fsck_global_ctx &&
12270 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12271 puts("\n");
12272 longjmp(e2fsck_global_ctx->abort_loc, 1);
12273 }
12274 puts(_("cancelled!\n"));
12275 return 0;
12276 }
12277 if (strchr(short_yes, (char) c)) {
12278 def = 1;
12279 break;
12280 }
12281 else if (strchr(short_no, (char) c)) {
12282 def = 0;
12283 break;
12284 }
12285 else if ((c == ' ' || c == '\n') && (def != -1))
12286 break;
12287 }
12288 if (def)
12289 puts("yes\n");
12290 else
12291 puts ("no\n");
12292#ifdef HAVE_TERMIOS_H
Denis Vlasenko202ac502008-11-05 13:20:58 +000012293 tcsetattr_stdin_TCSANOW(&termios);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012294#endif
12295 return def;
12296}
12297
12298int ask (e2fsck_t ctx, const char * string, int def)
12299{
12300 if (ctx->options & E2F_OPT_NO) {
12301 printf(_("%s? no\n\n"), string);
12302 return 0;
12303 }
12304 if (ctx->options & E2F_OPT_YES) {
12305 printf(_("%s? yes\n\n"), string);
12306 return 1;
12307 }
12308 if (ctx->options & E2F_OPT_PREEN) {
12309 printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12310 return def;
12311 }
12312 return ask_yn(string, def);
12313}
12314
12315void e2fsck_read_bitmaps(e2fsck_t ctx)
12316{
12317 ext2_filsys fs = ctx->fs;
12318 errcode_t retval;
12319
12320 if (ctx->invalid_bitmaps) {
12321 bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12322 ctx->device_name);
12323 bb_error_msg_and_die(0);
12324 }
12325
12326 ehandler_operation(_("reading inode and block bitmaps"));
12327 retval = ext2fs_read_bitmaps(fs);
12328 ehandler_operation(0);
12329 if (retval) {
12330 bb_error_msg(_("while retrying to read bitmaps for %s"),
12331 ctx->device_name);
12332 bb_error_msg_and_die(0);
12333 }
12334}
12335
12336static void e2fsck_write_bitmaps(e2fsck_t ctx)
12337{
12338 ext2_filsys fs = ctx->fs;
12339 errcode_t retval;
12340
12341 if (ext2fs_test_bb_dirty(fs)) {
12342 ehandler_operation(_("writing block bitmaps"));
12343 retval = ext2fs_write_block_bitmap(fs);
12344 ehandler_operation(0);
12345 if (retval) {
12346 bb_error_msg(_("while retrying to write block bitmaps for %s"),
12347 ctx->device_name);
12348 bb_error_msg_and_die(0);
12349 }
12350 }
12351
12352 if (ext2fs_test_ib_dirty(fs)) {
12353 ehandler_operation(_("writing inode bitmaps"));
12354 retval = ext2fs_write_inode_bitmap(fs);
12355 ehandler_operation(0);
12356 if (retval) {
12357 bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12358 ctx->device_name);
12359 bb_error_msg_and_die(0);
12360 }
12361 }
12362}
12363
12364void preenhalt(e2fsck_t ctx)
12365{
12366 ext2_filsys fs = ctx->fs;
12367
12368 if (!(ctx->options & E2F_OPT_PREEN))
12369 return;
12370 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12371 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12372 ctx->device_name);
12373 if (fs != NULL) {
12374 fs->super->s_state |= EXT2_ERROR_FS;
12375 ext2fs_mark_super_dirty(fs);
12376 ext2fs_close(fs);
12377 }
12378 exit(EXIT_UNCORRECTED);
12379}
12380
12381void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12382 struct ext2_inode * inode, const char *proc)
12383{
12384 int retval;
12385
12386 retval = ext2fs_read_inode(ctx->fs, ino, inode);
12387 if (retval) {
12388 bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12389 bb_error_msg_and_die(0);
12390 }
12391}
12392
12393extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12394 struct ext2_inode * inode, int bufsize,
12395 const char *proc)
12396{
12397 int retval;
12398
12399 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12400 if (retval) {
12401 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12402 bb_error_msg_and_die(0);
12403 }
12404}
12405
12406extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12407 struct ext2_inode * inode, const char *proc)
12408{
12409 int retval;
12410
12411 retval = ext2fs_write_inode(ctx->fs, ino, inode);
12412 if (retval) {
12413 bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12414 bb_error_msg_and_die(0);
12415 }
12416}
12417
12418blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12419 io_manager manager)
12420{
12421 struct ext2_super_block *sb;
12422 io_channel io = NULL;
12423 void *buf = NULL;
12424 int blocksize;
12425 blk_t superblock, ret_sb = 8193;
12426
12427 if (fs && fs->super) {
12428 ret_sb = (fs->super->s_blocks_per_group +
12429 fs->super->s_first_data_block);
12430 if (ctx) {
12431 ctx->superblock = ret_sb;
12432 ctx->blocksize = fs->blocksize;
12433 }
12434 return ret_sb;
12435 }
12436
12437 if (ctx) {
12438 if (ctx->blocksize) {
12439 ret_sb = ctx->blocksize * 8;
12440 if (ctx->blocksize == 1024)
12441 ret_sb++;
12442 ctx->superblock = ret_sb;
12443 return ret_sb;
12444 }
12445 ctx->superblock = ret_sb;
12446 ctx->blocksize = 1024;
12447 }
12448
12449 if (!name || !manager)
12450 goto cleanup;
12451
12452 if (manager->open(name, 0, &io) != 0)
12453 goto cleanup;
12454
12455 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12456 goto cleanup;
12457 sb = (struct ext2_super_block *) buf;
12458
12459 for (blocksize = EXT2_MIN_BLOCK_SIZE;
Denis Vlasenkob71c6682007-07-21 15:08:09 +000012460 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012461 superblock = blocksize*8;
12462 if (blocksize == 1024)
12463 superblock++;
12464 io_channel_set_blksize(io, blocksize);
12465 if (io_channel_read_blk(io, superblock,
12466 -SUPERBLOCK_SIZE, buf))
12467 continue;
12468#if BB_BIG_ENDIAN
12469 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12470 ext2fs_swap_super(sb);
12471#endif
12472 if (sb->s_magic == EXT2_SUPER_MAGIC) {
12473 ret_sb = superblock;
12474 if (ctx) {
12475 ctx->superblock = superblock;
12476 ctx->blocksize = blocksize;
12477 }
12478 break;
12479 }
12480 }
12481
12482cleanup:
12483 if (io)
12484 io_channel_close(io);
12485 ext2fs_free_mem(&buf);
12486 return ret_sb;
12487}
12488
12489
12490/*
12491 * This function runs through the e2fsck passes and calls them all,
12492 * returning restart, abort, or cancel as necessary...
12493 */
12494typedef void (*pass_t)(e2fsck_t ctx);
12495
12496static const pass_t e2fsck_passes[] = {
12497 e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12498 e2fsck_pass5, 0 };
12499
12500#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12501
12502static int e2fsck_run(e2fsck_t ctx)
12503{
12504 int i;
12505 pass_t e2fsck_pass;
12506
12507 if (setjmp(ctx->abort_loc)) {
12508 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12509 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12510 }
12511 ctx->flags |= E2F_FLAG_SETJMP_OK;
12512
12513 for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12514 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12515 break;
12516 e2fsck_pass(ctx);
12517 if (ctx->progress)
12518 (void) (ctx->progress)(ctx, 0, 0, 0);
12519 }
12520 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12521
12522 if (ctx->flags & E2F_FLAG_RUN_RETURN)
12523 return (ctx->flags & E2F_FLAG_RUN_RETURN);
12524 return 0;
12525}
12526
12527
12528/*
12529 * unix.c - The unix-specific code for e2fsck
12530 */
12531
12532
12533/* Command line options */
12534static int swapfs;
12535#ifdef ENABLE_SWAPFS
12536static int normalize_swapfs;
12537#endif
12538static int cflag; /* check disk */
12539static int show_version_only;
12540static int verbose;
12541
12542#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural)
12543
12544static void show_stats(e2fsck_t ctx)
12545{
12546 ext2_filsys fs = ctx->fs;
12547 int inodes, inodes_used, blocks, blocks_used;
12548 int dir_links;
12549 int num_files, num_links;
12550 int frag_percent;
12551
12552 dir_links = 2 * ctx->fs_directory_count - 1;
12553 num_files = ctx->fs_total_count - dir_links;
12554 num_links = ctx->fs_links_count - dir_links;
12555 inodes = fs->super->s_inodes_count;
12556 inodes_used = (fs->super->s_inodes_count -
12557 fs->super->s_free_inodes_count);
12558 blocks = fs->super->s_blocks_count;
12559 blocks_used = (fs->super->s_blocks_count -
12560 fs->super->s_free_blocks_count);
12561
12562 frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12563 frag_percent = (frag_percent + 5) / 10;
12564
12565 if (!verbose) {
12566 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12567 ctx->device_name, inodes_used, inodes,
12568 frag_percent / 10, frag_percent % 10,
12569 blocks_used, blocks);
12570 return;
12571 }
12572 printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12573 100 * inodes_used / inodes);
12574 printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12575 P_E2("", "s", ctx->fs_fragmented),
12576 frag_percent / 10, frag_percent % 10);
12577 printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12578 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12579 printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12580 (int) ((long long) 100 * blocks_used / blocks));
12581 printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12582 printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12583 printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12584 printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12585 printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12586 printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12587 printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12588 printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12589 printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12590 printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12591 printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12592}
12593
12594static void check_mount(e2fsck_t ctx)
12595{
12596 errcode_t retval;
12597 int cont;
12598
12599 retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12600 &ctx->mount_flags);
12601 if (retval) {
Denis Vlasenko54d10052008-12-24 03:11:43 +000012602 bb_error_msg(_("while determining whether %s is mounted"),
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012603 ctx->filesystem_name);
12604 return;
12605 }
12606
12607 /*
12608 * If the filesystem isn't mounted, or it's the root filesystem
12609 * and it's mounted read-only, then everything's fine.
12610 */
12611 if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12612 ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12613 (ctx->mount_flags & EXT2_MF_READONLY)))
12614 return;
12615
12616 if (ctx->options & E2F_OPT_READONLY) {
12617 printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name);
12618 return;
12619 }
12620
12621 printf(_("%s is mounted. "), ctx->filesystem_name);
12622 if (!ctx->interactive)
Denys Vlasenko6331cf02009-11-13 09:08:27 +010012623 bb_error_msg_and_die(_("can't continue, aborting"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012624 printf(_("\n\n\007\007\007\007WARNING!!! "
12625 "Running e2fsck on a mounted filesystem may cause\n"
12626 "SEVERE filesystem damage.\007\007\007\n\n"));
12627 cont = ask_yn(_("Do you really want to continue"), -1);
12628 if (!cont) {
12629 printf(_("check aborted.\n"));
Denis Vlasenko6398cf42007-04-11 17:04:29 +000012630 exit(0);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012631 }
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012632}
12633
12634static int is_on_batt(void)
12635{
12636 FILE *f;
12637 DIR *d;
12638 char tmp[80], tmp2[80], fname[80];
12639 unsigned int acflag;
12640 struct dirent* de;
12641
Denis Vlasenko5415c852008-07-21 23:05:26 +000012642 f = fopen_for_read("/proc/apm");
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012643 if (f) {
12644 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12645 acflag = 1;
12646 fclose(f);
12647 return (acflag != 1);
12648 }
12649 d = opendir("/proc/acpi/ac_adapter");
12650 if (d) {
12651 while ((de=readdir(d)) != NULL) {
12652 if (!strncmp(".", de->d_name, 1))
12653 continue;
12654 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12655 de->d_name);
Denis Vlasenko5415c852008-07-21 23:05:26 +000012656 f = fopen_for_read(fname);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012657 if (!f)
12658 continue;
12659 if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12660 tmp[0] = 0;
12661 fclose(f);
12662 if (strncmp(tmp, "off-line", 8) == 0) {
12663 closedir(d);
12664 return 1;
12665 }
12666 }
12667 closedir(d);
12668 }
12669 return 0;
12670}
12671
12672/*
12673 * This routine checks to see if a filesystem can be skipped; if so,
12674 * it will exit with EXIT_OK. Under some conditions it will print a
12675 * message explaining why a check is being forced.
12676 */
12677static void check_if_skip(e2fsck_t ctx)
12678{
12679 ext2_filsys fs = ctx->fs;
12680 const char *reason = NULL;
12681 unsigned int reason_arg = 0;
12682 long next_check;
12683 int batt = is_on_batt();
Denis Vlasenko04158e02009-02-02 10:48:06 +000012684 time_t now = time(NULL);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012685
12686 if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12687 return;
12688
12689 if ((fs->super->s_state & EXT2_ERROR_FS) ||
12690 !ext2fs_test_valid(fs))
12691 reason = _(" contains a file system with errors");
12692 else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12693 reason = _(" was not cleanly unmounted");
12694 else if ((fs->super->s_max_mnt_count > 0) &&
12695 (fs->super->s_mnt_count >=
12696 (unsigned) fs->super->s_max_mnt_count)) {
12697 reason = _(" has been mounted %u times without being checked");
12698 reason_arg = fs->super->s_mnt_count;
12699 if (batt && (fs->super->s_mnt_count <
12700 (unsigned) fs->super->s_max_mnt_count*2))
12701 reason = 0;
12702 } else if (fs->super->s_checkinterval &&
12703 ((now - fs->super->s_lastcheck) >=
12704 fs->super->s_checkinterval)) {
12705 reason = _(" has gone %u days without being checked");
12706 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12707 if (batt && ((now - fs->super->s_lastcheck) <
12708 fs->super->s_checkinterval*2))
12709 reason = 0;
12710 }
12711 if (reason) {
12712 fputs(ctx->device_name, stdout);
12713 printf(reason, reason_arg);
12714 fputs(_(", check forced.\n"), stdout);
12715 return;
12716 }
12717 printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12718 fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12719 fs->super->s_inodes_count,
12720 fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12721 fs->super->s_blocks_count);
12722 next_check = 100000;
12723 if (fs->super->s_max_mnt_count > 0) {
12724 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12725 if (next_check <= 0)
12726 next_check = 1;
12727 }
12728 if (fs->super->s_checkinterval &&
12729 ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12730 next_check = 1;
12731 if (next_check <= 5) {
12732 if (next_check == 1)
12733 fputs(_(" (check after next mount)"), stdout);
12734 else
12735 printf(_(" (check in %ld mounts)"), next_check);
12736 }
Denis Vlasenko4daad902007-09-27 10:20:47 +000012737 bb_putchar('\n');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012738 ext2fs_close(fs);
12739 ctx->fs = NULL;
12740 e2fsck_free_context(ctx);
12741 exit(EXIT_OK);
12742}
12743
12744/*
12745 * For completion notice
12746 */
12747struct percent_tbl {
12748 int max_pass;
12749 int table[32];
12750};
12751static const struct percent_tbl e2fsck_tbl = {
12752 5, { 0, 70, 90, 92, 95, 100 }
12753};
12754
12755static char bar[128], spaces[128];
12756
12757static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12758 int max)
12759{
12760 float percent;
12761
12762 if (pass <= 0)
12763 return 0.0;
12764 if (pass > tbl->max_pass || max == 0)
12765 return 100.0;
12766 percent = ((float) curr) / ((float) max);
12767 return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12768 + tbl->table[pass-1]);
12769}
12770
12771void e2fsck_clear_progbar(e2fsck_t ctx)
12772{
12773 if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12774 return;
12775
12776 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12777 ctx->stop_meta);
12778 fflush(stdout);
12779 ctx->flags &= ~E2F_FLAG_PROG_BAR;
12780}
12781
12782int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12783 unsigned int dpynum)
12784{
12785 static const char spinner[] = "\\|/-";
12786 int i;
12787 unsigned int tick;
12788 struct timeval tv;
12789 int dpywidth;
12790 int fixed_percent;
12791
12792 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12793 return 0;
12794
12795 /*
12796 * Calculate the new progress position. If the
12797 * percentage hasn't changed, then we skip out right
12798 * away.
12799 */
12800 fixed_percent = (int) ((10 * percent) + 0.5);
12801 if (ctx->progress_last_percent == fixed_percent)
12802 return 0;
12803 ctx->progress_last_percent = fixed_percent;
12804
12805 /*
12806 * If we've already updated the spinner once within
12807 * the last 1/8th of a second, no point doing it
12808 * again.
12809 */
12810 gettimeofday(&tv, NULL);
12811 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12812 if ((tick == ctx->progress_last_time) &&
12813 (fixed_percent != 0) && (fixed_percent != 1000))
12814 return 0;
12815 ctx->progress_last_time = tick;
12816
12817 /*
12818 * Advance the spinner, and note that the progress bar
12819 * will be on the screen
12820 */
12821 ctx->progress_pos = (ctx->progress_pos+1) & 3;
12822 ctx->flags |= E2F_FLAG_PROG_BAR;
12823
12824 dpywidth = 66 - strlen(label);
12825 dpywidth = 8 * (dpywidth / 8);
12826 if (dpynum)
12827 dpywidth -= 8;
12828
12829 i = ((percent * dpywidth) + 50) / 100;
12830 printf("%s%s: |%s%s", ctx->start_meta, label,
12831 bar + (sizeof(bar) - (i+1)),
12832 spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12833 if (fixed_percent == 1000)
Denis Vlasenko4daad902007-09-27 10:20:47 +000012834 bb_putchar('|');
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012835 else
Denis Vlasenko4daad902007-09-27 10:20:47 +000012836 bb_putchar(spinner[ctx->progress_pos & 3]);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012837 printf(" %4.1f%% ", percent);
12838 if (dpynum)
12839 printf("%u\r", dpynum);
12840 else
12841 fputs(" \r", stdout);
12842 fputs(ctx->stop_meta, stdout);
12843
12844 if (fixed_percent == 1000)
12845 e2fsck_clear_progbar(ctx);
12846 fflush(stdout);
12847
12848 return 0;
12849}
12850
12851static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12852 unsigned long cur, unsigned long max)
12853{
12854 char buf[80];
12855 float percent;
12856
12857 if (pass == 0)
12858 return 0;
12859
12860 if (ctx->progress_fd) {
12861 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
Denis Vlasenko73c571a2009-03-09 00:12:37 +000012862 xwrite_str(ctx->progress_fd, buf);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012863 } else {
12864 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12865 e2fsck_simple_progress(ctx, ctx->device_name,
12866 percent, 0);
12867 }
12868 return 0;
12869}
12870
12871static void reserve_stdio_fds(void)
12872{
12873 int fd;
12874
12875 while (1) {
12876 fd = open(bb_dev_null, O_RDWR);
12877 if (fd > 2)
12878 break;
12879 if (fd < 0) {
12880 fprintf(stderr, _("ERROR: Cannot open "
12881 "/dev/null (%s)\n"),
12882 strerror(errno));
12883 break;
12884 }
12885 }
12886 close(fd);
12887}
12888
12889static void signal_progress_on(int sig FSCK_ATTR((unused)))
12890{
12891 e2fsck_t ctx = e2fsck_global_ctx;
12892
12893 if (!ctx)
12894 return;
12895
12896 ctx->progress = e2fsck_update_progress;
12897 ctx->progress_fd = 0;
12898}
12899
12900static void signal_progress_off(int sig FSCK_ATTR((unused)))
12901{
12902 e2fsck_t ctx = e2fsck_global_ctx;
12903
12904 if (!ctx)
12905 return;
12906
12907 e2fsck_clear_progbar(ctx);
12908 ctx->progress = 0;
12909}
12910
12911static void signal_cancel(int sig FSCK_ATTR((unused)))
12912{
12913 e2fsck_t ctx = e2fsck_global_ctx;
12914
12915 if (!ctx)
12916 exit(FSCK_CANCELED);
12917
12918 ctx->flags |= E2F_FLAG_CANCEL;
12919}
12920
12921static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12922{
12923 char *buf, *token, *next, *p, *arg;
12924 int ea_ver;
12925 int extended_usage = 0;
12926
12927 buf = string_copy(opts, 0);
12928 for (token = buf; token && *token; token = next) {
12929 p = strchr(token, ',');
12930 next = 0;
12931 if (p) {
12932 *p = 0;
12933 next = p+1;
12934 }
12935 arg = strchr(token, '=');
12936 if (arg) {
12937 *arg = 0;
12938 arg++;
12939 }
12940 if (strcmp(token, "ea_ver") == 0) {
12941 if (!arg) {
12942 extended_usage++;
12943 continue;
12944 }
12945 ea_ver = strtoul(arg, &p, 0);
12946 if (*p ||
12947 ((ea_ver != 1) && (ea_ver != 2))) {
12948 fprintf(stderr,
12949 _("Invalid EA version.\n"));
12950 extended_usage++;
12951 continue;
12952 }
12953 ctx->ext_attr_ver = ea_ver;
12954 } else {
12955 fprintf(stderr, _("Unknown extended option: %s\n"),
12956 token);
12957 extended_usage++;
12958 }
12959 }
12960 if (extended_usage) {
12961 bb_error_msg_and_die(
12962 "Extended options are separated by commas, "
12963 "and may take an argument which\n"
12964 "is set off by an equals ('=') sign. "
12965 "Valid extended options are:\n"
12966 "\tea_ver=<ea_version (1 or 2)>\n\n");
12967 }
12968}
12969
12970
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000012971static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000012972{
12973 int flush = 0;
12974 int c, fd;
12975 e2fsck_t ctx;
12976 errcode_t retval;
12977 struct sigaction sa;
12978 char *extended_opts = 0;
12979
12980 retval = e2fsck_allocate_context(&ctx);
12981 if (retval)
12982 return retval;
12983
12984 *ret_ctx = ctx;
12985
12986 setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12987 setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12988 if (isatty(0) && isatty(1)) {
12989 ctx->interactive = 1;
12990 } else {
12991 ctx->start_meta[0] = '\001';
12992 ctx->stop_meta[0] = '\002';
12993 }
12994 memset(bar, '=', sizeof(bar)-1);
12995 memset(spaces, ' ', sizeof(spaces)-1);
12996 blkid_get_cache(&ctx->blkid, NULL);
12997
12998 if (argc && *argv)
12999 ctx->program_name = *argv;
13000 else
13001 ctx->program_name = "e2fsck";
13002 while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13003 switch (c) {
13004 case 'C':
13005 ctx->progress = e2fsck_update_progress;
13006 ctx->progress_fd = atoi(optarg);
13007 if (!ctx->progress_fd)
13008 break;
13009 /* Validate the file descriptor to avoid disasters */
13010 fd = dup(ctx->progress_fd);
13011 if (fd < 0) {
13012 fprintf(stderr,
13013 _("Error validating file descriptor %d: %s\n"),
13014 ctx->progress_fd,
13015 error_message(errno));
13016 bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13017 } else
13018 close(fd);
13019 break;
13020 case 'D':
13021 ctx->options |= E2F_OPT_COMPRESS_DIRS;
13022 break;
13023 case 'E':
13024 extended_opts = optarg;
13025 break;
13026 case 'p':
13027 case 'a':
13028 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13029 conflict_opt:
Denis Vlasenko54d10052008-12-24 03:11:43 +000013030 bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013031 }
13032 ctx->options |= E2F_OPT_PREEN;
13033 break;
13034 case 'n':
13035 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13036 goto conflict_opt;
13037 ctx->options |= E2F_OPT_NO;
13038 break;
13039 case 'y':
13040 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13041 goto conflict_opt;
13042 ctx->options |= E2F_OPT_YES;
13043 break;
13044 case 't':
13045 /* FIXME - This needs to go away in a future path - will change binary */
13046 fprintf(stderr, _("The -t option is not "
13047 "supported on this version of e2fsck.\n"));
13048 break;
13049 case 'c':
13050 if (cflag++)
13051 ctx->options |= E2F_OPT_WRITECHECK;
13052 ctx->options |= E2F_OPT_CHECKBLOCKS;
13053 break;
13054 case 'r':
13055 /* What we do by default, anyway! */
13056 break;
13057 case 'b':
13058 ctx->use_superblock = atoi(optarg);
13059 ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13060 break;
13061 case 'B':
13062 ctx->blocksize = atoi(optarg);
13063 break;
13064 case 'I':
13065 ctx->inode_buffer_blocks = atoi(optarg);
13066 break;
13067 case 'j':
13068 ctx->journal_name = string_copy(optarg, 0);
13069 break;
13070 case 'P':
13071 ctx->process_inode_size = atoi(optarg);
13072 break;
13073 case 'd':
13074 ctx->options |= E2F_OPT_DEBUG;
13075 break;
13076 case 'f':
13077 ctx->options |= E2F_OPT_FORCE;
13078 break;
13079 case 'F':
13080 flush = 1;
13081 break;
13082 case 'v':
13083 verbose = 1;
13084 break;
13085 case 'V':
13086 show_version_only = 1;
13087 break;
13088 case 'N':
13089 ctx->device_name = optarg;
13090 break;
13091#ifdef ENABLE_SWAPFS
13092 case 's':
13093 normalize_swapfs = 1;
13094 case 'S':
13095 swapfs = 1;
13096 break;
13097#else
13098 case 's':
13099 case 'S':
13100 fprintf(stderr, _("Byte-swapping filesystems "
13101 "not compiled in this version "
13102 "of e2fsck\n"));
13103 exit(1);
13104#endif
13105 default:
13106 bb_show_usage();
13107 }
13108 if (show_version_only)
13109 return 0;
13110 if (optind != argc - 1)
13111 bb_show_usage();
13112 if ((ctx->options & E2F_OPT_NO) &&
13113 !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13114 ctx->options |= E2F_OPT_READONLY;
13115 ctx->io_options = strchr(argv[optind], '?');
13116 if (ctx->io_options)
13117 *ctx->io_options++ = 0;
13118 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13119 if (!ctx->filesystem_name) {
13120 bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13121 bb_error_msg_and_die(0);
13122 }
13123 if (extended_opts)
13124 parse_extended_opts(ctx, extended_opts);
13125
13126 if (flush) {
13127 fd = open(ctx->filesystem_name, O_RDONLY, 0);
13128 if (fd < 0) {
13129 bb_error_msg(_("while opening %s for flushing"),
13130 ctx->filesystem_name);
13131 bb_error_msg_and_die(0);
13132 }
13133 if ((retval = ext2fs_sync_device(fd, 1))) {
13134 bb_error_msg(_("while trying to flush %s"),
13135 ctx->filesystem_name);
13136 bb_error_msg_and_die(0);
13137 }
13138 close(fd);
13139 }
13140#ifdef ENABLE_SWAPFS
13141 if (swapfs && cflag) {
13142 fprintf(stderr, _("Incompatible options not "
13143 "allowed when byte-swapping.\n"));
13144 exit(EXIT_USAGE);
13145 }
13146#endif
13147 /*
13148 * Set up signal action
13149 */
13150 memset(&sa, 0, sizeof(struct sigaction));
13151 sa.sa_handler = signal_cancel;
13152 sigaction(SIGINT, &sa, 0);
13153 sigaction(SIGTERM, &sa, 0);
13154#ifdef SA_RESTART
13155 sa.sa_flags = SA_RESTART;
13156#endif
13157 e2fsck_global_ctx = ctx;
13158 sa.sa_handler = signal_progress_on;
13159 sigaction(SIGUSR1, &sa, 0);
13160 sa.sa_handler = signal_progress_off;
13161 sigaction(SIGUSR2, &sa, 0);
13162
13163 /* Update our PATH to include /sbin if we need to run badblocks */
13164 if (cflag)
13165 e2fs_set_sbin_path();
13166 return 0;
13167}
13168
13169static const char my_ver_string[] = E2FSPROGS_VERSION;
13170static const char my_ver_date[] = E2FSPROGS_DATE;
13171
Bernhard Reutner-Fischerfebe3c42007-04-04 20:52:03 +000013172int e2fsck_main (int argc, char **argv);
13173int e2fsck_main (int argc, char **argv)
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013174{
13175 errcode_t retval;
13176 int exit_value = EXIT_OK;
13177 ext2_filsys fs = 0;
13178 io_manager io_ptr;
13179 struct ext2_super_block *sb;
13180 const char *lib_ver_date;
13181 int my_ver, lib_ver;
13182 e2fsck_t ctx;
13183 struct problem_context pctx;
13184 int flags, run_result;
13185
13186 clear_problem_context(&pctx);
13187
13188 my_ver = ext2fs_parse_version_string(my_ver_string);
13189 lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13190 if (my_ver > lib_ver) {
13191 fprintf( stderr, _("Error: ext2fs library version "
13192 "out of date!\n"));
13193 show_version_only++;
13194 }
13195
13196 retval = PRS(argc, argv, &ctx);
13197 if (retval) {
13198 bb_error_msg(_("while trying to initialize program"));
13199 exit(EXIT_ERROR);
13200 }
13201 reserve_stdio_fds();
13202
13203 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13204 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13205 my_ver_date);
13206
13207 if (show_version_only) {
13208 fprintf(stderr, _("\tUsing %s, %s\n"),
13209 error_message(EXT2_ET_BASE), lib_ver_date);
13210 exit(EXIT_OK);
13211 }
13212
13213 check_mount(ctx);
13214
13215 if (!(ctx->options & E2F_OPT_PREEN) &&
13216 !(ctx->options & E2F_OPT_NO) &&
13217 !(ctx->options & E2F_OPT_YES)) {
13218 if (!ctx->interactive)
13219 bb_error_msg_and_die(_("need terminal for interactive repairs"));
13220 }
13221 ctx->superblock = ctx->use_superblock;
13222restart:
13223#ifdef CONFIG_TESTIO_DEBUG
13224 io_ptr = test_io_manager;
13225 test_io_backing_manager = unix_io_manager;
13226#else
13227 io_ptr = unix_io_manager;
13228#endif
13229 flags = 0;
13230 if ((ctx->options & E2F_OPT_READONLY) == 0)
13231 flags |= EXT2_FLAG_RW;
13232
13233 if (ctx->superblock && ctx->blocksize) {
13234 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13235 flags, ctx->superblock, ctx->blocksize,
13236 io_ptr, &fs);
13237 } else if (ctx->superblock) {
13238 int blocksize;
13239 for (blocksize = EXT2_MIN_BLOCK_SIZE;
13240 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13241 retval = ext2fs_open2(ctx->filesystem_name,
13242 ctx->io_options, flags,
13243 ctx->superblock, blocksize,
13244 io_ptr, &fs);
13245 if (!retval)
13246 break;
13247 }
13248 } else
13249 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13250 flags, 0, 0, io_ptr, &fs);
13251 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13252 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13253 ((retval == EXT2_ET_BAD_MAGIC) ||
13254 ((retval == 0) && ext2fs_check_desc(fs)))) {
13255 if (!fs || (fs->group_desc_count > 1)) {
13256 printf(_("%s trying backup blocks...\n"),
13257 retval ? _("Couldn't find ext2 superblock,") :
13258 _("Group descriptors look bad..."));
13259 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13260 if (fs)
13261 ext2fs_close(fs);
13262 goto restart;
13263 }
13264 }
13265 if (retval) {
13266 bb_error_msg(_("while trying to open %s"),
13267 ctx->filesystem_name);
13268 if (retval == EXT2_ET_REV_TOO_HIGH) {
13269 printf(_("The filesystem revision is apparently "
13270 "too high for this version of e2fsck.\n"
13271 "(Or the filesystem superblock "
13272 "is corrupt)\n\n"));
13273 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13274 } else if (retval == EXT2_ET_SHORT_READ)
13275 printf(_("Could this be a zero-length partition?\n"));
13276 else if ((retval == EPERM) || (retval == EACCES))
13277 printf(_("You must have %s access to the "
13278 "filesystem or be root\n"),
13279 (ctx->options & E2F_OPT_READONLY) ?
13280 "r/o" : "r/w");
13281 else if (retval == ENXIO)
13282 printf(_("Possibly non-existent or swap device?\n"));
13283#ifdef EROFS
13284 else if (retval == EROFS)
13285 printf(_("Disk write-protected; use the -n option "
13286 "to do a read-only\n"
13287 "check of the device.\n"));
13288#endif
13289 else
13290 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13291 bb_error_msg_and_die(0);
13292 }
13293 ctx->fs = fs;
13294 fs->priv_data = ctx;
13295 sb = fs->super;
13296 if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13297 bb_error_msg(_("while trying to open %s"),
13298 ctx->filesystem_name);
13299 get_newer:
13300 bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13301 }
13302
13303 /*
13304 * Set the device name, which is used whenever we print error
13305 * or informational messages to the user.
13306 */
13307 if (ctx->device_name == 0 &&
13308 (sb->s_volume_name[0] != 0)) {
13309 ctx->device_name = string_copy(sb->s_volume_name,
13310 sizeof(sb->s_volume_name));
13311 }
13312 if (ctx->device_name == 0)
13313 ctx->device_name = ctx->filesystem_name;
13314
13315 /*
13316 * Make sure the ext3 superblock fields are consistent.
13317 */
13318 retval = e2fsck_check_ext3_journal(ctx);
13319 if (retval) {
13320 bb_error_msg(_("while checking ext3 journal for %s"),
13321 ctx->device_name);
13322 bb_error_msg_and_die(0);
13323 }
13324
13325 /*
13326 * Check to see if we need to do ext3-style recovery. If so,
13327 * do it, and then restart the fsck.
13328 */
13329 if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13330 if (ctx->options & E2F_OPT_READONLY) {
13331 printf(_("Warning: skipping journal recovery "
13332 "because doing a read-only filesystem "
13333 "check.\n"));
13334 io_channel_flush(ctx->fs->io);
13335 } else {
13336 if (ctx->flags & E2F_FLAG_RESTARTED) {
13337 /*
13338 * Whoops, we attempted to run the
13339 * journal twice. This should never
13340 * happen, unless the hardware or
13341 * device driver is being bogus.
13342 */
Denys Vlasenko6331cf02009-11-13 09:08:27 +010013343 bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013344 bb_error_msg_and_die(0);
13345 }
13346 retval = e2fsck_run_ext3_journal(ctx);
13347 if (retval) {
13348 bb_error_msg(_("while recovering ext3 journal of %s"),
13349 ctx->device_name);
13350 bb_error_msg_and_die(0);
13351 }
13352 ext2fs_close(ctx->fs);
13353 ctx->fs = 0;
13354 ctx->flags |= E2F_FLAG_RESTARTED;
13355 goto restart;
13356 }
13357 }
13358
13359 /*
13360 * Check for compatibility with the feature sets. We need to
13361 * be more stringent than ext2fs_open().
13362 */
13363 if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13364 (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13365 bb_error_msg("(%s)", ctx->device_name);
13366 goto get_newer;
13367 }
13368 if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13369 bb_error_msg("(%s)", ctx->device_name);
13370 goto get_newer;
13371 }
13372#ifdef ENABLE_COMPRESSION
13373 /* FIXME - do we support this at all? */
13374 if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
Denis Vlasenko54d10052008-12-24 03:11:43 +000013375 bb_error_msg(_("warning: compression support is experimental"));
Denis Vlasenkoc4f623e2006-12-26 01:30:59 +000013376#endif
13377#ifndef ENABLE_HTREE
13378 if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13379 bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13380 "but filesystem %s has HTREE directories."),
13381 ctx->device_name);
13382 goto get_newer;
13383 }
13384#endif
13385
13386 /*
13387 * If the user specified a specific superblock, presumably the
13388 * master superblock has been trashed. So we mark the
13389 * superblock as dirty, so it can be written out.
13390 */
13391 if (ctx->superblock &&
13392 !(ctx->options & E2F_OPT_READONLY))
13393 ext2fs_mark_super_dirty(fs);
13394
13395 /*
13396 * We only update the master superblock because (a) paranoia;
13397 * we don't want to corrupt the backup superblocks, and (b) we
13398 * don't need to update the mount count and last checked
13399 * fields in the backup superblock (the kernel doesn't
13400 * update the backup superblocks anyway).
13401 */
13402 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13403
13404 ehandler_init(fs->io);
13405
13406 if (ctx->superblock)
13407 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13408 ext2fs_mark_valid(fs);
13409 check_super_block(ctx);
13410 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13411 bb_error_msg_and_die(0);
13412 check_if_skip(ctx);
13413 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13414 bb_error_msg_and_die(0);
13415#ifdef ENABLE_SWAPFS
13416
13417#ifdef WORDS_BIGENDIAN
13418#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13419#else
13420#define NATIVE_FLAG 0
13421#endif
13422
13423
13424 if (normalize_swapfs) {
13425 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13426 fprintf(stderr, _("%s: Filesystem byte order "
13427 "already normalized.\n"), ctx->device_name);
13428 bb_error_msg_and_die(0);
13429 }
13430 }
13431 if (swapfs) {
13432 swap_filesys(ctx);
13433 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13434 bb_error_msg_and_die(0);
13435 }
13436#endif
13437
13438 /*
13439 * Mark the system as valid, 'til proven otherwise
13440 */
13441 ext2fs_mark_valid(fs);
13442
13443 retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13444 if (retval) {
13445 bb_error_msg(_("while reading bad blocks inode"));
13446 preenhalt(ctx);
13447 printf(_("This doesn't bode well,"
13448 " but we'll try to go on...\n"));
13449 }
13450
13451 run_result = e2fsck_run(ctx);
13452 e2fsck_clear_progbar(ctx);
13453 if (run_result == E2F_FLAG_RESTART) {
13454 printf(_("Restarting e2fsck from the beginning...\n"));
13455 retval = e2fsck_reset_context(ctx);
13456 if (retval) {
13457 bb_error_msg(_("while resetting context"));
13458 bb_error_msg_and_die(0);
13459 }
13460 ext2fs_close(fs);
13461 goto restart;
13462 }
13463 if (run_result & E2F_FLAG_CANCEL) {
13464 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13465 ctx->device_name : ctx->filesystem_name);
13466 exit_value |= FSCK_CANCELED;
13467 }
13468 if (run_result & E2F_FLAG_ABORT)
13469 bb_error_msg_and_die(_("aborted"));
13470
13471 /* Cleanup */
13472 if (ext2fs_test_changed(fs)) {
13473 exit_value |= EXIT_NONDESTRUCT;
13474 if (!(ctx->options & E2F_OPT_PREEN))
13475 printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13476 ctx->device_name);
13477 if (ctx->mount_flags & EXT2_MF_ISROOT) {
13478 printf(_("%s: ***** REBOOT LINUX *****\n"),
13479 ctx->device_name);
13480 exit_value |= EXIT_DESTRUCT;
13481 }
13482 }
13483 if (!ext2fs_test_valid(fs)) {
13484 printf(_("\n%s: ********** WARNING: Filesystem still has "
13485 "errors **********\n\n"), ctx->device_name);
13486 exit_value |= EXIT_UNCORRECTED;
13487 exit_value &= ~EXIT_NONDESTRUCT;
13488 }
13489 if (exit_value & FSCK_CANCELED)
13490 exit_value &= ~EXIT_NONDESTRUCT;
13491 else {
13492 show_stats(ctx);
13493 if (!(ctx->options & E2F_OPT_READONLY)) {
13494 if (ext2fs_test_valid(fs)) {
13495 if (!(sb->s_state & EXT2_VALID_FS))
13496 exit_value |= EXIT_NONDESTRUCT;
13497 sb->s_state = EXT2_VALID_FS;
13498 } else
13499 sb->s_state &= ~EXT2_VALID_FS;
13500 sb->s_mnt_count = 0;
13501 sb->s_lastcheck = time(NULL);
13502 ext2fs_mark_super_dirty(fs);
13503 }
13504 }
13505
13506 e2fsck_write_bitmaps(ctx);
13507
13508 ext2fs_close(fs);
13509 ctx->fs = NULL;
13510 free(ctx->filesystem_name);
13511 free(ctx->journal_name);
13512 e2fsck_free_context(ctx);
13513
13514 return exit_value;
13515}