Ext2fs cleanup from Garrett Kajmowicz.
[oweals/busybox.git] / e2fsprogs / e2fsck.c
1 /*
2  * e2fsck
3  *
4  * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5  * This file may be
6  * redistributed under the terms of the GNU Public License.
7  *
8  *
9  * Dictionary Abstract Data Type
10  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
11  * Free Software License:
12  * All rights are reserved by the author, with the following exceptions:
13  * Permission is granted to freely reproduce and distribute this software,
14  * possibly in exchange for a fee, provided that this copyright notice appears
15  * intact. Permission is also granted to adapt this software to produce
16  * derivative works, as long as the modified versions carry this copyright
17  * notice and additional notices stating that the work has been modified.
18  * This source code may be translated into executable form and incorporated
19  * into proprietary software; there is no requirement for such software to
20  * contain a copyright notice related to this source.
21  *
22  * linux/fs/recovery  and linux/fs/revoke
23  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
24  *
25  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
26  *
27  * This file is part of the Linux kernel and is made available under
28  * the terms of the GNU General Public License, version 2, or at your
29  * option, any later version, incorporated herein by reference.
30  *
31  * Journal recovery routines for the generic filesystem journaling code;
32  * part of the ext2fs journaling system.
33  */
34
35 #ifndef _GNU_SOURCE
36 #define _GNU_SOURCE 1 /* get strnlen() */
37 #endif
38
39 #include "e2fsck.h"     /*Put all of our defines here to clean things up*/
40
41 #ifdef __GNUC__
42 #define _INLINE_ __inline__
43 #define EXT2FS_ATTR(x) __attribute__(x)
44 #else
45 #define _INLINE_
46 #define EXT2FS_ATTR(x)
47 #endif
48
49 /*
50  * Procedure declarations
51  */
52
53 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
54
55 /* pass1.c */
56 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
57
58 /* pass2.c */
59 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
60                                     ext2_ino_t ino, char *buf);
61
62 /* pass3.c */
63 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
64 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
65                                          int num, int gauranteed_size);
66 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
67 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
68                                            int adj);
69
70 /* rehash.c */
71 static void e2fsck_rehash_directories(e2fsck_t ctx);
72
73 /* util.c */
74 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
75                                     const char *description);
76 static int ask(e2fsck_t ctx, const char * string, int def);
77 static void e2fsck_read_bitmaps(e2fsck_t ctx);
78 static void preenhalt(e2fsck_t ctx);
79 #ifdef RESOURCE_TRACK
80 static void print_resource_track(const char *desc,
81                                  struct resource_track *track);
82 static void init_resource_track(struct resource_track *track);
83 #endif
84 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
85                               struct ext2_inode * inode, const char * proc);
86 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
87                                struct ext2_inode * inode, const char * proc);
88 #ifdef MTRACE
89 static void mtrace_print(char *mesg);
90 #endif
91 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
92                            const char *name, io_manager manager);
93
94 /* unix.c */
95 static void e2fsck_clear_progbar(e2fsck_t ctx);
96 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
97                                   float percent, unsigned int dpynum);
98
99
100 /*
101  * problem.h --- e2fsck problem error codes
102  */
103
104 typedef __u32 problem_t;
105
106 struct problem_context {
107         errcode_t       errcode;
108         ext2_ino_t ino, ino2, dir;
109         struct ext2_inode *inode;
110         struct ext2_dir_entry *dirent;
111         blk_t   blk, blk2;
112         e2_blkcnt_t     blkcount;
113         int             group;
114         __u64   num;
115         const char *str;
116 };
117
118 /*
119  * We define a set of "latch groups"; these are problems which are
120  * handled as a set.  The user answers once for a particular latch
121  * group.
122  */
123 #define PR_LATCH_MASK         0x0ff0 /* Latch mask */
124 #define PR_LATCH_BLOCK        0x0010 /* Latch for illegal blocks (pass 1) */
125 #define PR_LATCH_BBLOCK       0x0020 /* Latch for bad block inode blocks (pass 1) */
126 #define PR_LATCH_IBITMAP      0x0030 /* Latch for pass 5 inode bitmap proc. */
127 #define PR_LATCH_BBITMAP      0x0040 /* Latch for pass 5 inode bitmap proc. */
128 #define PR_LATCH_RELOC        0x0050 /* Latch for superblock relocate hint */
129 #define PR_LATCH_DBLOCK       0x0060 /* Latch for pass 1b dup block headers */
130 #define PR_LATCH_LOW_DTIME    0x0070 /* Latch for pass1 orphaned list refugees */
131 #define PR_LATCH_TOOBIG       0x0080 /* Latch for file to big errors */
132 #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
133
134 #define PR_LATCH(x)     ((((x) & PR_LATCH_MASK) >> 4) - 1)
135
136 /*
137  * Latch group descriptor flags
138  */
139 #define PRL_YES         0x0001  /* Answer yes */
140 #define PRL_NO          0x0002  /* Answer no */
141 #define PRL_LATCHED     0x0004  /* The latch group is latched */
142 #define PRL_SUPPRESS    0x0008  /* Suppress all latch group questions */
143
144 #define PRL_VARIABLE    0x000f  /* All the flags that need to be reset */
145
146 /*
147  * Pre-Pass 1 errors
148  */
149
150 /* Block bitmap not in group */
151 #define PR_0_BB_NOT_GROUP       0x000001
152
153 /* Inode bitmap not in group */
154 #define PR_0_IB_NOT_GROUP       0x000002
155
156 /* Inode table not in group */
157 #define PR_0_ITABLE_NOT_GROUP   0x000003
158
159 /* Superblock corrupt */
160 #define PR_0_SB_CORRUPT         0x000004
161
162 /* Filesystem size is wrong */
163 #define PR_0_FS_SIZE_WRONG      0x000005
164
165 /* Fragments not supported */
166 #define PR_0_NO_FRAGMENTS       0x000006
167
168 /* Bad blocks_per_group */
169 #define PR_0_BLOCKS_PER_GROUP   0x000007
170
171 /* Bad first_data_block */
172 #define PR_0_FIRST_DATA_BLOCK   0x000008
173
174 /* Adding UUID to filesystem */
175 #define PR_0_ADD_UUID           0x000009
176
177 /* Relocate hint */
178 #define PR_0_RELOCATE_HINT      0x00000A
179
180 /* Miscellaneous superblock corruption */
181 #define PR_0_MISC_CORRUPT_SUPER 0x00000B
182
183 /* Error determing physical device size of filesystem */
184 #define PR_0_GETSIZE_ERROR      0x00000C
185
186 /* Inode count in the superblock incorrect */
187 #define PR_0_INODE_COUNT_WRONG  0x00000D
188
189 /* The Hurd does not support the filetype feature */
190 #define PR_0_HURD_CLEAR_FILETYPE 0x00000E
191
192 /* Journal inode is invalid */
193 #define PR_0_JOURNAL_BAD_INODE  0x00000F
194
195 /* The external journal has multiple filesystems (which we can't handle yet) */
196 #define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010
197
198 /* Can't find external journal */
199 #define PR_0_CANT_FIND_JOURNAL  0x000011
200
201 /* External journal has bad superblock */
202 #define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012
203
204 /* Superblock has a bad journal UUID */
205 #define PR_0_JOURNAL_BAD_UUID   0x000013
206
207 /* Journal has an unknown superblock type */
208 #define PR_0_JOURNAL_UNSUPP_SUPER 0x000014
209
210 /* Journal superblock is corrupt */
211 #define PR_0_JOURNAL_BAD_SUPER  0x000015
212
213 /* Journal superblock is corrupt */
214 #define PR_0_JOURNAL_HAS_JOURNAL 0x000016
215
216 /* Superblock has recovery flag set but no journal */
217 #define PR_0_JOURNAL_RECOVER_SET 0x000017
218
219 /* Journal has data, but recovery flag is clear */
220 #define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018
221
222 /* Ask if we should clear the journal */
223 #define PR_0_JOURNAL_RESET_JOURNAL 0x000019
224
225 /* Filesystem revision is 0, but feature flags are set */
226 #define PR_0_FS_REV_LEVEL       0x00001A
227
228 /* Clearing orphan inode */
229 #define PR_0_ORPHAN_CLEAR_INODE                 0x000020
230
231 /* Illegal block found in orphaned inode */
232 #define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM           0x000021
233
234 /* Already cleared block found in orphaned inode */
235 #define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK       0x000022
236
237 /* Illegal orphan inode in superblock */
238 #define PR_0_ORPHAN_ILLEGAL_HEAD_INODE          0x000023
239
240 /* Illegal inode in orphaned inode list */
241 #define PR_0_ORPHAN_ILLEGAL_INODE               0x000024
242
243 /* Journal has unsupported read-only feature - abort */
244 #define PR_0_JOURNAL_UNSUPP_ROCOMPAT            0x000025
245
246 /* Journal has unsupported incompatible feature - abort */
247 #define PR_0_JOURNAL_UNSUPP_INCOMPAT            0x000026
248
249 /* Journal has unsupported version number */
250 #define PR_0_JOURNAL_UNSUPP_VERSION             0x000027
251
252 /* Moving journal to hidden file */
253 #define PR_0_MOVE_JOURNAL                       0x000028
254
255 /* Error moving journal */
256 #define PR_0_ERR_MOVE_JOURNAL                   0x000029
257
258 /* Clearing V2 journal superblock */
259 #define PR_0_CLEAR_V2_JOURNAL                   0x00002A
260
261 /* Run journal anyway */
262 #define PR_0_JOURNAL_RUN                        0x00002B
263
264 /* Run journal anyway by default */
265 #define PR_0_JOURNAL_RUN_DEFAULT                0x00002C
266
267 /* Backup journal inode blocks */
268 #define PR_0_BACKUP_JNL                         0x00002D
269
270 /* Reserved blocks w/o resize_inode */
271 #define PR_0_NONZERO_RESERVED_GDT_BLOCKS        0x00002E
272
273 /* Resize_inode not enabled, but resize inode is non-zero */
274 #define PR_0_CLEAR_RESIZE_INODE                 0x00002F
275
276 /* Resize inode invalid */
277 #define PR_0_RESIZE_INODE_INVALID               0x000030
278
279 /*
280  * Pass 1 errors
281  */
282
283 /* Pass 1: Checking inodes, blocks, and sizes */
284 #define PR_1_PASS_HEADER                0x010000
285
286 /* Root directory is not an inode */
287 #define PR_1_ROOT_NO_DIR                0x010001
288
289 /* Root directory has dtime set */
290 #define PR_1_ROOT_DTIME                 0x010002
291
292 /* Reserved inode has bad mode */
293 #define PR_1_RESERVED_BAD_MODE          0x010003
294
295 /* Deleted inode has zero dtime */
296 #define PR_1_ZERO_DTIME                 0x010004
297
298 /* Inode in use, but dtime set */
299 #define PR_1_SET_DTIME                  0x010005
300
301 /* Zero-length directory */
302 #define PR_1_ZERO_LENGTH_DIR            0x010006
303
304 /* Block bitmap conflicts with some other fs block */
305 #define PR_1_BB_CONFLICT                0x010007
306
307 /* Inode bitmap conflicts with some other fs block */
308 #define PR_1_IB_CONFLICT                0x010008
309
310 /* Inode table conflicts with some other fs block */
311 #define PR_1_ITABLE_CONFLICT            0x010009
312
313 /* Block bitmap is on a bad block */
314 #define PR_1_BB_BAD_BLOCK               0x01000A
315
316 /* Inode bitmap is on a bad block */
317 #define PR_1_IB_BAD_BLOCK               0x01000B
318
319 /* Inode has incorrect i_size */
320 #define PR_1_BAD_I_SIZE                 0x01000C
321
322 /* Inode has incorrect i_blocks */
323 #define PR_1_BAD_I_BLOCKS               0x01000D
324
325 /* Illegal block number in inode */
326 #define PR_1_ILLEGAL_BLOCK_NUM          0x01000E
327
328 /* Block number overlaps fs metadata */
329 #define PR_1_BLOCK_OVERLAPS_METADATA    0x01000F
330
331 /* Inode has illegal blocks (latch question) */
332 #define PR_1_INODE_BLOCK_LATCH          0x010010
333
334 /* Too many bad blocks in inode */
335 #define PR_1_TOO_MANY_BAD_BLOCKS        0x010011
336
337 /* Illegal block number in bad block inode */
338 #define PR_1_BB_ILLEGAL_BLOCK_NUM       0x010012
339
340 /* Bad block inode has illegal blocks (latch question) */
341 #define PR_1_INODE_BBLOCK_LATCH         0x010013
342
343 /* Duplicate or bad blocks in use! */
344 #define PR_1_DUP_BLOCKS_PREENSTOP       0x010014
345
346 /* Bad block used as bad block indirect block */
347 #define PR_1_BBINODE_BAD_METABLOCK      0x010015
348
349 /* Inconsistency can't be fixed prompt */
350 #define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
351
352 /* Bad primary block */
353 #define PR_1_BAD_PRIMARY_BLOCK          0x010017
354
355 /* Bad primary block prompt */
356 #define PR_1_BAD_PRIMARY_BLOCK_PROMPT   0x010018
357
358 /* Bad primary superblock */
359 #define PR_1_BAD_PRIMARY_SUPERBLOCK     0x010019
360
361 /* Bad primary block group descriptors */
362 #define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A
363
364 /* Bad superblock in group */
365 #define PR_1_BAD_SUPERBLOCK             0x01001B
366
367 /* Bad block group descriptors in group */
368 #define PR_1_BAD_GROUP_DESCRIPTORS      0x01001C
369
370 /* Block claimed for no reason */
371 #define PR_1_PROGERR_CLAIMED_BLOCK      0x01001D
372
373 /* Error allocating blocks for relocating metadata */
374 #define PR_1_RELOC_BLOCK_ALLOCATE       0x01001E
375
376 /* Error allocating block buffer during relocation process */
377 #define PR_1_RELOC_MEMORY_ALLOCATE      0x01001F
378
379 /* Relocating metadata group information from X to Y */
380 #define PR_1_RELOC_FROM_TO              0x010020
381
382 /* Relocating metatdata group information to X */
383 #define PR_1_RELOC_TO                   0x010021
384
385 /* Block read error during relocation process */
386 #define PR_1_RELOC_READ_ERR             0x010022
387
388 /* Block write error during relocation process */
389 #define PR_1_RELOC_WRITE_ERR            0x010023
390
391 /* Error allocating inode bitmap */
392 #define PR_1_ALLOCATE_IBITMAP_ERROR     0x010024
393
394 /* Error allocating block bitmap */
395 #define PR_1_ALLOCATE_BBITMAP_ERROR     0x010025
396
397 /* Error allocating icount structure */
398 #define PR_1_ALLOCATE_ICOUNT            0x010026
399
400 /* Error allocating dbcount */
401 #define PR_1_ALLOCATE_DBCOUNT           0x010027
402
403 /* Error while scanning inodes */
404 #define PR_1_ISCAN_ERROR                0x010028
405
406 /* Error while iterating over blocks */
407 #define PR_1_BLOCK_ITERATE              0x010029
408
409 /* Error while storing inode count information */
410 #define PR_1_ICOUNT_STORE               0x01002A
411
412 /* Error while storing directory block information */
413 #define PR_1_ADD_DBLOCK                 0x01002B
414
415 /* Error while reading inode (for clearing) */
416 #define PR_1_READ_INODE                 0x01002C
417
418 /* Suppress messages prompt */
419 #define PR_1_SUPPRESS_MESSAGES          0x01002D
420
421 /* Imagic flag set on an inode when filesystem doesn't support it */
422 #define PR_1_SET_IMAGIC                 0x01002F
423
424 /* Immutable flag set on a device or socket inode */
425 #define PR_1_SET_IMMUTABLE              0x010030
426
427 /* Compression flag set on a non-compressed filesystem */
428 #define PR_1_COMPR_SET                  0x010031
429
430 /* Non-zero size on on device, fifo or socket inode */
431 #define PR_1_SET_NONZSIZE               0x010032
432
433 /* Filesystem revision is 0, but feature flags are set */
434 #define PR_1_FS_REV_LEVEL               0x010033
435
436 /* Journal inode not in use, needs clearing */
437 #define PR_1_JOURNAL_INODE_NOT_CLEAR    0x010034
438
439 /* Journal inode has wrong mode */
440 #define PR_1_JOURNAL_BAD_MODE           0x010035
441
442 /* Inode that was part of orphan linked list */
443 #define PR_1_LOW_DTIME                  0x010036
444
445 /* Latch question which asks how to deal with low dtime inodes */
446 #define PR_1_ORPHAN_LIST_REFUGEES       0x010037
447
448 /* Error allocating refcount structure */
449 #define PR_1_ALLOCATE_REFCOUNT          0x010038
450
451 /* Error reading Extended Attribute block */
452 #define PR_1_READ_EA_BLOCK              0x010039
453
454 /* Invalid Extended Attribute block */
455 #define PR_1_BAD_EA_BLOCK               0x01003A
456
457 /* Error reading Extended Attribute block while fixing refcount -- abort */
458 #define PR_1_EXTATTR_READ_ABORT         0x01003B
459
460 /* Extended attribute reference count incorrect */
461 #define PR_1_EXTATTR_REFCOUNT           0x01003C
462
463 /* Error writing Extended Attribute block while fixing refcount */
464 #define PR_1_EXTATTR_WRITE              0x01003D
465
466 /* Multiple EA blocks not supported */
467 #define PR_1_EA_MULTI_BLOCK             0x01003E
468
469 /* Error allocating EA region allocation structure */
470 #define PR_1_EA_ALLOC_REGION            0x01003F
471
472 /* Error EA allocation collision */
473 #define PR_1_EA_ALLOC_COLLISION         0x010040
474
475 /* Bad extended attribute name */
476 #define PR_1_EA_BAD_NAME                0x010041
477
478 /* Bad extended attribute value */
479 #define PR_1_EA_BAD_VALUE               0x010042
480
481 /* Inode too big (latch question) */
482 #define PR_1_INODE_TOOBIG               0x010043
483
484 /* Directory too big */
485 #define PR_1_TOOBIG_DIR                 0x010044
486
487 /* Regular file too big */
488 #define PR_1_TOOBIG_REG                 0x010045
489
490 /* Symlink too big */
491 #define PR_1_TOOBIG_SYMLINK             0x010046
492
493 /* INDEX_FL flag set on a non-HTREE filesystem */
494 #define PR_1_HTREE_SET                  0x010047
495
496 /* INDEX_FL flag set on a non-directory */
497 #define PR_1_HTREE_NODIR                0x010048
498
499 /* Invalid root node in HTREE directory */
500 #define PR_1_HTREE_BADROOT              0x010049
501
502 /* Unsupported hash version in HTREE directory */
503 #define PR_1_HTREE_HASHV                0x01004A
504
505 /* Incompatible flag in HTREE root node */
506 #define PR_1_HTREE_INCOMPAT             0x01004B
507
508 /* HTREE too deep */
509 #define PR_1_HTREE_DEPTH                0x01004C
510
511 /* Bad block has indirect block that conflicts with filesystem block */
512 #define PR_1_BB_FS_BLOCK                0x01004D
513
514 /* Resize inode failed */
515 #define PR_1_RESIZE_INODE_CREATE        0x01004E
516
517 /* inode->i_size is too long */
518 #define PR_1_EXTRA_ISIZE                0x01004F
519
520 /* attribute name is too long */
521 #define PR_1_ATTR_NAME_LEN              0x010050
522
523 /* wrong EA value offset */
524 #define PR_1_ATTR_VALUE_OFFSET          0x010051
525
526 /* wrong EA blocknumber */
527 #define PR_1_ATTR_VALUE_BLOCK           0x010052
528
529 /* wrong EA value size */
530 #define PR_1_ATTR_VALUE_SIZE            0x010053
531
532 /* wrong EA hash value */
533 #define PR_1_ATTR_HASH                  0x010054
534
535 /*
536  * Pass 1b errors
537  */
538
539 /* Pass 1B: Rescan for duplicate/bad blocks */
540 #define PR_1B_PASS_HEADER       0x011000
541
542 /* Duplicate/bad block(s) header */
543 #define PR_1B_DUP_BLOCK_HEADER  0x011001
544
545 /* Duplicate/bad block(s) in inode */
546 #define PR_1B_DUP_BLOCK         0x011002
547
548 /* Duplicate/bad block(s) end */
549 #define PR_1B_DUP_BLOCK_END     0x011003
550
551 /* Error while scanning inodes */
552 #define PR_1B_ISCAN_ERROR       0x011004
553
554 /* Error allocating inode bitmap */
555 #define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
556
557 /* Error while iterating over blocks */
558 #define PR_1B_BLOCK_ITERATE     0x0110006
559
560 /* Error adjusting EA refcount */
561 #define PR_1B_ADJ_EA_REFCOUNT   0x0110007
562
563
564 /* Pass 1C: Scan directories for inodes with dup blocks. */
565 #define PR_1C_PASS_HEADER       0x012000
566
567
568 /* Pass 1D: Reconciling duplicate blocks */
569 #define PR_1D_PASS_HEADER       0x013000
570
571 /* File has duplicate blocks */
572 #define PR_1D_DUP_FILE          0x013001
573
574 /* List of files sharing duplicate blocks */
575 #define PR_1D_DUP_FILE_LIST     0x013002
576
577 /* File sharing blocks with filesystem metadata  */
578 #define PR_1D_SHARE_METADATA    0x013003
579
580 /* Report of how many duplicate/bad inodes */
581 #define PR_1D_NUM_DUP_INODES    0x013004
582
583 /* Duplicated blocks already reassigned or cloned. */
584 #define PR_1D_DUP_BLOCKS_DEALT  0x013005
585
586 /* Clone duplicate/bad blocks? */
587 #define PR_1D_CLONE_QUESTION    0x013006
588
589 /* Delete file? */
590 #define PR_1D_DELETE_QUESTION   0x013007
591
592 /* Couldn't clone file (error) */
593 #define PR_1D_CLONE_ERROR       0x013008
594
595 /*
596  * Pass 2 errors
597  */
598
599 /* Pass 2: Checking directory structure */
600 #define PR_2_PASS_HEADER        0x020000
601
602 /* Bad inode number for '.' */
603 #define PR_2_BAD_INODE_DOT      0x020001
604
605 /* Directory entry has bad inode number */
606 #define PR_2_BAD_INO            0x020002
607
608 /* Directory entry has deleted or unused inode */
609 #define PR_2_UNUSED_INODE       0x020003
610
611 /* Directry entry is link to '.' */
612 #define PR_2_LINK_DOT           0x020004
613
614 /* Directory entry points to inode now located in a bad block */
615 #define PR_2_BB_INODE           0x020005
616
617 /* Directory entry contains a link to a directory */
618 #define PR_2_LINK_DIR           0x020006
619
620 /* Directory entry contains a link to the root directry */
621 #define PR_2_LINK_ROOT          0x020007
622
623 /* Directory entry has illegal characters in its name */
624 #define PR_2_BAD_NAME           0x020008
625
626 /* Missing '.' in directory inode */
627 #define PR_2_MISSING_DOT        0x020009
628
629 /* Missing '..' in directory inode */
630 #define PR_2_MISSING_DOT_DOT    0x02000A
631
632 /* First entry in directory inode doesn't contain '.' */
633 #define PR_2_1ST_NOT_DOT        0x02000B
634
635 /* Second entry in directory inode doesn't contain '..' */
636 #define PR_2_2ND_NOT_DOT_DOT    0x02000C
637
638 /* i_faddr should be zero */
639 #define PR_2_FADDR_ZERO         0x02000D
640
641 /* i_file_acl should be zero */
642 #define PR_2_FILE_ACL_ZERO      0x02000E
643
644 /* i_dir_acl should be zero */
645 #define PR_2_DIR_ACL_ZERO       0x02000F
646
647 /* i_frag should be zero */
648 #define PR_2_FRAG_ZERO          0x020010
649
650 /* i_fsize should be zero */
651 #define PR_2_FSIZE_ZERO         0x020011
652
653 /* inode has bad mode */
654 #define PR_2_BAD_MODE           0x020012
655
656 /* directory corrupted */
657 #define PR_2_DIR_CORRUPTED      0x020013
658
659 /* filename too long */
660 #define PR_2_FILENAME_LONG      0x020014
661
662 /* Directory inode has a missing block (hole) */
663 #define PR_2_DIRECTORY_HOLE     0x020015
664
665 /* '.' is not NULL terminated */
666 #define PR_2_DOT_NULL_TERM      0x020016
667
668 /* '..' is not NULL terminated */
669 #define PR_2_DOT_DOT_NULL_TERM  0x020017
670
671 /* Illegal character device in inode */
672 #define PR_2_BAD_CHAR_DEV       0x020018
673
674 /* Illegal block device in inode */
675 #define PR_2_BAD_BLOCK_DEV      0x020019
676
677 /* Duplicate '.' entry */
678 #define PR_2_DUP_DOT            0x02001A
679
680 /* Duplicate '..' entry */
681 #define PR_2_DUP_DOT_DOT        0x02001B
682
683 /* Internal error: couldn't find dir_info */
684 #define PR_2_NO_DIRINFO         0x02001C
685
686 /* Final rec_len is wrong */
687 #define PR_2_FINAL_RECLEN       0x02001D
688
689 /* Error allocating icount structure */
690 #define PR_2_ALLOCATE_ICOUNT    0x02001E
691
692 /* Error iterating over directory blocks */
693 #define PR_2_DBLIST_ITERATE     0x02001F
694
695 /* Error reading directory block */
696 #define PR_2_READ_DIRBLOCK      0x020020
697
698 /* Error writing directory block */
699 #define PR_2_WRITE_DIRBLOCK     0x020021
700
701 /* Error allocating new directory block */
702 #define PR_2_ALLOC_DIRBOCK      0x020022
703
704 /* Error deallocating inode */
705 #define PR_2_DEALLOC_INODE      0x020023
706
707 /* Directory entry for '.' is big.  Split? */
708 #define PR_2_SPLIT_DOT          0x020024
709
710 /* Illegal FIFO */
711 #define PR_2_BAD_FIFO           0x020025
712
713 /* Illegal socket */
714 #define PR_2_BAD_SOCKET         0x020026
715
716 /* Directory filetype not set */
717 #define PR_2_SET_FILETYPE       0x020027
718
719 /* Directory filetype incorrect */
720 #define PR_2_BAD_FILETYPE       0x020028
721
722 /* Directory filetype set when it shouldn't be */
723 #define PR_2_CLEAR_FILETYPE     0x020029
724
725 /* Directory filename can't be zero-length  */
726 #define PR_2_NULL_NAME          0x020030
727
728 /* Invalid symlink */
729 #define PR_2_INVALID_SYMLINK    0x020031
730
731 /* i_file_acl (extended attribute) is bad */
732 #define PR_2_FILE_ACL_BAD       0x020032
733
734 /* Filesystem contains large files, but has no such flag in sb */
735 #define PR_2_FEATURE_LARGE_FILES 0x020033
736
737 /* Node in HTREE directory not referenced */
738 #define PR_2_HTREE_NOTREF       0x020034
739
740 /* Node in HTREE directory referenced twice */
741 #define PR_2_HTREE_DUPREF       0x020035
742
743 /* Node in HTREE directory has bad min hash */
744 #define PR_2_HTREE_MIN_HASH     0x020036
745
746 /* Node in HTREE directory has bad max hash */
747 #define PR_2_HTREE_MAX_HASH     0x020037
748
749 /* Clear invalid HTREE directory */
750 #define PR_2_HTREE_CLEAR        0x020038
751
752 /* Clear the htree flag forcibly */
753 /* #define PR_2_HTREE_FCLR      0x020039 */
754
755 /* Bad block in htree interior node */
756 #define PR_2_HTREE_BADBLK       0x02003A
757
758 /* Error adjusting EA refcount */
759 #define PR_2_ADJ_EA_REFCOUNT    0x02003B
760
761 /* Invalid HTREE root node */
762 #define PR_2_HTREE_BAD_ROOT     0x02003C
763
764 /* Invalid HTREE limit */
765 #define PR_2_HTREE_BAD_LIMIT    0x02003D
766
767 /* Invalid HTREE count */
768 #define PR_2_HTREE_BAD_COUNT    0x02003E
769
770 /* HTREE interior node has out-of-order hashes in table */
771 #define PR_2_HTREE_HASH_ORDER   0x02003F
772
773 /* Node in HTREE directory has bad depth */
774 #define PR_2_HTREE_BAD_DEPTH    0x020040
775
776 /* Duplicate directory entry found */
777 #define PR_2_DUPLICATE_DIRENT   0x020041
778
779 /* Non-unique filename found */
780 #define PR_2_NON_UNIQUE_FILE    0x020042
781
782 /* Duplicate directory entry found */
783 #define PR_2_REPORT_DUP_DIRENT  0x020043
784
785 /*
786  * Pass 3 errors
787  */
788
789 /* Pass 3: Checking directory connectivity */
790 #define PR_3_PASS_HEADER                0x030000
791
792 /* Root inode not allocated */
793 #define PR_3_NO_ROOT_INODE              0x030001
794
795 /* No room in lost+found */
796 #define PR_3_EXPAND_LF_DIR              0x030002
797
798 /* Unconnected directory inode */
799 #define PR_3_UNCONNECTED_DIR            0x030003
800
801 /* /lost+found not found */
802 #define PR_3_NO_LF_DIR                  0x030004
803
804 /* .. entry is incorrect */
805 #define PR_3_BAD_DOT_DOT                0x030005
806
807 /* Bad or non-existent /lost+found.  Cannot reconnect */
808 #define PR_3_NO_LPF                     0x030006
809
810 /* Could not expand /lost+found */
811 #define PR_3_CANT_EXPAND_LPF            0x030007
812
813 /* Could not reconnect inode */
814 #define PR_3_CANT_RECONNECT             0x030008
815
816 /* Error while trying to find /lost+found */
817 #define PR_3_ERR_FIND_LPF               0x030009
818
819 /* Error in ext2fs_new_block while creating /lost+found */
820 #define PR_3_ERR_LPF_NEW_BLOCK          0x03000A
821
822 /* Error in ext2fs_new_inode while creating /lost+found */
823 #define PR_3_ERR_LPF_NEW_INODE          0x03000B
824
825 /* Error in ext2fs_new_dir_block while creating /lost+found */
826 #define PR_3_ERR_LPF_NEW_DIR_BLOCK      0x03000C
827
828 /* Error while writing directory block for /lost+found */
829 #define PR_3_ERR_LPF_WRITE_BLOCK        0x03000D
830
831 /* Error while adjusting inode count */
832 #define PR_3_ADJUST_INODE               0x03000E
833
834 /* Couldn't fix parent directory -- error */
835 #define PR_3_FIX_PARENT_ERR             0x03000F
836
837 /* Couldn't fix parent directory -- couldn't find it */
838 #define PR_3_FIX_PARENT_NOFIND          0x030010
839
840 /* Error allocating inode bitmap */
841 #define PR_3_ALLOCATE_IBITMAP_ERROR     0x030011
842
843 /* Error creating root directory */
844 #define PR_3_CREATE_ROOT_ERROR          0x030012
845
846 /* Error creating lost and found directory */
847 #define PR_3_CREATE_LPF_ERROR           0x030013
848
849 /* Root inode is not directory; aborting */
850 #define PR_3_ROOT_NOT_DIR_ABORT         0x030014
851
852 /* Cannot proceed without a root inode. */
853 #define PR_3_NO_ROOT_INODE_ABORT        0x030015
854
855 /* Internal error: couldn't find dir_info */
856 #define PR_3_NO_DIRINFO                 0x030016
857
858 /* Lost+found is not a directory */
859 #define PR_3_LPF_NOTDIR                 0x030017
860
861 /*
862  * Pass 3a --- rehashing diretories
863  */
864 /* Pass 3a: Reindexing directories */
865 #define PR_3A_PASS_HEADER               0x031000
866
867 /* Error iterating over directories */
868 #define PR_3A_OPTIMIZE_ITER             0x031001
869
870 /* Error rehash directory */
871 #define PR_3A_OPTIMIZE_DIR_ERR          0x031002
872
873 /* Rehashing dir header */
874 #define PR_3A_OPTIMIZE_DIR_HEADER               0x031003
875
876 /* Rehashing directory %d */
877 #define PR_3A_OPTIMIZE_DIR              0x031004
878
879 /* Rehashing dir end */
880 #define PR_3A_OPTIMIZE_DIR_END          0x031005
881
882 /*
883  * Pass 4 errors
884  */
885
886 /* Pass 4: Checking reference counts */
887 #define PR_4_PASS_HEADER        0x040000
888
889 /* Unattached zero-length inode */
890 #define PR_4_ZERO_LEN_INODE     0x040001
891
892 /* Unattached inode */
893 #define PR_4_UNATTACHED_INODE   0x040002
894
895 /* Inode ref count wrong */
896 #define PR_4_BAD_REF_COUNT      0x040003
897
898 /* Inconsistent inode count information cached */
899 #define PR_4_INCONSISTENT_COUNT 0x040004
900
901 /*
902  * Pass 5 errors
903  */
904
905 /* Pass 5: Checking group summary information */
906 #define PR_5_PASS_HEADER                0x050000
907
908 /* Padding at end of inode bitmap is not set. */
909 #define PR_5_INODE_BMAP_PADDING         0x050001
910
911 /* Padding at end of block bitmap is not set. */
912 #define PR_5_BLOCK_BMAP_PADDING         0x050002
913
914 /* Block bitmap differences header */
915 #define PR_5_BLOCK_BITMAP_HEADER        0x050003
916
917 /* Block not used, but marked in bitmap */
918 #define PR_5_BLOCK_UNUSED               0x050004
919
920 /* Block used, but not marked used in bitmap */
921 #define PR_5_BLOCK_USED                 0x050005
922
923 /* Block bitmap differences end */
924 #define PR_5_BLOCK_BITMAP_END           0x050006
925
926 /* Inode bitmap differences header */
927 #define PR_5_INODE_BITMAP_HEADER        0x050007
928
929 /* Inode not used, but marked in bitmap */
930 #define PR_5_INODE_UNUSED               0x050008
931
932 /* Inode used, but not marked used in bitmap */
933 #define PR_5_INODE_USED                 0x050009
934
935 /* Inode bitmap differences end */
936 #define PR_5_INODE_BITMAP_END           0x05000A
937
938 /* Free inodes count for group wrong */
939 #define PR_5_FREE_INODE_COUNT_GROUP     0x05000B
940
941 /* Directories count for group wrong */
942 #define PR_5_FREE_DIR_COUNT_GROUP       0x05000C
943
944 /* Free inodes count wrong */
945 #define PR_5_FREE_INODE_COUNT   0x05000D
946
947 /* Free blocks count for group wrong */
948 #define PR_5_FREE_BLOCK_COUNT_GROUP     0x05000E
949
950 /* Free blocks count wrong */
951 #define PR_5_FREE_BLOCK_COUNT           0x05000F
952
953 /* Programming error: bitmap endpoints don't match */
954 #define PR_5_BMAP_ENDPOINTS             0x050010
955
956 /* Internal error: fudging end of bitmap */
957 #define PR_5_FUDGE_BITMAP_ERROR         0x050011
958
959 /* Error copying in replacement inode bitmap */
960 #define PR_5_COPY_IBITMAP_ERROR         0x050012
961
962 /* Error copying in replacement block bitmap */
963 #define PR_5_COPY_BBITMAP_ERROR         0x050013
964
965 /* Block range not used, but marked in bitmap */
966 #define PR_5_BLOCK_RANGE_UNUSED         0x050014
967
968 /* Block range used, but not marked used in bitmap */
969 #define PR_5_BLOCK_RANGE_USED           0x050015
970
971 /* Inode range not used, but marked in bitmap */
972 #define PR_5_INODE_RANGE_UNUSED         0x050016
973
974 /* Inode rangeused, but not marked used in bitmap */
975 #define PR_5_INODE_RANGE_USED           0x050017
976
977 /*
978  * Function declarations
979  */
980 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
981 static int end_problem_latch(e2fsck_t ctx, int mask);
982 static int set_latch_flags(int mask, int setflags, int clearflags);
983 static void clear_problem_context(struct problem_context *ctx);
984
985 /*
986  * Dictionary Abstract Data Type
987  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
988  *
989  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
990  * kazlib_1_20
991  */
992
993 #ifndef DICT_H
994 #define DICT_H
995
996 /*
997  * Blurb for inclusion into C++ translation units
998  */
999
1000 typedef unsigned long dictcount_t;
1001 #define DICTCOUNT_T_MAX ULONG_MAX
1002
1003 /*
1004  * The dictionary is implemented as a red-black tree
1005  */
1006
1007 typedef enum { dnode_red, dnode_black } dnode_color_t;
1008
1009 typedef struct dnode_t {
1010     struct dnode_t *dict_left;
1011     struct dnode_t *dict_right;
1012     struct dnode_t *dict_parent;
1013     dnode_color_t dict_color;
1014     const void *dict_key;
1015     void *dict_data;
1016 } dnode_t;
1017
1018 typedef int (*dict_comp_t)(const void *, const void *);
1019 typedef void (*dnode_free_t)(dnode_t *);
1020
1021 typedef struct dict_t {
1022     dnode_t dict_nilnode;
1023     dictcount_t dict_nodecount;
1024     dictcount_t dict_maxcount;
1025     dict_comp_t dict_compare;
1026     dnode_free_t dict_freenode;
1027     int dict_dupes;
1028 } dict_t;
1029
1030 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
1031
1032 typedef struct dict_load_t {
1033     dict_t *dict_dictptr;
1034     dnode_t dict_nilnode;
1035 } dict_load_t;
1036
1037 #define dict_count(D) ((D)->dict_nodecount)
1038 #define dnode_get(N) ((N)->dict_data)
1039 #define dnode_getkey(N) ((N)->dict_key)
1040
1041 #endif
1042
1043 /*
1044  * Compatibility header file for e2fsck which should be included
1045  * instead of linux/jfs.h
1046  *
1047  * Copyright (C) 2000 Stephen C. Tweedie
1048  */
1049
1050 /*
1051  * Pull in the definition of the e2fsck context structure
1052  */
1053
1054 struct buffer_head {
1055         char            b_data[8192];
1056         e2fsck_t        b_ctx;
1057         io_channel      b_io;
1058         int             b_size;
1059         blk_t           b_blocknr;
1060         int             b_dirty;
1061         int             b_uptodate;
1062         int             b_err;
1063 };
1064
1065
1066 #define K_DEV_FS        1
1067 #define K_DEV_JOURNAL   2
1068
1069 #define lock_buffer(bh) do {} while(0)
1070 #define unlock_buffer(bh) do {} while(0)
1071 #define buffer_req(bh) 1
1072 #define do_readahead(journal, start) do {} while(0)
1073
1074 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
1075
1076 typedef struct {
1077         int     object_length;
1078 } kmem_cache_t;
1079
1080 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1081
1082 /*
1083  * We use the standard libext2fs portability tricks for inline
1084  * functions.
1085  */
1086
1087 static _INLINE_ kmem_cache_t * do_cache_create(int len)
1088 {
1089         kmem_cache_t *new_cache;
1090
1091         new_cache = malloc(sizeof(*new_cache));
1092         if (new_cache)
1093                 new_cache->object_length = len;
1094         return new_cache;
1095 }
1096
1097 static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1098 {
1099         free(cache);
1100 }
1101
1102 /*
1103  * badblocks.c --- replace/append bad blocks to the bad block inode
1104  */
1105
1106 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
1107                                  void *priv_data);
1108
1109
1110 static void invalid_block(ext2_filsys fs FSCK_ATTR((unused)), blk_t blk)
1111 {
1112         printf(_("Bad block %u out of range; ignored.\n"), blk);
1113         return;
1114 }
1115
1116 static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1117                           int replace_bad_blocks)
1118 {
1119         ext2_filsys fs = ctx->fs;
1120         errcode_t       retval;
1121         badblocks_list  bb_list = 0;
1122         FILE            *f;
1123         char            buf[1024];
1124
1125         e2fsck_read_bitmaps(ctx);
1126
1127         /*
1128          * Make sure the bad block inode is sane.  If there are any
1129          * illegal blocks, clear them.
1130          */
1131         retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
1132                                       check_bb_inode_blocks, 0);
1133         if (retval) {
1134                 com_err("ext2fs_block_iterate", retval,
1135                         _("while sanity checking the bad blocks inode"));
1136                 goto fatal;
1137         }
1138
1139         /*
1140          * If we're appending to the bad blocks inode, read in the
1141          * current bad blocks.
1142          */
1143         if (!replace_bad_blocks) {
1144                 retval = ext2fs_read_bb_inode(fs, &bb_list);
1145                 if (retval) {
1146                         com_err("ext2fs_read_bb_inode", retval,
1147                                 _("while reading the bad blocks inode"));
1148                         goto fatal;
1149                 }
1150         }
1151
1152         /*
1153          * Now read in the bad blocks from the file; if
1154          * bad_blocks_file is null, then try to run the badblocks
1155          * command.
1156          */
1157         if (bad_blocks_file) {
1158                 f = fopen(bad_blocks_file, "r");
1159                 if (!f) {
1160                         com_err("read_bad_blocks_file", errno,
1161                                 _("while trying to open %s"), bad_blocks_file);
1162                         goto fatal;
1163                 }
1164         } else {
1165                 sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
1166                         (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
1167                         (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
1168                         fs->device_name, fs->super->s_blocks_count);
1169                 f = popen(buf, "r");
1170                 if (!f) {
1171                         com_err("read_bad_blocks_file", errno,
1172                                 _("while trying popen '%s'"), buf);
1173                         goto fatal;
1174                 }
1175         }
1176         retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
1177         if (bad_blocks_file)
1178                 fclose(f);
1179         else
1180                 pclose(f);
1181         if (retval) {
1182                 com_err("ext2fs_read_bb_FILE", retval,
1183                         _("while reading in list of bad blocks from file"));
1184                 goto fatal;
1185         }
1186
1187         /*
1188          * Finally, update the bad blocks from the bad_block_map
1189          */
1190         retval = ext2fs_update_bb_inode(fs, bb_list);
1191         if (retval) {
1192                 com_err("ext2fs_update_bb_inode", retval,
1193                         _("while updating bad block inode"));
1194                 goto fatal;
1195         }
1196
1197         ext2fs_badblocks_list_free(bb_list);
1198         return;
1199
1200 fatal:
1201         ctx->flags |= E2F_FLAG_ABORT;
1202         return;
1203
1204 }
1205
1206 static int check_bb_inode_blocks(ext2_filsys fs,
1207                                  blk_t *block_nr,
1208                                  int blockcnt FSCK_ATTR((unused)),
1209                                  void *priv_data FSCK_ATTR((unused)))
1210 {
1211         if (!*block_nr)
1212                 return 0;
1213
1214         /*
1215          * If the block number is outrageous, clear it and ignore it.
1216          */
1217         if (*block_nr >= fs->super->s_blocks_count ||
1218             *block_nr < fs->super->s_first_data_block) {
1219                 printf(_("Warning illegal block %u found in bad block inode.  Cleared.\n"), *block_nr);
1220                 *block_nr = 0;
1221                 return BLOCK_CHANGED;
1222         }
1223
1224         return 0;
1225 }
1226
1227 /*
1228  * Dictionary Abstract Data Type
1229  */
1230
1231
1232 /*
1233  * These macros provide short convenient names for structure members,
1234  * which are embellished with dict_ prefixes so that they are
1235  * properly confined to the documented namespace. It's legal for a
1236  * program which uses dict to define, for instance, a macro called ``parent''.
1237  * Such a macro would interfere with the dnode_t struct definition.
1238  * In general, highly portable and reusable C modules which expose their
1239  * structures need to confine structure member names to well-defined spaces.
1240  * The resulting identifiers aren't necessarily convenient to use, nor
1241  * readable, in the implementation, however!
1242  */
1243
1244 #define left dict_left
1245 #define right dict_right
1246 #define parent dict_parent
1247 #define color dict_color
1248 #define key dict_key
1249 #define data dict_data
1250
1251 #define nilnode dict_nilnode
1252 #define maxcount dict_maxcount
1253 #define compare dict_compare
1254 #define dupes dict_dupes
1255
1256 #define dict_root(D) ((D)->nilnode.left)
1257 #define dict_nil(D) (&(D)->nilnode)
1258 #define DICT_DEPTH_MAX 64
1259
1260 static void dnode_free(dnode_t *node);
1261
1262 /*
1263  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
1264  * its right child C are rearranged so that the P instead becomes the left
1265  * child of C.   The left subtree of C is inherited as the new right subtree
1266  * for P.  The ordering of the keys within the tree is thus preserved.
1267  */
1268
1269 static void rotate_left(dnode_t *upper)
1270 {
1271     dnode_t *lower, *lowleft, *upparent;
1272
1273     lower = upper->right;
1274     upper->right = lowleft = lower->left;
1275     lowleft->parent = upper;
1276
1277     lower->parent = upparent = upper->parent;
1278
1279     /* don't need to check for root node here because root->parent is
1280        the sentinel nil node, and root->parent->left points back to root */
1281
1282     if (upper == upparent->left) {
1283         upparent->left = lower;
1284     } else {
1285         assert (upper == upparent->right);
1286         upparent->right = lower;
1287     }
1288
1289     lower->left = upper;
1290     upper->parent = lower;
1291 }
1292
1293 /*
1294  * This operation is the ``mirror'' image of rotate_left. It is
1295  * the same procedure, but with left and right interchanged.
1296  */
1297
1298 static void rotate_right(dnode_t *upper)
1299 {
1300     dnode_t *lower, *lowright, *upparent;
1301
1302     lower = upper->left;
1303     upper->left = lowright = lower->right;
1304     lowright->parent = upper;
1305
1306     lower->parent = upparent = upper->parent;
1307
1308     if (upper == upparent->right) {
1309         upparent->right = lower;
1310     } else {
1311         assert (upper == upparent->left);
1312         upparent->left = lower;
1313     }
1314
1315     lower->right = upper;
1316     upper->parent = lower;
1317 }
1318
1319 /*
1320  * Do a postorder traversal of the tree rooted at the specified
1321  * node and free everything under it.  Used by dict_free().
1322  */
1323
1324 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1325 {
1326     if (node == nil)
1327         return;
1328     free_nodes(dict, node->left, nil);
1329     free_nodes(dict, node->right, nil);
1330     dict->dict_freenode(node);
1331 }
1332
1333 /*
1334  * Verify that the tree contains the given node. This is done by
1335  * traversing all of the nodes and comparing their pointers to the
1336  * given pointer. Returns 1 if the node is found, otherwise
1337  * returns zero. It is intended for debugging purposes.
1338  */
1339
1340 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1341 {
1342     if (root != nil) {
1343         return root == node
1344                 || verify_dict_has_node(nil, root->left, node)
1345                 || verify_dict_has_node(nil, root->right, node);
1346     }
1347     return 0;
1348 }
1349
1350
1351 /*
1352  * Select a different set of node allocator routines.
1353  */
1354
1355 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1356 {
1357     assert (dict_count(dict) == 0);
1358     dict->dict_freenode = fr;
1359 }
1360
1361 /*
1362  * Free all the nodes in the dictionary by using the dictionary's
1363  * installed free routine. The dictionary is emptied.
1364  */
1365
1366 static void dict_free_nodes(dict_t *dict)
1367 {
1368     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1369     free_nodes(dict, root, nil);
1370     dict->dict_nodecount = 0;
1371     dict->nilnode.left = &dict->nilnode;
1372     dict->nilnode.right = &dict->nilnode;
1373 }
1374
1375 /*
1376  * Initialize a user-supplied dictionary object.
1377  */
1378
1379 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1380 {
1381     dict->compare = comp;
1382     dict->dict_freenode = dnode_free;
1383     dict->dict_nodecount = 0;
1384     dict->maxcount = maxcount;
1385     dict->nilnode.left = &dict->nilnode;
1386     dict->nilnode.right = &dict->nilnode;
1387     dict->nilnode.parent = &dict->nilnode;
1388     dict->nilnode.color = dnode_black;
1389     dict->dupes = 0;
1390     return dict;
1391 }
1392
1393 /*
1394  * Locate a node in the dictionary having the given key.
1395  * If the node is not found, a null a pointer is returned (rather than
1396  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
1397  * located node is returned.
1398  */
1399
1400 static dnode_t *dict_lookup(dict_t *dict, const void *key)
1401 {
1402     dnode_t *root = dict_root(dict);
1403     dnode_t *nil = dict_nil(dict);
1404     dnode_t *saved;
1405     int result;
1406
1407     /* simple binary search adapted for trees that contain duplicate keys */
1408
1409     while (root != nil) {
1410         result = dict->compare(key, root->key);
1411         if (result < 0)
1412             root = root->left;
1413         else if (result > 0)
1414             root = root->right;
1415         else {
1416             if (!dict->dupes) { /* no duplicates, return match          */
1417                 return root;
1418             } else {            /* could be dupes, find leftmost one    */
1419                 do {
1420                     saved = root;
1421                     root = root->left;
1422                     while (root != nil && dict->compare(key, root->key))
1423                         root = root->right;
1424                 } while (root != nil);
1425                 return saved;
1426             }
1427         }
1428     }
1429
1430     return NULL;
1431 }
1432
1433 /*
1434  * Insert a node into the dictionary. The node should have been
1435  * initialized with a data field. All other fields are ignored.
1436  * The behavior is undefined if the user attempts to insert into
1437  * a dictionary that is already full (for which the dict_isfull()
1438  * function returns true).
1439  */
1440
1441 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1442 {
1443     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1444     dnode_t *parent = nil, *uncle, *grandpa;
1445     int result = -1;
1446
1447     node->key = key;
1448
1449     /* basic binary tree insert */
1450
1451     while (where != nil) {
1452         parent = where;
1453         result = dict->compare(key, where->key);
1454         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
1455         assert (dict->dupes || result != 0);
1456         if (result < 0)
1457             where = where->left;
1458         else
1459             where = where->right;
1460     }
1461
1462     assert (where == nil);
1463
1464     if (result < 0)
1465         parent->left = node;
1466     else
1467         parent->right = node;
1468
1469     node->parent = parent;
1470     node->left = nil;
1471     node->right = nil;
1472
1473     dict->dict_nodecount++;
1474
1475     /* red black adjustments */
1476
1477     node->color = dnode_red;
1478
1479     while (parent->color == dnode_red) {
1480         grandpa = parent->parent;
1481         if (parent == grandpa->left) {
1482             uncle = grandpa->right;
1483             if (uncle->color == dnode_red) {    /* red parent, red uncle */
1484                 parent->color = dnode_black;
1485                 uncle->color = dnode_black;
1486                 grandpa->color = dnode_red;
1487                 node = grandpa;
1488                 parent = grandpa->parent;
1489             } else {                            /* red parent, black uncle */
1490                 if (node == parent->right) {
1491                     rotate_left(parent);
1492                     parent = node;
1493                     assert (grandpa == parent->parent);
1494                     /* rotation between parent and child preserves grandpa */
1495                 }
1496                 parent->color = dnode_black;
1497                 grandpa->color = dnode_red;
1498                 rotate_right(grandpa);
1499                 break;
1500             }
1501         } else {        /* symmetric cases: parent == parent->parent->right */
1502             uncle = grandpa->left;
1503             if (uncle->color == dnode_red) {
1504                 parent->color = dnode_black;
1505                 uncle->color = dnode_black;
1506                 grandpa->color = dnode_red;
1507                 node = grandpa;
1508                 parent = grandpa->parent;
1509             } else {
1510                 if (node == parent->left) {
1511                     rotate_right(parent);
1512                     parent = node;
1513                     assert (grandpa == parent->parent);
1514                 }
1515                 parent->color = dnode_black;
1516                 grandpa->color = dnode_red;
1517                 rotate_left(grandpa);
1518                 break;
1519             }
1520         }
1521     }
1522
1523     dict_root(dict)->color = dnode_black;
1524
1525 }
1526
1527 /*
1528  * Allocate a node using the dictionary's allocator routine, give it
1529  * the data item.
1530  */
1531
1532 static dnode_t *dnode_init(dnode_t *dnode, void *data)
1533 {
1534     dnode->data = data;
1535     dnode->parent = NULL;
1536     dnode->left = NULL;
1537     dnode->right = NULL;
1538     return dnode;
1539 }
1540
1541 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1542 {
1543     dnode_t *node = malloc(sizeof(dnode_t));
1544
1545     if (node) {
1546         dnode_init(node, data);
1547         dict_insert(dict, node, key);
1548         return 1;
1549     }
1550     return 0;
1551 }
1552
1553 /*
1554  * Return the node with the lowest (leftmost) key. If the dictionary is empty
1555  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
1556  */
1557
1558 static dnode_t *dict_first(dict_t *dict)
1559 {
1560     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
1561
1562     if (root != nil)
1563         while ((left = root->left) != nil)
1564             root = left;
1565
1566     return (root == nil) ? NULL : root;
1567 }
1568
1569 /*
1570  * Return the given node's successor node---the node which has the
1571  * next key in the the left to right ordering. If the node has
1572  * no successor, a null pointer is returned rather than a pointer to
1573  * the nil node.
1574  */
1575
1576 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
1577 {
1578     dnode_t *nil = dict_nil(dict), *parent, *left;
1579
1580     if (curr->right != nil) {
1581         curr = curr->right;
1582         while ((left = curr->left) != nil)
1583             curr = left;
1584         return curr;
1585     }
1586
1587     parent = curr->parent;
1588
1589     while (parent != nil && curr == parent->right) {
1590         curr = parent;
1591         parent = curr->parent;
1592     }
1593
1594     return (parent == nil) ? NULL : parent;
1595 }
1596
1597
1598 static void dnode_free(dnode_t *node)
1599 {
1600     free(node);
1601 }
1602
1603
1604 #undef left
1605 #undef right
1606 #undef parent
1607 #undef color
1608 #undef key
1609 #undef data
1610
1611 #undef nilnode
1612 #undef maxcount
1613 #undef compare
1614 #undef dupes
1615
1616
1617 /*
1618  * dirinfo.c --- maintains the directory information table for e2fsck.
1619  */
1620
1621 /*
1622  * This subroutine is called during pass1 to create a directory info
1623  * entry.  During pass1, the passed-in parent is 0; it will get filled
1624  * in during pass2.
1625  */
1626 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
1627 {
1628         struct dir_info *dir;
1629         int             i, j;
1630         ext2_ino_t      num_dirs;
1631         errcode_t       retval;
1632         unsigned long   old_size;
1633
1634 #if 0
1635         printf("add_dir_info for inode %lu...\n", ino);
1636 #endif
1637         if (!ctx->dir_info) {
1638                 ctx->dir_info_count = 0;
1639                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
1640                 if (retval)
1641                         num_dirs = 1024;        /* Guess */
1642                 ctx->dir_info_size = num_dirs + 10;
1643                 ctx->dir_info  = (struct dir_info *)
1644                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
1645                                                * sizeof (struct dir_info),
1646                                                "directory map");
1647         }
1648
1649         if (ctx->dir_info_count >= ctx->dir_info_size) {
1650                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
1651                 ctx->dir_info_size += 10;
1652                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
1653                                            sizeof(struct dir_info),
1654                                            &ctx->dir_info);
1655                 if (retval) {
1656                         ctx->dir_info_size -= 10;
1657                         return;
1658                 }
1659         }
1660
1661         /*
1662          * Normally, add_dir_info is called with each inode in
1663          * sequential order; but once in a while (like when pass 3
1664          * needs to recreate the root directory or lost+found
1665          * directory) it is called out of order.  In those cases, we
1666          * need to move the dir_info entries down to make room, since
1667          * the dir_info array needs to be sorted by inode number for
1668          * get_dir_info()'s sake.
1669          */
1670         if (ctx->dir_info_count &&
1671             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
1672                 for (i = ctx->dir_info_count-1; i > 0; i--)
1673                         if (ctx->dir_info[i-1].ino < ino)
1674                                 break;
1675                 dir = &ctx->dir_info[i];
1676                 if (dir->ino != ino)
1677                         for (j = ctx->dir_info_count++; j > i; j--)
1678                                 ctx->dir_info[j] = ctx->dir_info[j-1];
1679         } else
1680                 dir = &ctx->dir_info[ctx->dir_info_count++];
1681
1682         dir->ino = ino;
1683         dir->dotdot = parent;
1684         dir->parent = parent;
1685 }
1686
1687 /*
1688  * get_dir_info() --- given an inode number, try to find the directory
1689  * information entry for it.
1690  */
1691 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
1692 {
1693         int     low, high, mid;
1694
1695         low = 0;
1696         high = ctx->dir_info_count-1;
1697         if (!ctx->dir_info)
1698                 return 0;
1699         if (ino == ctx->dir_info[low].ino)
1700                 return &ctx->dir_info[low];
1701         if  (ino == ctx->dir_info[high].ino)
1702                 return &ctx->dir_info[high];
1703
1704         while (low < high) {
1705                 mid = (low+high)/2;
1706                 if (mid == low || mid == high)
1707                         break;
1708                 if (ino == ctx->dir_info[mid].ino)
1709                         return &ctx->dir_info[mid];
1710                 if (ino < ctx->dir_info[mid].ino)
1711                         high = mid;
1712                 else
1713                         low = mid;
1714         }
1715         return 0;
1716 }
1717
1718 /*
1719  * Free the dir_info structure when it isn't needed any more.
1720  */
1721 static void e2fsck_free_dir_info(e2fsck_t ctx)
1722 {
1723         ext2fs_free_mem(&ctx->dir_info);
1724         ctx->dir_info_size = 0;
1725         ctx->dir_info_count = 0;
1726 }
1727
1728 /*
1729  * Return the count of number of directories in the dir_info structure
1730  */
1731 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
1732 {
1733         return ctx->dir_info_count;
1734 }
1735
1736 /*
1737  * A simple interator function
1738  */
1739 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
1740 {
1741         if (*control >= ctx->dir_info_count)
1742                 return 0;
1743
1744         return(ctx->dir_info + (*control)++);
1745 }
1746
1747 /*
1748  * dirinfo.c --- maintains the directory information table for e2fsck.
1749  *
1750  */
1751
1752 #ifdef ENABLE_HTREE
1753
1754 /*
1755  * This subroutine is called during pass1 to create a directory info
1756  * entry.  During pass1, the passed-in parent is 0; it will get filled
1757  * in during pass2.
1758  */
1759 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
1760 {
1761         struct dx_dir_info *dir;
1762         int             i, j;
1763         errcode_t       retval;
1764         unsigned long   old_size;
1765
1766 #if 0
1767         printf("add_dx_dir_info for inode %lu...\n", ino);
1768 #endif
1769         if (!ctx->dx_dir_info) {
1770                 ctx->dx_dir_info_count = 0;
1771                 ctx->dx_dir_info_size = 100; /* Guess */
1772                 ctx->dx_dir_info  = (struct dx_dir_info *)
1773                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
1774                                                * sizeof (struct dx_dir_info),
1775                                                "directory map");
1776         }
1777
1778         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
1779                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
1780                 ctx->dx_dir_info_size += 10;
1781                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
1782                                            sizeof(struct dx_dir_info),
1783                                            &ctx->dx_dir_info);
1784                 if (retval) {
1785                         ctx->dx_dir_info_size -= 10;
1786                         return;
1787                 }
1788         }
1789
1790         /*
1791          * Normally, add_dx_dir_info is called with each inode in
1792          * sequential order; but once in a while (like when pass 3
1793          * needs to recreate the root directory or lost+found
1794          * directory) it is called out of order.  In those cases, we
1795          * need to move the dx_dir_info entries down to make room, since
1796          * the dx_dir_info array needs to be sorted by inode number for
1797          * get_dx_dir_info()'s sake.
1798          */
1799         if (ctx->dx_dir_info_count &&
1800             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
1801                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
1802                         if (ctx->dx_dir_info[i-1].ino < ino)
1803                                 break;
1804                 dir = &ctx->dx_dir_info[i];
1805                 if (dir->ino != ino)
1806                         for (j = ctx->dx_dir_info_count++; j > i; j--)
1807                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
1808         } else
1809                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
1810
1811         dir->ino = ino;
1812         dir->numblocks = num_blocks;
1813         dir->hashversion = 0;
1814         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
1815                                        * sizeof (struct dx_dirblock_info),
1816                                        "dx_block info array");
1817
1818 }
1819
1820 /*
1821  * get_dx_dir_info() --- given an inode number, try to find the directory
1822  * information entry for it.
1823  */
1824 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
1825 {
1826         int     low, high, mid;
1827
1828         low = 0;
1829         high = ctx->dx_dir_info_count-1;
1830         if (!ctx->dx_dir_info)
1831                 return 0;
1832         if (ino == ctx->dx_dir_info[low].ino)
1833                 return &ctx->dx_dir_info[low];
1834         if  (ino == ctx->dx_dir_info[high].ino)
1835                 return &ctx->dx_dir_info[high];
1836
1837         while (low < high) {
1838                 mid = (low+high)/2;
1839                 if (mid == low || mid == high)
1840                         break;
1841                 if (ino == ctx->dx_dir_info[mid].ino)
1842                         return &ctx->dx_dir_info[mid];
1843                 if (ino < ctx->dx_dir_info[mid].ino)
1844                         high = mid;
1845                 else
1846                         low = mid;
1847         }
1848         return 0;
1849 }
1850
1851 /*
1852  * Free the dx_dir_info structure when it isn't needed any more.
1853  */
1854 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
1855 {
1856         int     i;
1857         struct dx_dir_info *dir;
1858
1859         if (ctx->dx_dir_info) {
1860                 dir = ctx->dx_dir_info;
1861                 for (i=0; i < ctx->dx_dir_info_count; i++) {
1862                         ext2fs_free_mem(&dir->dx_block);
1863                 }
1864                 ext2fs_free_mem(&ctx->dx_dir_info);
1865         }
1866         ctx->dx_dir_info_size = 0;
1867         ctx->dx_dir_info_count = 0;
1868 }
1869
1870 /*
1871  * A simple interator function
1872  */
1873 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
1874 {
1875         if (*control >= ctx->dx_dir_info_count)
1876                 return 0;
1877
1878         return(ctx->dx_dir_info + (*control)++);
1879 }
1880
1881 #endif /* ENABLE_HTREE */
1882 /*
1883  * e2fsck.c - a consistency checker for the new extended file system.
1884  *
1885  */
1886
1887 /*
1888  * This function allocates an e2fsck context
1889  */
1890 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
1891 {
1892         e2fsck_t        context;
1893         errcode_t       retval;
1894
1895         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
1896         if (retval)
1897                 return retval;
1898
1899         memset(context, 0, sizeof(struct e2fsck_struct));
1900
1901         context->process_inode_size = 256;
1902         context->ext_attr_ver = 2;
1903
1904         *ret = context;
1905         return 0;
1906 }
1907
1908 struct ea_refcount_el {
1909         blk_t   ea_blk;
1910         int     ea_count;
1911 };
1912
1913 struct ea_refcount {
1914         blk_t           count;
1915         blk_t           size;
1916         blk_t           cursor;
1917         struct ea_refcount_el   *list;
1918 };
1919
1920 static void ea_refcount_free(ext2_refcount_t refcount)
1921 {
1922         if (!refcount)
1923                 return;
1924
1925         ext2fs_free_mem(&refcount->list);
1926         ext2fs_free_mem(&refcount);
1927 }
1928
1929 /*
1930  * This function resets an e2fsck context; it is called when e2fsck
1931  * needs to be restarted.
1932  */
1933 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
1934 {
1935         ctx->flags = 0;
1936         ctx->lost_and_found = 0;
1937         ctx->bad_lost_and_found = 0;
1938         ext2fs_free_inode_bitmap(ctx->inode_used_map);
1939         ctx->inode_used_map = 0;
1940         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
1941         ctx->inode_dir_map = 0;
1942         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
1943         ctx->inode_reg_map = 0;
1944         ext2fs_free_block_bitmap(ctx->block_found_map);
1945         ctx->block_found_map = 0;
1946         ext2fs_free_icount(ctx->inode_link_info);
1947         ctx->inode_link_info = 0;
1948         if (ctx->journal_io) {
1949                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1950                         io_channel_close(ctx->journal_io);
1951                 ctx->journal_io = 0;
1952         }
1953         if (ctx->fs) {
1954                 ext2fs_free_dblist(ctx->fs->dblist);
1955                 ctx->fs->dblist = 0;
1956         }
1957         e2fsck_free_dir_info(ctx);
1958 #ifdef ENABLE_HTREE
1959         e2fsck_free_dx_dir_info(ctx);
1960 #endif
1961         ea_refcount_free(ctx->refcount);
1962         ctx->refcount = 0;
1963         ea_refcount_free(ctx->refcount_extra);
1964         ctx->refcount_extra = 0;
1965         ext2fs_free_block_bitmap(ctx->block_dup_map);
1966         ctx->block_dup_map = 0;
1967         ext2fs_free_block_bitmap(ctx->block_ea_map);
1968         ctx->block_ea_map = 0;
1969         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
1970         ctx->inode_bb_map = 0;
1971         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
1972         ctx->inode_bad_map = 0;
1973         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
1974         ctx->inode_imagic_map = 0;
1975         ext2fs_u32_list_free(ctx->dirs_to_hash);
1976         ctx->dirs_to_hash = 0;
1977
1978         /*
1979          * Clear the array of invalid meta-data flags
1980          */
1981         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
1982         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
1983         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
1984
1985         /* Clear statistic counters */
1986         ctx->fs_directory_count = 0;
1987         ctx->fs_regular_count = 0;
1988         ctx->fs_blockdev_count = 0;
1989         ctx->fs_chardev_count = 0;
1990         ctx->fs_links_count = 0;
1991         ctx->fs_symlinks_count = 0;
1992         ctx->fs_fast_symlinks_count = 0;
1993         ctx->fs_fifo_count = 0;
1994         ctx->fs_total_count = 0;
1995         ctx->fs_badblocks_count = 0;
1996         ctx->fs_sockets_count = 0;
1997         ctx->fs_ind_count = 0;
1998         ctx->fs_dind_count = 0;
1999         ctx->fs_tind_count = 0;
2000         ctx->fs_fragmented = 0;
2001         ctx->large_files = 0;
2002
2003         /* Reset the superblock to the user's requested value */
2004         ctx->superblock = ctx->use_superblock;
2005
2006         return 0;
2007 }
2008
2009 static void e2fsck_free_context(e2fsck_t ctx)
2010 {
2011         if (!ctx)
2012                 return;
2013
2014         e2fsck_reset_context(ctx);
2015         if (ctx->blkid)
2016                 blkid_put_cache(ctx->blkid);
2017
2018         ext2fs_free_mem(&ctx);
2019 }
2020
2021 /*
2022  * ea_refcount.c
2023  */
2024
2025 /*
2026  * The strategy we use for keeping track of EA refcounts is as
2027  * follows.  We keep a sorted array of first EA blocks and its
2028  * reference counts.  Once the refcount has dropped to zero, it is
2029  * removed from the array to save memory space.  Once the EA block is
2030  * checked, its bit is set in the block_ea_map bitmap.
2031  */
2032
2033
2034 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2035 {
2036         ext2_refcount_t refcount;
2037         errcode_t       retval;
2038         size_t          bytes;
2039
2040         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2041         if (retval)
2042                 return retval;
2043         memset(refcount, 0, sizeof(struct ea_refcount));
2044
2045         if (!size)
2046                 size = 500;
2047         refcount->size = size;
2048         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2049 #ifdef DEBUG
2050         printf("Refcount allocated %d entries, %d bytes.\n",
2051                refcount->size, bytes);
2052 #endif
2053         retval = ext2fs_get_mem(bytes, &refcount->list);
2054         if (retval)
2055                 goto errout;
2056         memset(refcount->list, 0, bytes);
2057
2058         refcount->count = 0;
2059         refcount->cursor = 0;
2060
2061         *ret = refcount;
2062         return 0;
2063
2064 errout:
2065         ea_refcount_free(refcount);
2066         return(retval);
2067 }
2068
2069 /*
2070  * collapse_refcount() --- go through the refcount array, and get rid
2071  * of any count == zero entries
2072  */
2073 static void refcount_collapse(ext2_refcount_t refcount)
2074 {
2075         unsigned int    i, j;
2076         struct ea_refcount_el   *list;
2077
2078         list = refcount->list;
2079         for (i = 0, j = 0; i < refcount->count; i++) {
2080                 if (list[i].ea_count) {
2081                         if (i != j)
2082                                 list[j] = list[i];
2083                         j++;
2084                 }
2085         }
2086 #if defined(DEBUG) || defined(TEST_PROGRAM)
2087         printf("Refcount_collapse: size was %d, now %d\n",
2088                refcount->count, j);
2089 #endif
2090         refcount->count = j;
2091 }
2092
2093
2094 /*
2095  * insert_refcount_el() --- Insert a new entry into the sorted list at a
2096  *      specified position.
2097  */
2098 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2099                                                  blk_t blk, int pos)
2100 {
2101         struct ea_refcount_el   *el;
2102         errcode_t               retval;
2103         blk_t                   new_size = 0;
2104         int                     num;
2105
2106         if (refcount->count >= refcount->size) {
2107                 new_size = refcount->size + 100;
2108 #ifdef DEBUG
2109                 printf("Reallocating refcount %d entries...\n", new_size);
2110 #endif
2111                 retval = ext2fs_resize_mem((size_t) refcount->size *
2112                                            sizeof(struct ea_refcount_el),
2113                                            (size_t) new_size *
2114                                            sizeof(struct ea_refcount_el),
2115                                            &refcount->list);
2116                 if (retval)
2117                         return 0;
2118                 refcount->size = new_size;
2119         }
2120         num = (int) refcount->count - pos;
2121         if (num < 0)
2122                 return 0;       /* should never happen */
2123         if (num) {
2124                 memmove(&refcount->list[pos+1], &refcount->list[pos],
2125                         sizeof(struct ea_refcount_el) * num);
2126         }
2127         refcount->count++;
2128         el = &refcount->list[pos];
2129         el->ea_count = 0;
2130         el->ea_blk = blk;
2131         return el;
2132 }
2133
2134
2135 /*
2136  * get_refcount_el() --- given an block number, try to find refcount
2137  *      information in the sorted list.  If the create flag is set,
2138  *      and we can't find an entry, create one in the sorted list.
2139  */
2140 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2141                                               blk_t blk, int create)
2142 {
2143         float   range;
2144         int     low, high, mid;
2145         blk_t   lowval, highval;
2146
2147         if (!refcount || !refcount->list)
2148                 return 0;
2149 retry:
2150         low = 0;
2151         high = (int) refcount->count-1;
2152         if (create && ((refcount->count == 0) ||
2153                        (blk > refcount->list[high].ea_blk))) {
2154                 if (refcount->count >= refcount->size)
2155                         refcount_collapse(refcount);
2156
2157                 return insert_refcount_el(refcount, blk,
2158                                           (unsigned) refcount->count);
2159         }
2160         if (refcount->count == 0)
2161                 return 0;
2162
2163         if (refcount->cursor >= refcount->count)
2164                 refcount->cursor = 0;
2165         if (blk == refcount->list[refcount->cursor].ea_blk)
2166                 return &refcount->list[refcount->cursor++];
2167 #ifdef DEBUG
2168         printf("Non-cursor get_refcount_el: %u\n", blk);
2169 #endif
2170         while (low <= high) {
2171 #if 0
2172                 mid = (low+high)/2;
2173 #else
2174                 if (low == high)
2175                         mid = low;
2176                 else {
2177                         /* Interpolate for efficiency */
2178                         lowval = refcount->list[low].ea_blk;
2179                         highval = refcount->list[high].ea_blk;
2180
2181                         if (blk < lowval)
2182                                 range = 0;
2183                         else if (blk > highval)
2184                                 range = 1;
2185                         else
2186                                 range = ((float) (blk - lowval)) /
2187                                         (highval - lowval);
2188                         mid = low + ((int) (range * (high-low)));
2189                 }
2190 #endif
2191                 if (blk == refcount->list[mid].ea_blk) {
2192                         refcount->cursor = mid+1;
2193                         return &refcount->list[mid];
2194                 }
2195                 if (blk < refcount->list[mid].ea_blk)
2196                         high = mid-1;
2197                 else
2198                         low = mid+1;
2199         }
2200         /*
2201          * If we need to create a new entry, it should be right at
2202          * low (where high will be left at low-1).
2203          */
2204         if (create) {
2205                 if (refcount->count >= refcount->size) {
2206                         refcount_collapse(refcount);
2207                         if (refcount->count < refcount->size)
2208                                 goto retry;
2209                 }
2210                 return insert_refcount_el(refcount, blk, low);
2211         }
2212         return 0;
2213 }
2214
2215 static errcode_t
2216 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2217 {
2218         struct ea_refcount_el   *el;
2219
2220         el = get_refcount_el(refcount, blk, 1);
2221         if (!el)
2222                 return EXT2_ET_NO_MEMORY;
2223         el->ea_count++;
2224
2225         if (ret)
2226                 *ret = el->ea_count;
2227         return 0;
2228 }
2229
2230 static errcode_t
2231 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2232 {
2233         struct ea_refcount_el   *el;
2234
2235         el = get_refcount_el(refcount, blk, 0);
2236         if (!el || el->ea_count == 0)
2237                 return EXT2_ET_INVALID_ARGUMENT;
2238
2239         el->ea_count--;
2240
2241         if (ret)
2242                 *ret = el->ea_count;
2243         return 0;
2244 }
2245
2246 static errcode_t
2247 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2248 {
2249         struct ea_refcount_el   *el;
2250
2251         /*
2252          * Get the refcount element
2253          */
2254         el = get_refcount_el(refcount, blk, count ? 1 : 0);
2255         if (!el)
2256                 return count ? EXT2_ET_NO_MEMORY : 0;
2257         el->ea_count = count;
2258         return 0;
2259 }
2260
2261 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2262 {
2263         refcount->cursor = 0;
2264 }
2265
2266
2267 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2268 {
2269         struct ea_refcount_el   *list;
2270
2271         while (1) {
2272                 if (refcount->cursor >= refcount->count)
2273                         return 0;
2274                 list = refcount->list;
2275                 if (list[refcount->cursor].ea_count) {
2276                         if (ret)
2277                                 *ret = list[refcount->cursor].ea_count;
2278                         return list[refcount->cursor++].ea_blk;
2279                 }
2280                 refcount->cursor++;
2281         }
2282 }
2283
2284
2285 /*
2286  * ehandler.c --- handle bad block errors which come up during the
2287  *      course of an e2fsck session.
2288  */
2289
2290
2291 static const char *operation;
2292
2293 static errcode_t
2294 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2295                          void *data, size_t size FSCK_ATTR((unused)),
2296                          int actual FSCK_ATTR((unused)), errcode_t error)
2297 {
2298         int     i;
2299         char    *p;
2300         ext2_filsys fs = (ext2_filsys) channel->app_data;
2301         e2fsck_t ctx;
2302
2303         ctx = (e2fsck_t) fs->priv_data;
2304
2305         /*
2306          * If more than one block was read, try reading each block
2307          * separately.  We could use the actual bytes read to figure
2308          * out where to start, but we don't bother.
2309          */
2310         if (count > 1) {
2311                 p = (char *) data;
2312                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2313                         error = io_channel_read_blk(channel, block,
2314                                                     1, p);
2315                         if (error)
2316                                 return error;
2317                 }
2318                 return 0;
2319         }
2320         if (operation)
2321                 printf(_("Error reading block %lu (%s) while %s.  "), block,
2322                        error_message(error), operation);
2323         else
2324                 printf(_("Error reading block %lu (%s).  "), block,
2325                        error_message(error));
2326         preenhalt(ctx);
2327         if (ask(ctx, _("Ignore error"), 1)) {
2328                 if (ask(ctx, _("Force rewrite"), 1))
2329                         io_channel_write_blk(channel, block, 1, data);
2330                 return 0;
2331         }
2332
2333         return error;
2334 }
2335
2336 static errcode_t
2337 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2338                         const void *data, size_t size FSCK_ATTR((unused)),
2339                         int actual FSCK_ATTR((unused)), errcode_t error)
2340 {
2341         int             i;
2342         const char      *p;
2343         ext2_filsys fs = (ext2_filsys) channel->app_data;
2344         e2fsck_t ctx;
2345
2346         ctx = (e2fsck_t) fs->priv_data;
2347
2348         /*
2349          * If more than one block was written, try writing each block
2350          * separately.  We could use the actual bytes read to figure
2351          * out where to start, but we don't bother.
2352          */
2353         if (count > 1) {
2354                 p = (const char *) data;
2355                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2356                         error = io_channel_write_blk(channel, block,
2357                                                      1, p);
2358                         if (error)
2359                                 return error;
2360                 }
2361                 return 0;
2362         }
2363
2364         if (operation)
2365                 printf(_("Error writing block %lu (%s) while %s.  "), block,
2366                        error_message(error), operation);
2367         else
2368                 printf(_("Error writing block %lu (%s).  "), block,
2369                        error_message(error));
2370         preenhalt(ctx);
2371         if (ask(ctx, _("Ignore error"), 1))
2372                 return 0;
2373
2374         return error;
2375 }
2376
2377 static inline const char *ehandler_operation(const char *op)
2378 {
2379         const char *ret = operation;
2380
2381         operation = op;
2382         return ret;
2383 }
2384
2385 static void ehandler_init(io_channel channel)
2386 {
2387         channel->read_error = e2fsck_handle_read_error;
2388         channel->write_error = e2fsck_handle_write_error;
2389 }
2390
2391 /*
2392  * journal.c --- code for handling the "ext3" journal
2393  *
2394  * Copyright (C) 2000 Andreas Dilger
2395  * Copyright (C) 2000 Theodore Ts'o
2396  *
2397  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2398  * Copyright (C) 1999 Red Hat Software
2399  *
2400  * This file may be redistributed under the terms of the
2401  * GNU General Public License version 2 or at your discretion
2402  * any later version.
2403  */
2404
2405 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2406
2407 /*
2408  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2409  * This creates a larger static binary, and a smaller binary using
2410  * shared libraries.  It's also probably slightly less CPU-efficient,
2411  * which is why it's not on by default.  But, it's a good way of
2412  * testing the functions in inode_io.c and fileio.c.
2413  */
2414 #undef USE_INODE_IO
2415
2416 /* Kernel compatibility functions for handling the journal.  These allow us
2417  * to use the recovery.c file virtually unchanged from the kernel, so we
2418  * don't have to do much to keep kernel and user recovery in sync.
2419  */
2420 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2421 {
2422 #ifdef USE_INODE_IO
2423         *phys = block;
2424         return 0;
2425 #else
2426         struct inode    *inode = journal->j_inode;
2427         errcode_t       retval;
2428         blk_t           pblk;
2429
2430         if (!inode) {
2431                 *phys = block;
2432                 return 0;
2433         }
2434
2435         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2436                             &inode->i_ext2, NULL, 0, block, &pblk);
2437         *phys = pblk;
2438         return (retval);
2439 #endif
2440 }
2441
2442 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2443 {
2444         struct buffer_head *bh;
2445
2446         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2447         if (!bh)
2448                 return NULL;
2449
2450         bh->b_ctx = kdev->k_ctx;
2451         if (kdev->k_dev == K_DEV_FS)
2452                 bh->b_io = kdev->k_ctx->fs->io;
2453         else
2454                 bh->b_io = kdev->k_ctx->journal_io;
2455         bh->b_size = blocksize;
2456         bh->b_blocknr = blocknr;
2457
2458         return bh;
2459 }
2460
2461 static void sync_blockdev(kdev_t kdev)
2462 {
2463         io_channel      io;
2464
2465         if (kdev->k_dev == K_DEV_FS)
2466                 io = kdev->k_ctx->fs->io;
2467         else
2468                 io = kdev->k_ctx->journal_io;
2469
2470         io_channel_flush(io);
2471 }
2472
2473 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2474 {
2475         int retval;
2476         struct buffer_head *bh;
2477
2478         for (; nr > 0; --nr) {
2479                 bh = *bhp++;
2480                 if (rw == READ && !bh->b_uptodate) {
2481                         retval = io_channel_read_blk(bh->b_io,
2482                                                      bh->b_blocknr,
2483                                                      1, bh->b_data);
2484                         if (retval) {
2485                                 com_err(bh->b_ctx->device_name, retval,
2486                                         "while reading block %lu\n",
2487                                         (unsigned long) bh->b_blocknr);
2488                                 bh->b_err = retval;
2489                                 continue;
2490                         }
2491                         bh->b_uptodate = 1;
2492                 } else if (rw == WRITE && bh->b_dirty) {
2493                         retval = io_channel_write_blk(bh->b_io,
2494                                                       bh->b_blocknr,
2495                                                       1, bh->b_data);
2496                         if (retval) {
2497                                 com_err(bh->b_ctx->device_name, retval,
2498                                         "while writing block %lu\n",
2499                                         (unsigned long) bh->b_blocknr);
2500                                 bh->b_err = retval;
2501                                 continue;
2502                         }
2503                         bh->b_dirty = 0;
2504                         bh->b_uptodate = 1;
2505                 }
2506         }
2507 }
2508
2509 static inline void mark_buffer_dirty(struct buffer_head *bh)
2510 {
2511         bh->b_dirty = 1;
2512 }
2513
2514 static inline void mark_buffer_clean(struct buffer_head * bh)
2515 {
2516         bh->b_dirty = 0;
2517 }
2518
2519 static void brelse(struct buffer_head *bh)
2520 {
2521         if (bh->b_dirty)
2522                 ll_rw_block(WRITE, 1, &bh);
2523         ext2fs_free_mem(&bh);
2524 }
2525
2526 static inline int buffer_uptodate(struct buffer_head *bh)
2527 {
2528         return bh->b_uptodate;
2529 }
2530
2531 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2532 {
2533         bh->b_uptodate = val;
2534 }
2535
2536 static void wait_on_buffer(struct buffer_head *bh)
2537 {
2538         if (!bh->b_uptodate)
2539                 ll_rw_block(READ, 1, &bh);
2540 }
2541
2542
2543 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2544 {
2545         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2546
2547         /* if we had an error doing journal recovery, we need a full fsck */
2548         if (error)
2549                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2550         ext2fs_mark_super_dirty(ctx->fs);
2551 }
2552
2553 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2554 {
2555         struct ext2_super_block *sb = ctx->fs->super;
2556         struct ext2_super_block jsuper;
2557         struct problem_context  pctx;
2558         struct buffer_head      *bh;
2559         struct inode            *j_inode = NULL;
2560         struct kdev_s           *dev_fs = NULL, *dev_journal;
2561         const char              *journal_name = 0;
2562         journal_t               *journal = NULL;
2563         errcode_t               retval = 0;
2564         io_manager              io_ptr = 0;
2565         unsigned long           start = 0;
2566         blk_t                   blk;
2567         int                     ext_journal = 0;
2568         int                     tried_backup_jnl = 0;
2569         int                     i;
2570
2571         clear_problem_context(&pctx);
2572
2573         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2574         if (!journal) {
2575                 return EXT2_ET_NO_MEMORY;
2576         }
2577
2578         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2579         if (!dev_fs) {
2580                 retval = EXT2_ET_NO_MEMORY;
2581                 goto errout;
2582         }
2583         dev_journal = dev_fs+1;
2584
2585         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2586         dev_fs->k_dev = K_DEV_FS;
2587         dev_journal->k_dev = K_DEV_JOURNAL;
2588
2589         journal->j_dev = dev_journal;
2590         journal->j_fs_dev = dev_fs;
2591         journal->j_inode = NULL;
2592         journal->j_blocksize = ctx->fs->blocksize;
2593
2594         if (uuid_is_null(sb->s_journal_uuid)) {
2595                 if (!sb->s_journal_inum)
2596                         return EXT2_ET_BAD_INODE_NUM;
2597                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2598                                                  "journal inode");
2599                 if (!j_inode) {
2600                         retval = EXT2_ET_NO_MEMORY;
2601                         goto errout;
2602                 }
2603
2604                 j_inode->i_ctx = ctx;
2605                 j_inode->i_ino = sb->s_journal_inum;
2606
2607                 if ((retval = ext2fs_read_inode(ctx->fs,
2608                                                 sb->s_journal_inum,
2609                                                 &j_inode->i_ext2))) {
2610                 try_backup_journal:
2611                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
2612                             tried_backup_jnl)
2613                                 goto errout;
2614                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
2615                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
2616                                EXT2_N_BLOCKS*4);
2617                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
2618                         j_inode->i_ext2.i_links_count = 1;
2619                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
2620                         tried_backup_jnl++;
2621                 }
2622                 if (!j_inode->i_ext2.i_links_count ||
2623                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
2624                         retval = EXT2_ET_NO_JOURNAL;
2625                         goto try_backup_journal;
2626                 }
2627                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
2628                     JFS_MIN_JOURNAL_BLOCKS) {
2629                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
2630                         goto try_backup_journal;
2631                 }
2632                 for (i=0; i < EXT2_N_BLOCKS; i++) {
2633                         blk = j_inode->i_ext2.i_block[i];
2634                         if (!blk) {
2635                                 if (i < EXT2_NDIR_BLOCKS) {
2636                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
2637                                         goto try_backup_journal;
2638                                 }
2639                                 continue;
2640                         }
2641                         if (blk < sb->s_first_data_block ||
2642                             blk >= sb->s_blocks_count) {
2643                                 retval = EXT2_ET_BAD_BLOCK_NUM;
2644                                 goto try_backup_journal;
2645                         }
2646                 }
2647                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
2648
2649 #ifdef USE_INODE_IO
2650                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
2651                                                  &j_inode->i_ext2,
2652                                                  &journal_name);
2653                 if (retval)
2654                         goto errout;
2655
2656                 io_ptr = inode_io_manager;
2657 #else
2658                 journal->j_inode = j_inode;
2659                 ctx->journal_io = ctx->fs->io;
2660                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
2661                         goto errout;
2662 #endif
2663         } else {
2664                 ext_journal = 1;
2665                 if (!ctx->journal_name) {
2666                         char uuid[37];
2667
2668                         uuid_unparse(sb->s_journal_uuid, uuid);
2669                         ctx->journal_name = blkid_get_devname(ctx->blkid,
2670                                                               "UUID", uuid);
2671                         if (!ctx->journal_name)
2672                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
2673                 }
2674                 journal_name = ctx->journal_name;
2675
2676                 if (!journal_name) {
2677                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
2678                         return EXT2_ET_LOAD_EXT_JOURNAL;
2679                 }
2680
2681                 io_ptr = unix_io_manager;
2682         }
2683
2684 #ifndef USE_INODE_IO
2685         if (ext_journal)
2686 #endif
2687                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
2688                                       &ctx->journal_io);
2689         if (retval)
2690                 goto errout;
2691
2692         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
2693
2694         if (ext_journal) {
2695                 if (ctx->fs->blocksize == 1024)
2696                         start = 1;
2697                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
2698                 if (!bh) {
2699                         retval = EXT2_ET_NO_MEMORY;
2700                         goto errout;
2701                 }
2702                 ll_rw_block(READ, 1, &bh);
2703                 if ((retval = bh->b_err) != 0)
2704                         goto errout;
2705                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
2706                        sizeof(jsuper));
2707                 brelse(bh);
2708 #ifdef EXT2FS_ENABLE_SWAPFS
2709                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
2710                         ext2fs_swap_super(&jsuper);
2711 #endif
2712                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
2713                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
2714                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
2715                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
2716                         goto errout;
2717                 }
2718                 /* Make sure the journal UUID is correct */
2719                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
2720                            sizeof(jsuper.s_uuid))) {
2721                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
2722                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
2723                         goto errout;
2724                 }
2725
2726                 journal->j_maxlen = jsuper.s_blocks_count;
2727                 start++;
2728         }
2729
2730         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
2731                 retval = EXT2_ET_NO_MEMORY;
2732                 goto errout;
2733         }
2734
2735         journal->j_sb_buffer = bh;
2736         journal->j_superblock = (journal_superblock_t *)bh->b_data;
2737
2738 #ifdef USE_INODE_IO
2739         ext2fs_free_mem(&j_inode);
2740 #endif
2741
2742         *ret_journal = journal;
2743         return 0;
2744
2745 errout:
2746         ext2fs_free_mem(&dev_fs);
2747         ext2fs_free_mem(&j_inode);
2748         ext2fs_free_mem(&journal);
2749         return retval;
2750
2751 }
2752
2753 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
2754                                               struct problem_context *pctx)
2755 {
2756         struct ext2_super_block *sb = ctx->fs->super;
2757         int recover = ctx->fs->super->s_feature_incompat &
2758                 EXT3_FEATURE_INCOMPAT_RECOVER;
2759         int has_journal = ctx->fs->super->s_feature_compat &
2760                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2761
2762         if (has_journal || sb->s_journal_inum) {
2763                 /* The journal inode is bogus, remove and force full fsck */
2764                 pctx->ino = sb->s_journal_inum;
2765                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
2766                         if (has_journal && sb->s_journal_inum)
2767                                 printf("*** ext3 journal has been deleted - "
2768                                        "filesystem is now ext2 only ***\n\n");
2769                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2770                         sb->s_journal_inum = 0;
2771                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
2772                         e2fsck_clear_recover(ctx, 1);
2773                         return 0;
2774                 }
2775                 return EXT2_ET_BAD_INODE_NUM;
2776         } else if (recover) {
2777                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
2778                         e2fsck_clear_recover(ctx, 1);
2779                         return 0;
2780                 }
2781                 return EXT2_ET_UNSUPP_FEATURE;
2782         }
2783         return 0;
2784 }
2785
2786 #define V1_SB_SIZE      0x0024
2787 static void clear_v2_journal_fields(journal_t *journal)
2788 {
2789         e2fsck_t ctx = journal->j_dev->k_ctx;
2790         struct problem_context pctx;
2791
2792         clear_problem_context(&pctx);
2793
2794         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
2795                 return;
2796
2797         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
2798                ctx->fs->blocksize-V1_SB_SIZE);
2799         mark_buffer_dirty(journal->j_sb_buffer);
2800 }
2801
2802
2803 static errcode_t e2fsck_journal_load(journal_t *journal)
2804 {
2805         e2fsck_t ctx = journal->j_dev->k_ctx;
2806         journal_superblock_t *jsb;
2807         struct buffer_head *jbh = journal->j_sb_buffer;
2808         struct problem_context pctx;
2809
2810         clear_problem_context(&pctx);
2811
2812         ll_rw_block(READ, 1, &jbh);
2813         if (jbh->b_err) {
2814                 com_err(ctx->device_name, jbh->b_err,
2815                         _("reading journal superblock\n"));
2816                 return jbh->b_err;
2817         }
2818
2819         jsb = journal->j_superblock;
2820         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
2821         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
2822                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2823
2824         switch (ntohl(jsb->s_header.h_blocktype)) {
2825         case JFS_SUPERBLOCK_V1:
2826                 journal->j_format_version = 1;
2827                 if (jsb->s_feature_compat ||
2828                     jsb->s_feature_incompat ||
2829                     jsb->s_feature_ro_compat ||
2830                     jsb->s_nr_users)
2831                         clear_v2_journal_fields(journal);
2832                 break;
2833
2834         case JFS_SUPERBLOCK_V2:
2835                 journal->j_format_version = 2;
2836                 if (ntohl(jsb->s_nr_users) > 1 &&
2837                     uuid_is_null(ctx->fs->super->s_journal_uuid))
2838                         clear_v2_journal_fields(journal);
2839                 if (ntohl(jsb->s_nr_users) > 1) {
2840                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
2841                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
2842                 }
2843                 break;
2844
2845         /*
2846          * These should never appear in a journal super block, so if
2847          * they do, the journal is badly corrupted.
2848          */
2849         case JFS_DESCRIPTOR_BLOCK:
2850         case JFS_COMMIT_BLOCK:
2851         case JFS_REVOKE_BLOCK:
2852                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2853
2854         /* If we don't understand the superblock major type, but there
2855          * is a magic number, then it is likely to be a new format we
2856          * just don't understand, so leave it alone. */
2857         default:
2858                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
2859         }
2860
2861         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
2862                 return EXT2_ET_UNSUPP_FEATURE;
2863
2864         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
2865                 return EXT2_ET_RO_UNSUPP_FEATURE;
2866
2867         /* We have now checked whether we know enough about the journal
2868          * format to be able to proceed safely, so any other checks that
2869          * fail we should attempt to recover from. */
2870         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
2871                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
2872                         _("%s: no valid journal superblock found\n"),
2873                         ctx->device_name);
2874                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2875         }
2876
2877         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
2878                 journal->j_maxlen = ntohl(jsb->s_maxlen);
2879         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
2880                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
2881                         _("%s: journal too short\n"),
2882                         ctx->device_name);
2883                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2884         }
2885
2886         journal->j_tail_sequence = ntohl(jsb->s_sequence);
2887         journal->j_transaction_sequence = journal->j_tail_sequence;
2888         journal->j_tail = ntohl(jsb->s_start);
2889         journal->j_first = ntohl(jsb->s_first);
2890         journal->j_last = ntohl(jsb->s_maxlen);
2891
2892         return 0;
2893 }
2894
2895 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
2896                                        journal_t *journal)
2897 {
2898         char *p;
2899         union {
2900                 uuid_t uuid;
2901                 __u32 val[4];
2902         } u;
2903         __u32 new_seq = 0;
2904         int i;
2905
2906         /* Leave a valid existing V1 superblock signature alone.
2907          * Anything unrecognisable we overwrite with a new V2
2908          * signature. */
2909
2910         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
2911             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
2912                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
2913                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
2914         }
2915
2916         /* Zero out everything else beyond the superblock header */
2917
2918         p = ((char *) jsb) + sizeof(journal_header_t);
2919         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
2920
2921         jsb->s_blocksize = htonl(ctx->fs->blocksize);
2922         jsb->s_maxlen = htonl(journal->j_maxlen);
2923         jsb->s_first = htonl(1);
2924
2925         /* Initialize the journal sequence number so that there is "no"
2926          * chance we will find old "valid" transactions in the journal.
2927          * This avoids the need to zero the whole journal (slow to do,
2928          * and risky when we are just recovering the filesystem).
2929          */
2930         uuid_generate(u.uuid);
2931         for (i = 0; i < 4; i ++)
2932                 new_seq ^= u.val[i];
2933         jsb->s_sequence = htonl(new_seq);
2934
2935         mark_buffer_dirty(journal->j_sb_buffer);
2936         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
2937 }
2938
2939 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
2940                                                   journal_t *journal,
2941                                                   struct problem_context *pctx)
2942 {
2943         struct ext2_super_block *sb = ctx->fs->super;
2944         int recover = ctx->fs->super->s_feature_incompat &
2945                 EXT3_FEATURE_INCOMPAT_RECOVER;
2946
2947         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
2948                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
2949                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
2950                                                    journal);
2951                         journal->j_transaction_sequence = 1;
2952                         e2fsck_clear_recover(ctx, recover);
2953                         return 0;
2954                 }
2955                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2956         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
2957                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2958
2959         return 0;
2960 }
2961
2962 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
2963                                    int reset, int drop)
2964 {
2965         journal_superblock_t *jsb;
2966
2967         if (drop)
2968                 mark_buffer_clean(journal->j_sb_buffer);
2969         else if (!(ctx->options & E2F_OPT_READONLY)) {
2970                 jsb = journal->j_superblock;
2971                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
2972                 if (reset)
2973                         jsb->s_start = 0; /* this marks the journal as empty */
2974                 mark_buffer_dirty(journal->j_sb_buffer);
2975         }
2976         brelse(journal->j_sb_buffer);
2977
2978         if (ctx->journal_io) {
2979                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2980                         io_channel_close(ctx->journal_io);
2981                 ctx->journal_io = 0;
2982         }
2983
2984 #ifndef USE_INODE_IO
2985         ext2fs_free_mem(&journal->j_inode);
2986 #endif
2987         ext2fs_free_mem(&journal->j_fs_dev);
2988         ext2fs_free_mem(&journal);
2989 }
2990
2991 /*
2992  * This function makes sure that the superblock fields regarding the
2993  * journal are consistent.
2994  */
2995 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
2996 {
2997         struct ext2_super_block *sb = ctx->fs->super;
2998         journal_t *journal;
2999         int recover = ctx->fs->super->s_feature_incompat &
3000                 EXT3_FEATURE_INCOMPAT_RECOVER;
3001         struct problem_context pctx;
3002         problem_t problem;
3003         int reset = 0, force_fsck = 0;
3004         int retval;
3005
3006         /* If we don't have any journal features, don't do anything more */
3007         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3008             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
3009             uuid_is_null(sb->s_journal_uuid))
3010                 return 0;
3011
3012         clear_problem_context(&pctx);
3013         pctx.num = sb->s_journal_inum;
3014
3015         retval = e2fsck_get_journal(ctx, &journal);
3016         if (retval) {
3017                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3018                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3019                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3020                     (retval == EXT2_ET_NO_JOURNAL))
3021                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3022                 return retval;
3023         }
3024
3025         retval = e2fsck_journal_load(journal);
3026         if (retval) {
3027                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3028                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3029                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3030                                   &pctx))) ||
3031                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3032                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3033                                   &pctx))) ||
3034                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3035                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3036                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3037                                                                   &pctx);
3038                 e2fsck_journal_release(ctx, journal, 0, 1);
3039                 return retval;
3040         }
3041
3042         /*
3043          * We want to make the flags consistent here.  We will not leave with
3044          * needs_recovery set but has_journal clear.  We can't get in a loop
3045          * with -y, -n, or -p, only if a user isn't making up their mind.
3046          */
3047 no_has_journal:
3048         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3049                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3050                 pctx.str = "inode";
3051                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3052                         if (recover &&
3053                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3054                                 goto no_has_journal;
3055                         /*
3056                          * Need a full fsck if we are releasing a
3057                          * journal stored on a reserved inode.
3058                          */
3059                         force_fsck = recover ||
3060                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3061                         /* Clear all of the journal fields */
3062                         sb->s_journal_inum = 0;
3063                         sb->s_journal_dev = 0;
3064                         memset(sb->s_journal_uuid, 0,
3065                                sizeof(sb->s_journal_uuid));
3066                         e2fsck_clear_recover(ctx, force_fsck);
3067                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3068                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3069                         ext2fs_mark_super_dirty(ctx->fs);
3070                 }
3071         }
3072
3073         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3074             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3075             journal->j_superblock->s_start != 0) {
3076                 /* Print status information */
3077                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3078                 if (ctx->superblock)
3079                         problem = PR_0_JOURNAL_RUN_DEFAULT;
3080                 else
3081                         problem = PR_0_JOURNAL_RUN;
3082                 if (fix_problem(ctx, problem, &pctx)) {
3083                         ctx->options |= E2F_OPT_FORCE;
3084                         sb->s_feature_incompat |=
3085                                 EXT3_FEATURE_INCOMPAT_RECOVER;
3086                         ext2fs_mark_super_dirty(ctx->fs);
3087                 } else if (fix_problem(ctx,
3088                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3089                         reset = 1;
3090                         sb->s_state &= ~EXT2_VALID_FS;
3091                         ext2fs_mark_super_dirty(ctx->fs);
3092                 }
3093                 /*
3094                  * If the user answers no to the above question, we
3095                  * ignore the fact that journal apparently has data;
3096                  * accidentally replaying over valid data would be far
3097                  * worse than skipping a questionable recovery.
3098                  *
3099                  * XXX should we abort with a fatal error here?  What
3100                  * will the ext3 kernel code do if a filesystem with
3101                  * !NEEDS_RECOVERY but with a non-zero
3102                  * journal->j_superblock->s_start is mounted?
3103                  */
3104         }
3105
3106         e2fsck_journal_release(ctx, journal, reset, 0);
3107         return retval;
3108 }
3109
3110 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3111 {
3112         journal_t *journal;
3113         int retval;
3114
3115         journal_init_revoke_caches();
3116         retval = e2fsck_get_journal(ctx, &journal);
3117         if (retval)
3118                 return retval;
3119
3120         retval = e2fsck_journal_load(journal);
3121         if (retval)
3122                 goto errout;
3123
3124         retval = journal_init_revoke(journal, 1024);
3125         if (retval)
3126                 goto errout;
3127
3128         retval = -journal_recover(journal);
3129         if (retval)
3130                 goto errout;
3131
3132         if (journal->j_superblock->s_errno) {
3133                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3134                 ext2fs_mark_super_dirty(ctx->fs);
3135                 journal->j_superblock->s_errno = 0;
3136                 mark_buffer_dirty(journal->j_sb_buffer);
3137         }
3138
3139 errout:
3140         journal_destroy_revoke(journal);
3141         journal_destroy_revoke_caches();
3142         e2fsck_journal_release(ctx, journal, 1, 0);
3143         return retval;
3144 }
3145
3146 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3147 {
3148         io_manager io_ptr = ctx->fs->io->manager;
3149         int blocksize = ctx->fs->blocksize;
3150         errcode_t       retval, recover_retval;
3151
3152         printf(_("%s: recovering journal\n"), ctx->device_name);
3153         if (ctx->options & E2F_OPT_READONLY) {
3154                 printf(_("%s: won't do journal recovery while read-only\n"),
3155                        ctx->device_name);
3156                 return EXT2_ET_FILE_RO;
3157         }
3158
3159         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3160                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
3161
3162         recover_retval = recover_ext3_journal(ctx);
3163
3164         /*
3165          * Reload the filesystem context to get up-to-date data from disk
3166          * because journal recovery will change the filesystem under us.
3167          */
3168         ext2fs_close(ctx->fs);
3169         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3170                              ctx->superblock, blocksize, io_ptr,
3171                              &ctx->fs);
3172
3173         if (retval) {
3174                 com_err(ctx->program_name, retval,
3175                         _("while trying to re-open %s"),
3176                         ctx->device_name);
3177                 fatal_error(ctx, 0);
3178         }
3179         ctx->fs->priv_data = ctx;
3180
3181         /* Set the superblock flags */
3182         e2fsck_clear_recover(ctx, recover_retval);
3183         return recover_retval;
3184 }
3185
3186 /*
3187  * This function will move the journal inode from a visible file in
3188  * the filesystem directory hierarchy to the reserved inode if necessary.
3189  */
3190 static const char * const journal_names[] = {
3191         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3192
3193 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3194 {
3195         struct ext2_super_block *sb = ctx->fs->super;
3196         struct problem_context  pctx;
3197         struct ext2_inode       inode;
3198         ext2_filsys             fs = ctx->fs;
3199         ext2_ino_t              ino;
3200         errcode_t               retval;
3201         const char * const *    cpp;
3202         int                     group, mount_flags;
3203
3204         clear_problem_context(&pctx);
3205
3206         /*
3207          * If the filesystem is opened read-only, or there is no
3208          * journal, then do nothing.
3209          */
3210         if ((ctx->options & E2F_OPT_READONLY) ||
3211             (sb->s_journal_inum == 0) ||
3212             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3213                 return;
3214
3215         /*
3216          * Read in the journal inode
3217          */
3218         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3219                 return;
3220
3221         /*
3222          * If it's necessary to backup the journal inode, do so.
3223          */
3224         if ((sb->s_jnl_backup_type == 0) ||
3225             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3226              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3227                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3228                         memcpy(sb->s_jnl_blocks, inode.i_block,
3229                                EXT2_N_BLOCKS*4);
3230                         sb->s_jnl_blocks[16] = inode.i_size;
3231                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3232                         ext2fs_mark_super_dirty(fs);
3233                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3234                 }
3235         }
3236
3237         /*
3238          * If the journal is already the hidden inode, then do nothing
3239          */
3240         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3241                 return;
3242
3243         /*
3244          * The journal inode had better have only one link and not be readable.
3245          */
3246         if (inode.i_links_count != 1)
3247                 return;
3248
3249         /*
3250          * If the filesystem is mounted, or we can't tell whether
3251          * or not it's mounted, do nothing.
3252          */
3253         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3254         if (retval || (mount_flags & EXT2_MF_MOUNTED))
3255                 return;
3256
3257         /*
3258          * If we can't find the name of the journal inode, then do
3259          * nothing.
3260          */
3261         for (cpp = journal_names; *cpp; cpp++) {
3262                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3263                                        strlen(*cpp), 0, &ino);
3264                 if ((retval == 0) && (ino == sb->s_journal_inum))
3265                         break;
3266         }
3267         if (*cpp == 0)
3268                 return;
3269
3270         /* We need the inode bitmap to be loaded */
3271         retval = ext2fs_read_bitmaps(fs);
3272         if (retval)
3273                 return;
3274
3275         pctx.str = *cpp;
3276         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3277                 return;
3278
3279         /*
3280          * OK, we've done all the checks, let's actually move the
3281          * journal inode.  Errors at this point mean we need to force
3282          * an ext2 filesystem check.
3283          */
3284         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3285                 goto err_out;
3286         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3287                 goto err_out;
3288         sb->s_journal_inum = EXT2_JOURNAL_INO;
3289         ext2fs_mark_super_dirty(fs);
3290         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3291         inode.i_links_count = 0;
3292         inode.i_dtime = time(0);
3293         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3294                 goto err_out;
3295
3296         group = ext2fs_group_of_ino(fs, ino);
3297         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3298         ext2fs_mark_ib_dirty(fs);
3299         fs->group_desc[group].bg_free_inodes_count++;
3300         fs->super->s_free_inodes_count++;
3301         return;
3302
3303 err_out:
3304         pctx.errcode = retval;
3305         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3306         fs->super->s_state &= ~EXT2_VALID_FS;
3307         ext2fs_mark_super_dirty(fs);
3308         return;
3309 }
3310
3311 /*
3312  * message.c --- print e2fsck messages (with compression)
3313  *
3314  * print_e2fsck_message() prints a message to the user, using
3315  * compression techniques and expansions of abbreviations.
3316  *
3317  * The following % expansions are supported:
3318  *
3319  *      %b      <blk>                   block number
3320  *      %B      <blkcount>              integer
3321  *      %c      <blk2>                  block number
3322  *      %Di     <dirent>->ino           inode number
3323  *      %Dn     <dirent>->name          string
3324  *      %Dr     <dirent>->rec_len
3325  *      %Dl     <dirent>->name_len
3326  *      %Dt     <dirent>->filetype
3327  *      %d      <dir>                   inode number
3328  *      %g      <group>                 integer
3329  *      %i      <ino>                   inode number
3330  *      %Is     <inode> -> i_size
3331  *      %IS     <inode> -> i_extra_isize
3332  *      %Ib     <inode> -> i_blocks
3333  *      %Il     <inode> -> i_links_count
3334  *      %Im     <inode> -> i_mode
3335  *      %IM     <inode> -> i_mtime
3336  *      %IF     <inode> -> i_faddr
3337  *      %If     <inode> -> i_file_acl
3338  *      %Id     <inode> -> i_dir_acl
3339  *      %Iu     <inode> -> i_uid
3340  *      %Ig     <inode> -> i_gid
3341  *      %j      <ino2>                  inode number
3342  *      %m      <com_err error message>
3343  *      %N      <num>
3344  *      %p      ext2fs_get_pathname of directory <ino>
3345  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
3346  *                      the containing directory.  (If dirent is NULL
3347  *                      then return the pathname of directory <ino2>)
3348  *      %q      ext2fs_get_pathname of directory <dir>
3349  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
3350  *                      the containing directory.
3351  *      %s      <str>                   miscellaneous string
3352  *      %S      backup superblock
3353  *      %X      <num> hexadecimal format
3354  *
3355  * The following '@' expansions are supported:
3356  *
3357  *      @a      extended attribute
3358  *      @A      error allocating
3359  *      @b      block
3360  *      @B      bitmap
3361  *      @c      compress
3362  *      @C      conflicts with some other fs block
3363  *      @D      deleted
3364  *      @d      directory
3365  *      @e      entry
3366  *      @E      Entry '%Dn' in %p (%i)
3367  *      @f      filesystem
3368  *      @F      for @i %i (%Q) is
3369  *      @g      group
3370  *      @h      HTREE directory inode
3371  *      @i      inode
3372  *      @I      illegal
3373  *      @j      journal
3374  *      @l      lost+found
3375  *      @L      is a link
3376  *      @m      multiply-claimed
3377  *      @n      invalid
3378  *      @o      orphaned
3379  *      @p      problem in
3380  *      @r      root inode
3381  *      @s      should be
3382  *      @S      superblock
3383  *      @u      unattached
3384  *      @v      device
3385  *      @z      zero-length
3386  */
3387
3388
3389 /*
3390  * This structure defines the abbreviations used by the text strings
3391  * below.  The first character in the string is the index letter.  An
3392  * abbreviation of the form '@<i>' is expanded by looking up the index
3393  * letter <i> in the table below.
3394  */
3395 static const char * const abbrevs[] = {
3396         N_("aextended attribute"),
3397         N_("Aerror allocating"),
3398         N_("bblock"),
3399         N_("Bbitmap"),
3400         N_("ccompress"),
3401         N_("Cconflicts with some other fs @b"),
3402         N_("iinode"),
3403         N_("Iillegal"),
3404         N_("jjournal"),
3405         N_("Ddeleted"),
3406         N_("ddirectory"),
3407         N_("eentry"),
3408         N_("E@e '%Dn' in %p (%i)"),
3409         N_("ffilesystem"),
3410         N_("Ffor @i %i (%Q) is"),
3411         N_("ggroup"),
3412         N_("hHTREE @d @i"),
3413         N_("llost+found"),
3414         N_("Lis a link"),
3415     N_("mmultiply-claimed"),
3416     N_("ninvalid"),
3417         N_("oorphaned"),
3418         N_("pproblem in"),
3419         N_("rroot @i"),
3420         N_("sshould be"),
3421         N_("Ssuper@b"),
3422         N_("uunattached"),
3423         N_("vdevice"),
3424         N_("zzero-length"),
3425         "@@",
3426         0
3427         };
3428
3429 /*
3430  * Give more user friendly names to the "special" inodes.
3431  */
3432 #define num_special_inodes      11
3433 static const char * const special_inode_name[] =
3434 {
3435         N_("<The NULL inode>"),                 /* 0 */
3436         N_("<The bad blocks inode>"),           /* 1 */
3437         "/",                                    /* 2 */
3438         N_("<The ACL index inode>"),            /* 3 */
3439         N_("<The ACL data inode>"),             /* 4 */
3440         N_("<The boot loader inode>"),          /* 5 */
3441         N_("<The undelete directory inode>"),   /* 6 */
3442         N_("<The group descriptor inode>"),     /* 7 */
3443         N_("<The journal inode>"),              /* 8 */
3444         N_("<Reserved inode 9>"),               /* 9 */
3445         N_("<Reserved inode 10>"),              /* 10 */
3446 };
3447
3448 /*
3449  * This function does "safe" printing.  It will convert non-printable
3450  * ASCII characters using '^' and M- notation.
3451  */
3452 static void safe_print(const char *cp, int len)
3453 {
3454         unsigned char   ch;
3455
3456         if (len < 0)
3457                 len = strlen(cp);
3458
3459         while (len--) {
3460                 ch = *cp++;
3461                 if (ch > 128) {
3462                         fputs("M-", stdout);
3463                         ch -= 128;
3464                 }
3465                 if ((ch < 32) || (ch == 0x7f)) {
3466                         fputc('^', stdout);
3467                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3468                 }
3469                 fputc(ch, stdout);
3470         }
3471 }
3472
3473
3474 /*
3475  * This function prints a pathname, using the ext2fs_get_pathname
3476  * function
3477  */
3478 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3479 {
3480         errcode_t       retval;
3481         char            *path;
3482
3483         if (!dir && (ino < num_special_inodes)) {
3484                 fputs(_(special_inode_name[ino]), stdout);
3485                 return;
3486         }
3487
3488         retval = ext2fs_get_pathname(fs, dir, ino, &path);
3489         if (retval)
3490                 fputs("???", stdout);
3491         else {
3492                 safe_print(path, -1);
3493                 ext2fs_free_mem(&path);
3494         }
3495 }
3496
3497 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3498                           struct problem_context *pctx, int first);
3499 /*
3500  * This function handles the '@' expansion.  We allow recursive
3501  * expansion; an @ expression can contain further '@' and '%'
3502  * expressions.
3503  */
3504 static void expand_at_expression(e2fsck_t ctx, char ch,
3505                                           struct problem_context *pctx,
3506                                           int *first)
3507 {
3508         const char * const *cpp;
3509         const char *str;
3510
3511         /* Search for the abbreviation */
3512         for (cpp = abbrevs; *cpp; cpp++) {
3513                 if (ch == *cpp[0])
3514                         break;
3515         }
3516         if (*cpp) {
3517                 str = _(*cpp) + 1;
3518                 if (*first && islower(*str)) {
3519                         *first = 0;
3520                         fputc(toupper(*str++), stdout);
3521                 }
3522                 print_e2fsck_message(ctx, str, pctx, *first);
3523         } else
3524                 printf("@%c", ch);
3525 }
3526
3527 /*
3528  * This function expands '%IX' expressions
3529  */
3530 static void expand_inode_expression(char ch,
3531                                              struct problem_context *ctx)
3532 {
3533         struct ext2_inode       *inode;
3534         struct ext2_inode_large *large_inode;
3535         char *                  time_str;
3536         time_t                  t;
3537         int                     do_gmt = -1;
3538
3539         if (!ctx || !ctx->inode)
3540                 goto no_inode;
3541
3542         inode = ctx->inode;
3543         large_inode = (struct ext2_inode_large *) inode;
3544
3545         switch (ch) {
3546         case 's':
3547                 if (LINUX_S_ISDIR(inode->i_mode))
3548                         printf("%u", inode->i_size);
3549                 else {
3550 #ifdef EXT2_NO_64_TYPE
3551                         if (inode->i_size_high)
3552                                 printf("0x%x%08x", inode->i_size_high,
3553                                        inode->i_size);
3554                         else
3555                                 printf("%u", inode->i_size);
3556 #else
3557                         printf("%llu", (inode->i_size |
3558                                         ((__u64) inode->i_size_high << 32)));
3559 #endif
3560                 }
3561                 break;
3562         case 'S':
3563                 printf("%u", large_inode->i_extra_isize);
3564                 break;
3565         case 'b':
3566                 printf("%u", inode->i_blocks);
3567                 break;
3568         case 'l':
3569                 printf("%d", inode->i_links_count);
3570                 break;
3571         case 'm':
3572                 printf("0%o", inode->i_mode);
3573                 break;
3574         case 'M':
3575                 /* The diet libc doesn't respect the TZ environemnt variable */
3576                 if (do_gmt == -1) {
3577                         time_str = getenv("TZ");
3578                         if (!time_str)
3579                                 time_str = "";
3580                         do_gmt = !strcmp(time_str, "GMT");
3581                 }
3582                 t = inode->i_mtime;
3583                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3584                 printf("%.24s", time_str);
3585                 break;
3586         case 'F':
3587                 printf("%u", inode->i_faddr);
3588                 break;
3589         case 'f':
3590                 printf("%u", inode->i_file_acl);
3591                 break;
3592         case 'd':
3593                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3594                               inode->i_dir_acl : 0));
3595                 break;
3596         case 'u':
3597                 printf("%d", (inode->i_uid |
3598                               (inode->osd2.linux2.l_i_uid_high << 16)));
3599                 break;
3600         case 'g':
3601                 printf("%d", (inode->i_gid |
3602                               (inode->osd2.linux2.l_i_gid_high << 16)));
3603                 break;
3604         default:
3605         no_inode:
3606                 printf("%%I%c", ch);
3607                 break;
3608         }
3609 }
3610
3611 /*
3612  * This function expands '%dX' expressions
3613  */
3614 static _INLINE_ void expand_dirent_expression(char ch,
3615                                               struct problem_context *ctx)
3616 {
3617         struct ext2_dir_entry   *dirent;
3618         int     len;
3619
3620         if (!ctx || !ctx->dirent)
3621                 goto no_dirent;
3622
3623         dirent = ctx->dirent;
3624
3625         switch (ch) {
3626         case 'i':
3627                 printf("%u", dirent->inode);
3628                 break;
3629         case 'n':
3630                 len = dirent->name_len & 0xFF;
3631                 if (len > EXT2_NAME_LEN)
3632                         len = EXT2_NAME_LEN;
3633                 if (len > dirent->rec_len)
3634                         len = dirent->rec_len;
3635                 safe_print(dirent->name, len);
3636                 break;
3637         case 'r':
3638                 printf("%u", dirent->rec_len);
3639                 break;
3640         case 'l':
3641                 printf("%u", dirent->name_len & 0xFF);
3642                 break;
3643         case 't':
3644                 printf("%u", dirent->name_len >> 8);
3645                 break;
3646         default:
3647         no_dirent:
3648                 printf("%%D%c", ch);
3649                 break;
3650         }
3651 }
3652
3653 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
3654                                                struct problem_context *ctx)
3655 {
3656         if (!ctx)
3657                 goto no_context;
3658
3659         switch (ch) {
3660         case '%':
3661                 fputc('%', stdout);
3662                 break;
3663         case 'b':
3664                 printf("%u", ctx->blk);
3665                 break;
3666         case 'B':
3667 #ifdef EXT2_NO_64_TYPE
3668                 printf("%d", ctx->blkcount);
3669 #else
3670                 printf("%lld", ctx->blkcount);
3671 #endif
3672                 break;
3673         case 'c':
3674                 printf("%u", ctx->blk2);
3675                 break;
3676         case 'd':
3677                 printf("%u", ctx->dir);
3678                 break;
3679         case 'g':
3680                 printf("%d", ctx->group);
3681                 break;
3682         case 'i':
3683                 printf("%u", ctx->ino);
3684                 break;
3685         case 'j':
3686                 printf("%u", ctx->ino2);
3687                 break;
3688         case 'm':
3689                 printf("%s", error_message(ctx->errcode));
3690                 break;
3691         case 'N':
3692 #ifdef EXT2_NO_64_TYPE
3693                 printf("%u", ctx->num);
3694 #else
3695                 printf("%llu", ctx->num);
3696 #endif
3697                 break;
3698         case 'p':
3699                 print_pathname(fs, ctx->ino, 0);
3700                 break;
3701         case 'P':
3702                 print_pathname(fs, ctx->ino2,
3703                                ctx->dirent ? ctx->dirent->inode : 0);
3704                 break;
3705         case 'q':
3706                 print_pathname(fs, ctx->dir, 0);
3707                 break;
3708         case 'Q':
3709                 print_pathname(fs, ctx->dir, ctx->ino);
3710                 break;
3711         case 'S':
3712                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
3713                 break;
3714         case 's':
3715                 printf("%s", ctx->str ? ctx->str : "NULL");
3716                 break;
3717         case 'X':
3718 #ifdef EXT2_NO_64_TYPE
3719                 printf("0x%x", ctx->num);
3720 #else
3721                 printf("0x%llx", ctx->num);
3722 #endif
3723                 break;
3724         default:
3725         no_context:
3726                 printf("%%%c", ch);
3727                 break;
3728         }
3729 }
3730
3731
3732 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3733                           struct problem_context *pctx, int first)
3734 {
3735         ext2_filsys fs = ctx->fs;
3736         const char *    cp;
3737         int             i;
3738
3739         e2fsck_clear_progbar(ctx);
3740         for (cp = msg; *cp; cp++) {
3741                 if (cp[0] == '@') {
3742                         cp++;
3743                         expand_at_expression(ctx, *cp, pctx, &first);
3744                 } else if (cp[0] == '%' && cp[1] == 'I') {
3745                         cp += 2;
3746                         expand_inode_expression(*cp, pctx);
3747                 } else if (cp[0] == '%' && cp[1] == 'D') {
3748                         cp += 2;
3749                         expand_dirent_expression(*cp, pctx);
3750                 } else if ((cp[0] == '%')) {
3751                         cp++;
3752                         expand_percent_expression(fs, *cp, pctx);
3753                 } else {
3754                         for (i=0; cp[i]; i++)
3755                                 if ((cp[i] == '@') || cp[i] == '%')
3756                                         break;
3757                         printf("%.*s", i, cp);
3758                         cp += i-1;
3759                 }
3760                 first = 0;
3761         }
3762 }
3763
3764
3765 /*
3766  * region.c --- code which manages allocations within a region.
3767  */
3768
3769 struct region_el {
3770         region_addr_t   start;
3771         region_addr_t   end;
3772         struct region_el *next;
3773 };
3774
3775 struct region_struct {
3776         region_addr_t   min;
3777         region_addr_t   max;
3778         struct region_el *allocated;
3779 };
3780
3781 static region_t region_create(region_addr_t min, region_addr_t max)
3782 {
3783         region_t        region;
3784
3785         region = malloc(sizeof(struct region_struct));
3786         if (!region)
3787                 return NULL;
3788         memset(region, 0, sizeof(struct region_struct));
3789         region->min = min;
3790         region->max = max;
3791         return region;
3792 }
3793
3794 static void region_free(region_t region)
3795 {
3796         struct region_el        *r, *next;
3797
3798         for (r = region->allocated; r; r = next) {
3799                 next = r->next;
3800                 free(r);
3801         }
3802         memset(region, 0, sizeof(struct region_struct));
3803         free(region);
3804 }
3805
3806 static int region_allocate(region_t region, region_addr_t start, int n)
3807 {
3808         struct region_el        *r, *new_region, *prev, *next;
3809         region_addr_t end;
3810
3811         end = start+n;
3812         if ((start < region->min) || (end > region->max))
3813                 return -1;
3814         if (n == 0)
3815                 return 1;
3816
3817         /*
3818          * Search through the linked list.  If we find that it
3819          * conflicts witih something that's already allocated, return
3820          * 1; if we can find an existing region which we can grow, do
3821          * so.  Otherwise, stop when we find the appropriate place
3822          * insert a new region element into the linked list.
3823          */
3824         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
3825                 if (((start >= r->start) && (start < r->end)) ||
3826                     ((end > r->start) && (end <= r->end)) ||
3827                     ((start <= r->start) && (end >= r->end)))
3828                         return 1;
3829                 if (end == r->start) {
3830                         r->start = start;
3831                         return 0;
3832                 }
3833                 if (start == r->end) {
3834                         if ((next = r->next)) {
3835                                 if (end > next->start)
3836                                         return 1;
3837                                 if (end == next->start) {
3838                                         r->end = next->end;
3839                                         r->next = next->next;
3840                                         free(next);
3841                                         return 0;
3842                                 }
3843                         }
3844                         r->end = end;
3845                         return 0;
3846                 }
3847                 if (start < r->start)
3848                         break;
3849         }
3850         /*
3851          * Insert a new region element structure into the linked list
3852          */
3853         new_region = malloc(sizeof(struct region_el));
3854         if (!new_region)
3855                 return -1;
3856         new_region->start = start;
3857         new_region->end = start + n;
3858         new_region->next = r;
3859         if (prev)
3860                 prev->next = new_region;
3861         else
3862                 region->allocated = new_region;
3863         return 0;
3864 }
3865
3866 /*
3867  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
3868  *
3869  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
3870  * and applies the following tests to each inode:
3871  *
3872  *      - The mode field of the inode must be legal.
3873  *      - The size and block count fields of the inode are correct.
3874  *      - A data block must not be used by another inode
3875  *
3876  * Pass 1 also gathers the collects the following information:
3877  *
3878  *      - A bitmap of which inodes are in use.          (inode_used_map)
3879  *      - A bitmap of which inodes are directories.     (inode_dir_map)
3880  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
3881  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
3882  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
3883  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
3884  *      - A bitmap of which blocks are in use.          (block_found_map)
3885  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
3886  *      - The data blocks of the directory inodes.      (dir_map)
3887  *
3888  * Pass 1 is designed to stash away enough information so that the
3889  * other passes should not need to read in the inode information
3890  * during the normal course of a filesystem check.  (Althogh if an
3891  * inconsistency is detected, other passes may need to read in an
3892  * inode to fix it.)
3893  *
3894  * Note that pass 1B will be invoked if there are any duplicate blocks
3895  * found.
3896  */
3897
3898
3899 static int process_block(ext2_filsys fs, blk_t  *blocknr,
3900                          e2_blkcnt_t blockcnt, blk_t ref_blk,
3901                          int ref_offset, void *priv_data);
3902 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
3903                              e2_blkcnt_t blockcnt, blk_t ref_blk,
3904                              int ref_offset, void *priv_data);
3905 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
3906                          char *block_buf);
3907 static void mark_table_blocks(e2fsck_t ctx);
3908 static void alloc_bb_map(e2fsck_t ctx);
3909 static void alloc_imagic_map(e2fsck_t ctx);
3910 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
3911 static void handle_fs_bad_blocks(e2fsck_t ctx);
3912 static void process_inodes(e2fsck_t ctx, char *block_buf);
3913 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
3914 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
3915                                   dgrp_t group, void * priv_data);
3916 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3917                                     char *block_buf, int adjust_sign);
3918 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
3919
3920 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
3921                                struct ext2_inode * inode, int bufsize,
3922                                const char *proc);
3923
3924 struct process_block_struct_1 {
3925         ext2_ino_t      ino;
3926         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
3927                                 fragmented:1, compressed:1, bbcheck:1;
3928         blk_t           num_blocks;
3929         blk_t           max_blocks;
3930         e2_blkcnt_t     last_block;
3931         int             num_illegal_blocks;
3932         blk_t           previous_block;
3933         struct ext2_inode *inode;
3934         struct problem_context *pctx;
3935         ext2fs_block_bitmap fs_meta_blocks;
3936         e2fsck_t        ctx;
3937 };
3938
3939 struct process_inode_block {
3940         ext2_ino_t ino;
3941         struct ext2_inode inode;
3942 };
3943
3944 struct scan_callback_struct {
3945         e2fsck_t        ctx;
3946         char            *block_buf;
3947 };
3948
3949 /*
3950  * For the inodes to process list.
3951  */
3952 static struct process_inode_block *inodes_to_process;
3953 static int process_inode_count;
3954
3955 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
3956                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
3957
3958 /*
3959  * Free all memory allocated by pass1 in preparation for restarting
3960  * things.
3961  */
3962 static void unwind_pass1(void)
3963 {
3964         ext2fs_free_mem(&inodes_to_process);
3965 }
3966
3967 /*
3968  * Check to make sure a device inode is real.  Returns 1 if the device
3969  * checks out, 0 if not.
3970  *
3971  * Note: this routine is now also used to check FIFO's and Sockets,
3972  * since they have the same requirement; the i_block fields should be
3973  * zero.
3974  */
3975 static int
3976 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
3977 {
3978         int     i;
3979
3980         /*
3981          * If i_blocks is non-zero, or the index flag is set, then
3982          * this is a bogus device/fifo/socket
3983          */
3984         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
3985             (inode->i_flags & EXT2_INDEX_FL))
3986                 return 0;
3987
3988         /*
3989          * We should be able to do the test below all the time, but
3990          * because the kernel doesn't forcibly clear the device
3991          * inode's additional i_block fields, there are some rare
3992          * occasions when a legitimate device inode will have non-zero
3993          * additional i_block fields.  So for now, we only complain
3994          * when the immutable flag is set, which should never happen
3995          * for devices.  (And that's when the problem is caused, since
3996          * you can't set or clear immutable flags for devices.)  Once
3997          * the kernel has been fixed we can change this...
3998          */
3999         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4000                 for (i=4; i < EXT2_N_BLOCKS; i++)
4001                         if (inode->i_block[i])
4002                                 return 0;
4003         }
4004         return 1;
4005 }
4006
4007 /*
4008  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
4009  * checks out, 0 if not.
4010  */
4011 static int
4012 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4013 {
4014         unsigned int len;
4015         int i;
4016         blk_t   blocks;
4017
4018         if ((inode->i_size_high || inode->i_size == 0) ||
4019             (inode->i_flags & EXT2_INDEX_FL))
4020                 return 0;
4021
4022         blocks = ext2fs_inode_data_blocks(fs, inode);
4023         if (blocks) {
4024                 if ((inode->i_size >= fs->blocksize) ||
4025                     (blocks != fs->blocksize >> 9) ||
4026                     (inode->i_block[0] < fs->super->s_first_data_block) ||
4027                     (inode->i_block[0] >= fs->super->s_blocks_count))
4028                         return 0;
4029
4030                 for (i = 1; i < EXT2_N_BLOCKS; i++)
4031                         if (inode->i_block[i])
4032                                 return 0;
4033
4034                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4035                         return 0;
4036
4037                 len = strnlen(buf, fs->blocksize);
4038                 if (len == fs->blocksize)
4039                         return 0;
4040         } else {
4041                 if (inode->i_size >= sizeof(inode->i_block))
4042                         return 0;
4043
4044                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4045                 if (len == sizeof(inode->i_block))
4046                         return 0;
4047         }
4048         if (len != inode->i_size)
4049                 return 0;
4050         return 1;
4051 }
4052
4053 /*
4054  * If the immutable (or append-only) flag is set on the inode, offer
4055  * to clear it.
4056  */
4057 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4058 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4059 {
4060         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4061                 return;
4062
4063         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4064                 return;
4065
4066         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4067         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4068 }
4069
4070 /*
4071  * If device, fifo or socket, check size is zero -- if not offer to
4072  * clear it
4073  */
4074 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4075 {
4076         struct ext2_inode *inode = pctx->inode;
4077
4078         if ((inode->i_size == 0) && (inode->i_size_high == 0))
4079                 return;
4080
4081         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4082                 return;
4083
4084         inode->i_size = 0;
4085         inode->i_size_high = 0;
4086         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4087 }
4088
4089 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4090 {
4091         struct ext2_super_block *sb = ctx->fs->super;
4092         struct ext2_inode_large *inode;
4093         struct ext2_ext_attr_entry *entry;
4094         char *start, *end;
4095         int storage_size, remain, offs;
4096         int problem = 0;
4097
4098         inode = (struct ext2_inode_large *) pctx->inode;
4099         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4100                 inode->i_extra_isize;
4101         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4102                 inode->i_extra_isize + sizeof(__u32);
4103         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4104         entry = (struct ext2_ext_attr_entry *) start;
4105
4106         /* scan all entry's headers first */
4107
4108         /* take finish entry 0UL into account */
4109         remain = storage_size - sizeof(__u32);
4110         offs = end - start;
4111
4112         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4113
4114                 /* header eats this space */
4115                 remain -= sizeof(struct ext2_ext_attr_entry);
4116
4117                 /* is attribute name valid? */
4118                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4119                         pctx->num = entry->e_name_len;
4120                         problem = PR_1_ATTR_NAME_LEN;
4121                         goto fix;
4122                 }
4123
4124                 /* attribute len eats this space */
4125                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4126
4127                 /* check value size */
4128                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4129                         pctx->num = entry->e_value_size;
4130                         problem = PR_1_ATTR_VALUE_SIZE;
4131                         goto fix;
4132                 }
4133
4134                 /* check value placement */
4135                 if (entry->e_value_offs +
4136                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4137                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4138                         pctx->num = entry->e_value_offs;
4139                         problem = PR_1_ATTR_VALUE_OFFSET;
4140                         goto fix;
4141                 }
4142
4143                 /* e_value_block must be 0 in inode's ea */
4144                 if (entry->e_value_block != 0) {
4145                         pctx->num = entry->e_value_block;
4146                         problem = PR_1_ATTR_VALUE_BLOCK;
4147                         goto fix;
4148                 }
4149
4150                 /* e_hash must be 0 in inode's ea */
4151                 if (entry->e_hash != 0) {
4152                         pctx->num = entry->e_hash;
4153                         problem = PR_1_ATTR_HASH;
4154                         goto fix;
4155                 }
4156
4157                 remain -= entry->e_value_size;
4158                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4159
4160                 entry = EXT2_EXT_ATTR_NEXT(entry);
4161         }
4162 fix:
4163         /*
4164          * it seems like a corruption. it's very unlikely we could repair
4165          * EA(s) in automatic fashion -bzzz
4166          */
4167 #if 0
4168         problem = PR_1_ATTR_HASH;
4169 #endif
4170         if (problem == 0 || !fix_problem(ctx, problem, pctx))
4171                 return;
4172
4173         /* simple remove all possible EA(s) */
4174         *((__u32 *)start) = 0UL;
4175         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4176                                 EXT2_INODE_SIZE(sb), "pass1");
4177 }
4178
4179 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4180 {
4181         struct ext2_super_block *sb = ctx->fs->super;
4182         struct ext2_inode_large *inode;
4183         __u32 *eamagic;
4184         int min, max;
4185
4186         inode = (struct ext2_inode_large *) pctx->inode;
4187         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4188                 /* this isn't large inode. so, nothing to check */
4189                 return;
4190         }
4191
4192 #if 0
4193         printf("inode #%u, i_extra_size %d\n", pctx->ino,
4194                         inode->i_extra_isize);
4195 #endif
4196         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4197         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4198         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4199         /*
4200          * For now we will allow i_extra_isize to be 0, but really
4201          * implementations should never allow i_extra_isize to be 0
4202          */
4203         if (inode->i_extra_isize &&
4204             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4205                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4206                         return;
4207                 inode->i_extra_isize = min;
4208                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4209                                         EXT2_INODE_SIZE(sb), "pass1");
4210                 return;
4211         }
4212
4213         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4214                         inode->i_extra_isize);
4215         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4216                 /* it seems inode has an extended attribute(s) in body */
4217                 check_ea_in_inode(ctx, pctx);
4218         }
4219 }
4220
4221 static void e2fsck_pass1(e2fsck_t ctx)
4222 {
4223         int     i;
4224         __u64   max_sizes;
4225         ext2_filsys fs = ctx->fs;
4226         ext2_ino_t      ino;
4227         struct ext2_inode *inode;
4228         ext2_inode_scan scan;
4229         char            *block_buf;
4230 #ifdef RESOURCE_TRACK
4231         struct resource_track   rtrack;
4232 #endif
4233         unsigned char   frag, fsize;
4234         struct          problem_context pctx;
4235         struct          scan_callback_struct scan_struct;
4236         struct ext2_super_block *sb = ctx->fs->super;
4237         int             imagic_fs;
4238         int             busted_fs_time = 0;
4239         int             inode_size;
4240
4241 #ifdef RESOURCE_TRACK
4242         init_resource_track(&rtrack);
4243 #endif
4244         clear_problem_context(&pctx);
4245
4246         if (!(ctx->options & E2F_OPT_PREEN))
4247                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4248
4249         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4250             !(ctx->options & E2F_OPT_NO)) {
4251                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4252                         ctx->dirs_to_hash = 0;
4253         }
4254
4255 #ifdef MTRACE
4256         mtrace_print("Pass 1");
4257 #endif
4258
4259 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4260
4261         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4262                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4263                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4264                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4265                 max_sizes = (max_sizes * (1UL << i)) - 1;
4266                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4267         }
4268 #undef EXT2_BPP
4269
4270         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4271
4272         /*
4273          * Allocate bitmaps structures
4274          */
4275         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4276                                               &ctx->inode_used_map);
4277         if (pctx.errcode) {
4278                 pctx.num = 1;
4279                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4280                 ctx->flags |= E2F_FLAG_ABORT;
4281                 return;
4282         }
4283         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4284                                 _("directory inode map"), &ctx->inode_dir_map);
4285         if (pctx.errcode) {
4286                 pctx.num = 2;
4287                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4288                 ctx->flags |= E2F_FLAG_ABORT;
4289                 return;
4290         }
4291         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4292                         _("regular file inode map"), &ctx->inode_reg_map);
4293         if (pctx.errcode) {
4294                 pctx.num = 6;
4295                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4296                 ctx->flags |= E2F_FLAG_ABORT;
4297                 return;
4298         }
4299         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4300                                               &ctx->block_found_map);
4301         if (pctx.errcode) {
4302                 pctx.num = 1;
4303                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4304                 ctx->flags |= E2F_FLAG_ABORT;
4305                 return;
4306         }
4307         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4308                                              &ctx->inode_link_info);
4309         if (pctx.errcode) {
4310                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4311                 ctx->flags |= E2F_FLAG_ABORT;
4312                 return;
4313         }
4314         inode_size = EXT2_INODE_SIZE(fs->super);
4315         inode = (struct ext2_inode *)
4316                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4317
4318         inodes_to_process = (struct process_inode_block *)
4319                 e2fsck_allocate_memory(ctx,
4320                                        (ctx->process_inode_size *
4321                                         sizeof(struct process_inode_block)),
4322                                        "array of inodes to process");
4323         process_inode_count = 0;
4324
4325         pctx.errcode = ext2fs_init_dblist(fs, 0);
4326         if (pctx.errcode) {
4327                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4328                 ctx->flags |= E2F_FLAG_ABORT;
4329                 return;
4330         }
4331
4332         /*
4333          * If the last orphan field is set, clear it, since the pass1
4334          * processing will automatically find and clear the orphans.
4335          * In the future, we may want to try using the last_orphan
4336          * linked list ourselves, but for now, we clear it so that the
4337          * ext3 mount code won't get confused.
4338          */
4339         if (!(ctx->options & E2F_OPT_READONLY)) {
4340                 if (fs->super->s_last_orphan) {
4341                         fs->super->s_last_orphan = 0;
4342                         ext2fs_mark_super_dirty(fs);
4343                 }
4344         }
4345
4346         mark_table_blocks(ctx);
4347         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4348                                                     "block interate buffer");
4349         e2fsck_use_inode_shortcuts(ctx, 1);
4350         ehandler_operation(_("doing inode scan"));
4351         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4352                                               &scan);
4353         if (pctx.errcode) {
4354                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4355                 ctx->flags |= E2F_FLAG_ABORT;
4356                 return;
4357         }
4358         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4359         ctx->stashed_inode = inode;
4360         scan_struct.ctx = ctx;
4361         scan_struct.block_buf = block_buf;
4362         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4363         if (ctx->progress)
4364                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4365                         return;
4366         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
4367             (fs->super->s_mtime < fs->super->s_inodes_count))
4368                 busted_fs_time = 1;
4369
4370         while (1) {
4371                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4372                                                           inode, inode_size);
4373                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4374                         return;
4375                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4376                         if (!ctx->inode_bb_map)
4377                                 alloc_bb_map(ctx);
4378                         ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4379                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4380                         continue;
4381                 }
4382                 if (pctx.errcode) {
4383                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4384                         ctx->flags |= E2F_FLAG_ABORT;
4385                         return;
4386                 }
4387                 if (!ino)
4388                         break;
4389                 pctx.ino = ino;
4390                 pctx.inode = inode;
4391                 ctx->stashed_ino = ino;
4392                 if (inode->i_links_count) {
4393                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4394                                            ino, inode->i_links_count);
4395                         if (pctx.errcode) {
4396                                 pctx.num = inode->i_links_count;
4397                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4398                                 ctx->flags |= E2F_FLAG_ABORT;
4399                                 return;
4400                         }
4401                 }
4402                 if (ino == EXT2_BAD_INO) {
4403                         struct process_block_struct_1 pb;
4404
4405                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4406                                                           &pb.fs_meta_blocks);
4407                         if (pctx.errcode) {
4408                                 pctx.num = 4;
4409                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4410                                 ctx->flags |= E2F_FLAG_ABORT;
4411                                 return;
4412                         }
4413                         pb.ino = EXT2_BAD_INO;
4414                         pb.num_blocks = pb.last_block = 0;
4415                         pb.num_illegal_blocks = 0;
4416                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4417                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4418                         pb.inode = inode;
4419                         pb.pctx = &pctx;
4420                         pb.ctx = ctx;
4421                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4422                                      block_buf, process_bad_block, &pb);
4423                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4424                         if (pctx.errcode) {
4425                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4426                                 ctx->flags |= E2F_FLAG_ABORT;
4427                                 return;
4428                         }
4429                         if (pb.bbcheck)
4430                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4431                                 ctx->flags |= E2F_FLAG_ABORT;
4432                                 return;
4433                         }
4434                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4435                         clear_problem_context(&pctx);
4436                         continue;
4437                 } else if (ino == EXT2_ROOT_INO) {
4438                         /*
4439                          * Make sure the root inode is a directory; if
4440                          * not, offer to clear it.  It will be
4441                          * regnerated in pass #3.
4442                          */
4443                         if (!LINUX_S_ISDIR(inode->i_mode)) {
4444                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4445                                         inode->i_dtime = time(0);
4446                                         inode->i_links_count = 0;
4447                                         ext2fs_icount_store(ctx->inode_link_info,
4448                                                             ino, 0);
4449                                         e2fsck_write_inode(ctx, ino, inode,
4450                                                            "pass1");
4451                                 }
4452
4453                         }
4454                         /*
4455                          * If dtime is set, offer to clear it.  mke2fs
4456                          * version 0.2b created filesystems with the
4457                          * dtime field set for the root and lost+found
4458                          * directories.  We won't worry about
4459                          * /lost+found, since that can be regenerated
4460                          * easily.  But we will fix the root directory
4461                          * as a special case.
4462                          */
4463                         if (inode->i_dtime && inode->i_links_count) {
4464                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4465                                         inode->i_dtime = 0;
4466                                         e2fsck_write_inode(ctx, ino, inode,
4467                                                            "pass1");
4468                                 }
4469                         }
4470                 } else if (ino == EXT2_JOURNAL_INO) {
4471                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4472                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4473                                 if (!LINUX_S_ISREG(inode->i_mode) &&
4474                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4475                                                 &pctx)) {
4476                                         inode->i_mode = LINUX_S_IFREG;
4477                                         e2fsck_write_inode(ctx, ino, inode,
4478                                                            "pass1");
4479                                 }
4480                                 check_blocks(ctx, &pctx, block_buf);
4481                                 continue;
4482                         }
4483                         if ((inode->i_links_count || inode->i_blocks ||
4484                              inode->i_blocks || inode->i_block[0]) &&
4485                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4486                                         &pctx)) {
4487                                 memset(inode, 0, inode_size);
4488                                 ext2fs_icount_store(ctx->inode_link_info,
4489                                                     ino, 0);
4490                                 e2fsck_write_inode_full(ctx, ino, inode,
4491                                                         inode_size, "pass1");
4492                         }
4493                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4494                         int     problem = 0;
4495
4496                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4497                         if (ino == EXT2_BOOT_LOADER_INO) {
4498                                 if (LINUX_S_ISDIR(inode->i_mode))
4499                                         problem = PR_1_RESERVED_BAD_MODE;
4500                         } else if (ino == EXT2_RESIZE_INO) {
4501                                 if (inode->i_mode &&
4502                                     !LINUX_S_ISREG(inode->i_mode))
4503                                         problem = PR_1_RESERVED_BAD_MODE;
4504                         } else {
4505                                 if (inode->i_mode != 0)
4506                                         problem = PR_1_RESERVED_BAD_MODE;
4507                         }
4508                         if (problem) {
4509                                 if (fix_problem(ctx, problem, &pctx)) {
4510                                         inode->i_mode = 0;
4511                                         e2fsck_write_inode(ctx, ino, inode,
4512                                                            "pass1");
4513                                 }
4514                         }
4515                         check_blocks(ctx, &pctx, block_buf);
4516                         continue;
4517                 }
4518                 /*
4519                  * Check for inodes who might have been part of the
4520                  * orphaned list linked list.  They should have gotten
4521                  * dealt with by now, unless the list had somehow been
4522                  * corrupted.
4523                  *
4524                  * FIXME: In the future, inodes which are still in use
4525                  * (and which are therefore) pending truncation should
4526                  * be handled specially.  Right now we just clear the
4527                  * dtime field, and the normal e2fsck handling of
4528                  * inodes where i_size and the inode blocks are
4529                  * inconsistent is to fix i_size, instead of releasing
4530                  * the extra blocks.  This won't catch the inodes that
4531                  * was at the end of the orphan list, but it's better
4532                  * than nothing.  The right answer is that there
4533                  * shouldn't be any bugs in the orphan list handling.  :-)
4534                  */
4535                 if (inode->i_dtime && !busted_fs_time &&
4536                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
4537                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4538                                 inode->i_dtime = inode->i_links_count ?
4539                                         0 : time(0);
4540                                 e2fsck_write_inode(ctx, ino, inode,
4541                                                    "pass1");
4542                         }
4543                 }
4544
4545                 /*
4546                  * This code assumes that deleted inodes have
4547                  * i_links_count set to 0.
4548                  */
4549                 if (!inode->i_links_count) {
4550                         if (!inode->i_dtime && inode->i_mode) {
4551                                 if (fix_problem(ctx,
4552                                             PR_1_ZERO_DTIME, &pctx)) {
4553                                         inode->i_dtime = time(0);
4554                                         e2fsck_write_inode(ctx, ino, inode,
4555                                                            "pass1");
4556                                 }
4557                         }
4558                         continue;
4559                 }
4560                 /*
4561                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
4562                  * deleted files.  Oops.
4563                  *
4564                  * Since all new ext2 implementations get this right,
4565                  * we now assume that the case of non-zero
4566                  * i_links_count and non-zero dtime means that we
4567                  * should keep the file, not delete it.
4568                  *
4569                  */
4570                 if (inode->i_dtime) {
4571                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4572                                 inode->i_dtime = 0;
4573                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
4574                         }
4575                 }
4576
4577                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4578                 switch (fs->super->s_creator_os) {
4579                     case EXT2_OS_LINUX:
4580                         frag = inode->osd2.linux2.l_i_frag;
4581                         fsize = inode->osd2.linux2.l_i_fsize;
4582                         break;
4583                     case EXT2_OS_HURD:
4584                         frag = inode->osd2.hurd2.h_i_frag;
4585                         fsize = inode->osd2.hurd2.h_i_fsize;
4586                         break;
4587                     case EXT2_OS_MASIX:
4588                         frag = inode->osd2.masix2.m_i_frag;
4589                         fsize = inode->osd2.masix2.m_i_fsize;
4590                         break;
4591                     default:
4592                         frag = fsize = 0;
4593                 }
4594
4595                 if (inode->i_faddr || frag || fsize ||
4596                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4597                         mark_inode_bad(ctx, ino);
4598                 if (inode->i_flags & EXT2_IMAGIC_FL) {
4599                         if (imagic_fs) {
4600                                 if (!ctx->inode_imagic_map)
4601                                         alloc_imagic_map(ctx);
4602                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4603                                                          ino);
4604                         } else {
4605                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4606                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
4607                                         e2fsck_write_inode(ctx, ino,
4608                                                            inode, "pass1");
4609                                 }
4610                         }
4611                 }
4612
4613                 check_inode_extra_space(ctx, &pctx);
4614
4615                 if (LINUX_S_ISDIR(inode->i_mode)) {
4616                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
4617                         e2fsck_add_dir_info(ctx, ino, 0);
4618                         ctx->fs_directory_count++;
4619                 } else if (LINUX_S_ISREG (inode->i_mode)) {
4620                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
4621                         ctx->fs_regular_count++;
4622                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
4623                            e2fsck_pass1_check_device_inode(fs, inode)) {
4624                         check_immutable(ctx, &pctx);
4625                         check_size(ctx, &pctx);
4626                         ctx->fs_chardev_count++;
4627                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
4628                            e2fsck_pass1_check_device_inode(fs, inode)) {
4629                         check_immutable(ctx, &pctx);
4630                         check_size(ctx, &pctx);
4631                         ctx->fs_blockdev_count++;
4632                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
4633                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
4634                         check_immutable(ctx, &pctx);
4635                         ctx->fs_symlinks_count++;
4636                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
4637                                 ctx->fs_fast_symlinks_count++;
4638                                 check_blocks(ctx, &pctx, block_buf);
4639                                 continue;
4640                         }
4641                 }
4642                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
4643                          e2fsck_pass1_check_device_inode(fs, inode)) {
4644                         check_immutable(ctx, &pctx);
4645                         check_size(ctx, &pctx);
4646                         ctx->fs_fifo_count++;
4647                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
4648                            e2fsck_pass1_check_device_inode(fs, inode)) {
4649                         check_immutable(ctx, &pctx);
4650                         check_size(ctx, &pctx);
4651                         ctx->fs_sockets_count++;
4652                 } else
4653                         mark_inode_bad(ctx, ino);
4654                 if (inode->i_block[EXT2_IND_BLOCK])
4655                         ctx->fs_ind_count++;
4656                 if (inode->i_block[EXT2_DIND_BLOCK])
4657                         ctx->fs_dind_count++;
4658                 if (inode->i_block[EXT2_TIND_BLOCK])
4659                         ctx->fs_tind_count++;
4660                 if (inode->i_block[EXT2_IND_BLOCK] ||
4661                     inode->i_block[EXT2_DIND_BLOCK] ||
4662                     inode->i_block[EXT2_TIND_BLOCK] ||
4663                     inode->i_file_acl) {
4664                         inodes_to_process[process_inode_count].ino = ino;
4665                         inodes_to_process[process_inode_count].inode = *inode;
4666                         process_inode_count++;
4667                 } else
4668                         check_blocks(ctx, &pctx, block_buf);
4669
4670                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4671                         return;
4672
4673                 if (process_inode_count >= ctx->process_inode_size) {
4674                         process_inodes(ctx, block_buf);
4675
4676                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4677                                 return;
4678                 }
4679         }
4680         process_inodes(ctx, block_buf);
4681         ext2fs_close_inode_scan(scan);
4682         ehandler_operation(0);
4683
4684         /*
4685          * If any extended attribute blocks' reference counts need to
4686          * be adjusted, either up (ctx->refcount_extra), or down
4687          * (ctx->refcount), then fix them.
4688          */
4689         if (ctx->refcount) {
4690                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
4691                 ea_refcount_free(ctx->refcount);
4692                 ctx->refcount = 0;
4693         }
4694         if (ctx->refcount_extra) {
4695                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
4696                                         block_buf, +1);
4697                 ea_refcount_free(ctx->refcount_extra);
4698                 ctx->refcount_extra = 0;
4699         }
4700
4701         if (ctx->invalid_bitmaps)
4702                 handle_fs_bad_blocks(ctx);
4703
4704         /* We don't need the block_ea_map any more */
4705         ext2fs_free_block_bitmap(ctx->block_ea_map);
4706         ctx->block_ea_map = 0;
4707
4708         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
4709                 ext2fs_block_bitmap save_bmap;
4710
4711                 save_bmap = fs->block_map;
4712                 fs->block_map = ctx->block_found_map;
4713                 clear_problem_context(&pctx);
4714                 pctx.errcode = ext2fs_create_resize_inode(fs);
4715                 if (pctx.errcode) {
4716                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
4717                         /* Should never get here */
4718                         ctx->flags |= E2F_FLAG_ABORT;
4719                         return;
4720                 }
4721                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
4722                                   "recreate inode");
4723                 inode->i_mtime = time(0);
4724                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, 
4725                                   "recreate inode");
4726                 fs->block_map = save_bmap;
4727                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
4728         }
4729
4730         if (ctx->flags & E2F_FLAG_RESTART) {
4731                 /*
4732                  * Only the master copy of the superblock and block
4733                  * group descriptors are going to be written during a
4734                  * restart, so set the superblock to be used to be the
4735                  * master superblock.
4736                  */
4737                 ctx->use_superblock = 0;
4738                 unwind_pass1();
4739                 goto endit;
4740         }
4741
4742         if (ctx->block_dup_map) {
4743                 if (ctx->options & E2F_OPT_PREEN) {
4744                         clear_problem_context(&pctx);
4745                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
4746                 }
4747                 e2fsck_pass1_dupblocks(ctx, block_buf);
4748         }
4749         ext2fs_free_mem(&inodes_to_process);
4750 endit:
4751         e2fsck_use_inode_shortcuts(ctx, 0);
4752
4753         ext2fs_free_mem(&block_buf);
4754         ext2fs_free_mem(&inode);
4755
4756 #ifdef RESOURCE_TRACK
4757         if (ctx->options & E2F_OPT_TIME2) {
4758                 e2fsck_clear_progbar(ctx);
4759                 print_resource_track(_("Pass 1"), &rtrack);
4760         }
4761 #endif
4762 }
4763
4764 /*
4765  * When the inode_scan routines call this callback at the end of the
4766  * glock group, call process_inodes.
4767  */
4768 static errcode_t scan_callback(ext2_filsys fs,
4769                                ext2_inode_scan scan FSCK_ATTR((unused)),
4770                                dgrp_t group, void * priv_data)
4771 {
4772         struct scan_callback_struct *scan_struct;
4773         e2fsck_t ctx;
4774
4775         scan_struct = (struct scan_callback_struct *) priv_data;
4776         ctx = scan_struct->ctx;
4777
4778         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
4779
4780         if (ctx->progress)
4781                 if ((ctx->progress)(ctx, 1, group+1,
4782                                     ctx->fs->group_desc_count))
4783                         return EXT2_ET_CANCEL_REQUESTED;
4784
4785         return 0;
4786 }
4787
4788 /*
4789  * Process the inodes in the "inodes to process" list.
4790  */
4791 static void process_inodes(e2fsck_t ctx, char *block_buf)
4792 {
4793         int                     i;
4794         struct ext2_inode       *old_stashed_inode;
4795         ext2_ino_t              old_stashed_ino;
4796         const char              *old_operation;
4797         char                    buf[80];
4798         struct problem_context  pctx;
4799
4800 #if 0
4801         printf("begin process_inodes: ");
4802 #endif
4803         if (process_inode_count == 0)
4804                 return;
4805         old_operation = ehandler_operation(0);
4806         old_stashed_inode = ctx->stashed_inode;
4807         old_stashed_ino = ctx->stashed_ino;
4808         qsort(inodes_to_process, process_inode_count,
4809                       sizeof(struct process_inode_block), process_inode_cmp);
4810         clear_problem_context(&pctx);
4811         for (i=0; i < process_inode_count; i++) {
4812                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
4813                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
4814
4815 #if 0
4816                 printf("%u ", pctx.ino);
4817 #endif
4818                 sprintf(buf, _("reading indirect blocks of inode %u"),
4819                         pctx.ino);
4820                 ehandler_operation(buf);
4821                 check_blocks(ctx, &pctx, block_buf);
4822                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4823                         break;
4824         }
4825         ctx->stashed_inode = old_stashed_inode;
4826         ctx->stashed_ino = old_stashed_ino;
4827         process_inode_count = 0;
4828 #if 0
4829         printf("end process inodes\n");
4830 #endif
4831         ehandler_operation(old_operation);
4832 }
4833
4834 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
4835 {
4836         const struct process_inode_block *ib_a =
4837                 (const struct process_inode_block *) a;
4838         const struct process_inode_block *ib_b =
4839                 (const struct process_inode_block *) b;
4840         int     ret;
4841
4842         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
4843                ib_b->inode.i_block[EXT2_IND_BLOCK]);
4844         if (ret == 0)
4845                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
4846         return ret;
4847 }
4848
4849 /*
4850  * Mark an inode as being bad in some what
4851  */
4852 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
4853 {
4854         struct          problem_context pctx;
4855
4856         if (!ctx->inode_bad_map) {
4857                 clear_problem_context(&pctx);
4858
4859                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
4860                             _("bad inode map"), &ctx->inode_bad_map);
4861                 if (pctx.errcode) {
4862                         pctx.num = 3;
4863                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4864                         /* Should never get here */
4865                         ctx->flags |= E2F_FLAG_ABORT;
4866                         return;
4867                 }
4868         }
4869         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
4870 }
4871
4872
4873 /*
4874  * This procedure will allocate the inode "bb" (badblock) map table
4875  */
4876 static void alloc_bb_map(e2fsck_t ctx)
4877 {
4878         struct          problem_context pctx;
4879
4880         clear_problem_context(&pctx);
4881         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
4882                                               _("inode in bad block map"),
4883                                               &ctx->inode_bb_map);
4884         if (pctx.errcode) {
4885                 pctx.num = 4;
4886                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4887                 /* Should never get here */
4888                 ctx->flags |= E2F_FLAG_ABORT;
4889                 return;
4890         }
4891 }
4892
4893 /*
4894  * This procedure will allocate the inode imagic table
4895  */
4896 static void alloc_imagic_map(e2fsck_t ctx)
4897 {
4898         struct          problem_context pctx;
4899
4900         clear_problem_context(&pctx);
4901         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
4902                                               _("imagic inode map"),
4903                                               &ctx->inode_imagic_map);
4904         if (pctx.errcode) {
4905                 pctx.num = 5;
4906                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4907                 /* Should never get here */
4908                 ctx->flags |= E2F_FLAG_ABORT;
4909                 return;
4910         }
4911 }
4912
4913 /*
4914  * Marks a block as in use, setting the dup_map if it's been set
4915  * already.  Called by process_block and process_bad_block.
4916  *
4917  * WARNING: Assumes checks have already been done to make sure block
4918  * is valid.  This is true in both process_block and process_bad_block.
4919  */
4920 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
4921 {
4922         struct          problem_context pctx;
4923
4924         clear_problem_context(&pctx);
4925
4926         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
4927                 if (!ctx->block_dup_map) {
4928                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
4929                               _("multiply claimed block map"),
4930                               &ctx->block_dup_map);
4931                         if (pctx.errcode) {
4932                                 pctx.num = 3;
4933                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
4934                                             &pctx);
4935                                 /* Should never get here */
4936                                 ctx->flags |= E2F_FLAG_ABORT;
4937                                 return;
4938                         }
4939                 }
4940                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
4941         } else {
4942                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
4943         }
4944 }
4945
4946 /*
4947  * Adjust the extended attribute block's reference counts at the end
4948  * of pass 1, either by subtracting out references for EA blocks that
4949  * are still referenced in ctx->refcount, or by adding references for
4950  * EA blocks that had extra references as accounted for in
4951  * ctx->refcount_extra.
4952  */
4953 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4954                                     char *block_buf, int adjust_sign)
4955 {
4956         struct ext2_ext_attr_header     *header;
4957         struct problem_context          pctx;
4958         ext2_filsys                     fs = ctx->fs;
4959         blk_t                           blk;
4960         __u32                           should_be;
4961         int                             count;
4962
4963         clear_problem_context(&pctx);
4964
4965         ea_refcount_intr_begin(refcount);
4966         while (1) {
4967                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
4968                         break;
4969                 pctx.blk = blk;
4970                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
4971                 if (pctx.errcode) {
4972                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
4973                         return;
4974                 }
4975                 header = (struct ext2_ext_attr_header *) block_buf;
4976                 pctx.blkcount = header->h_refcount;
4977                 should_be = header->h_refcount + adjust_sign * count;
4978                 pctx.num = should_be;
4979                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
4980                         header->h_refcount = should_be;
4981                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
4982                                                              block_buf);
4983                         if (pctx.errcode) {
4984                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
4985                                 continue;
4986                         }
4987                 }
4988         }
4989 }
4990
4991 /*
4992  * Handle processing the extended attribute blocks
4993  */
4994 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
4995                            char *block_buf)
4996 {
4997         ext2_filsys fs = ctx->fs;
4998         ext2_ino_t      ino = pctx->ino;
4999         struct ext2_inode *inode = pctx->inode;
5000         blk_t           blk;
5001         char *          end;
5002         struct ext2_ext_attr_header *header;
5003         struct ext2_ext_attr_entry *entry;
5004         int             count;
5005         region_t        region;
5006
5007         blk = inode->i_file_acl;
5008         if (blk == 0)
5009                 return 0;
5010
5011         /*
5012          * If the Extended attribute flag isn't set, then a non-zero
5013          * file acl means that the inode is corrupted.
5014          *
5015          * Or if the extended attribute block is an invalid block,
5016          * then the inode is also corrupted.
5017          */
5018         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5019             (blk < fs->super->s_first_data_block) ||
5020             (blk >= fs->super->s_blocks_count)) {
5021                 mark_inode_bad(ctx, ino);
5022                 return 0;
5023         }
5024
5025         /* If ea bitmap hasn't been allocated, create it */
5026         if (!ctx->block_ea_map) {
5027                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5028                                                       _("ext attr block map"),
5029                                                       &ctx->block_ea_map);
5030                 if (pctx->errcode) {
5031                         pctx->num = 2;
5032                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5033                         ctx->flags |= E2F_FLAG_ABORT;
5034                         return 0;
5035                 }
5036         }
5037
5038         /* Create the EA refcount structure if necessary */
5039         if (!ctx->refcount) {
5040                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5041                 if (pctx->errcode) {
5042                         pctx->num = 1;
5043                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5044                         ctx->flags |= E2F_FLAG_ABORT;
5045                         return 0;
5046                 }
5047         }
5048
5049 #if 0
5050         /* Debugging text */
5051         printf("Inode %u has EA block %u\n", ino, blk);
5052 #endif
5053
5054         /* Have we seen this EA block before? */
5055         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5056                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5057                         return 1;
5058                 /* Ooops, this EA was referenced more than it stated */
5059                 if (!ctx->refcount_extra) {
5060                         pctx->errcode = ea_refcount_create(0,
5061                                            &ctx->refcount_extra);
5062                         if (pctx->errcode) {
5063                                 pctx->num = 2;
5064                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5065                                 ctx->flags |= E2F_FLAG_ABORT;
5066                                 return 0;
5067                         }
5068                 }
5069                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5070                 return 1;
5071         }
5072
5073         /*
5074          * OK, we haven't seen this EA block yet.  So we need to
5075          * validate it
5076          */
5077         pctx->blk = blk;
5078         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5079         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5080                 goto clear_extattr;
5081         header = (struct ext2_ext_attr_header *) block_buf;
5082         pctx->blk = inode->i_file_acl;
5083         if (((ctx->ext_attr_ver == 1) &&
5084              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5085             ((ctx->ext_attr_ver == 2) &&
5086              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5087                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5088                         goto clear_extattr;
5089         }
5090
5091         if (header->h_blocks != 1) {
5092                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5093                         goto clear_extattr;
5094         }
5095
5096         region = region_create(0, fs->blocksize);
5097         if (!region) {
5098                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5099                 ctx->flags |= E2F_FLAG_ABORT;
5100                 return 0;
5101         }
5102         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5103                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5104                         goto clear_extattr;
5105         }
5106
5107         entry = (struct ext2_ext_attr_entry *)(header+1);
5108         end = block_buf + fs->blocksize;
5109         while ((char *)entry < end && *(__u32 *)entry) {
5110                 if (region_allocate(region, (char *)entry - (char *)header,
5111                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5112                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5113                                 goto clear_extattr;
5114                 }
5115                 if ((ctx->ext_attr_ver == 1 &&
5116                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5117                     (ctx->ext_attr_ver == 2 &&
5118                      entry->e_name_index == 0)) {
5119                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5120                                 goto clear_extattr;
5121                 }
5122                 if (entry->e_value_block != 0) {
5123                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5124                                 goto clear_extattr;
5125                 }
5126                 if (entry->e_value_size &&
5127                     region_allocate(region, entry->e_value_offs,
5128                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5129                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5130                                 goto clear_extattr;
5131                 }
5132                 entry = EXT2_EXT_ATTR_NEXT(entry);
5133         }
5134         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5135                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5136                         goto clear_extattr;
5137         }
5138         region_free(region);
5139
5140         count = header->h_refcount - 1;
5141         if (count)
5142                 ea_refcount_store(ctx->refcount, blk, count);
5143         mark_block_used(ctx, blk);
5144         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5145
5146         return 1;
5147
5148 clear_extattr:
5149         inode->i_file_acl = 0;
5150         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5151         return 0;
5152 }
5153
5154 /* Returns 1 if bad htree, 0 if OK */
5155 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5156                         ext2_ino_t ino FSCK_ATTR((unused)),
5157                         struct ext2_inode *inode,
5158                         char *block_buf)
5159 {
5160         struct ext2_dx_root_info        *root;
5161         ext2_filsys                     fs = ctx->fs;
5162         errcode_t                       retval;
5163         blk_t                           blk;
5164
5165         if ((!LINUX_S_ISDIR(inode->i_mode) &&
5166              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5167             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5168              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5169                 return 1;
5170
5171         blk = inode->i_block[0];
5172         if (((blk == 0) ||
5173              (blk < fs->super->s_first_data_block) ||
5174              (blk >= fs->super->s_blocks_count)) &&
5175             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5176                 return 1;
5177
5178         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5179         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5180                 return 1;
5181
5182         /* XXX should check that beginning matches a directory */
5183         root = (struct ext2_dx_root_info *) (block_buf + 24);
5184
5185         if ((root->reserved_zero || root->info_length < 8) &&
5186             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5187                 return 1;
5188
5189         pctx->num = root->hash_version;
5190         if ((root->hash_version != EXT2_HASH_LEGACY) &&
5191             (root->hash_version != EXT2_HASH_HALF_MD4) &&
5192             (root->hash_version != EXT2_HASH_TEA) &&
5193             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5194                 return 1;
5195
5196         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5197             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5198                 return 1;
5199
5200         pctx->num = root->indirect_levels;
5201         if ((root->indirect_levels > 1) &&
5202             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5203                 return 1;
5204
5205         return 0;
5206 }
5207
5208 /*
5209  * This subroutine is called on each inode to account for all of the
5210  * blocks used by that inode.
5211  */
5212 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5213                          char *block_buf)
5214 {
5215         ext2_filsys fs = ctx->fs;
5216         struct process_block_struct_1 pb;
5217         ext2_ino_t      ino = pctx->ino;
5218         struct ext2_inode *inode = pctx->inode;
5219         int             bad_size = 0;
5220         int             dirty_inode = 0;
5221         __u64           size;
5222
5223         pb.ino = ino;
5224         pb.num_blocks = 0;
5225         pb.last_block = -1;
5226         pb.num_illegal_blocks = 0;
5227         pb.suppress = 0; pb.clear = 0;
5228         pb.fragmented = 0;
5229         pb.compressed = 0;
5230         pb.previous_block = 0;
5231         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5232         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5233         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5234         pb.inode = inode;
5235         pb.pctx = pctx;
5236         pb.ctx = ctx;
5237         pctx->ino = ino;
5238         pctx->errcode = 0;
5239
5240         if (inode->i_flags & EXT2_COMPRBLK_FL) {
5241                 if (fs->super->s_feature_incompat &
5242                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
5243                         pb.compressed = 1;
5244                 else {
5245                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5246                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5247                                 dirty_inode++;
5248                         }
5249                 }
5250         }
5251
5252         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5253                 pb.num_blocks++;
5254
5255         if (ext2fs_inode_has_valid_blocks(inode))
5256                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5257                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5258                                        block_buf, process_block, &pb);
5259         end_problem_latch(ctx, PR_LATCH_BLOCK);
5260         end_problem_latch(ctx, PR_LATCH_TOOBIG);
5261         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5262                 goto out;
5263         if (pctx->errcode)
5264                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5265
5266         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5267                 ctx->fs_fragmented++;
5268
5269         if (pb.clear) {
5270                 inode->i_links_count = 0;
5271                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5272                 inode->i_dtime = time(0);
5273                 dirty_inode++;
5274                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5275                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5276                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5277                 /*
5278                  * The inode was probably partially accounted for
5279                  * before processing was aborted, so we need to
5280                  * restart the pass 1 scan.
5281                  */
5282                 ctx->flags |= E2F_FLAG_RESTART;
5283                 goto out;
5284         }
5285
5286         if (inode->i_flags & EXT2_INDEX_FL) {
5287                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5288                         inode->i_flags &= ~EXT2_INDEX_FL;
5289                         dirty_inode++;
5290                 } else {
5291 #ifdef ENABLE_HTREE
5292                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5293 #endif
5294                 }
5295         }
5296         if (ctx->dirs_to_hash && pb.is_dir &&
5297             !(inode->i_flags & EXT2_INDEX_FL) &&
5298             ((inode->i_size / fs->blocksize) >= 3))
5299                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5300
5301         if (!pb.num_blocks && pb.is_dir) {
5302                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5303                         inode->i_links_count = 0;
5304                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5305                         inode->i_dtime = time(0);
5306                         dirty_inode++;
5307                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5308                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5309                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5310                         ctx->fs_directory_count--;
5311                         goto out;
5312                 }
5313         }
5314
5315         pb.num_blocks *= (fs->blocksize / 512);
5316 #if 0
5317         printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5318                ino, inode->i_size, pb.last_block, inode->i_blocks,
5319                pb.num_blocks);
5320 #endif
5321         if (pb.is_dir) {
5322                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5323                 if (nblock > (pb.last_block + 1))
5324                         bad_size = 1;
5325                 else if (nblock < (pb.last_block + 1)) {
5326                         if (((pb.last_block + 1) - nblock) >
5327                             fs->super->s_prealloc_dir_blocks)
5328                                 bad_size = 2;
5329                 }
5330         } else {
5331                 size = EXT2_I_SIZE(inode);
5332                 if ((pb.last_block >= 0) &&
5333                     (size < (__u64) pb.last_block * fs->blocksize))
5334                         bad_size = 3;
5335                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5336                         bad_size = 4;
5337         }
5338         /* i_size for symlinks is checked elsewhere */
5339         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5340                 pctx->num = (pb.last_block+1) * fs->blocksize;
5341                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5342                         inode->i_size = pctx->num;
5343                         if (!LINUX_S_ISDIR(inode->i_mode))
5344                                 inode->i_size_high = pctx->num >> 32;
5345                         dirty_inode++;
5346                 }
5347                 pctx->num = 0;
5348         }
5349         if (LINUX_S_ISREG(inode->i_mode) &&
5350             (inode->i_size_high || inode->i_size & 0x80000000UL))
5351                 ctx->large_files++;
5352         if (pb.num_blocks != inode->i_blocks) {
5353                 pctx->num = pb.num_blocks;
5354                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5355                         inode->i_blocks = pb.num_blocks;
5356                         dirty_inode++;
5357                 }
5358                 pctx->num = 0;
5359         }
5360 out:
5361         if (dirty_inode)
5362                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5363 }
5364
5365 #if 0
5366 /*
5367  * Helper function called by process block when an illegal block is
5368  * found.  It returns a description about why the block is illegal
5369  */
5370 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5371 {
5372         blk_t   super;
5373         int     i;
5374         static char     problem[80];
5375
5376         super = fs->super->s_first_data_block;
5377         strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5378         if (block < super) {
5379                 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5380                 return(problem);
5381         } else if (block >= fs->super->s_blocks_count) {
5382                 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5383                 return(problem);
5384         }
5385         for (i = 0; i < fs->group_desc_count; i++) {
5386                 if (block == super) {
5387                         sprintf(problem, "is the superblock in group %d", i);
5388                         break;
5389                 }
5390                 if (block > super &&
5391                     block <= (super + fs->desc_blocks)) {
5392                         sprintf(problem, "is in the group descriptors "
5393                                 "of group %d", i);
5394                         break;
5395                 }
5396                 if (block == fs->group_desc[i].bg_block_bitmap) {
5397                         sprintf(problem, "is the block bitmap of group %d", i);
5398                         break;
5399                 }
5400                 if (block == fs->group_desc[i].bg_inode_bitmap) {
5401                         sprintf(problem, "is the inode bitmap of group %d", i);
5402                         break;
5403                 }
5404                 if (block >= fs->group_desc[i].bg_inode_table &&
5405                     (block < fs->group_desc[i].bg_inode_table
5406                      + fs->inode_blocks_per_group)) {
5407                         sprintf(problem, "is in the inode table of group %d",
5408                                 i);
5409                         break;
5410                 }
5411                 super += fs->super->s_blocks_per_group;
5412         }
5413         return(problem);
5414 }
5415 #endif
5416
5417 /*
5418  * This is a helper function for check_blocks().
5419  */
5420 static int process_block(ext2_filsys fs,
5421                   blk_t *block_nr,
5422                   e2_blkcnt_t blockcnt,
5423                   blk_t ref_block FSCK_ATTR((unused)),
5424                   int ref_offset FSCK_ATTR((unused)),
5425                   void *priv_data)
5426 {
5427         struct process_block_struct_1 *p;
5428         struct problem_context *pctx;
5429         blk_t   blk = *block_nr;
5430         int     ret_code = 0;
5431         int     problem = 0;
5432         e2fsck_t        ctx;
5433
5434         p = (struct process_block_struct_1 *) priv_data;
5435         pctx = p->pctx;
5436         ctx = p->ctx;
5437
5438         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5439                 /* todo: Check that the comprblk_fl is high, that the
5440                    blkaddr pattern looks right (all non-holes up to
5441                    first EXT2FS_COMPRESSED_BLKADDR, then all
5442                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5443                    that the feature_incompat bit is high, and that the
5444                    inode is a regular file.  If we're doing a "full
5445                    check" (a concept introduced to e2fsck by e2compr,
5446                    meaning that we look at data blocks as well as
5447                    metadata) then call some library routine that
5448                    checks the compressed data.  I'll have to think
5449                    about this, because one particularly important
5450                    problem to be able to fix is to recalculate the
5451                    cluster size if necessary.  I think that perhaps
5452                    we'd better do most/all e2compr-specific checks
5453                    separately, after the non-e2compr checks.  If not
5454                    doing a full check, it may be useful to test that
5455                    the personality is linux; e.g. if it isn't then
5456                    perhaps this really is just an illegal block. */
5457                 return 0;
5458         }
5459
5460         if (blk == 0) {
5461                 if (p->is_dir == 0) {
5462                         /*
5463                          * Should never happen, since only directories
5464                          * get called with BLOCK_FLAG_HOLE
5465                          */
5466 #if DEBUG_E2FSCK
5467                         printf("process_block() called with blk == 0, "
5468                                "blockcnt=%d, inode %lu???\n",
5469                                blockcnt, p->ino);
5470 #endif
5471                         return 0;
5472                 }
5473                 if (blockcnt < 0)
5474                         return 0;
5475                 if (blockcnt * fs->blocksize < p->inode->i_size) {
5476 #if 0
5477                         printf("Missing block (#%d) in directory inode %lu!\n",
5478                                blockcnt, p->ino);
5479 #endif
5480                         goto mark_dir;
5481                 }
5482                 return 0;
5483         }
5484
5485 #if 0
5486         printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5487                blockcnt);
5488 #endif
5489
5490         /*
5491          * Simplistic fragmentation check.  We merely require that the
5492          * file be contiguous.  (Which can never be true for really
5493          * big files that are greater than a block group.)
5494          */
5495         if (!HOLE_BLKADDR(p->previous_block)) {
5496                 if (p->previous_block+1 != blk)
5497                         p->fragmented = 1;
5498         }
5499         p->previous_block = blk;
5500
5501         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5502                 problem = PR_1_TOOBIG_DIR;
5503         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5504                 problem = PR_1_TOOBIG_REG;
5505         if (!p->is_dir && !p->is_reg && blockcnt > 0)
5506                 problem = PR_1_TOOBIG_SYMLINK;
5507
5508         if (blk < fs->super->s_first_data_block ||
5509             blk >= fs->super->s_blocks_count)
5510                 problem = PR_1_ILLEGAL_BLOCK_NUM;
5511
5512         if (problem) {
5513                 p->num_illegal_blocks++;
5514                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5515                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5516                                 p->clear = 1;
5517                                 return BLOCK_ABORT;
5518                         }
5519                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5520                                 p->suppress = 1;
5521                                 set_latch_flags(PR_LATCH_BLOCK,
5522                                                 PRL_SUPPRESS, 0);
5523                         }
5524                 }
5525                 pctx->blk = blk;
5526                 pctx->blkcount = blockcnt;
5527                 if (fix_problem(ctx, problem, pctx)) {
5528                         blk = *block_nr = 0;
5529                         ret_code = BLOCK_CHANGED;
5530                         goto mark_dir;
5531                 } else
5532                         return 0;
5533         }
5534
5535         if (p->ino == EXT2_RESIZE_INO) {
5536                 /*
5537                  * The resize inode has already be sanity checked
5538                  * during pass #0 (the superblock checks).  All we
5539                  * have to do is mark the double indirect block as
5540                  * being in use; all of the other blocks are handled
5541                  * by mark_table_blocks()).
5542                  */
5543                 if (blockcnt == BLOCK_COUNT_DIND)
5544                         mark_block_used(ctx, blk);
5545         } else
5546                 mark_block_used(ctx, blk);
5547         p->num_blocks++;
5548         if (blockcnt >= 0)
5549                 p->last_block = blockcnt;
5550 mark_dir:
5551         if (p->is_dir && (blockcnt >= 0)) {
5552                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5553                                                     blk, blockcnt);
5554                 if (pctx->errcode) {
5555                         pctx->blk = blk;
5556                         pctx->num = blockcnt;
5557                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5558                         /* Should never get here */
5559                         ctx->flags |= E2F_FLAG_ABORT;
5560                         return BLOCK_ABORT;
5561                 }
5562         }
5563         return ret_code;
5564 }
5565
5566 static int process_bad_block(ext2_filsys fs,
5567                       blk_t *block_nr,
5568                       e2_blkcnt_t blockcnt,
5569                       blk_t ref_block FSCK_ATTR((unused)),
5570                       int ref_offset FSCK_ATTR((unused)),
5571                       void *priv_data)
5572 {
5573         struct process_block_struct_1 *p;
5574         blk_t           blk = *block_nr;
5575         blk_t           first_block;
5576         dgrp_t          i;
5577         struct problem_context *pctx;
5578         e2fsck_t        ctx;
5579
5580         /*
5581          * Note: This function processes blocks for the bad blocks
5582          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
5583          */
5584
5585         if (!blk)
5586                 return 0;
5587
5588         p = (struct process_block_struct_1 *) priv_data;
5589         ctx = p->ctx;
5590         pctx = p->pctx;
5591
5592         pctx->ino = EXT2_BAD_INO;
5593         pctx->blk = blk;
5594         pctx->blkcount = blockcnt;
5595
5596         if ((blk < fs->super->s_first_data_block) ||
5597             (blk >= fs->super->s_blocks_count)) {
5598                 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5599                         *block_nr = 0;
5600                         return BLOCK_CHANGED;
5601                 } else
5602                         return 0;
5603         }
5604
5605         if (blockcnt < 0) {
5606                 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5607                         p->bbcheck = 1;
5608                         if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5609                                 *block_nr = 0;
5610                                 return BLOCK_CHANGED;
5611                         }
5612                 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5613                                                     blk)) {
5614                         p->bbcheck = 1;
5615                         if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5616                                         pctx)) {
5617                                 *block_nr = 0;
5618                                 return BLOCK_CHANGED;
5619                         }
5620                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5621                                 return BLOCK_ABORT;
5622                 } else
5623                         mark_block_used(ctx, blk);
5624                 return 0;
5625         }
5626 #if 0
5627         printf ("DEBUG: Marking %u as bad.\n", blk);
5628 #endif
5629         ctx->fs_badblocks_count++;
5630         /*
5631          * If the block is not used, then mark it as used and return.
5632          * If it is already marked as found, this must mean that
5633          * there's an overlap between the filesystem table blocks
5634          * (bitmaps and inode table) and the bad block list.
5635          */
5636         if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
5637                 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
5638                 return 0;
5639         }
5640         /*
5641          * Try to find the where the filesystem block was used...
5642          */
5643         first_block = fs->super->s_first_data_block;
5644
5645         for (i = 0; i < fs->group_desc_count; i++ ) {
5646                 pctx->group = i;
5647                 pctx->blk = blk;
5648                 if (!ext2fs_bg_has_super(fs, i))
5649                         goto skip_super;
5650                 if (blk == first_block) {
5651                         if (i == 0) {
5652                                 if (fix_problem(ctx,
5653                                                 PR_1_BAD_PRIMARY_SUPERBLOCK,
5654                                                 pctx)) {
5655                                         *block_nr = 0;
5656                                         return BLOCK_CHANGED;
5657                                 }
5658                                 return 0;
5659                         }
5660                         fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
5661                         return 0;
5662                 }
5663                 if ((blk > first_block) &&
5664                     (blk <= first_block + fs->desc_blocks)) {
5665                         if (i == 0) {
5666                                 pctx->blk = *block_nr;
5667                                 if (fix_problem(ctx,
5668                         PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
5669                                         *block_nr = 0;
5670                                         return BLOCK_CHANGED;
5671                                 }
5672                                 return 0;
5673                         }
5674                         fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
5675                         return 0;
5676                 }
5677         skip_super:
5678                 if (blk == fs->group_desc[i].bg_block_bitmap) {
5679                         if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
5680                                 ctx->invalid_block_bitmap_flag[i]++;
5681                                 ctx->invalid_bitmaps++;
5682                         }
5683                         return 0;
5684                 }
5685                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
5686                         if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
5687                                 ctx->invalid_inode_bitmap_flag[i]++;
5688                                 ctx->invalid_bitmaps++;
5689                         }
5690                         return 0;
5691                 }
5692                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
5693                     (blk < (fs->group_desc[i].bg_inode_table +
5694                             fs->inode_blocks_per_group))) {
5695                         /*
5696                          * If there are bad blocks in the inode table,
5697                          * the inode scan code will try to do
5698                          * something reasonable automatically.
5699                          */
5700                         return 0;
5701                 }
5702                 first_block += fs->super->s_blocks_per_group;
5703         }
5704         /*
5705          * If we've gotten to this point, then the only
5706          * possibility is that the bad block inode meta data
5707          * is using a bad block.
5708          */
5709         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
5710             (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
5711             (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
5712                 p->bbcheck = 1;
5713                 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
5714                         *block_nr = 0;
5715                         return BLOCK_CHANGED;
5716                 }
5717                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5718                         return BLOCK_ABORT;
5719                 return 0;
5720         }
5721
5722         pctx->group = -1;
5723
5724         /* Warn user that the block wasn't claimed */
5725         fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
5726
5727         return 0;
5728 }
5729
5730 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
5731                             const char *name, int num, blk_t *new_block)
5732 {
5733         ext2_filsys fs = ctx->fs;
5734         blk_t           old_block = *new_block;
5735         int             i;
5736         char            *buf;
5737         struct problem_context  pctx;
5738
5739         clear_problem_context(&pctx);
5740
5741         pctx.group = group;
5742         pctx.blk = old_block;
5743         pctx.str = name;
5744
5745         pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
5746                         first_block + fs->super->s_blocks_per_group,
5747                                         num, ctx->block_found_map, new_block);
5748         if (pctx.errcode) {
5749                 pctx.num = num;
5750                 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
5751                 ext2fs_unmark_valid(fs);
5752                 return;
5753         }
5754         pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
5755         if (pctx.errcode) {
5756                 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
5757                 ext2fs_unmark_valid(fs);
5758                 return;
5759         }
5760         ext2fs_mark_super_dirty(fs);
5761         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
5762         pctx.blk2 = *new_block;
5763         fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
5764                           PR_1_RELOC_TO), &pctx);
5765         pctx.blk2 = 0;
5766         for (i = 0; i < num; i++) {
5767                 pctx.blk = i;
5768                 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
5769                 if (old_block) {
5770                         pctx.errcode = io_channel_read_blk(fs->io,
5771                                    old_block + i, 1, buf);
5772                         if (pctx.errcode)
5773                                 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
5774                 } else
5775                         memset(buf, 0, fs->blocksize);
5776
5777                 pctx.blk = (*new_block) + i;
5778                 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
5779                                               1, buf);
5780                 if (pctx.errcode)
5781                         fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
5782         }
5783         ext2fs_free_mem(&buf);
5784 }
5785
5786 /*
5787  * This routine gets called at the end of pass 1 if bad blocks are
5788  * detected in the superblock, group descriptors, inode_bitmaps, or
5789  * block bitmaps.  At this point, all of the blocks have been mapped
5790  * out, so we can try to allocate new block(s) to replace the bad
5791  * blocks.
5792  */
5793 static void handle_fs_bad_blocks(e2fsck_t ctx)
5794 {
5795         ext2_filsys fs = ctx->fs;
5796         dgrp_t          i;
5797         int             first_block = fs->super->s_first_data_block;
5798
5799         for (i = 0; i < fs->group_desc_count; i++) {
5800                 if (ctx->invalid_block_bitmap_flag[i]) {
5801                         new_table_block(ctx, first_block, i, _("block bitmap"),
5802                                         1, &fs->group_desc[i].bg_block_bitmap);
5803                 }
5804                 if (ctx->invalid_inode_bitmap_flag[i]) {
5805                         new_table_block(ctx, first_block, i, _("inode bitmap"),
5806                                         1, &fs->group_desc[i].bg_inode_bitmap);
5807                 }
5808                 if (ctx->invalid_inode_table_flag[i]) {
5809                         new_table_block(ctx, first_block, i, _("inode table"),
5810                                         fs->inode_blocks_per_group,
5811                                         &fs->group_desc[i].bg_inode_table);
5812                         ctx->flags |= E2F_FLAG_RESTART;
5813                 }
5814                 first_block += fs->super->s_blocks_per_group;
5815         }
5816         ctx->invalid_bitmaps = 0;
5817 }
5818
5819 /*
5820  * This routine marks all blocks which are used by the superblock,
5821  * group descriptors, inode bitmaps, and block bitmaps.
5822  */
5823 static void mark_table_blocks(e2fsck_t ctx)
5824 {
5825         ext2_filsys fs = ctx->fs;
5826         blk_t   block, b;
5827         dgrp_t  i;
5828         int     j;
5829         struct problem_context pctx;
5830
5831         clear_problem_context(&pctx);
5832
5833         block = fs->super->s_first_data_block;
5834         for (i = 0; i < fs->group_desc_count; i++) {
5835                 pctx.group = i;
5836
5837                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
5838
5839                 /*
5840                  * Mark the blocks used for the inode table
5841                  */
5842                 if (fs->group_desc[i].bg_inode_table) {
5843                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
5844                              j < fs->inode_blocks_per_group;
5845                              j++, b++) {
5846                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
5847                                                              b)) {
5848                                         pctx.blk = b;
5849                                         if (fix_problem(ctx,
5850                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
5851                                                 ctx->invalid_inode_table_flag[i]++;
5852                                                 ctx->invalid_bitmaps++;
5853                                         }
5854                                 } else {
5855                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
5856                                                              b);
5857                                 }
5858                         }
5859                 }
5860
5861                 /*
5862                  * Mark block used for the block bitmap
5863                  */
5864                 if (fs->group_desc[i].bg_block_bitmap) {
5865                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
5866                                      fs->group_desc[i].bg_block_bitmap)) {
5867                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
5868                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
5869                                         ctx->invalid_block_bitmap_flag[i]++;
5870                                         ctx->invalid_bitmaps++;
5871                                 }
5872                         } else {
5873                             ext2fs_mark_block_bitmap(ctx->block_found_map,
5874                                      fs->group_desc[i].bg_block_bitmap);
5875                     }
5876
5877                 }
5878                 /*
5879                  * Mark block used for the inode bitmap
5880                  */
5881                 if (fs->group_desc[i].bg_inode_bitmap) {
5882                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
5883                                      fs->group_desc[i].bg_inode_bitmap)) {
5884                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
5885                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
5886                                         ctx->invalid_inode_bitmap_flag[i]++;
5887                                         ctx->invalid_bitmaps++;
5888                                 }
5889                         } else {
5890                             ext2fs_mark_block_bitmap(ctx->block_found_map,
5891                                      fs->group_desc[i].bg_inode_bitmap);
5892                         }
5893                 }
5894                 block += fs->super->s_blocks_per_group;
5895         }
5896 }
5897
5898 /*
5899  * Thes subroutines short circuits ext2fs_get_blocks and
5900  * ext2fs_check_directory; we use them since we already have the inode
5901  * structure, so there's no point in letting the ext2fs library read
5902  * the inode again.
5903  */
5904 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
5905                                   blk_t *blocks)
5906 {
5907         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5908         int     i;
5909
5910         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
5911                 return EXT2_ET_CALLBACK_NOTHANDLED;
5912
5913         for (i=0; i < EXT2_N_BLOCKS; i++)
5914                 blocks[i] = ctx->stashed_inode->i_block[i];
5915         return 0;
5916 }
5917
5918 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
5919                                   struct ext2_inode *inode)
5920 {
5921         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5922
5923         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
5924                 return EXT2_ET_CALLBACK_NOTHANDLED;
5925         *inode = *ctx->stashed_inode;
5926         return 0;
5927 }
5928
5929 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
5930                             struct ext2_inode *inode)
5931 {
5932         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5933
5934         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
5935                 *ctx->stashed_inode = *inode;
5936         return EXT2_ET_CALLBACK_NOTHANDLED;
5937 }
5938
5939 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
5940 {
5941         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5942
5943         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
5944                 return EXT2_ET_CALLBACK_NOTHANDLED;
5945
5946         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
5947                 return EXT2_ET_NO_DIRECTORY;
5948         return 0;
5949 }
5950
5951 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
5952 {
5953         ext2_filsys fs = ctx->fs;
5954
5955         if (bool) {
5956                 fs->get_blocks = pass1_get_blocks;
5957                 fs->check_directory = pass1_check_directory;
5958                 fs->read_inode = pass1_read_inode;
5959                 fs->write_inode = pass1_write_inode;
5960                 ctx->stashed_ino = 0;
5961         } else {
5962                 fs->get_blocks = 0;
5963                 fs->check_directory = 0;
5964                 fs->read_inode = 0;
5965                 fs->write_inode = 0;
5966         }
5967 }
5968
5969 /*
5970  * pass1b.c --- Pass #1b of e2fsck
5971  *
5972  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
5973  * only invoked if pass 1 discovered blocks which are in use by more
5974  * than one inode.
5975  *
5976  * Pass1B scans the data blocks of all the inodes again, generating a
5977  * complete list of duplicate blocks and which inodes have claimed
5978  * them.
5979  *
5980  * Pass1C does a tree-traversal of the filesystem, to determine the
5981  * parent directories of these inodes.  This step is necessary so that
5982  * e2fsck can print out the pathnames of affected inodes.
5983  *
5984  * Pass1D is a reconciliation pass.  For each inode with duplicate
5985  * blocks, the user is prompted if s/he would like to clone the file
5986  * (so that the file gets a fresh copy of the duplicated blocks) or
5987  * simply to delete the file.
5988  *
5989  */
5990
5991
5992 /* Needed for architectures where sizeof(int) != sizeof(void *) */
5993 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
5994 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
5995
5996 /* Define an extension to the ext2 library's block count information */
5997 #define BLOCK_COUNT_EXTATTR     (-5)
5998
5999 struct block_el {
6000         blk_t   block;
6001         struct block_el *next;
6002 };
6003
6004 struct inode_el {
6005         ext2_ino_t      inode;
6006         struct inode_el *next;
6007 };
6008
6009 struct dup_block {
6010         int             num_bad;
6011         struct inode_el *inode_list;
6012 };
6013
6014 /*
6015  * This structure stores information about a particular inode which
6016  * is sharing blocks with other inodes.  This information is collected
6017  * to display to the user, so that the user knows what files he or she
6018  * is dealing with, when trying to decide how to resolve the conflict
6019  * of multiply-claimed blocks.
6020  */
6021 struct dup_inode {
6022         ext2_ino_t              dir;
6023         int                     num_dupblocks;
6024         struct ext2_inode       inode;
6025         struct block_el         *block_list;
6026 };
6027
6028 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
6029                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
6030                                 int ref_offset, void *priv_data);
6031 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6032                         struct dup_inode *dp, char *block_buf);
6033 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6034                       struct dup_inode *dp, char* block_buf);
6035 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6036
6037 static void pass1b(e2fsck_t ctx, char *block_buf);
6038 static void pass1c(e2fsck_t ctx, char *block_buf);
6039 static void pass1d(e2fsck_t ctx, char *block_buf);
6040
6041 static int dup_inode_count = 0;
6042
6043 static dict_t blk_dict, ino_dict;
6044
6045 static ext2fs_inode_bitmap inode_dup_map;
6046
6047 static int dict_int_cmp(const void *a, const void *b)
6048 {
6049         intptr_t        ia, ib;
6050
6051         ia = (intptr_t)a;
6052         ib = (intptr_t)b;
6053
6054         return (ia-ib);
6055 }
6056
6057 /*
6058  * Add a duplicate block record
6059  */
6060 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6061                      struct ext2_inode *inode)
6062 {
6063         dnode_t *n;
6064         struct dup_block        *db;
6065         struct dup_inode        *di;
6066         struct block_el         *blk_el;
6067         struct inode_el         *ino_el;
6068
6069         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6070         if (n)
6071                 db = (struct dup_block *) dnode_get(n);
6072         else {
6073                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6074                          sizeof(struct dup_block), "duplicate block header");
6075                 db->num_bad = 0;
6076                 db->inode_list = 0;
6077                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6078         }
6079         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6080                          sizeof(struct inode_el), "inode element");
6081         ino_el->inode = ino;
6082         ino_el->next = db->inode_list;
6083         db->inode_list = ino_el;
6084         db->num_bad++;
6085
6086         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6087         if (n)
6088                 di = (struct dup_inode *) dnode_get(n);
6089         else {
6090                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6091                          sizeof(struct dup_inode), "duplicate inode header");
6092                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6093                 di->num_dupblocks = 0;
6094                 di->block_list = 0;
6095                 di->inode = *inode;
6096                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6097         }
6098         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6099                          sizeof(struct block_el), "block element");
6100         blk_el->block = blk;
6101         blk_el->next = di->block_list;
6102         di->block_list = blk_el;
6103         di->num_dupblocks++;
6104 }
6105
6106 /*
6107  * Free a duplicate inode record
6108  */
6109 static void inode_dnode_free(dnode_t *node)
6110 {
6111         struct dup_inode        *di;
6112         struct block_el         *p, *next;
6113
6114         di = (struct dup_inode *) dnode_get(node);
6115         for (p = di->block_list; p; p = next) {
6116                 next = p->next;
6117                 free(p);
6118         }
6119         free(node);
6120 }
6121
6122 /*
6123  * Free a duplicate block record
6124  */
6125 static void block_dnode_free(dnode_t *node)
6126 {
6127         struct dup_block        *db;
6128         struct inode_el         *p, *next;
6129
6130         db = (struct dup_block *) dnode_get(node);
6131         for (p = db->inode_list; p; p = next) {
6132                 next = p->next;
6133                 free(p);
6134         }
6135         free(node);
6136 }
6137
6138
6139 /*
6140  * Main procedure for handling duplicate blocks
6141  */
6142 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6143 {
6144         ext2_filsys             fs = ctx->fs;
6145         struct problem_context  pctx;
6146
6147         clear_problem_context(&pctx);
6148
6149         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6150                       _("multiply claimed inode map"), &inode_dup_map);
6151         if (pctx.errcode) {
6152                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6153                 ctx->flags |= E2F_FLAG_ABORT;
6154                 return;
6155         }
6156
6157         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6158         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6159         dict_set_allocator(&ino_dict, inode_dnode_free);
6160         dict_set_allocator(&blk_dict, block_dnode_free);
6161
6162         pass1b(ctx, block_buf);
6163         pass1c(ctx, block_buf);
6164         pass1d(ctx, block_buf);
6165
6166         /*
6167          * Time to free all of the accumulated data structures that we
6168          * don't need anymore.
6169          */
6170         dict_free_nodes(&ino_dict);
6171         dict_free_nodes(&blk_dict);
6172 }
6173
6174 /*
6175  * Scan the inodes looking for inodes that contain duplicate blocks.
6176  */
6177 struct process_block_struct_1b {
6178         e2fsck_t        ctx;
6179         ext2_ino_t      ino;
6180         int             dup_blocks;
6181         struct ext2_inode *inode;
6182         struct problem_context *pctx;
6183 };
6184
6185 static void pass1b(e2fsck_t ctx, char *block_buf)
6186 {
6187         ext2_filsys fs = ctx->fs;
6188         ext2_ino_t ino;
6189         struct ext2_inode inode;
6190         ext2_inode_scan scan;
6191         struct process_block_struct_1b pb;
6192         struct problem_context pctx;
6193
6194         clear_problem_context(&pctx);
6195
6196         if (!(ctx->options & E2F_OPT_PREEN))
6197                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6198         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6199                                               &scan);
6200         if (pctx.errcode) {
6201                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6202                 ctx->flags |= E2F_FLAG_ABORT;
6203                 return;
6204         }
6205         ctx->stashed_inode = &inode;
6206         pb.ctx = ctx;
6207         pb.pctx = &pctx;
6208         pctx.str = "pass1b";
6209         while (1) {
6210                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6211                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6212                         continue;
6213                 if (pctx.errcode) {
6214                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6215                         ctx->flags |= E2F_FLAG_ABORT;
6216                         return;
6217                 }
6218                 if (!ino)
6219                         break;
6220                 pctx.ino = ctx->stashed_ino = ino;
6221                 if ((ino != EXT2_BAD_INO) &&
6222                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6223                         continue;
6224
6225                 pb.ino = ino;
6226                 pb.dup_blocks = 0;
6227                 pb.inode = &inode;
6228
6229                 if (ext2fs_inode_has_valid_blocks(&inode) ||
6230                     (ino == EXT2_BAD_INO))
6231                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
6232                                      0, block_buf, process_pass1b_block, &pb);
6233                 if (inode.i_file_acl)
6234                         process_pass1b_block(fs, &inode.i_file_acl,
6235                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6236                 if (pb.dup_blocks) {
6237                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
6238                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
6239                             ino == EXT2_ROOT_INO)
6240                                 dup_inode_count++;
6241                 }
6242                 if (pctx.errcode)
6243                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6244         }
6245         ext2fs_close_inode_scan(scan);
6246         e2fsck_use_inode_shortcuts(ctx, 0);
6247 }
6248
6249 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6250                                 blk_t   *block_nr,
6251                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6252                                 blk_t ref_blk FSCK_ATTR((unused)),
6253                                 int ref_offset FSCK_ATTR((unused)),
6254                                 void *priv_data)
6255 {
6256         struct process_block_struct_1b *p;
6257         e2fsck_t ctx;
6258
6259         if (HOLE_BLKADDR(*block_nr))
6260                 return 0;
6261         p = (struct process_block_struct_1b *) priv_data;
6262         ctx = p->ctx;
6263
6264         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6265                 return 0;
6266
6267         /* OK, this is a duplicate block */
6268         if (p->ino != EXT2_BAD_INO) {
6269                 p->pctx->blk = *block_nr;
6270                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6271         }
6272         p->dup_blocks++;
6273         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6274
6275         add_dupe(ctx, p->ino, *block_nr, p->inode);
6276
6277         return 0;
6278 }
6279
6280 /*
6281  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
6282  * is used so that we can print pathnames when prompting the user for
6283  * what to do.
6284  */
6285 struct search_dir_struct {
6286         int             count;
6287         ext2_ino_t      first_inode;
6288         ext2_ino_t      max_inode;
6289 };
6290
6291 static int search_dirent_proc(ext2_ino_t dir, int entry,
6292                               struct ext2_dir_entry *dirent,
6293                               int offset FSCK_ATTR((unused)),
6294                               int blocksize FSCK_ATTR((unused)),
6295                               char *buf FSCK_ATTR((unused)),
6296                               void *priv_data)
6297 {
6298         struct search_dir_struct *sd;
6299         struct dup_inode        *p;
6300         dnode_t                 *n;
6301
6302         sd = (struct search_dir_struct *) priv_data;
6303
6304         if (dirent->inode > sd->max_inode)
6305                 /* Should abort this inode, but not everything */
6306                 return 0;
6307
6308         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6309             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6310                 return 0;
6311
6312         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6313         if (!n)
6314                 return 0;
6315         p = (struct dup_inode *) dnode_get(n);
6316         p->dir = dir;
6317         sd->count--;
6318
6319         return(sd->count ? 0 : DIRENT_ABORT);
6320 }
6321
6322
6323 static void pass1c(e2fsck_t ctx, char *block_buf)
6324 {
6325         ext2_filsys fs = ctx->fs;
6326         struct search_dir_struct sd;
6327         struct problem_context pctx;
6328
6329         clear_problem_context(&pctx);
6330
6331         if (!(ctx->options & E2F_OPT_PREEN))
6332                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6333
6334         /*
6335          * Search through all directories to translate inodes to names
6336          * (by searching for the containing directory for that inode.)
6337          */
6338         sd.count = dup_inode_count;
6339         sd.first_inode = EXT2_FIRST_INODE(fs->super);
6340         sd.max_inode = fs->super->s_inodes_count;
6341         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6342                                   search_dirent_proc, &sd);
6343 }
6344
6345 static void pass1d(e2fsck_t ctx, char *block_buf)
6346 {
6347         ext2_filsys fs = ctx->fs;
6348         struct dup_inode        *p, *t;
6349         struct dup_block        *q;
6350         ext2_ino_t              *shared, ino;
6351         int     shared_len;
6352         int     i;
6353         int     file_ok;
6354         int     meta_data = 0;
6355         struct problem_context pctx;
6356         dnode_t *n, *m;
6357         struct block_el *s;
6358         struct inode_el *r;
6359
6360         clear_problem_context(&pctx);
6361
6362         if (!(ctx->options & E2F_OPT_PREEN))
6363                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6364         e2fsck_read_bitmaps(ctx);
6365
6366         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6367         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6368         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6369                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6370                                 "Shared inode list");
6371         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6372                 p = (struct dup_inode *) dnode_get(n);
6373                 shared_len = 0;
6374                 file_ok = 1;
6375                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6376                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
6377                         continue;
6378
6379                 /*
6380                  * Find all of the inodes which share blocks with this
6381                  * one.  First we find all of the duplicate blocks
6382                  * belonging to this inode, and then search each block
6383                  * get the list of inodes, and merge them together.
6384                  */
6385                 for (s = p->block_list; s; s = s->next) {
6386                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6387                         if (!m)
6388                                 continue; /* Should never happen... */
6389                         q = (struct dup_block *) dnode_get(m);
6390                         if (q->num_bad > 1)
6391                                 file_ok = 0;
6392                         if (check_if_fs_block(ctx, s->block)) {
6393                                 file_ok = 0;
6394                                 meta_data = 1;
6395                         }
6396
6397                         /*
6398                          * Add all inodes used by this block to the
6399                          * shared[] --- which is a unique list, so
6400                          * if an inode is already in shared[], don't
6401                          * add it again.
6402                          */
6403                         for (r = q->inode_list; r; r = r->next) {
6404                                 if (r->inode == ino)
6405                                         continue;
6406                                 for (i = 0; i < shared_len; i++)
6407                                         if (shared[i] == r->inode)
6408                                                 break;
6409                                 if (i == shared_len) {
6410                                         shared[shared_len++] = r->inode;
6411                                 }
6412                         }
6413                 }
6414
6415                 /*
6416                  * Report the inode that we are working on
6417                  */
6418                 pctx.inode = &p->inode;
6419                 pctx.ino = ino;
6420                 pctx.dir = p->dir;
6421                 pctx.blkcount = p->num_dupblocks;
6422                 pctx.num = meta_data ? shared_len+1 : shared_len;
6423                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6424                 pctx.blkcount = 0;
6425                 pctx.num = 0;
6426
6427                 if (meta_data)
6428                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6429
6430                 for (i = 0; i < shared_len; i++) {
6431                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6432                         if (!m)
6433                                 continue; /* should never happen */
6434                         t = (struct dup_inode *) dnode_get(m);
6435                         /*
6436                          * Report the inode that we are sharing with
6437                          */
6438                         pctx.inode = &t->inode;
6439                         pctx.ino = shared[i];
6440                         pctx.dir = t->dir;
6441                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6442                 }
6443                 if (file_ok) {
6444                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6445                         continue;
6446                 }
6447                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6448                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
6449                         if (pctx.errcode)
6450                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6451                         else
6452                                 continue;
6453                 }
6454                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6455                         delete_file(ctx, ino, p, block_buf);
6456                 else
6457                         ext2fs_unmark_valid(fs);
6458         }
6459         ext2fs_free_mem(&shared);
6460 }
6461
6462 /*
6463  * Drop the refcount on the dup_block structure, and clear the entry
6464  * in the block_dup_map if appropriate.
6465  */
6466 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6467 {
6468         p->num_bad--;
6469         if (p->num_bad <= 0 ||
6470             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6471                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6472 }
6473
6474 static int delete_file_block(ext2_filsys fs,
6475                              blk_t      *block_nr,
6476                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6477                              blk_t ref_block FSCK_ATTR((unused)),
6478                              int ref_offset FSCK_ATTR((unused)),
6479                              void *priv_data)
6480 {
6481         struct process_block_struct_1b *pb;
6482         struct dup_block *p;
6483         dnode_t *n;
6484         e2fsck_t ctx;
6485
6486         pb = (struct process_block_struct_1b *) priv_data;
6487         ctx = pb->ctx;
6488
6489         if (HOLE_BLKADDR(*block_nr))
6490                 return 0;
6491
6492         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6493                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6494                 if (n) {
6495                         p = (struct dup_block *) dnode_get(n);
6496                         decrement_badcount(ctx, *block_nr, p);
6497                 } else
6498                         com_err("delete_file_block", 0,
6499                             _("internal error; can't find dup_blk for %d\n"),
6500                                 *block_nr);
6501         } else {
6502                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6503                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6504         }
6505
6506         return 0;
6507 }
6508
6509 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6510                         struct dup_inode *dp, char* block_buf)
6511 {
6512         ext2_filsys fs = ctx->fs;
6513         struct process_block_struct_1b pb;
6514         struct ext2_inode       inode;
6515         struct problem_context  pctx;
6516         unsigned int            count;
6517
6518         clear_problem_context(&pctx);
6519         pctx.ino = pb.ino = ino;
6520         pb.dup_blocks = dp->num_dupblocks;
6521         pb.ctx = ctx;
6522         pctx.str = "delete_file";
6523
6524         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6525         if (ext2fs_inode_has_valid_blocks(&inode))
6526                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6527                                                      delete_file_block, &pb);
6528         if (pctx.errcode)
6529                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6530         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6531         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6532         if (ctx->inode_bad_map)
6533                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6534         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6535
6536         /* Inode may have changed by block_iterate, so reread it */
6537         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6538         inode.i_links_count = 0;
6539         inode.i_dtime = time(0);
6540         if (inode.i_file_acl &&
6541             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6542                 count = 1;
6543                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6544                                                    block_buf, -1, &count);
6545                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6546                         pctx.errcode = 0;
6547                         count = 1;
6548                 }
6549                 if (pctx.errcode) {
6550                         pctx.blk = inode.i_file_acl;
6551                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6552                 }
6553                 /*
6554                  * If the count is zero, then arrange to have the
6555                  * block deleted.  If the block is in the block_dup_map,
6556                  * also call delete_file_block since it will take care
6557                  * of keeping the accounting straight.
6558                  */
6559                 if ((count == 0) ||
6560                     ext2fs_test_block_bitmap(ctx->block_dup_map,
6561                                              inode.i_file_acl))
6562                         delete_file_block(fs, &inode.i_file_acl,
6563                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6564         }
6565         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6566 }
6567
6568 struct clone_struct {
6569         errcode_t       errcode;
6570         ext2_ino_t      dir;
6571         char    *buf;
6572         e2fsck_t ctx;
6573 };
6574
6575 static int clone_file_block(ext2_filsys fs,
6576                             blk_t       *block_nr,
6577                             e2_blkcnt_t blockcnt,
6578                             blk_t ref_block FSCK_ATTR((unused)),
6579                             int ref_offset FSCK_ATTR((unused)),
6580                             void *priv_data)
6581 {
6582         struct dup_block *p;
6583         blk_t   new_block;
6584         errcode_t       retval;
6585         struct clone_struct *cs = (struct clone_struct *) priv_data;
6586         dnode_t *n;
6587         e2fsck_t ctx;
6588
6589         ctx = cs->ctx;
6590
6591         if (HOLE_BLKADDR(*block_nr))
6592                 return 0;
6593
6594         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6595                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6596                 if (n) {
6597                         p = (struct dup_block *) dnode_get(n);
6598                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6599                                                   &new_block);
6600                         if (retval) {
6601                                 cs->errcode = retval;
6602                                 return BLOCK_ABORT;
6603                         }
6604                         if (cs->dir && (blockcnt >= 0)) {
6605                                 retval = ext2fs_set_dir_block(fs->dblist,
6606                                       cs->dir, new_block, blockcnt);
6607                                 if (retval) {
6608                                         cs->errcode = retval;
6609                                         return BLOCK_ABORT;
6610                                 }
6611                         }
6612 #if 0
6613                         printf("Cloning block %u to %u\n", *block_nr,
6614                                new_block);
6615 #endif
6616                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
6617                                                      cs->buf);
6618                         if (retval) {
6619                                 cs->errcode = retval;
6620                                 return BLOCK_ABORT;
6621                         }
6622                         retval = io_channel_write_blk(fs->io, new_block, 1,
6623                                                       cs->buf);
6624                         if (retval) {
6625                                 cs->errcode = retval;
6626                                 return BLOCK_ABORT;
6627                         }
6628                         decrement_badcount(ctx, *block_nr, p);
6629                         *block_nr = new_block;
6630                         ext2fs_mark_block_bitmap(ctx->block_found_map,
6631                                                  new_block);
6632                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
6633                         return BLOCK_CHANGED;
6634                 } else
6635                         com_err("clone_file_block", 0,
6636                             _("internal error; can't find dup_blk for %d\n"),
6637                                 *block_nr);
6638         }
6639         return 0;
6640 }
6641
6642 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6643                       struct dup_inode *dp, char* block_buf)
6644 {
6645         ext2_filsys fs = ctx->fs;
6646         errcode_t       retval;
6647         struct clone_struct cs;
6648         struct problem_context  pctx;
6649         blk_t           blk;
6650         dnode_t         *n;
6651         struct inode_el *ino_el;
6652         struct dup_block        *db;
6653         struct dup_inode        *di;
6654
6655         clear_problem_context(&pctx);
6656         cs.errcode = 0;
6657         cs.dir = 0;
6658         cs.ctx = ctx;
6659         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
6660         if (retval)
6661                 return retval;
6662
6663         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
6664                 cs.dir = ino;
6665
6666         pctx.ino = ino;
6667         pctx.str = "clone_file";
6668         if (ext2fs_inode_has_valid_blocks(&dp->inode))
6669                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6670                                                      clone_file_block, &cs);
6671         ext2fs_mark_bb_dirty(fs);
6672         if (pctx.errcode) {
6673                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6674                 retval = pctx.errcode;
6675                 goto errout;
6676         }
6677         if (cs.errcode) {
6678                 com_err("clone_file", cs.errcode,
6679                         _("returned from clone_file_block"));
6680                 retval = cs.errcode;
6681                 goto errout;
6682         }
6683         /* The inode may have changed on disk, so we have to re-read it */
6684         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
6685         blk = dp->inode.i_file_acl;
6686         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
6687                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
6688                     BLOCK_CHANGED)) {
6689                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
6690                 /*
6691                  * If we cloned the EA block, find all other inodes
6692                  * which refered to that EA block, and modify
6693                  * them to point to the new EA block.
6694                  */
6695                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6696                 db = (struct dup_block *) dnode_get(n);
6697                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
6698                         if (ino_el->inode == ino)
6699                                 continue;
6700                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
6701                         di = (struct dup_inode *) dnode_get(n);
6702                         if (di->inode.i_file_acl == blk) {
6703                                 di->inode.i_file_acl = dp->inode.i_file_acl;
6704                                 e2fsck_write_inode(ctx, ino_el->inode,
6705                                            &di->inode, "clone file EA");
6706                                 decrement_badcount(ctx, blk, db);
6707                         }
6708                 }
6709         }
6710         retval = 0;
6711 errout:
6712         ext2fs_free_mem(&cs.buf);
6713         return retval;
6714 }
6715
6716 /*
6717  * This routine returns 1 if a block overlaps with one of the superblocks,
6718  * group descriptors, inode bitmaps, or block bitmaps.
6719  */
6720 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
6721 {
6722         ext2_filsys fs = ctx->fs;
6723         blk_t   block;
6724         dgrp_t  i;
6725
6726         block = fs->super->s_first_data_block;
6727         for (i = 0; i < fs->group_desc_count; i++) {
6728
6729                 /* Check superblocks/block group descriptros */
6730                 if (ext2fs_bg_has_super(fs, i)) {
6731                         if (test_block >= block &&
6732                             (test_block <= block + fs->desc_blocks))
6733                                 return 1;
6734                 }
6735
6736                 /* Check the inode table */
6737                 if ((fs->group_desc[i].bg_inode_table) &&
6738                     (test_block >= fs->group_desc[i].bg_inode_table) &&
6739                     (test_block < (fs->group_desc[i].bg_inode_table +
6740                                    fs->inode_blocks_per_group)))
6741                         return 1;
6742
6743                 /* Check the bitmap blocks */
6744                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
6745                     (test_block == fs->group_desc[i].bg_inode_bitmap))
6746                         return 1;
6747
6748                 block += fs->super->s_blocks_per_group;
6749         }
6750         return 0;
6751 }
6752 /*
6753  * pass2.c --- check directory structure
6754  *
6755  * Pass 2 of e2fsck iterates through all active directory inodes, and
6756  * applies to following tests to each directory entry in the directory
6757  * blocks in the inodes:
6758  *
6759  *      - The length of the directory entry (rec_len) should be at
6760  *              least 8 bytes, and no more than the remaining space
6761  *              left in the directory block.
6762  *      - The length of the name in the directory entry (name_len)
6763  *              should be less than (rec_len - 8).
6764  *      - The inode number in the directory entry should be within
6765  *              legal bounds.
6766  *      - The inode number should refer to a in-use inode.
6767  *      - The first entry should be '.', and its inode should be
6768  *              the inode of the directory.
6769  *      - The second entry should be '..'.
6770  *
6771  * To minimize disk seek time, the directory blocks are processed in
6772  * sorted order of block numbers.
6773  *
6774  * Pass 2 also collects the following information:
6775  *      - The inode numbers of the subdirectories for each directory.
6776  *
6777  * Pass 2 relies on the following information from previous passes:
6778  *      - The directory information collected in pass 1.
6779  *      - The inode_used_map bitmap
6780  *      - The inode_bad_map bitmap
6781  *      - The inode_dir_map bitmap
6782  *
6783  * Pass 2 frees the following data structures
6784  *      - The inode_bad_map bitmap
6785  *      - The inode_reg_map bitmap
6786  */
6787
6788 /* #define DX_DEBUG */
6789
6790 /*
6791  * Keeps track of how many times an inode is referenced.
6792  */
6793 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
6794 static int check_dir_block(ext2_filsys fs,
6795                            struct ext2_db_entry *dir_blocks_info,
6796                            void *priv_data);
6797 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
6798                               struct problem_context *pctx);
6799 static int update_dir_block(ext2_filsys fs,
6800                             blk_t       *block_nr,
6801                             e2_blkcnt_t blockcnt,
6802                             blk_t       ref_block,
6803                             int         ref_offset,
6804                             void        *priv_data);
6805 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
6806 static int htree_depth(struct dx_dir_info *dx_dir,
6807                        struct dx_dirblock_info *dx_db);
6808 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
6809
6810 struct check_dir_struct {
6811         char *buf;
6812         struct problem_context  pctx;
6813         int     count, max;
6814         e2fsck_t ctx;
6815 };
6816
6817 static void e2fsck_pass2(e2fsck_t ctx)
6818 {
6819         struct ext2_super_block *sb = ctx->fs->super;
6820         struct problem_context  pctx;
6821         ext2_filsys             fs = ctx->fs;
6822         char                    *buf;
6823 #ifdef RESOURCE_TRACK
6824         struct resource_track   rtrack;
6825 #endif
6826         struct dir_info         *dir;
6827         struct check_dir_struct cd;
6828         struct dx_dir_info      *dx_dir;
6829         struct dx_dirblock_info *dx_db, *dx_parent;
6830         int                     b;
6831         int                     i, depth;
6832         problem_t               code;
6833         int                     bad_dir;
6834
6835 #ifdef RESOURCE_TRACK
6836         init_resource_track(&rtrack);
6837 #endif
6838
6839         clear_problem_context(&cd.pctx);
6840
6841 #ifdef MTRACE
6842         mtrace_print("Pass 2");
6843 #endif
6844
6845         if (!(ctx->options & E2F_OPT_PREEN))
6846                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
6847
6848         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
6849                                                 0, ctx->inode_link_info,
6850                                                 &ctx->inode_count);
6851         if (cd.pctx.errcode) {
6852                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
6853                 ctx->flags |= E2F_FLAG_ABORT;
6854                 return;
6855         }
6856         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
6857                                               "directory scan buffer");
6858
6859         /*
6860          * Set up the parent pointer for the root directory, if
6861          * present.  (If the root directory is not present, we will
6862          * create it in pass 3.)
6863          */
6864         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
6865         if (dir)
6866                 dir->parent = EXT2_ROOT_INO;
6867
6868         cd.buf = buf;
6869         cd.ctx = ctx;
6870         cd.count = 1;
6871         cd.max = ext2fs_dblist_count(fs->dblist);
6872
6873         if (ctx->progress)
6874                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
6875
6876         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
6877                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
6878
6879         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
6880                                                 &cd);
6881         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6882                 return;
6883         if (cd.pctx.errcode) {
6884                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
6885                 ctx->flags |= E2F_FLAG_ABORT;
6886                 return;
6887         }
6888
6889 #ifdef ENABLE_HTREE
6890         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
6891                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6892                         return;
6893                 if (dx_dir->numblocks == 0)
6894                         continue;
6895                 clear_problem_context(&pctx);
6896                 bad_dir = 0;
6897                 pctx.dir = dx_dir->ino;
6898                 dx_db = dx_dir->dx_block;
6899                 if (dx_db->flags & DX_FLAG_REFERENCED)
6900                         dx_db->flags |= DX_FLAG_DUP_REF;
6901                 else
6902                         dx_db->flags |= DX_FLAG_REFERENCED;
6903                 /*
6904                  * Find all of the first and last leaf blocks, and
6905                  * update their parent's min and max hash values
6906                  */
6907                 for (b=0, dx_db = dx_dir->dx_block;
6908                      b < dx_dir->numblocks;
6909                      b++, dx_db++) {
6910                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
6911                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
6912                                 continue;
6913                         dx_parent = &dx_dir->dx_block[dx_db->parent];
6914                         /*
6915                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
6916                          */
6917                         if (dx_db->flags & DX_FLAG_FIRST)
6918                                 dx_parent->min_hash = dx_db->min_hash;
6919                         /*
6920                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
6921                          */
6922                         if (dx_db->flags & DX_FLAG_LAST)
6923                                 dx_parent->max_hash = dx_db->max_hash;
6924                 }
6925
6926                 for (b=0, dx_db = dx_dir->dx_block;
6927                      b < dx_dir->numblocks;
6928                      b++, dx_db++) {
6929                         pctx.blkcount = b;
6930                         pctx.group = dx_db->parent;
6931                         code = 0;
6932                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
6933                             (dx_db->min_hash < dx_db->node_min_hash)) {
6934                                 pctx.blk = dx_db->min_hash;
6935                                 pctx.blk2 = dx_db->node_min_hash;
6936                                 code = PR_2_HTREE_MIN_HASH;
6937                                 fix_problem(ctx, code, &pctx);
6938                                 bad_dir++;
6939                         }
6940                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
6941                                 depth = htree_depth(dx_dir, dx_db);
6942                                 if (depth != dx_dir->depth) {
6943                                         code = PR_2_HTREE_BAD_DEPTH;
6944                                         fix_problem(ctx, code, &pctx);
6945                                         bad_dir++;
6946                                 }
6947                         }
6948                         /*
6949                          * This test doesn't apply for the root block
6950                          * at block #0
6951                          */
6952                         if (b &&
6953                             (dx_db->max_hash > dx_db->node_max_hash)) {
6954                                 pctx.blk = dx_db->max_hash;
6955                                 pctx.blk2 = dx_db->node_max_hash;
6956                                 code = PR_2_HTREE_MAX_HASH;
6957                                 fix_problem(ctx, code, &pctx);
6958                                 bad_dir++;
6959                         }
6960                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
6961                                 code = PR_2_HTREE_NOTREF;
6962                                 fix_problem(ctx, code, &pctx);
6963                                 bad_dir++;
6964                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
6965                                 code = PR_2_HTREE_DUPREF;
6966                                 fix_problem(ctx, code, &pctx);
6967                                 bad_dir++;
6968                         }
6969                         if (code == 0)
6970                                 continue;
6971                 }
6972                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
6973                         clear_htree(ctx, dx_dir->ino);
6974                         dx_dir->numblocks = 0;
6975                 }
6976         }
6977 #endif
6978         ext2fs_free_mem(&buf);
6979         ext2fs_free_dblist(fs->dblist);
6980
6981         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
6982         ctx->inode_bad_map = 0;
6983         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
6984         ctx->inode_reg_map = 0;
6985
6986         clear_problem_context(&pctx);
6987         if (ctx->large_files) {
6988                 if (!(sb->s_feature_ro_compat &
6989                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
6990                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
6991                         sb->s_feature_ro_compat |=
6992                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
6993                         ext2fs_mark_super_dirty(fs);
6994                 }
6995                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
6996                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
6997                         ext2fs_update_dynamic_rev(fs);
6998                         ext2fs_mark_super_dirty(fs);
6999                 }
7000         } else if (!ctx->large_files &&
7001             (sb->s_feature_ro_compat &
7002               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7003                 if (fs->flags & EXT2_FLAG_RW) {
7004                         sb->s_feature_ro_compat &=
7005                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7006                         ext2fs_mark_super_dirty(fs);
7007                 }
7008         }
7009
7010 #ifdef RESOURCE_TRACK
7011         if (ctx->options & E2F_OPT_TIME2) {
7012                 e2fsck_clear_progbar(ctx);
7013                 print_resource_track(_("Pass 2"), &rtrack);
7014         }
7015 #endif
7016 }
7017
7018 #define MAX_DEPTH 32000
7019 static int htree_depth(struct dx_dir_info *dx_dir,
7020                        struct dx_dirblock_info *dx_db)
7021 {
7022         int     depth = 0;
7023
7024         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7025                 dx_db = &dx_dir->dx_block[dx_db->parent];
7026                 depth++;
7027         }
7028         return depth;
7029 }
7030
7031 static int dict_de_cmp(const void *a, const void *b)
7032 {
7033         const struct ext2_dir_entry *de_a, *de_b;
7034         int     a_len, b_len;
7035
7036         de_a = (const struct ext2_dir_entry *) a;
7037         a_len = de_a->name_len & 0xFF;
7038         de_b = (const struct ext2_dir_entry *) b;
7039         b_len = de_b->name_len & 0xFF;
7040
7041         if (a_len != b_len)
7042                 return (a_len - b_len);
7043
7044         return strncmp(de_a->name, de_b->name, a_len);
7045 }
7046
7047 /*
7048  * This is special sort function that makes sure that directory blocks
7049  * with a dirblock of zero are sorted to the beginning of the list.
7050  * This guarantees that the root node of the htree directories are
7051  * processed first, so we know what hash version to use.
7052  */
7053 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7054 {
7055         const struct ext2_db_entry *db_a =
7056                 (const struct ext2_db_entry *) a;
7057         const struct ext2_db_entry *db_b =
7058                 (const struct ext2_db_entry *) b;
7059
7060         if (db_a->blockcnt && !db_b->blockcnt)
7061                 return 1;
7062
7063         if (!db_a->blockcnt && db_b->blockcnt)
7064                 return -1;
7065
7066         if (db_a->blk != db_b->blk)
7067                 return (int) (db_a->blk - db_b->blk);
7068
7069         if (db_a->ino != db_b->ino)
7070                 return (int) (db_a->ino - db_b->ino);
7071
7072         return (int) (db_a->blockcnt - db_b->blockcnt);
7073 }
7074
7075
7076 /*
7077  * Make sure the first entry in the directory is '.', and that the
7078  * directory entry is sane.
7079  */
7080 static int check_dot(e2fsck_t ctx,
7081                      struct ext2_dir_entry *dirent,
7082                      ext2_ino_t ino, struct problem_context *pctx)
7083 {
7084         struct ext2_dir_entry *nextdir;
7085         int     status = 0;
7086         int     created = 0;
7087         int     new_len;
7088         int     problem = 0;
7089
7090         if (!dirent->inode)
7091                 problem = PR_2_MISSING_DOT;
7092         else if (((dirent->name_len & 0xFF) != 1) ||
7093                  (dirent->name[0] != '.'))
7094                 problem = PR_2_1ST_NOT_DOT;
7095         else if (dirent->name[1] != '\0')
7096                 problem = PR_2_DOT_NULL_TERM;
7097
7098         if (problem) {
7099                 if (fix_problem(ctx, problem, pctx)) {
7100                         if (dirent->rec_len < 12)
7101                                 dirent->rec_len = 12;
7102                         dirent->inode = ino;
7103                         dirent->name_len = 1;
7104                         dirent->name[0] = '.';
7105                         dirent->name[1] = '\0';
7106                         status = 1;
7107                         created = 1;
7108                 }
7109         }
7110         if (dirent->inode != ino) {
7111                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7112                         dirent->inode = ino;
7113                         status = 1;
7114                 }
7115         }
7116         if (dirent->rec_len > 12) {
7117                 new_len = dirent->rec_len - 12;
7118                 if (new_len > 12) {
7119                         if (created ||
7120                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7121                                 nextdir = (struct ext2_dir_entry *)
7122                                         ((char *) dirent + 12);
7123                                 dirent->rec_len = 12;
7124                                 nextdir->rec_len = new_len;
7125                                 nextdir->inode = 0;
7126                                 nextdir->name_len = 0;
7127                                 status = 1;
7128                         }
7129                 }
7130         }
7131         return status;
7132 }
7133
7134 /*
7135  * Make sure the second entry in the directory is '..', and that the
7136  * directory entry is sane.  We do not check the inode number of '..'
7137  * here; this gets done in pass 3.
7138  */
7139 static int check_dotdot(e2fsck_t ctx,
7140                         struct ext2_dir_entry *dirent,
7141                         struct dir_info *dir, struct problem_context *pctx)
7142 {
7143         int             problem = 0;
7144
7145         if (!dirent->inode)
7146                 problem = PR_2_MISSING_DOT_DOT;
7147         else if (((dirent->name_len & 0xFF) != 2) ||
7148                  (dirent->name[0] != '.') ||
7149                  (dirent->name[1] != '.'))
7150                 problem = PR_2_2ND_NOT_DOT_DOT;
7151         else if (dirent->name[2] != '\0')
7152                 problem = PR_2_DOT_DOT_NULL_TERM;
7153
7154         if (problem) {
7155                 if (fix_problem(ctx, problem, pctx)) {
7156                         if (dirent->rec_len < 12)
7157                                 dirent->rec_len = 12;
7158                         /*
7159                          * Note: we don't have the parent inode just
7160                          * yet, so we will fill it in with the root
7161                          * inode.  This will get fixed in pass 3.
7162                          */
7163                         dirent->inode = EXT2_ROOT_INO;
7164                         dirent->name_len = 2;
7165                         dirent->name[0] = '.';
7166                         dirent->name[1] = '.';
7167                         dirent->name[2] = '\0';
7168                         return 1;
7169                 }
7170                 return 0;
7171         }
7172         dir->dotdot = dirent->inode;
7173         return 0;
7174 }
7175
7176 /*
7177  * Check to make sure a directory entry doesn't contain any illegal
7178  * characters.
7179  */
7180 static int check_name(e2fsck_t ctx,
7181                       struct ext2_dir_entry *dirent,
7182                       struct problem_context *pctx)
7183 {
7184         int     i;
7185         int     fixup = -1;
7186         int     ret = 0;
7187
7188         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7189                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7190                         if (fixup < 0) {
7191                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7192                         }
7193                         if (fixup) {
7194                                 dirent->name[i] = '.';
7195                                 ret = 1;
7196                         }
7197                 }
7198         }
7199         return ret;
7200 }
7201
7202 /*
7203  * Check the directory filetype (if present)
7204  */
7205
7206 /*
7207  * Given a mode, return the ext2 file type
7208  */
7209 static int ext2_file_type(unsigned int mode)
7210 {
7211         if (LINUX_S_ISREG(mode))
7212                 return EXT2_FT_REG_FILE;
7213
7214         if (LINUX_S_ISDIR(mode))
7215                 return EXT2_FT_DIR;
7216
7217         if (LINUX_S_ISCHR(mode))
7218                 return EXT2_FT_CHRDEV;
7219
7220         if (LINUX_S_ISBLK(mode))
7221                 return EXT2_FT_BLKDEV;
7222
7223         if (LINUX_S_ISLNK(mode))
7224                 return EXT2_FT_SYMLINK;
7225
7226         if (LINUX_S_ISFIFO(mode))
7227                 return EXT2_FT_FIFO;
7228
7229         if (LINUX_S_ISSOCK(mode))
7230                 return EXT2_FT_SOCK;
7231
7232         return 0;
7233 }
7234
7235 static _INLINE_ int check_filetype(e2fsck_t ctx,
7236                                    struct ext2_dir_entry *dirent,
7237                                    struct problem_context *pctx)
7238 {
7239         int     filetype = dirent->name_len >> 8;
7240         int     should_be = EXT2_FT_UNKNOWN;
7241         struct ext2_inode       inode;
7242
7243         if (!(ctx->fs->super->s_feature_incompat &
7244               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7245                 if (filetype == 0 ||
7246                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7247                         return 0;
7248                 dirent->name_len = dirent->name_len & 0xFF;
7249                 return 1;
7250         }
7251
7252         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7253                 should_be = EXT2_FT_DIR;
7254         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7255                                             dirent->inode)) {
7256                 should_be = EXT2_FT_REG_FILE;
7257         } else if (ctx->inode_bad_map &&
7258                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7259                                             dirent->inode))
7260                 should_be = 0;
7261         else {
7262                 e2fsck_read_inode(ctx, dirent->inode, &inode,
7263                                   "check_filetype");
7264                 should_be = ext2_file_type(inode.i_mode);
7265         }
7266         if (filetype == should_be)
7267                 return 0;
7268         pctx->num = should_be;
7269
7270         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7271                         pctx) == 0)
7272                 return 0;
7273
7274         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7275         return 1;
7276 }
7277
7278 #ifdef ENABLE_HTREE
7279 static void parse_int_node(ext2_filsys fs,
7280                            struct ext2_db_entry *db,
7281                            struct check_dir_struct *cd,
7282                            struct dx_dir_info   *dx_dir,
7283                            char *block_buf)
7284 {
7285         struct          ext2_dx_root_info  *root;
7286         struct          ext2_dx_entry *ent;
7287         struct          ext2_dx_countlimit *limit;
7288         struct dx_dirblock_info *dx_db;
7289         int             i, expect_limit, count;
7290         blk_t           blk;
7291         ext2_dirhash_t  min_hash = 0xffffffff;
7292         ext2_dirhash_t  max_hash = 0;
7293         ext2_dirhash_t  hash = 0, prev_hash;
7294
7295         if (db->blockcnt == 0) {
7296                 root = (struct ext2_dx_root_info *) (block_buf + 24);
7297
7298 #ifdef DX_DEBUG
7299                 printf("Root node dump:\n");
7300                 printf("\t Reserved zero: %d\n", root->reserved_zero);
7301                 printf("\t Hash Version: %d\n", root->hash_version);
7302                 printf("\t Info length: %d\n", root->info_length);
7303                 printf("\t Indirect levels: %d\n", root->indirect_levels);
7304                 printf("\t Flags: %d\n", root->unused_flags);
7305 #endif
7306
7307                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7308         } else {
7309                 ent = (struct ext2_dx_entry *) (block_buf+8);
7310         }
7311         limit = (struct ext2_dx_countlimit *) ent;
7312
7313 #ifdef DX_DEBUG
7314         printf("Number of entries (count): %d\n",
7315                ext2fs_le16_to_cpu(limit->count));
7316         printf("Number of entries (limit): %d\n",
7317                ext2fs_le16_to_cpu(limit->limit));
7318 #endif
7319
7320         count = ext2fs_le16_to_cpu(limit->count);
7321         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7322                 sizeof(struct ext2_dx_entry);
7323         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7324                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7325                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7326                         goto clear_and_exit;
7327         }
7328         if (count > expect_limit) {
7329                 cd->pctx.num = count;
7330                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7331                         goto clear_and_exit;
7332                 count = expect_limit;
7333         }
7334
7335         for (i=0; i < count; i++) {
7336                 prev_hash = hash;
7337                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7338 #ifdef DX_DEBUG
7339                 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7340                        hash, ext2fs_le32_to_cpu(ent[i].block));
7341 #endif
7342                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7343                 /* Check to make sure the block is valid */
7344                 if (blk > (blk_t) dx_dir->numblocks) {
7345                         cd->pctx.blk = blk;
7346                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7347                                         &cd->pctx))
7348                                 goto clear_and_exit;
7349                 }
7350                 if (hash < prev_hash &&
7351                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7352                         goto clear_and_exit;
7353                 dx_db = &dx_dir->dx_block[blk];
7354                 if (dx_db->flags & DX_FLAG_REFERENCED) {
7355                         dx_db->flags |= DX_FLAG_DUP_REF;
7356                 } else {
7357                         dx_db->flags |= DX_FLAG_REFERENCED;
7358                         dx_db->parent = db->blockcnt;
7359                 }
7360                 if (hash < min_hash)
7361                         min_hash = hash;
7362                 if (hash > max_hash)
7363                         max_hash = hash;
7364                 dx_db->node_min_hash = hash;
7365                 if ((i+1) < count)
7366                         dx_db->node_max_hash =
7367                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7368                 else {
7369                         dx_db->node_max_hash = 0xfffffffe;
7370                         dx_db->flags |= DX_FLAG_LAST;
7371                 }
7372                 if (i == 0)
7373                         dx_db->flags |= DX_FLAG_FIRST;
7374         }
7375 #ifdef DX_DEBUG
7376         printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7377                db->blockcnt, min_hash, max_hash);
7378 #endif
7379         dx_db = &dx_dir->dx_block[db->blockcnt];
7380         dx_db->min_hash = min_hash;
7381         dx_db->max_hash = max_hash;
7382         return;
7383
7384 clear_and_exit:
7385         clear_htree(cd->ctx, cd->pctx.ino);
7386         dx_dir->numblocks = 0;
7387 }
7388 #endif /* ENABLE_HTREE */
7389
7390 /*
7391  * Given a busted directory, try to salvage it somehow.
7392  *
7393  */
7394 static void salvage_directory(ext2_filsys fs,
7395                               struct ext2_dir_entry *dirent,
7396                               struct ext2_dir_entry *prev,
7397                               unsigned int *offset)
7398 {
7399         char    *cp = (char *) dirent;
7400         int left = fs->blocksize - *offset - dirent->rec_len;
7401         int name_len = dirent->name_len & 0xFF;
7402
7403         /*
7404          * Special case of directory entry of size 8: copy what's left
7405          * of the directory block up to cover up the invalid hole.
7406          */
7407         if ((left >= 12) && (dirent->rec_len == 8)) {
7408                 memmove(cp, cp+8, left);
7409                 memset(cp + left, 0, 8);
7410                 return;
7411         }
7412         /*
7413          * If the directory entry overruns the end of the directory
7414          * block, and the name is small enough to fit, then adjust the
7415          * record length.
7416          */
7417         if ((left < 0) &&
7418             (name_len + 8 <= dirent->rec_len + left) &&
7419             dirent->inode <= fs->super->s_inodes_count &&
7420             strnlen(dirent->name, name_len) == name_len) {
7421                 dirent->rec_len += left;
7422                 return;
7423         }
7424         /*
7425          * If the directory entry is a multiple of four, so it is
7426          * valid, let the previous directory entry absorb the invalid
7427          * one.
7428          */
7429         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7430                 prev->rec_len += dirent->rec_len;
7431                 *offset += dirent->rec_len;
7432                 return;
7433         }
7434         /*
7435          * Default salvage method --- kill all of the directory
7436          * entries for the rest of the block.  We will either try to
7437          * absorb it into the previous directory entry, or create a
7438          * new empty directory entry the rest of the directory block.
7439          */
7440         if (prev) {
7441                 prev->rec_len += fs->blocksize - *offset;
7442                 *offset = fs->blocksize;
7443         } else {
7444                 dirent->rec_len = fs->blocksize - *offset;
7445                 dirent->name_len = 0;
7446                 dirent->inode = 0;
7447         }
7448 }
7449
7450 static int check_dir_block(ext2_filsys fs,
7451                            struct ext2_db_entry *db,
7452                            void *priv_data)
7453 {
7454         struct dir_info         *subdir, *dir;
7455         struct dx_dir_info      *dx_dir;
7456 #ifdef ENABLE_HTREE
7457         struct dx_dirblock_info *dx_db = 0;
7458 #endif /* ENABLE_HTREE */
7459         struct ext2_dir_entry   *dirent, *prev;
7460         ext2_dirhash_t          hash;
7461         unsigned int            offset = 0;
7462         int                     dir_modified = 0;
7463         int                     dot_state;
7464         blk_t                   block_nr = db->blk;
7465         ext2_ino_t              ino = db->ino;
7466         __u16                   links;
7467         struct check_dir_struct *cd;
7468         char                    *buf;
7469         e2fsck_t                ctx;
7470         int                     problem;
7471         struct ext2_dx_root_info *root;
7472         struct ext2_dx_countlimit *limit;
7473         static dict_t de_dict;
7474         struct problem_context  pctx;
7475         int     dups_found = 0;
7476
7477         cd = (struct check_dir_struct *) priv_data;
7478         buf = cd->buf;
7479         ctx = cd->ctx;
7480
7481         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7482                 return DIRENT_ABORT;
7483
7484         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7485                 return DIRENT_ABORT;
7486
7487         /*
7488          * Make sure the inode is still in use (could have been
7489          * deleted in the duplicate/bad blocks pass.
7490          */
7491         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7492                 return 0;
7493
7494         cd->pctx.ino = ino;
7495         cd->pctx.blk = block_nr;
7496         cd->pctx.blkcount = db->blockcnt;
7497         cd->pctx.ino2 = 0;
7498         cd->pctx.dirent = 0;
7499         cd->pctx.num = 0;
7500
7501         if (db->blk == 0) {
7502                 if (allocate_dir_block(ctx, db, &cd->pctx))
7503                         return 0;
7504                 block_nr = db->blk;
7505         }
7506
7507         if (db->blockcnt)
7508                 dot_state = 2;
7509         else
7510                 dot_state = 0;
7511
7512         if (ctx->dirs_to_hash &&
7513             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7514                 dups_found++;
7515
7516 #if 0
7517         printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7518                db->blockcnt, ino);
7519 #endif
7520
7521         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7522         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7523                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7524         if (cd->pctx.errcode) {
7525                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7526                         ctx->flags |= E2F_FLAG_ABORT;
7527                         return DIRENT_ABORT;
7528                 }
7529                 memset(buf, 0, fs->blocksize);
7530         }
7531 #ifdef ENABLE_HTREE
7532         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7533         if (dx_dir && dx_dir->numblocks) {
7534                 if (db->blockcnt >= dx_dir->numblocks) {
7535                         printf("XXX should never happen!!!\n");
7536                         abort();
7537                 }
7538                 dx_db = &dx_dir->dx_block[db->blockcnt];
7539                 dx_db->type = DX_DIRBLOCK_LEAF;
7540                 dx_db->phys = block_nr;
7541                 dx_db->min_hash = ~0;
7542                 dx_db->max_hash = 0;
7543
7544                 dirent = (struct ext2_dir_entry *) buf;
7545                 limit = (struct ext2_dx_countlimit *) (buf+8);
7546                 if (db->blockcnt == 0) {
7547                         root = (struct ext2_dx_root_info *) (buf + 24);
7548                         dx_db->type = DX_DIRBLOCK_ROOT;
7549                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7550                         if ((root->reserved_zero ||
7551                              root->info_length < 8 ||
7552                              root->indirect_levels > 1) &&
7553                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7554                                 clear_htree(ctx, ino);
7555                                 dx_dir->numblocks = 0;
7556                                 dx_db = 0;
7557                         }
7558                         dx_dir->hashversion = root->hash_version;
7559                         dx_dir->depth = root->indirect_levels + 1;
7560                 } else if ((dirent->inode == 0) &&
7561                            (dirent->rec_len == fs->blocksize) &&
7562                            (dirent->name_len == 0) &&
7563                            (ext2fs_le16_to_cpu(limit->limit) ==
7564                             ((fs->blocksize-8) /
7565                              sizeof(struct ext2_dx_entry))))
7566                         dx_db->type = DX_DIRBLOCK_NODE;
7567         }
7568 #endif /* ENABLE_HTREE */
7569
7570         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7571         prev = 0;
7572         do {
7573                 problem = 0;
7574                 dirent = (struct ext2_dir_entry *) (buf + offset);
7575                 cd->pctx.dirent = dirent;
7576                 cd->pctx.num = offset;
7577                 if (((offset + dirent->rec_len) > fs->blocksize) ||
7578                     (dirent->rec_len < 12) ||
7579                     ((dirent->rec_len % 4) != 0) ||
7580                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7581                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7582                                 salvage_directory(fs, dirent, prev, &offset);
7583                                 dir_modified++;
7584                                 continue;
7585                         } else
7586                                 goto abort_free_dict;
7587                 }
7588                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7589                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7590                                 dirent->name_len = EXT2_NAME_LEN;
7591                                 dir_modified++;
7592                         }
7593                 }
7594
7595                 if (dot_state == 0) {
7596                         if (check_dot(ctx, dirent, ino, &cd->pctx))
7597                                 dir_modified++;
7598                 } else if (dot_state == 1) {
7599                         dir = e2fsck_get_dir_info(ctx, ino);
7600                         if (!dir) {
7601                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7602                                 goto abort_free_dict;
7603                         }
7604                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7605                                 dir_modified++;
7606                 } else if (dirent->inode == ino) {
7607                         problem = PR_2_LINK_DOT;
7608                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7609                                 dirent->inode = 0;
7610                                 dir_modified++;
7611                                 goto next;
7612                         }
7613                 }
7614                 if (!dirent->inode)
7615                         goto next;
7616
7617                 /*
7618                  * Make sure the inode listed is a legal one.
7619                  */
7620                 if (((dirent->inode != EXT2_ROOT_INO) &&
7621                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
7622                     (dirent->inode > fs->super->s_inodes_count)) {
7623                         problem = PR_2_BAD_INO;
7624                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
7625                                                dirent->inode))) {
7626                         /*
7627                          * If the inode is unused, offer to clear it.
7628                          */
7629                         problem = PR_2_UNUSED_INODE;
7630                 } else if (ctx->inode_bb_map &&
7631                            (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
7632                                                      dirent->inode))) {
7633                         /*
7634                          * If the inode is in a bad block, offer to
7635                          * clear it.
7636                          */
7637                         problem = PR_2_BB_INODE;
7638                 } else if ((dot_state > 1) &&
7639                            ((dirent->name_len & 0xFF) == 1) &&
7640                            (dirent->name[0] == '.')) {
7641                         /*
7642                          * If there's a '.' entry in anything other
7643                          * than the first directory entry, it's a
7644                          * duplicate entry that should be removed.
7645                          */
7646                         problem = PR_2_DUP_DOT;
7647                 } else if ((dot_state > 1) &&
7648                            ((dirent->name_len & 0xFF) == 2) &&
7649                            (dirent->name[0] == '.') &&
7650                            (dirent->name[1] == '.')) {
7651                         /*
7652                          * If there's a '..' entry in anything other
7653                          * than the second directory entry, it's a
7654                          * duplicate entry that should be removed.
7655                          */
7656                         problem = PR_2_DUP_DOT_DOT;
7657                 } else if ((dot_state > 1) &&
7658                            (dirent->inode == EXT2_ROOT_INO)) {
7659                         /*
7660                          * Don't allow links to the root directory.
7661                          * We check this specially to make sure we
7662                          * catch this error case even if the root
7663                          * directory hasn't been created yet.
7664                          */
7665                         problem = PR_2_LINK_ROOT;
7666                 } else if ((dot_state > 1) &&
7667                            (dirent->name_len & 0xFF) == 0) {
7668                         /*
7669                          * Don't allow zero-length directory names.
7670                          */
7671                         problem = PR_2_NULL_NAME;
7672                 }
7673
7674                 if (problem) {
7675                         if (fix_problem(ctx, problem, &cd->pctx)) {
7676                                 dirent->inode = 0;
7677                                 dir_modified++;
7678                                 goto next;
7679                         } else {
7680                                 ext2fs_unmark_valid(fs);
7681                                 if (problem == PR_2_BAD_INO)
7682                                         goto next;
7683                         }
7684                 }
7685
7686                 /*
7687                  * If the inode was marked as having bad fields in
7688                  * pass1, process it and offer to fix/clear it.
7689                  * (We wait until now so that we can display the
7690                  * pathname to the user.)
7691                  */
7692                 if (ctx->inode_bad_map &&
7693                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7694                                              dirent->inode)) {
7695                         if (e2fsck_process_bad_inode(ctx, ino,
7696                                                      dirent->inode,
7697                                                      buf + fs->blocksize)) {
7698                                 dirent->inode = 0;
7699                                 dir_modified++;
7700                                 goto next;
7701                         }
7702                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7703                                 return DIRENT_ABORT;
7704                 }
7705
7706                 if (check_name(ctx, dirent, &cd->pctx))
7707                         dir_modified++;
7708
7709                 if (check_filetype(ctx, dirent, &cd->pctx))
7710                         dir_modified++;
7711
7712 #ifdef ENABLE_HTREE
7713                 if (dx_db) {
7714                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
7715                                        (dirent->name_len & 0xFF),
7716                                        fs->super->s_hash_seed, &hash, 0);
7717                         if (hash < dx_db->min_hash)
7718                                 dx_db->min_hash = hash;
7719                         if (hash > dx_db->max_hash)
7720                                 dx_db->max_hash = hash;
7721                 }
7722 #endif
7723
7724                 /*
7725                  * If this is a directory, then mark its parent in its
7726                  * dir_info structure.  If the parent field is already
7727                  * filled in, then this directory has more than one
7728                  * hard link.  We assume the first link is correct,
7729                  * and ask the user if he/she wants to clear this one.
7730                  */
7731                 if ((dot_state > 1) &&
7732                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
7733                                               dirent->inode))) {
7734                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
7735                         if (!subdir) {
7736                                 cd->pctx.ino = dirent->inode;
7737                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7738                                 goto abort_free_dict;
7739                         }
7740                         if (subdir->parent) {
7741                                 cd->pctx.ino2 = subdir->parent;
7742                                 if (fix_problem(ctx, PR_2_LINK_DIR,
7743                                                 &cd->pctx)) {
7744                                         dirent->inode = 0;
7745                                         dir_modified++;
7746                                         goto next;
7747                                 }
7748                                 cd->pctx.ino2 = 0;
7749                         } else
7750                                 subdir->parent = ino;
7751                 }
7752
7753                 if (dups_found) {
7754                         ;
7755                 } else if (dict_lookup(&de_dict, dirent)) {
7756                         clear_problem_context(&pctx);
7757                         pctx.ino = ino;
7758                         pctx.dirent = dirent;
7759                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
7760                         if (!ctx->dirs_to_hash)
7761                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
7762                         if (ctx->dirs_to_hash)
7763                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
7764                         dups_found++;
7765                 } else
7766                         dict_alloc_insert(&de_dict, dirent, dirent);
7767
7768                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
7769                                         &links);
7770                 if (links > 1)
7771                         ctx->fs_links_count++;
7772                 ctx->fs_total_count++;
7773         next:
7774                 prev = dirent;
7775                 offset += dirent->rec_len;
7776                 dot_state++;
7777         } while (offset < fs->blocksize);
7778 #if 0
7779         printf("\n");
7780 #endif
7781 #ifdef ENABLE_HTREE
7782         if (dx_db) {
7783 #ifdef DX_DEBUG
7784                 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
7785                        db->blockcnt, dx_db->type,
7786                        dx_db->min_hash, dx_db->max_hash);
7787 #endif
7788                 cd->pctx.dir = cd->pctx.ino;
7789                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
7790                     (dx_db->type == DX_DIRBLOCK_NODE))
7791                         parse_int_node(fs, db, cd, dx_dir, buf);
7792         }
7793 #endif /* ENABLE_HTREE */
7794         if (offset != fs->blocksize) {
7795                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
7796                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
7797                         dirent->rec_len = cd->pctx.num;
7798                         dir_modified++;
7799                 }
7800         }
7801         if (dir_modified) {
7802                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
7803                 if (cd->pctx.errcode) {
7804                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
7805                                          &cd->pctx))
7806                                 goto abort_free_dict;
7807                 }
7808                 ext2fs_mark_changed(fs);
7809         }
7810         dict_free_nodes(&de_dict);
7811         return 0;
7812 abort_free_dict:
7813         dict_free_nodes(&de_dict);
7814         ctx->flags |= E2F_FLAG_ABORT;
7815         return DIRENT_ABORT;
7816 }
7817
7818 /*
7819  * This function is called to deallocate a block, and is an interator
7820  * functioned called by deallocate inode via ext2fs_iterate_block().
7821  */
7822 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
7823                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
7824                                   blk_t ref_block FSCK_ATTR((unused)),
7825                                   int ref_offset FSCK_ATTR((unused)),
7826                                   void *priv_data)
7827 {
7828         e2fsck_t        ctx = (e2fsck_t) priv_data;
7829
7830         if (HOLE_BLKADDR(*block_nr))
7831                 return 0;
7832         if ((*block_nr < fs->super->s_first_data_block) ||
7833             (*block_nr >= fs->super->s_blocks_count))
7834                 return 0;
7835         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
7836         ext2fs_block_alloc_stats(fs, *block_nr, -1);
7837         return 0;
7838 }
7839
7840 /*
7841  * This fuction deallocates an inode
7842  */
7843 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
7844 {
7845         ext2_filsys fs = ctx->fs;
7846         struct ext2_inode       inode;
7847         struct problem_context  pctx;
7848         __u32                   count;
7849
7850         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
7851         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
7852         inode.i_links_count = 0;
7853         inode.i_dtime = time(0);
7854         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
7855         clear_problem_context(&pctx);
7856         pctx.ino = ino;
7857
7858         /*
7859          * Fix up the bitmaps...
7860          */
7861         e2fsck_read_bitmaps(ctx);
7862         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
7863         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
7864         if (ctx->inode_bad_map)
7865                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
7866         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
7867
7868         if (inode.i_file_acl &&
7869             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
7870                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
7871                                                    block_buf, -1, &count);
7872                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
7873                         pctx.errcode = 0;
7874                         count = 1;
7875                 }
7876                 if (pctx.errcode) {
7877                         pctx.blk = inode.i_file_acl;
7878                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
7879                         ctx->flags |= E2F_FLAG_ABORT;
7880                         return;
7881                 }
7882                 if (count == 0) {
7883                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
7884                                                    inode.i_file_acl);
7885                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
7886                 }
7887                 inode.i_file_acl = 0;
7888         }
7889
7890         if (!ext2fs_inode_has_valid_blocks(&inode))
7891                 return;
7892
7893         if (LINUX_S_ISREG(inode.i_mode) &&
7894             (inode.i_size_high || inode.i_size & 0x80000000UL))
7895                 ctx->large_files--;
7896
7897         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7898                                             deallocate_inode_block, ctx);
7899         if (pctx.errcode) {
7900                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
7901                 ctx->flags |= E2F_FLAG_ABORT;
7902                 return;
7903         }
7904 }
7905
7906 /*
7907  * This fuction clears the htree flag on an inode
7908  */
7909 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
7910 {
7911         struct ext2_inode       inode;
7912
7913         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
7914         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
7915         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
7916         if (ctx->dirs_to_hash)
7917                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
7918 }
7919
7920
7921 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
7922                                     ext2_ino_t ino, char *buf)
7923 {
7924         ext2_filsys fs = ctx->fs;
7925         struct ext2_inode       inode;
7926         int                     inode_modified = 0;
7927         int                     not_fixed = 0;
7928         unsigned char           *frag, *fsize;
7929         struct problem_context  pctx;
7930         int     problem = 0;
7931
7932         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
7933
7934         clear_problem_context(&pctx);
7935         pctx.ino = ino;
7936         pctx.dir = dir;
7937         pctx.inode = &inode;
7938
7939         if (inode.i_file_acl &&
7940             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
7941             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
7942                 inode.i_file_acl = 0;
7943 #ifdef EXT2FS_ENABLE_SWAPFS
7944                 /*
7945                  * This is a special kludge to deal with long symlinks
7946                  * on big endian systems.  i_blocks had already been
7947                  * decremented earlier in pass 1, but since i_file_acl
7948                  * hadn't yet been cleared, ext2fs_read_inode()
7949                  * assumed that the file was short symlink and would
7950                  * not have byte swapped i_block[0].  Hence, we have
7951                  * to byte-swap it here.
7952                  */
7953                 if (LINUX_S_ISLNK(inode.i_mode) &&
7954                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
7955                     (inode.i_blocks == fs->blocksize >> 9))
7956                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
7957 #endif
7958                 inode_modified++;
7959         } else
7960                 not_fixed++;
7961
7962         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
7963             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
7964             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
7965             !(LINUX_S_ISSOCK(inode.i_mode)))
7966                 problem = PR_2_BAD_MODE;
7967         else if (LINUX_S_ISCHR(inode.i_mode)
7968                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7969                 problem = PR_2_BAD_CHAR_DEV;
7970         else if (LINUX_S_ISBLK(inode.i_mode)
7971                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7972                 problem = PR_2_BAD_BLOCK_DEV;
7973         else if (LINUX_S_ISFIFO(inode.i_mode)
7974                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7975                 problem = PR_2_BAD_FIFO;
7976         else if (LINUX_S_ISSOCK(inode.i_mode)
7977                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7978                 problem = PR_2_BAD_SOCKET;
7979         else if (LINUX_S_ISLNK(inode.i_mode)
7980                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
7981                 problem = PR_2_INVALID_SYMLINK;
7982         }
7983
7984         if (problem) {
7985                 if (fix_problem(ctx, problem, &pctx)) {
7986                         deallocate_inode(ctx, ino, 0);
7987                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7988                                 return 0;
7989                         return 1;
7990                 } else
7991                         not_fixed++;
7992                 problem = 0;
7993         }
7994
7995         if (inode.i_faddr) {
7996                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
7997                         inode.i_faddr = 0;
7998                         inode_modified++;
7999                 } else
8000                         not_fixed++;
8001         }
8002
8003         switch (fs->super->s_creator_os) {
8004             case EXT2_OS_LINUX:
8005                 frag = &inode.osd2.linux2.l_i_frag;
8006                 fsize = &inode.osd2.linux2.l_i_fsize;
8007                 break;
8008             case EXT2_OS_HURD:
8009                 frag = &inode.osd2.hurd2.h_i_frag;
8010                 fsize = &inode.osd2.hurd2.h_i_fsize;
8011                 break;
8012             case EXT2_OS_MASIX:
8013                 frag = &inode.osd2.masix2.m_i_frag;
8014                 fsize = &inode.osd2.masix2.m_i_fsize;
8015                 break;
8016             default:
8017                 frag = fsize = 0;
8018         }
8019         if (frag && *frag) {
8020                 pctx.num = *frag;
8021                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8022                         *frag = 0;
8023                         inode_modified++;
8024                 } else
8025                         not_fixed++;
8026                 pctx.num = 0;
8027         }
8028         if (fsize && *fsize) {
8029                 pctx.num = *fsize;
8030                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8031                         *fsize = 0;
8032                         inode_modified++;
8033                 } else
8034                         not_fixed++;
8035                 pctx.num = 0;
8036         }
8037
8038         if (inode.i_file_acl &&
8039             ((inode.i_file_acl < fs->super->s_first_data_block) ||
8040              (inode.i_file_acl >= fs->super->s_blocks_count))) {
8041                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8042                         inode.i_file_acl = 0;
8043                         inode_modified++;
8044                 } else
8045                         not_fixed++;
8046         }
8047         if (inode.i_dir_acl &&
8048             LINUX_S_ISDIR(inode.i_mode)) {
8049                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8050                         inode.i_dir_acl = 0;
8051                         inode_modified++;
8052                 } else
8053                         not_fixed++;
8054         }
8055
8056         if (inode_modified)
8057                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8058         if (!not_fixed)
8059                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8060         return 0;
8061 }
8062
8063
8064 /*
8065  * allocate_dir_block --- this function allocates a new directory
8066  *      block for a particular inode; this is done if a directory has
8067  *      a "hole" in it, or if a directory has a illegal block number
8068  *      that was zeroed out and now needs to be replaced.
8069  */
8070 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8071                               struct problem_context *pctx)
8072 {
8073         ext2_filsys fs = ctx->fs;
8074         blk_t                   blk;
8075         char                    *block;
8076         struct ext2_inode       inode;
8077
8078         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8079                 return 1;
8080
8081         /*
8082          * Read the inode and block bitmaps in; we'll be messing with
8083          * them.
8084          */
8085         e2fsck_read_bitmaps(ctx);
8086
8087         /*
8088          * First, find a free block
8089          */
8090         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8091         if (pctx->errcode) {
8092                 pctx->str = "ext2fs_new_block";
8093                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8094                 return 1;
8095         }
8096         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8097         ext2fs_mark_block_bitmap(fs->block_map, blk);
8098         ext2fs_mark_bb_dirty(fs);
8099
8100         /*
8101          * Now let's create the actual data block for the inode
8102          */
8103         if (db->blockcnt)
8104                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8105         else
8106                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8107                                                      EXT2_ROOT_INO, &block);
8108
8109         if (pctx->errcode) {
8110                 pctx->str = "ext2fs_new_dir_block";
8111                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8112                 return 1;
8113         }
8114
8115         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8116         ext2fs_free_mem(&block);
8117         if (pctx->errcode) {
8118                 pctx->str = "ext2fs_write_dir_block";
8119                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8120                 return 1;
8121         }
8122
8123         /*
8124          * Update the inode block count
8125          */
8126         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8127         inode.i_blocks += fs->blocksize / 512;
8128         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8129                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8130         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8131
8132         /*
8133          * Finally, update the block pointers for the inode
8134          */
8135         db->blk = blk;
8136         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8137                                       0, update_dir_block, db);
8138         if (pctx->errcode) {
8139                 pctx->str = "ext2fs_block_iterate";
8140                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8141                 return 1;
8142         }
8143
8144         return 0;
8145 }
8146
8147 /*
8148  * This is a helper function for allocate_dir_block().
8149  */
8150 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8151                             blk_t       *block_nr,
8152                             e2_blkcnt_t blockcnt,
8153                             blk_t ref_block FSCK_ATTR((unused)),
8154                             int ref_offset FSCK_ATTR((unused)),
8155                             void *priv_data)
8156 {
8157         struct ext2_db_entry *db;
8158
8159         db = (struct ext2_db_entry *) priv_data;
8160         if (db->blockcnt == (int) blockcnt) {
8161                 *block_nr = db->blk;
8162                 return BLOCK_CHANGED;
8163         }
8164         return 0;
8165 }
8166
8167 /*
8168  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8169  *
8170  * Pass #3 assures that all directories are connected to the
8171  * filesystem tree, using the following algorithm:
8172  *
8173  * First, the root directory is checked to make sure it exists; if
8174  * not, e2fsck will offer to create a new one.  It is then marked as
8175  * "done".
8176  *
8177  * Then, pass3 interates over all directory inodes; for each directory
8178  * it attempts to trace up the filesystem tree, using dirinfo.parent
8179  * until it reaches a directory which has been marked "done".  If it
8180  * can not do so, then the directory must be disconnected, and e2fsck
8181  * will offer to reconnect it to /lost+found.  While it is chasing
8182  * parent pointers up the filesystem tree, if pass3 sees a directory
8183  * twice, then it has detected a filesystem loop, and it will again
8184  * offer to reconnect the directory to /lost+found in to break the
8185  * filesystem loop.
8186  *
8187  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8188  * reconnect inodes to /lost+found; this subroutine is also used by
8189  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
8190  * is responsible for creating /lost+found if it does not exist.
8191  *
8192  * Pass 3 frees the following data structures:
8193  *      - The dirinfo directory information cache.
8194  */
8195
8196 static void check_root(e2fsck_t ctx);
8197 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8198                            struct problem_context *pctx);
8199 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8200
8201 static ext2fs_inode_bitmap inode_loop_detect;
8202 static ext2fs_inode_bitmap inode_done_map;
8203
8204 static void e2fsck_pass3(e2fsck_t ctx)
8205 {
8206         ext2_filsys fs = ctx->fs;
8207         int             i;
8208 #ifdef RESOURCE_TRACK
8209         struct resource_track   rtrack;
8210 #endif
8211         struct problem_context  pctx;
8212         struct dir_info *dir;
8213         unsigned long maxdirs, count;
8214
8215 #ifdef RESOURCE_TRACK
8216         init_resource_track(&rtrack);
8217 #endif
8218
8219         clear_problem_context(&pctx);
8220
8221 #ifdef MTRACE
8222         mtrace_print("Pass 3");
8223 #endif
8224
8225         if (!(ctx->options & E2F_OPT_PREEN))
8226                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8227
8228         /*
8229          * Allocate some bitmaps to do loop detection.
8230          */
8231         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8232                                                     &inode_done_map);
8233         if (pctx.errcode) {
8234                 pctx.num = 2;
8235                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8236                 ctx->flags |= E2F_FLAG_ABORT;
8237                 goto abort_exit;
8238         }
8239 #ifdef RESOURCE_TRACK
8240         if (ctx->options & E2F_OPT_TIME) {
8241                 e2fsck_clear_progbar(ctx);
8242                 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8243         }
8244 #endif
8245
8246         check_root(ctx);
8247         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8248                 goto abort_exit;
8249
8250         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8251
8252         maxdirs = e2fsck_get_num_dirinfo(ctx);
8253         count = 1;
8254
8255         if (ctx->progress)
8256                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8257                         goto abort_exit;
8258
8259         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8260                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8261                         goto abort_exit;
8262                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8263                         goto abort_exit;
8264                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8265                         if (check_directory(ctx, dir, &pctx))
8266                                 goto abort_exit;
8267         }
8268
8269         /*
8270          * Force the creation of /lost+found if not present
8271          */
8272         if ((ctx->flags & E2F_OPT_READONLY) == 0)
8273                 e2fsck_get_lost_and_found(ctx, 1);
8274
8275         /*
8276          * If there are any directories that need to be indexed or
8277          * optimized, do it here.
8278          */
8279         e2fsck_rehash_directories(ctx);
8280
8281 abort_exit:
8282         e2fsck_free_dir_info(ctx);
8283         ext2fs_free_inode_bitmap(inode_loop_detect);
8284         inode_loop_detect = 0;
8285         ext2fs_free_inode_bitmap(inode_done_map);
8286         inode_done_map = 0;
8287
8288 #ifdef RESOURCE_TRACK
8289         if (ctx->options & E2F_OPT_TIME2) {
8290                 e2fsck_clear_progbar(ctx);
8291                 print_resource_track(_("Pass 3"), &rtrack);
8292         }
8293 #endif
8294 }
8295
8296 /*
8297  * This makes sure the root inode is present; if not, we ask if the
8298  * user wants us to create it.  Not creating it is a fatal error.
8299  */
8300 static void check_root(e2fsck_t ctx)
8301 {
8302         ext2_filsys fs = ctx->fs;
8303         blk_t                   blk;
8304         struct ext2_inode       inode;
8305         char *                  block;
8306         struct problem_context  pctx;
8307
8308         clear_problem_context(&pctx);
8309
8310         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8311                 /*
8312                  * If the root inode is not a directory, die here.  The
8313                  * user must have answered 'no' in pass1 when we
8314                  * offered to clear it.
8315                  */
8316                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8317                                                EXT2_ROOT_INO))) {
8318                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8319                         ctx->flags |= E2F_FLAG_ABORT;
8320                 }
8321                 return;
8322         }
8323
8324         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8325                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8326                 ctx->flags |= E2F_FLAG_ABORT;
8327                 return;
8328         }
8329
8330         e2fsck_read_bitmaps(ctx);
8331
8332         /*
8333          * First, find a free block
8334          */
8335         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8336         if (pctx.errcode) {
8337                 pctx.str = "ext2fs_new_block";
8338                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8339                 ctx->flags |= E2F_FLAG_ABORT;
8340                 return;
8341         }
8342         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8343         ext2fs_mark_block_bitmap(fs->block_map, blk);
8344         ext2fs_mark_bb_dirty(fs);
8345
8346         /*
8347          * Now let's create the actual data block for the inode
8348          */
8349         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8350                                             &block);
8351         if (pctx.errcode) {
8352                 pctx.str = "ext2fs_new_dir_block";
8353                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8354                 ctx->flags |= E2F_FLAG_ABORT;
8355                 return;
8356         }
8357
8358         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8359         if (pctx.errcode) {
8360                 pctx.str = "ext2fs_write_dir_block";
8361                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8362                 ctx->flags |= E2F_FLAG_ABORT;
8363                 return;
8364         }
8365         ext2fs_free_mem(&block);
8366
8367         /*
8368          * Set up the inode structure
8369          */
8370         memset(&inode, 0, sizeof(inode));
8371         inode.i_mode = 040755;
8372         inode.i_size = fs->blocksize;
8373         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8374         inode.i_links_count = 2;
8375         inode.i_blocks = fs->blocksize / 512;
8376         inode.i_block[0] = blk;
8377
8378         /*
8379          * Write out the inode.
8380          */
8381         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8382         if (pctx.errcode) {
8383                 pctx.str = "ext2fs_write_inode";
8384                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8385                 ctx->flags |= E2F_FLAG_ABORT;
8386                 return;
8387         }
8388
8389         /*
8390          * Miscellaneous bookkeeping...
8391          */
8392         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8393         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8394         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8395
8396         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8397         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8398         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8399         ext2fs_mark_ib_dirty(fs);
8400 }
8401
8402 /*
8403  * This subroutine is responsible for making sure that a particular
8404  * directory is connected to the root; if it isn't we trace it up as
8405  * far as we can go, and then offer to connect the resulting parent to
8406  * the lost+found.  We have to do loop detection; if we ever discover
8407  * a loop, we treat that as a disconnected directory and offer to
8408  * reparent it to lost+found.
8409  *
8410  * However, loop detection is expensive, because for very large
8411  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8412  * is non-trivial.  Loops in filesystems are also a rare error case,
8413  * and we shouldn't optimize for error cases.  So we try two passes of
8414  * the algorithm.  The first time, we ignore loop detection and merely
8415  * increment a counter; if the counter exceeds some extreme threshold,
8416  * then we try again with the loop detection bitmap enabled.
8417  */
8418 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8419                            struct problem_context *pctx)
8420 {
8421         ext2_filsys     fs = ctx->fs;
8422         struct dir_info *p = dir;
8423         int             loop_pass = 0, parent_count = 0;
8424
8425         if (!p)
8426                 return 0;
8427
8428         while (1) {
8429                 /*
8430                  * Mark this inode as being "done"; by the time we
8431                  * return from this function, the inode we either be
8432                  * verified as being connected to the directory tree,
8433                  * or we will have offered to reconnect this to
8434                  * lost+found.
8435                  *
8436                  * If it was marked done already, then we've reached a
8437                  * parent we've already checked.
8438                  */
8439                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8440                         break;
8441
8442                 /*
8443                  * If this directory doesn't have a parent, or we've
8444                  * seen the parent once already, then offer to
8445                  * reparent it to lost+found
8446                  */
8447                 if (!p->parent ||
8448                     (loop_pass &&
8449                      (ext2fs_test_inode_bitmap(inode_loop_detect,
8450                                               p->parent)))) {
8451                         pctx->ino = p->ino;
8452                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8453                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
8454                                         ext2fs_unmark_valid(fs);
8455                                 else {
8456                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
8457                                         p->parent = ctx->lost_and_found;
8458                                         fix_dotdot(ctx, p, ctx->lost_and_found);
8459                                 }
8460                         }
8461                         break;
8462                 }
8463                 p = e2fsck_get_dir_info(ctx, p->parent);
8464                 if (!p) {
8465                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8466                         return 0;
8467                 }
8468                 if (loop_pass) {
8469                         ext2fs_mark_inode_bitmap(inode_loop_detect,
8470                                                  p->ino);
8471                 } else if (parent_count++ > 2048) {
8472                         /*
8473                          * If we've run into a path depth that's
8474                          * greater than 2048, try again with the inode
8475                          * loop bitmap turned on and start from the
8476                          * top.
8477                          */
8478                         loop_pass = 1;
8479                         if (inode_loop_detect)
8480                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
8481                         else {
8482                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8483                                 if (pctx->errcode) {
8484                                         pctx->num = 1;
8485                                         fix_problem(ctx,
8486                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8487                                         ctx->flags |= E2F_FLAG_ABORT;
8488                                         return -1;
8489                                 }
8490                         }
8491                         p = dir;
8492                 }
8493         }
8494
8495         /*
8496          * Make sure that .. and the parent directory are the same;
8497          * offer to fix it if not.
8498          */
8499         if (dir->parent != dir->dotdot) {
8500                 pctx->ino = dir->ino;
8501                 pctx->ino2 = dir->dotdot;
8502                 pctx->dir = dir->parent;
8503                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8504                         fix_dotdot(ctx, dir, dir->parent);
8505         }
8506         return 0;
8507 }
8508
8509 /*
8510  * This routine gets the lost_and_found inode, making it a directory
8511  * if necessary
8512  */
8513 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8514 {
8515         ext2_filsys fs = ctx->fs;
8516         ext2_ino_t                      ino;
8517         blk_t                   blk;
8518         errcode_t               retval;
8519         struct ext2_inode       inode;
8520         char *                  block;
8521         static const char       name[] = "lost+found";
8522         struct  problem_context pctx;
8523         struct dir_info         *dirinfo;
8524
8525         if (ctx->lost_and_found)
8526                 return ctx->lost_and_found;
8527
8528         clear_problem_context(&pctx);
8529
8530         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8531                                sizeof(name)-1, 0, &ino);
8532         if (retval && !fix)
8533                 return 0;
8534         if (!retval) {
8535                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8536                         ctx->lost_and_found = ino;
8537                         return ino;
8538                 }
8539
8540                 /* Lost+found isn't a directory! */
8541                 if (!fix)
8542                         return 0;
8543                 pctx.ino = ino;
8544                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8545                         return 0;
8546
8547                 /* OK, unlink the old /lost+found file. */
8548                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8549                 if (pctx.errcode) {
8550                         pctx.str = "ext2fs_unlink";
8551                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8552                         return 0;
8553                 }
8554                 dirinfo = e2fsck_get_dir_info(ctx, ino);
8555                 if (dirinfo)
8556                         dirinfo->parent = 0;
8557                 e2fsck_adjust_inode_count(ctx, ino, -1);
8558         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8559                 pctx.errcode = retval;
8560                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8561         }
8562         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8563                 return 0;
8564
8565         /*
8566          * Read the inode and block bitmaps in; we'll be messing with
8567          * them.
8568          */
8569         e2fsck_read_bitmaps(ctx);
8570
8571         /*
8572          * First, find a free block
8573          */
8574         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8575         if (retval) {
8576                 pctx.errcode = retval;
8577                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8578                 return 0;
8579         }
8580         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8581         ext2fs_block_alloc_stats(fs, blk, +1);
8582
8583         /*
8584          * Next find a free inode.
8585          */
8586         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8587                                   ctx->inode_used_map, &ino);
8588         if (retval) {
8589                 pctx.errcode = retval;
8590                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8591                 return 0;
8592         }
8593         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8594         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8595         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8596
8597         /*
8598          * Now let's create the actual data block for the inode
8599          */
8600         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8601         if (retval) {
8602                 pctx.errcode = retval;
8603                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8604                 return 0;
8605         }
8606
8607         retval = ext2fs_write_dir_block(fs, blk, block);
8608         ext2fs_free_mem(&block);
8609         if (retval) {
8610                 pctx.errcode = retval;
8611                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
8612                 return 0;
8613         }
8614
8615         /*
8616          * Set up the inode structure
8617          */
8618         memset(&inode, 0, sizeof(inode));
8619         inode.i_mode = 040700;
8620         inode.i_size = fs->blocksize;
8621         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8622         inode.i_links_count = 2;
8623         inode.i_blocks = fs->blocksize / 512;
8624         inode.i_block[0] = blk;
8625
8626         /*
8627          * Next, write out the inode.
8628          */
8629         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
8630         if (pctx.errcode) {
8631                 pctx.str = "ext2fs_write_inode";
8632                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8633                 return 0;
8634         }
8635         /*
8636          * Finally, create the directory link
8637          */
8638         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
8639         if (pctx.errcode) {
8640                 pctx.str = "ext2fs_link";
8641                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8642                 return 0;
8643         }
8644
8645         /*
8646          * Miscellaneous bookkeeping that needs to be kept straight.
8647          */
8648         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
8649         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
8650         ext2fs_icount_store(ctx->inode_count, ino, 2);
8651         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
8652         ctx->lost_and_found = ino;
8653 #if 0
8654         printf("/lost+found created; inode #%lu\n", ino);
8655 #endif
8656         return ino;
8657 }
8658
8659 /*
8660  * This routine will connect a file to lost+found
8661  */
8662 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
8663 {
8664         ext2_filsys fs = ctx->fs;
8665         errcode_t       retval;
8666         char            name[80];
8667         struct problem_context  pctx;
8668         struct ext2_inode       inode;
8669         int             file_type = 0;
8670
8671         clear_problem_context(&pctx);
8672         pctx.ino = ino;
8673
8674         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
8675                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
8676                         ctx->bad_lost_and_found++;
8677         }
8678         if (ctx->bad_lost_and_found) {
8679                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
8680                 return 1;
8681         }
8682
8683         sprintf(name, "#%u", ino);
8684         if (ext2fs_read_inode(fs, ino, &inode) == 0)
8685                 file_type = ext2_file_type(inode.i_mode);
8686         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
8687         if (retval == EXT2_ET_DIR_NO_SPACE) {
8688                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
8689                         return 1;
8690                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
8691                                                  1, 0);
8692                 if (retval) {
8693                         pctx.errcode = retval;
8694                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
8695                         return 1;
8696                 }
8697                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
8698                                      ino, file_type);
8699         }
8700         if (retval) {
8701                 pctx.errcode = retval;
8702                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
8703                 return 1;
8704         }
8705         e2fsck_adjust_inode_count(ctx, ino, 1);
8706
8707         return 0;
8708 }
8709
8710 /*
8711  * Utility routine to adjust the inode counts on an inode.
8712  */
8713 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
8714 {
8715         ext2_filsys fs = ctx->fs;
8716         errcode_t               retval;
8717         struct ext2_inode       inode;
8718
8719         if (!ino)
8720                 return 0;
8721
8722         retval = ext2fs_read_inode(fs, ino, &inode);
8723         if (retval)
8724                 return retval;
8725
8726 #if 0
8727         printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
8728                inode.i_links_count);
8729 #endif
8730
8731         if (adj == 1) {
8732                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
8733                 if (inode.i_links_count == (__u16) ~0)
8734                         return 0;
8735                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
8736                 inode.i_links_count++;
8737         } else if (adj == -1) {
8738                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
8739                 if (inode.i_links_count == 0)
8740                         return 0;
8741                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
8742                 inode.i_links_count--;
8743         }
8744
8745         retval = ext2fs_write_inode(fs, ino, &inode);
8746         if (retval)
8747                 return retval;
8748
8749         return 0;
8750 }
8751
8752 /*
8753  * Fix parent --- this routine fixes up the parent of a directory.
8754  */
8755 struct fix_dotdot_struct {
8756         ext2_filsys     fs;
8757         ext2_ino_t      parent;
8758         int             done;
8759         e2fsck_t        ctx;
8760 };
8761
8762 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
8763                            int  offset FSCK_ATTR((unused)),
8764                            int  blocksize FSCK_ATTR((unused)),
8765                            char *buf FSCK_ATTR((unused)),
8766                            void *priv_data)
8767 {
8768         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
8769         errcode_t       retval;
8770         struct problem_context pctx;
8771
8772         if ((dirent->name_len & 0xFF) != 2)
8773                 return 0;
8774         if (strncmp(dirent->name, "..", 2))
8775                 return 0;
8776
8777         clear_problem_context(&pctx);
8778
8779         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
8780         if (retval) {
8781                 pctx.errcode = retval;
8782                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
8783         }
8784         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
8785         if (retval) {
8786                 pctx.errcode = retval;
8787                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
8788         }
8789         dirent->inode = fp->parent;
8790
8791         fp->done++;
8792         return DIRENT_ABORT | DIRENT_CHANGED;
8793 }
8794
8795 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
8796 {
8797         ext2_filsys fs = ctx->fs;
8798         errcode_t       retval;
8799         struct fix_dotdot_struct fp;
8800         struct problem_context pctx;
8801
8802         fp.fs = fs;
8803         fp.parent = parent;
8804         fp.done = 0;
8805         fp.ctx = ctx;
8806
8807 #if 0
8808         printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
8809 #endif
8810
8811         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
8812                                     0, fix_dotdot_proc, &fp);
8813         if (retval || !fp.done) {
8814                 clear_problem_context(&pctx);
8815                 pctx.ino = dir->ino;
8816                 pctx.errcode = retval;
8817                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
8818                             PR_3_FIX_PARENT_NOFIND, &pctx);
8819                 ext2fs_unmark_valid(fs);
8820         }
8821         dir->dotdot = parent;
8822
8823         return;
8824 }
8825
8826 /*
8827  * These routines are responsible for expanding a /lost+found if it is
8828  * too small.
8829  */
8830
8831 struct expand_dir_struct {
8832         int                     num;
8833         int                     guaranteed_size;
8834         int                     newblocks;
8835         int                     last_block;
8836         errcode_t               err;
8837         e2fsck_t                ctx;
8838 };
8839
8840 static int expand_dir_proc(ext2_filsys fs,
8841                            blk_t        *blocknr,
8842                            e2_blkcnt_t  blockcnt,
8843                            blk_t ref_block FSCK_ATTR((unused)),
8844                            int ref_offset FSCK_ATTR((unused)),
8845                            void *priv_data)
8846 {
8847         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
8848         blk_t   new_blk;
8849         static blk_t    last_blk = 0;
8850         char            *block;
8851         errcode_t       retval;
8852         e2fsck_t        ctx;
8853
8854         ctx = es->ctx;
8855
8856         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
8857                 return BLOCK_ABORT;
8858
8859         if (blockcnt > 0)
8860                 es->last_block = blockcnt;
8861         if (*blocknr) {
8862                 last_blk = *blocknr;
8863                 return 0;
8864         }
8865         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
8866                                   &new_blk);
8867         if (retval) {
8868                 es->err = retval;
8869                 return BLOCK_ABORT;
8870         }
8871         if (blockcnt > 0) {
8872                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
8873                 if (retval) {
8874                         es->err = retval;
8875                         return BLOCK_ABORT;
8876                 }
8877                 es->num--;
8878                 retval = ext2fs_write_dir_block(fs, new_blk, block);
8879         } else {
8880                 retval = ext2fs_get_mem(fs->blocksize, &block);
8881                 if (retval) {
8882                         es->err = retval;
8883                         return BLOCK_ABORT;
8884                 }
8885                 memset(block, 0, fs->blocksize);
8886                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
8887         }
8888         if (retval) {
8889                 es->err = retval;
8890                 return BLOCK_ABORT;
8891         }
8892         ext2fs_free_mem(&block);
8893         *blocknr = new_blk;
8894         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
8895         ext2fs_block_alloc_stats(fs, new_blk, +1);
8896         es->newblocks++;
8897
8898         if (es->num == 0)
8899                 return (BLOCK_CHANGED | BLOCK_ABORT);
8900         else
8901                 return BLOCK_CHANGED;
8902 }
8903
8904 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
8905                                   int num, int guaranteed_size)
8906 {
8907         ext2_filsys fs = ctx->fs;
8908         errcode_t       retval;
8909         struct expand_dir_struct es;
8910         struct ext2_inode       inode;
8911
8912         if (!(fs->flags & EXT2_FLAG_RW))
8913                 return EXT2_ET_RO_FILSYS;
8914
8915         /*
8916          * Read the inode and block bitmaps in; we'll be messing with
8917          * them.
8918          */
8919         e2fsck_read_bitmaps(ctx);
8920
8921         retval = ext2fs_check_directory(fs, dir);
8922         if (retval)
8923                 return retval;
8924
8925         es.num = num;
8926         es.guaranteed_size = guaranteed_size;
8927         es.last_block = 0;
8928         es.err = 0;
8929         es.newblocks = 0;
8930         es.ctx = ctx;
8931
8932         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
8933                                        0, expand_dir_proc, &es);
8934
8935         if (es.err)
8936                 return es.err;
8937
8938         /*
8939          * Update the size and block count fields in the inode.
8940          */
8941         retval = ext2fs_read_inode(fs, dir, &inode);
8942         if (retval)
8943                 return retval;
8944
8945         inode.i_size = (es.last_block + 1) * fs->blocksize;
8946         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
8947
8948         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
8949
8950         return 0;
8951 }
8952
8953 /*
8954  * pass4.c -- pass #4 of e2fsck: Check reference counts
8955  *
8956  * Pass 4 frees the following data structures:
8957  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
8958  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
8959  */
8960
8961 /*
8962  * This routine is called when an inode is not connected to the
8963  * directory tree.
8964  *
8965  * This subroutine returns 1 then the caller shouldn't bother with the
8966  * rest of the pass 4 tests.
8967  */
8968 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
8969 {
8970         ext2_filsys fs = ctx->fs;
8971         struct ext2_inode       inode;
8972         struct problem_context  pctx;
8973
8974         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
8975         clear_problem_context(&pctx);
8976         pctx.ino = i;
8977         pctx.inode = &inode;
8978
8979         /*
8980          * Offer to delete any zero-length files that does not have
8981          * blocks.  If there is an EA block, it might have useful
8982          * information, so we won't prompt to delete it, but let it be
8983          * reconnected to lost+found.
8984          */
8985         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
8986                                 LINUX_S_ISDIR(inode.i_mode))) {
8987                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
8988                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
8989                         inode.i_links_count = 0;
8990                         inode.i_dtime = time(0);
8991                         e2fsck_write_inode(ctx, i, &inode,
8992                                            "disconnect_inode");
8993                         /*
8994                          * Fix up the bitmaps...
8995                          */
8996                         e2fsck_read_bitmaps(ctx);
8997                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
8998                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
8999                         ext2fs_inode_alloc_stats2(fs, i, -1,
9000                                                   LINUX_S_ISDIR(inode.i_mode));
9001                         return 0;
9002                 }
9003         }
9004
9005         /*
9006          * Prompt to reconnect.
9007          */
9008         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9009                 if (e2fsck_reconnect_file(ctx, i))
9010                         ext2fs_unmark_valid(fs);
9011         } else {
9012                 /*
9013                  * If we don't attach the inode, then skip the
9014                  * i_links_test since there's no point in trying to
9015                  * force i_links_count to zero.
9016                  */
9017                 ext2fs_unmark_valid(fs);
9018                 return 1;
9019         }
9020         return 0;
9021 }
9022
9023
9024 static void e2fsck_pass4(e2fsck_t ctx)
9025 {
9026         ext2_filsys fs = ctx->fs;
9027         ext2_ino_t      i;
9028         struct ext2_inode       inode;
9029 #ifdef RESOURCE_TRACK
9030         struct resource_track   rtrack;
9031 #endif
9032         struct problem_context  pctx;
9033         __u16   link_count, link_counted;
9034         char    *buf = 0;
9035         int     group, maxgroup;
9036
9037 #ifdef RESOURCE_TRACK
9038         init_resource_track(&rtrack);
9039 #endif
9040
9041 #ifdef MTRACE
9042         mtrace_print("Pass 4");
9043 #endif
9044
9045         clear_problem_context(&pctx);
9046
9047         if (!(ctx->options & E2F_OPT_PREEN))
9048                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9049
9050         group = 0;
9051         maxgroup = fs->group_desc_count;
9052         if (ctx->progress)
9053                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9054                         return;
9055
9056         for (i=1; i <= fs->super->s_inodes_count; i++) {
9057                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9058                         return;
9059                 if ((i % fs->super->s_inodes_per_group) == 0) {
9060                         group++;
9061                         if (ctx->progress)
9062                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
9063                                         return;
9064                 }
9065                 if (i == EXT2_BAD_INO ||
9066                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9067                         continue;
9068                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9069                     (ctx->inode_imagic_map &&
9070                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9071                     (ctx->inode_bb_map &&
9072                      ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9073                         continue;
9074                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9075                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9076                 if (link_counted == 0) {
9077                         if (!buf)
9078                                 buf = e2fsck_allocate_memory(ctx,
9079                                      fs->blocksize, "bad_inode buffer");
9080                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9081                                 continue;
9082                         if (disconnect_inode(ctx, i))
9083                                 continue;
9084                         ext2fs_icount_fetch(ctx->inode_link_info, i,
9085                                             &link_count);
9086                         ext2fs_icount_fetch(ctx->inode_count, i,
9087                                             &link_counted);
9088                 }
9089                 if (link_counted != link_count) {
9090                         e2fsck_read_inode(ctx, i, &inode, "pass4");
9091                         pctx.ino = i;
9092                         pctx.inode = &inode;
9093                         if (link_count != inode.i_links_count) {
9094                                 pctx.num = link_count;
9095                                 fix_problem(ctx,
9096                                             PR_4_INCONSISTENT_COUNT, &pctx);
9097                         }
9098                         pctx.num = link_counted;
9099                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9100                                 inode.i_links_count = link_counted;
9101                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
9102                         }
9103                 }
9104         }
9105         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9106         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9107         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9108         ctx->inode_bb_map = 0;
9109         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9110         ctx->inode_imagic_map = 0;
9111         ext2fs_free_mem(&buf);
9112 #ifdef RESOURCE_TRACK
9113         if (ctx->options & E2F_OPT_TIME2) {
9114                 e2fsck_clear_progbar(ctx);
9115                 print_resource_track(_("Pass 4"), &rtrack);
9116         }
9117 #endif
9118 }
9119
9120 /*
9121  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9122  */
9123
9124 #define NO_BLK ((blk_t) -1)
9125
9126 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9127                             struct problem_context *pctx)
9128 {
9129         switch (problem) {
9130         case PR_5_BLOCK_UNUSED:
9131                 if (pctx->blk == pctx->blk2)
9132                         pctx->blk2 = 0;
9133                 else
9134                         problem = PR_5_BLOCK_RANGE_UNUSED;
9135                 break;
9136         case PR_5_BLOCK_USED:
9137                 if (pctx->blk == pctx->blk2)
9138                         pctx->blk2 = 0;
9139                 else
9140                         problem = PR_5_BLOCK_RANGE_USED;
9141                 break;
9142         case PR_5_INODE_UNUSED:
9143                 if (pctx->ino == pctx->ino2)
9144                         pctx->ino2 = 0;
9145                 else
9146                         problem = PR_5_INODE_RANGE_UNUSED;
9147                 break;
9148         case PR_5_INODE_USED:
9149                 if (pctx->ino == pctx->ino2)
9150                         pctx->ino2 = 0;
9151                 else
9152                         problem = PR_5_INODE_RANGE_USED;
9153                 break;
9154         }
9155         fix_problem(ctx, problem, pctx);
9156         pctx->blk = pctx->blk2 = NO_BLK;
9157         pctx->ino = pctx->ino2 = 0;
9158 }
9159
9160 static void check_block_bitmaps(e2fsck_t ctx)
9161 {
9162         ext2_filsys fs = ctx->fs;
9163         blk_t   i;
9164         int     *free_array;
9165         int     group = 0;
9166         unsigned int    blocks = 0;
9167         unsigned int    free_blocks = 0;
9168         int     group_free = 0;
9169         int     actual, bitmap;
9170         struct problem_context  pctx;
9171         int     problem, save_problem, fixit, had_problem;
9172         errcode_t       retval;
9173
9174         clear_problem_context(&pctx);
9175         free_array = (int *) e2fsck_allocate_memory(ctx,
9176             fs->group_desc_count * sizeof(int), "free block count array");
9177
9178         if ((fs->super->s_first_data_block <
9179              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9180             (fs->super->s_blocks_count-1 >
9181              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9182                 pctx.num = 1;
9183                 pctx.blk = fs->super->s_first_data_block;
9184                 pctx.blk2 = fs->super->s_blocks_count -1;
9185                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9186                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9187                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9188
9189                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9190                 return;
9191         }
9192
9193         if ((fs->super->s_first_data_block <
9194              ext2fs_get_block_bitmap_start(fs->block_map)) ||
9195             (fs->super->s_blocks_count-1 >
9196              ext2fs_get_block_bitmap_end(fs->block_map))) {
9197                 pctx.num = 2;
9198                 pctx.blk = fs->super->s_first_data_block;
9199                 pctx.blk2 = fs->super->s_blocks_count -1;
9200                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9201                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9202                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9203
9204                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9205                 return;
9206         }
9207
9208 redo_counts:
9209         had_problem = 0;
9210         save_problem = 0;
9211         pctx.blk = pctx.blk2 = NO_BLK;
9212         for (i = fs->super->s_first_data_block;
9213              i < fs->super->s_blocks_count;
9214              i++) {
9215                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9216                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9217
9218                 if (actual == bitmap)
9219                         goto do_counts;
9220
9221                 if (!actual && bitmap) {
9222                         /*
9223                          * Block not used, but marked in use in the bitmap.
9224                          */
9225                         problem = PR_5_BLOCK_UNUSED;
9226                 } else {
9227                         /*
9228                          * Block used, but not marked in use in the bitmap.
9229                          */
9230                         problem = PR_5_BLOCK_USED;
9231                 }
9232                 if (pctx.blk == NO_BLK) {
9233                         pctx.blk = pctx.blk2 = i;
9234                         save_problem = problem;
9235                 } else {
9236                         if ((problem == save_problem) &&
9237                             (pctx.blk2 == i-1))
9238                                 pctx.blk2++;
9239                         else {
9240                                 print_bitmap_problem(ctx, save_problem, &pctx);
9241                                 pctx.blk = pctx.blk2 = i;
9242                                 save_problem = problem;
9243                         }
9244                 }
9245                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9246                 had_problem++;
9247
9248         do_counts:
9249                 if (!bitmap) {
9250                         group_free++;
9251                         free_blocks++;
9252                 }
9253                 blocks ++;
9254                 if ((blocks == fs->super->s_blocks_per_group) ||
9255                     (i == fs->super->s_blocks_count-1)) {
9256                         free_array[group] = group_free;
9257                         group ++;
9258                         blocks = 0;
9259                         group_free = 0;
9260                         if (ctx->progress)
9261                                 if ((ctx->progress)(ctx, 5, group,
9262                                                     fs->group_desc_count*2))
9263                                         return;
9264                 }
9265         }
9266         if (pctx.blk != NO_BLK)
9267                 print_bitmap_problem(ctx, save_problem, &pctx);
9268         if (had_problem)
9269                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9270         else
9271                 fixit = -1;
9272         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9273
9274         if (fixit == 1) {
9275                 ext2fs_free_block_bitmap(fs->block_map);
9276                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9277                                                   &fs->block_map);
9278                 if (retval) {
9279                         clear_problem_context(&pctx);
9280                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9281                         ctx->flags |= E2F_FLAG_ABORT;
9282                         return;
9283                 }
9284                 ext2fs_set_bitmap_padding(fs->block_map);
9285                 ext2fs_mark_bb_dirty(fs);
9286
9287                 /* Redo the counts */
9288                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9289                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9290                 goto redo_counts;
9291         } else if (fixit == 0)
9292                 ext2fs_unmark_valid(fs);
9293
9294         for (i = 0; i < fs->group_desc_count; i++) {
9295                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9296                         pctx.group = i;
9297                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9298                         pctx.blk2 = free_array[i];
9299
9300                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9301                                         &pctx)) {
9302                                 fs->group_desc[i].bg_free_blocks_count =
9303                                         free_array[i];
9304                                 ext2fs_mark_super_dirty(fs);
9305                         } else
9306                                 ext2fs_unmark_valid(fs);
9307                 }
9308         }
9309         if (free_blocks != fs->super->s_free_blocks_count) {
9310                 pctx.group = 0;
9311                 pctx.blk = fs->super->s_free_blocks_count;
9312                 pctx.blk2 = free_blocks;
9313
9314                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9315                         fs->super->s_free_blocks_count = free_blocks;
9316                         ext2fs_mark_super_dirty(fs);
9317                 } else
9318                         ext2fs_unmark_valid(fs);
9319         }
9320         ext2fs_free_mem(&free_array);
9321 }
9322
9323 static void check_inode_bitmaps(e2fsck_t ctx)
9324 {
9325         ext2_filsys fs = ctx->fs;
9326         ext2_ino_t      i;
9327         unsigned int    free_inodes = 0;
9328         int             group_free = 0;
9329         int             dirs_count = 0;
9330         int             group = 0;
9331         unsigned int    inodes = 0;
9332         int             *free_array;
9333         int             *dir_array;
9334         int             actual, bitmap;
9335         errcode_t       retval;
9336         struct problem_context  pctx;
9337         int             problem, save_problem, fixit, had_problem;
9338
9339         clear_problem_context(&pctx);
9340         free_array = (int *) e2fsck_allocate_memory(ctx,
9341             fs->group_desc_count * sizeof(int), "free inode count array");
9342
9343         dir_array = (int *) e2fsck_allocate_memory(ctx,
9344            fs->group_desc_count * sizeof(int), "directory count array");
9345
9346         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9347             (fs->super->s_inodes_count >
9348              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9349                 pctx.num = 3;
9350                 pctx.blk = 1;
9351                 pctx.blk2 = fs->super->s_inodes_count;
9352                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9353                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9354                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9355
9356                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9357                 return;
9358         }
9359         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9360             (fs->super->s_inodes_count >
9361              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9362                 pctx.num = 4;
9363                 pctx.blk = 1;
9364                 pctx.blk2 = fs->super->s_inodes_count;
9365                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9366                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9367                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9368
9369                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9370                 return;
9371         }
9372
9373 redo_counts:
9374         had_problem = 0;
9375         save_problem = 0;
9376         pctx.ino = pctx.ino2 = 0;
9377         for (i = 1; i <= fs->super->s_inodes_count; i++) {
9378                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9379                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9380
9381                 if (actual == bitmap)
9382                         goto do_counts;
9383
9384                 if (!actual && bitmap) {
9385                         /*
9386                          * Inode wasn't used, but marked in bitmap
9387                          */
9388                         problem = PR_5_INODE_UNUSED;
9389                 } else /* if (actual && !bitmap) */ {
9390                         /*
9391                          * Inode used, but not in bitmap
9392                          */
9393                         problem = PR_5_INODE_USED;
9394                 }
9395                 if (pctx.ino == 0) {
9396                         pctx.ino = pctx.ino2 = i;
9397                         save_problem = problem;
9398                 } else {
9399                         if ((problem == save_problem) &&
9400                             (pctx.ino2 == i-1))
9401                                 pctx.ino2++;
9402                         else {
9403                                 print_bitmap_problem(ctx, save_problem, &pctx);
9404                                 pctx.ino = pctx.ino2 = i;
9405                                 save_problem = problem;
9406                         }
9407                 }
9408                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9409                 had_problem++;
9410
9411 do_counts:
9412                 if (!bitmap) {
9413                         group_free++;
9414                         free_inodes++;
9415                 } else {
9416                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9417                                 dirs_count++;
9418                 }
9419                 inodes++;
9420                 if ((inodes == fs->super->s_inodes_per_group) ||
9421                     (i == fs->super->s_inodes_count)) {
9422                         free_array[group] = group_free;
9423                         dir_array[group] = dirs_count;
9424                         group ++;
9425                         inodes = 0;
9426                         group_free = 0;
9427                         dirs_count = 0;
9428                         if (ctx->progress)
9429                                 if ((ctx->progress)(ctx, 5,
9430                                             group + fs->group_desc_count,
9431                                             fs->group_desc_count*2))
9432                                         return;
9433                 }
9434         }
9435         if (pctx.ino)
9436                 print_bitmap_problem(ctx, save_problem, &pctx);
9437
9438         if (had_problem)
9439                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9440         else
9441                 fixit = -1;
9442         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9443
9444         if (fixit == 1) {
9445                 ext2fs_free_inode_bitmap(fs->inode_map);
9446                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9447                                                   &fs->inode_map);
9448                 if (retval) {
9449                         clear_problem_context(&pctx);
9450                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9451                         ctx->flags |= E2F_FLAG_ABORT;
9452                         return;
9453                 }
9454                 ext2fs_set_bitmap_padding(fs->inode_map);
9455                 ext2fs_mark_ib_dirty(fs);
9456
9457                 /* redo counts */
9458                 inodes = 0; free_inodes = 0; group_free = 0;
9459                 dirs_count = 0; group = 0;
9460                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9461                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9462                 goto redo_counts;
9463         } else if (fixit == 0)
9464                 ext2fs_unmark_valid(fs);
9465
9466         for (i = 0; i < fs->group_desc_count; i++) {
9467                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9468                         pctx.group = i;
9469                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9470                         pctx.ino2 = free_array[i];
9471                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9472                                         &pctx)) {
9473                                 fs->group_desc[i].bg_free_inodes_count =
9474                                         free_array[i];
9475                                 ext2fs_mark_super_dirty(fs);
9476                         } else
9477                                 ext2fs_unmark_valid(fs);
9478                 }
9479                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9480                         pctx.group = i;
9481                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9482                         pctx.ino2 = dir_array[i];
9483
9484                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9485                                         &pctx)) {
9486                                 fs->group_desc[i].bg_used_dirs_count =
9487                                         dir_array[i];
9488                                 ext2fs_mark_super_dirty(fs);
9489                         } else
9490                                 ext2fs_unmark_valid(fs);
9491                 }
9492         }
9493         if (free_inodes != fs->super->s_free_inodes_count) {
9494                 pctx.group = -1;
9495                 pctx.ino = fs->super->s_free_inodes_count;
9496                 pctx.ino2 = free_inodes;
9497
9498                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9499                         fs->super->s_free_inodes_count = free_inodes;
9500                         ext2fs_mark_super_dirty(fs);
9501                 } else
9502                         ext2fs_unmark_valid(fs);
9503         }
9504         ext2fs_free_mem(&free_array);
9505         ext2fs_free_mem(&dir_array);
9506 }
9507
9508 static void check_inode_end(e2fsck_t ctx)
9509 {
9510         ext2_filsys fs = ctx->fs;
9511         ext2_ino_t      end, save_inodes_count, i;
9512         struct problem_context  pctx;
9513
9514         clear_problem_context(&pctx);
9515
9516         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9517         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9518                                                      &save_inodes_count);
9519         if (pctx.errcode) {
9520                 pctx.num = 1;
9521                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9522                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9523                 return;
9524         }
9525         if (save_inodes_count == end)
9526                 return;
9527
9528         for (i = save_inodes_count + 1; i <= end; i++) {
9529                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9530                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9531                                 for (i = save_inodes_count + 1; i <= end; i++)
9532                                         ext2fs_mark_inode_bitmap(fs->inode_map,
9533                                                                  i);
9534                                 ext2fs_mark_ib_dirty(fs);
9535                         } else
9536                                 ext2fs_unmark_valid(fs);
9537                         break;
9538                 }
9539         }
9540
9541         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9542                                                      save_inodes_count, 0);
9543         if (pctx.errcode) {
9544                 pctx.num = 2;
9545                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9546                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9547                 return;
9548         }
9549 }
9550
9551 static void check_block_end(e2fsck_t ctx)
9552 {
9553         ext2_filsys fs = ctx->fs;
9554         blk_t   end, save_blocks_count, i;
9555         struct problem_context  pctx;
9556
9557         clear_problem_context(&pctx);
9558
9559         end = fs->block_map->start +
9560                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9561         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9562                                                      &save_blocks_count);
9563         if (pctx.errcode) {
9564                 pctx.num = 3;
9565                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9566                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9567                 return;
9568         }
9569         if (save_blocks_count == end)
9570                 return;
9571
9572         for (i = save_blocks_count + 1; i <= end; i++) {
9573                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9574                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9575                                 for (i = save_blocks_count + 1; i <= end; i++)
9576                                         ext2fs_mark_block_bitmap(fs->block_map,
9577                                                                  i);
9578                                 ext2fs_mark_bb_dirty(fs);
9579                         } else
9580                                 ext2fs_unmark_valid(fs);
9581                         break;
9582                 }
9583         }
9584
9585         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9586                                                      save_blocks_count, 0);
9587         if (pctx.errcode) {
9588                 pctx.num = 4;
9589                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9590                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9591                 return;
9592         }
9593 }
9594
9595 static void e2fsck_pass5(e2fsck_t ctx)
9596 {
9597 #ifdef RESOURCE_TRACK
9598         struct resource_track   rtrack;
9599 #endif
9600         struct problem_context  pctx;
9601
9602 #ifdef MTRACE
9603         mtrace_print("Pass 5");
9604 #endif
9605
9606 #ifdef RESOURCE_TRACK
9607         init_resource_track(&rtrack);
9608 #endif
9609
9610         clear_problem_context(&pctx);
9611
9612         if (!(ctx->options & E2F_OPT_PREEN))
9613                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9614
9615         if (ctx->progress)
9616                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9617                         return;
9618
9619         e2fsck_read_bitmaps(ctx);
9620
9621         check_block_bitmaps(ctx);
9622         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9623                 return;
9624         check_inode_bitmaps(ctx);
9625         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9626                 return;
9627         check_inode_end(ctx);
9628         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9629                 return;
9630         check_block_end(ctx);
9631         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9632                 return;
9633
9634         ext2fs_free_inode_bitmap(ctx->inode_used_map);
9635         ctx->inode_used_map = 0;
9636         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9637         ctx->inode_dir_map = 0;
9638         ext2fs_free_block_bitmap(ctx->block_found_map);
9639         ctx->block_found_map = 0;
9640
9641 #ifdef RESOURCE_TRACK
9642         if (ctx->options & E2F_OPT_TIME2) {
9643                 e2fsck_clear_progbar(ctx);
9644                 print_resource_track(_("Pass 5"), &rtrack);
9645         }
9646 #endif
9647 }
9648
9649 /*
9650  * problem.c --- report filesystem problems to the user
9651  */
9652
9653 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
9654 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
9655 #define PR_NO_DEFAULT   0x000004 /* Default to no */
9656 #define PR_MSG_ONLY     0x000008 /* Print message only */
9657
9658 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
9659
9660 #define PR_FATAL        0x001000 /* Fatal error */
9661 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
9662                                  /* ask another */
9663 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
9664 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
9665 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
9666 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
9667 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
9668
9669
9670 #define PROMPT_NONE     0
9671 #define PROMPT_FIX      1
9672 #define PROMPT_CLEAR    2
9673 #define PROMPT_RELOCATE 3
9674 #define PROMPT_ALLOCATE 4
9675 #define PROMPT_EXPAND   5
9676 #define PROMPT_CONNECT  6
9677 #define PROMPT_CREATE   7
9678 #define PROMPT_SALVAGE  8
9679 #define PROMPT_TRUNCATE 9
9680 #define PROMPT_CLEAR_INODE 10
9681 #define PROMPT_ABORT    11
9682 #define PROMPT_SPLIT    12
9683 #define PROMPT_CONTINUE 13
9684 #define PROMPT_CLONE    14
9685 #define PROMPT_DELETE   15
9686 #define PROMPT_SUPPRESS 16
9687 #define PROMPT_UNLINK   17
9688 #define PROMPT_CLEAR_HTREE 18
9689 #define PROMPT_RECREATE 19
9690 #define PROMPT_NULL     20
9691
9692 struct e2fsck_problem {
9693         problem_t       e2p_code;
9694         const char *    e2p_description;
9695         char            prompt;
9696         int             flags;
9697         problem_t       second_code;
9698 };
9699
9700 struct latch_descr {
9701         int             latch_code;
9702         problem_t       question;
9703         problem_t       end_message;
9704         int             flags;
9705 };
9706
9707 /*
9708  * These are the prompts which are used to ask the user if they want
9709  * to fix a problem.
9710  */
9711 static const char * const prompt[] = {
9712         N_("(no prompt)"),      /* 0 */
9713         N_("Fix"),              /* 1 */
9714         N_("Clear"),            /* 2 */
9715         N_("Relocate"),         /* 3 */
9716         N_("Allocate"),         /* 4 */
9717         N_("Expand"),           /* 5 */
9718         N_("Connect to /lost+found"), /* 6 */
9719         N_("Create"),           /* 7 */
9720         N_("Salvage"),          /* 8 */
9721         N_("Truncate"),         /* 9 */
9722         N_("Clear inode"),      /* 10 */
9723         N_("Abort"),            /* 11 */
9724         N_("Split"),            /* 12 */
9725         N_("Continue"),         /* 13 */
9726         N_("Clone multiply-claimed blocks"), /* 14 */
9727         N_("Delete file"),      /* 15 */
9728         N_("Suppress messages"),/* 16 */
9729         N_("Unlink"),           /* 17 */
9730         N_("Clear HTree index"),/* 18 */
9731         N_("Recreate"),         /* 19 */
9732         "",                     /* 20 */
9733 };
9734
9735 /*
9736  * These messages are printed when we are preen mode and we will be
9737  * automatically fixing the problem.
9738  */
9739 static const char * const preen_msg[] = {
9740         N_("(NONE)"),           /* 0 */
9741         N_("FIXED"),            /* 1 */
9742         N_("CLEARED"),          /* 2 */
9743         N_("RELOCATED"),        /* 3 */
9744         N_("ALLOCATED"),        /* 4 */
9745         N_("EXPANDED"),         /* 5 */
9746         N_("RECONNECTED"),      /* 6 */
9747         N_("CREATED"),          /* 7 */
9748         N_("SALVAGED"),         /* 8 */
9749         N_("TRUNCATED"),        /* 9 */
9750         N_("INODE CLEARED"),    /* 10 */
9751         N_("ABORTED"),          /* 11 */
9752         N_("SPLIT"),            /* 12 */
9753         N_("CONTINUING"),       /* 13 */
9754         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
9755         N_("FILE DELETED"),     /* 15 */
9756         N_("SUPPRESSED"),       /* 16 */
9757         N_("UNLINKED"),         /* 17 */
9758         N_("HTREE INDEX CLEARED"),/* 18 */
9759         N_("WILL RECREATE"),    /* 19 */
9760         "",                     /* 20 */
9761 };
9762
9763 static const struct e2fsck_problem problem_table[] = {
9764
9765         /* Pre-Pass 1 errors */
9766
9767         /* Block bitmap not in group */
9768         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
9769           PROMPT_RELOCATE, PR_LATCH_RELOC },
9770
9771         /* Inode bitmap not in group */
9772         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
9773           PROMPT_RELOCATE, PR_LATCH_RELOC },
9774
9775         /* Inode table not in group */
9776         { PR_0_ITABLE_NOT_GROUP,
9777           N_("@i table for @g %g is not in @g.  (@b %b)\n"
9778           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
9779           PROMPT_RELOCATE, PR_LATCH_RELOC },
9780
9781         /* Superblock corrupt */
9782         { PR_0_SB_CORRUPT,
9783           N_("\nThe @S could not be read or does not describe a correct ext2\n"
9784           "@f.  If the @v is valid and it really contains an ext2\n"
9785           "@f (and not swap or ufs or something else), then the @S\n"
9786           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
9787           "    e2fsck -b %S <@v>\n\n"),
9788           PROMPT_NONE, PR_FATAL },
9789
9790         /* Filesystem size is wrong */
9791         { PR_0_FS_SIZE_WRONG,
9792           N_("The @f size (according to the @S) is %b @bs\n"
9793           "The physical size of the @v is %c @bs\n"
9794           "Either the @S or the partition table is likely to be corrupt!\n"),
9795           PROMPT_ABORT, 0 },
9796
9797         /* Fragments not supported */
9798         { PR_0_NO_FRAGMENTS,
9799           N_("@S @b_size = %b, fragsize = %c.\n"
9800           "This version of e2fsck does not support fragment sizes different\n"
9801           "from the @b size.\n"),
9802           PROMPT_NONE, PR_FATAL },
9803
9804           /* Bad blocks_per_group */
9805         { PR_0_BLOCKS_PER_GROUP,
9806           N_("@S @bs_per_group = %b, should have been %c\n"),
9807           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
9808
9809         /* Bad first_data_block */
9810         { PR_0_FIRST_DATA_BLOCK,
9811           N_("@S first_data_@b = %b, should have been %c\n"),
9812           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
9813
9814         /* Adding UUID to filesystem */
9815         { PR_0_ADD_UUID,
9816           N_("@f did not have a UUID; generating one.\n\n"),
9817           PROMPT_NONE, 0 },
9818
9819         /* Relocate hint */
9820         { PR_0_RELOCATE_HINT,
9821           N_("Note: if several inode or block bitmap blocks or part\n"
9822           "of the inode table require relocation, you may wish to try\n"
9823           "running e2fsck with the '-b %S' option first.  The problem\n"
9824           "may lie only with the primary block group descriptors, and\n"
9825           "the backup block group descriptors may be OK.\n\n"),
9826           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
9827
9828         /* Miscellaneous superblock corruption */
9829         { PR_0_MISC_CORRUPT_SUPER,
9830           N_("Corruption found in @S.  (%s = %N).\n"),
9831           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
9832
9833         /* Error determing physical device size of filesystem */
9834         { PR_0_GETSIZE_ERROR,
9835           N_("Error determining size of the physical @v: %m\n"),
9836           PROMPT_NONE, PR_FATAL },
9837
9838         /* Inode count in superblock is incorrect */
9839         { PR_0_INODE_COUNT_WRONG,
9840           N_("@i count in @S is %i, @s %j.\n"),
9841           PROMPT_FIX, 0 },
9842
9843         { PR_0_HURD_CLEAR_FILETYPE,
9844           N_("The Hurd does not support the filetype feature.\n"),
9845           PROMPT_CLEAR, 0 },
9846
9847         /* Journal inode is invalid */
9848         { PR_0_JOURNAL_BAD_INODE,
9849           N_("@S has an @n ext3 @j (@i %i).\n"),
9850           PROMPT_CLEAR, PR_PREEN_OK },
9851
9852         /* The external journal has (unsupported) multiple filesystems */
9853         { PR_0_JOURNAL_UNSUPP_MULTIFS,
9854           N_("External @j has multiple @f users (unsupported).\n"),
9855           PROMPT_NONE, PR_FATAL },
9856
9857         /* Can't find external journal */
9858         { PR_0_CANT_FIND_JOURNAL,
9859           N_("Can't find external @j\n"),
9860           PROMPT_NONE, PR_FATAL },
9861
9862         /* External journal has bad superblock */
9863         { PR_0_EXT_JOURNAL_BAD_SUPER,
9864           N_("External @j has bad @S\n"),
9865           PROMPT_NONE, PR_FATAL },
9866
9867         /* Superblock has a bad journal UUID */
9868         { PR_0_JOURNAL_BAD_UUID,
9869           N_("External @j does not support this @f\n"),
9870           PROMPT_NONE, PR_FATAL },
9871
9872         /* Journal has an unknown superblock type */
9873         { PR_0_JOURNAL_UNSUPP_SUPER,
9874           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
9875              "It is likely that your copy of e2fsck is old and/or doesn't "
9876              "support this @j format.\n"
9877              "It is also possible the @j @S is corrupt.\n"),
9878           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
9879
9880         /* Journal superblock is corrupt */
9881         { PR_0_JOURNAL_BAD_SUPER,
9882           N_("Ext3 @j @S is corrupt.\n"),
9883           PROMPT_FIX, PR_PREEN_OK },
9884
9885         /* Superblock flag should be cleared */
9886         { PR_0_JOURNAL_HAS_JOURNAL,
9887           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
9888           PROMPT_CLEAR, PR_PREEN_OK },
9889
9890         /* Superblock flag is incorrect */
9891         { PR_0_JOURNAL_RECOVER_SET,
9892           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
9893           PROMPT_CLEAR, PR_PREEN_OK },
9894
9895         /* Journal has data, but recovery flag is clear */
9896         { PR_0_JOURNAL_RECOVERY_CLEAR,
9897           N_("ext3 recovery flag is clear, but @j has data.\n"),
9898           PROMPT_NONE, 0 },
9899
9900         /* Ask if we should clear the journal */
9901         { PR_0_JOURNAL_RESET_JOURNAL,
9902           N_("Clear @j"),
9903           PROMPT_NULL, PR_PREEN_NOMSG },
9904
9905         /* Ask if we should run the journal anyway */
9906         { PR_0_JOURNAL_RUN,
9907           N_("Run @j anyway"),
9908           PROMPT_NULL, 0 },
9909
9910         /* Run the journal by default */
9911         { PR_0_JOURNAL_RUN_DEFAULT,
9912           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
9913           PROMPT_NONE, 0 },
9914
9915         /* Clearing orphan inode */
9916         { PR_0_ORPHAN_CLEAR_INODE,
9917           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
9918           PROMPT_NONE, 0 },
9919
9920         /* Illegal block found in orphaned inode */
9921         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
9922            N_("@I @b #%B (%b) found in @o @i %i.\n"),
9923           PROMPT_NONE, 0 },
9924
9925         /* Already cleared block found in orphaned inode */
9926         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
9927            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
9928           PROMPT_NONE, 0 },
9929
9930         /* Illegal orphan inode in superblock */
9931         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
9932           N_("@I @o @i %i in @S.\n"),
9933           PROMPT_NONE, 0 },
9934
9935         /* Illegal inode in orphaned inode list */
9936         { PR_0_ORPHAN_ILLEGAL_INODE,
9937           N_("@I @i %i in @o @i list.\n"),
9938           PROMPT_NONE, 0 },
9939
9940         /* Filesystem revision is 0, but feature flags are set */
9941         { PR_0_FS_REV_LEVEL,
9942           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
9943           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
9944
9945         /* Journal superblock has an unknown read-only feature flag set */
9946         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
9947           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
9948           PROMPT_ABORT, 0 },
9949
9950         /* Journal superblock has an unknown incompatible feature flag set */
9951         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
9952           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
9953           PROMPT_ABORT, 0 },
9954
9955         /* Journal has unsupported version number */
9956         { PR_0_JOURNAL_UNSUPP_VERSION,
9957           N_("@j version not supported by this e2fsck.\n"),
9958           PROMPT_ABORT, 0 },
9959
9960         /* Moving journal to hidden file */
9961         { PR_0_MOVE_JOURNAL,
9962           N_("Moving @j from /%s to hidden @i.\n\n"),
9963           PROMPT_NONE, 0 },
9964
9965         /* Error moving journal to hidden file */
9966         { PR_0_ERR_MOVE_JOURNAL,
9967           N_("Error moving @j: %m\n\n"),
9968           PROMPT_NONE, 0 },
9969
9970         /* Clearing V2 journal superblock */
9971         { PR_0_CLEAR_V2_JOURNAL,
9972           N_("Found @n V2 @j @S fields (from V1 @j).\n"
9973              "Clearing fields beyond the V1 @j @S...\n\n"),
9974           PROMPT_NONE, 0 },
9975
9976         /* Backup journal inode blocks */
9977         { PR_0_BACKUP_JNL,
9978           N_("Backing up @j @i @b information.\n\n"),
9979           PROMPT_NONE, 0 },
9980
9981         /* Reserved blocks w/o resize_inode */
9982         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
9983           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
9984              "is %N; @s zero.  "),
9985           PROMPT_FIX, 0 },
9986
9987         /* Resize_inode not enabled, but resize inode is non-zero */
9988         { PR_0_CLEAR_RESIZE_INODE,
9989           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
9990           PROMPT_CLEAR, 0 },
9991
9992         /* Resize inode invalid */
9993         { PR_0_RESIZE_INODE_INVALID,
9994           N_("Resize @i not valid.  "),
9995           PROMPT_RECREATE, 0 },
9996
9997         /* Pass 1 errors */
9998
9999         /* Pass 1: Checking inodes, blocks, and sizes */
10000         { PR_1_PASS_HEADER,
10001           N_("Pass 1: Checking @is, @bs, and sizes\n"),
10002           PROMPT_NONE, 0 },
10003
10004         /* Root directory is not an inode */
10005         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
10006           PROMPT_CLEAR, 0 },
10007
10008         /* Root directory has dtime set */
10009         { PR_1_ROOT_DTIME,
10010           N_("@r has dtime set (probably due to old mke2fs).  "),
10011           PROMPT_FIX, PR_PREEN_OK },
10012
10013         /* Reserved inode has bad mode */
10014         { PR_1_RESERVED_BAD_MODE,
10015           N_("Reserved @i %i (%Q) has @n mode.  "),
10016           PROMPT_CLEAR, PR_PREEN_OK },
10017
10018         /* Deleted inode has zero dtime */
10019         { PR_1_ZERO_DTIME,
10020           N_("@D @i %i has zero dtime.  "),
10021           PROMPT_FIX, PR_PREEN_OK },
10022
10023         /* Inode in use, but dtime set */
10024         { PR_1_SET_DTIME,
10025           N_("@i %i is in use, but has dtime set.  "),
10026           PROMPT_FIX, PR_PREEN_OK },
10027
10028         /* Zero-length directory */
10029         { PR_1_ZERO_LENGTH_DIR,
10030           N_("@i %i is a @z @d.  "),
10031           PROMPT_CLEAR, PR_PREEN_OK },
10032
10033         /* Block bitmap conflicts with some other fs block */
10034         { PR_1_BB_CONFLICT,
10035           N_("@g %g's @b @B at %b @C.\n"),
10036           PROMPT_RELOCATE, 0 },
10037
10038         /* Inode bitmap conflicts with some other fs block */
10039         { PR_1_IB_CONFLICT,
10040           N_("@g %g's @i @B at %b @C.\n"),
10041           PROMPT_RELOCATE, 0 },
10042
10043         /* Inode table conflicts with some other fs block */
10044         { PR_1_ITABLE_CONFLICT,
10045           N_("@g %g's @i table at %b @C.\n"),
10046           PROMPT_RELOCATE, 0 },
10047
10048         /* Block bitmap is on a bad block */
10049         { PR_1_BB_BAD_BLOCK,
10050           N_("@g %g's @b @B (%b) is bad.  "),
10051           PROMPT_RELOCATE, 0 },
10052
10053         /* Inode bitmap is on a bad block */
10054         { PR_1_IB_BAD_BLOCK,
10055           N_("@g %g's @i @B (%b) is bad.  "),
10056           PROMPT_RELOCATE, 0 },
10057
10058         /* Inode has incorrect i_size */
10059         { PR_1_BAD_I_SIZE,
10060           N_("@i %i, i_size is %Is, @s %N.  "),
10061           PROMPT_FIX, PR_PREEN_OK },
10062
10063         /* Inode has incorrect i_blocks */
10064         { PR_1_BAD_I_BLOCKS,
10065           N_("@i %i, i_@bs is %Ib, @s %N.  "),
10066           PROMPT_FIX, PR_PREEN_OK },
10067
10068         /* Illegal blocknumber in inode */
10069         { PR_1_ILLEGAL_BLOCK_NUM,
10070           N_("@I @b #%B (%b) in @i %i.  "),
10071           PROMPT_CLEAR, PR_LATCH_BLOCK },
10072
10073         /* Block number overlaps fs metadata */
10074         { PR_1_BLOCK_OVERLAPS_METADATA,
10075           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
10076           PROMPT_CLEAR, PR_LATCH_BLOCK },
10077
10078         /* Inode has illegal blocks (latch question) */
10079         { PR_1_INODE_BLOCK_LATCH,
10080           N_("@i %i has illegal @b(s).  "),
10081           PROMPT_CLEAR, 0 },
10082
10083         /* Too many bad blocks in inode */
10084         { PR_1_TOO_MANY_BAD_BLOCKS,
10085           N_("Too many illegal @bs in @i %i.\n"),
10086           PROMPT_CLEAR_INODE, PR_NO_OK },
10087
10088         /* Illegal block number in bad block inode */
10089         { PR_1_BB_ILLEGAL_BLOCK_NUM,
10090           N_("@I @b #%B (%b) in bad @b @i.  "),
10091           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10092
10093         /* Bad block inode has illegal blocks (latch question) */
10094         { PR_1_INODE_BBLOCK_LATCH,
10095           N_("Bad @b @i has illegal @b(s).  "),
10096           PROMPT_CLEAR, 0 },
10097
10098         /* Duplicate or bad blocks in use! */
10099         { PR_1_DUP_BLOCKS_PREENSTOP,
10100           N_("Duplicate or bad @b in use!\n"),
10101           PROMPT_NONE, 0 },
10102
10103         /* Bad block used as bad block indirect block */
10104         { PR_1_BBINODE_BAD_METABLOCK,
10105           N_("Bad @b %b used as bad @b @i indirect @b.  "),
10106           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10107
10108         /* Inconsistency can't be fixed prompt */
10109         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10110           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
10111              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10112              "in the @f.\n"),
10113           PROMPT_CONTINUE, PR_PREEN_NOMSG },
10114
10115         /* Bad primary block */
10116         { PR_1_BAD_PRIMARY_BLOCK,
10117           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10118           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10119
10120         /* Bad primary block prompt */
10121         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10122           N_("You can remove this @b from the bad @b list and hope\n"
10123              "that the @b is really OK.  But there are no guarantees.\n\n"),
10124           PROMPT_CLEAR, PR_PREEN_NOMSG },
10125
10126         /* Bad primary superblock */
10127         { PR_1_BAD_PRIMARY_SUPERBLOCK,
10128           N_("The primary @S (%b) is on the bad @b list.\n"),
10129           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10130
10131         /* Bad primary block group descriptors */
10132         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10133           N_("Block %b in the primary @g descriptors "
10134           "is on the bad @b list\n"),
10135           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10136
10137         /* Bad superblock in group */
10138         { PR_1_BAD_SUPERBLOCK,
10139           N_("Warning: Group %g's @S (%b) is bad.\n"),
10140           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10141
10142         /* Bad block group descriptors in group */
10143         { PR_1_BAD_GROUP_DESCRIPTORS,
10144           N_("Warning: Group %g's copy of the @g descriptors has a bad "
10145           "@b (%b).\n"),
10146           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10147
10148         /* Block claimed for no reason */
10149         { PR_1_PROGERR_CLAIMED_BLOCK,
10150           N_("Programming error?  @b #%b claimed for no reason in "
10151           "process_bad_@b.\n"),
10152           PROMPT_NONE, PR_PREEN_OK },
10153
10154         /* Error allocating blocks for relocating metadata */
10155         { PR_1_RELOC_BLOCK_ALLOCATE,
10156           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10157           PROMPT_NONE, PR_PREEN_OK },
10158
10159         /* Error allocating block buffer during relocation process */
10160         { PR_1_RELOC_MEMORY_ALLOCATE,
10161           N_("@A @b buffer for relocating %s\n"),
10162           PROMPT_NONE, PR_PREEN_OK },
10163
10164         /* Relocating metadata group information from X to Y */
10165         { PR_1_RELOC_FROM_TO,
10166           N_("Relocating @g %g's %s from %b to %c...\n"),
10167           PROMPT_NONE, PR_PREEN_OK },
10168
10169         /* Relocating metatdata group information to X */
10170         { PR_1_RELOC_TO,
10171           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10172           PROMPT_NONE, PR_PREEN_OK },
10173
10174         /* Block read error during relocation process */
10175         { PR_1_RELOC_READ_ERR,
10176           N_("Warning: could not read @b %b of %s: %m\n"),
10177           PROMPT_NONE, PR_PREEN_OK },
10178
10179         /* Block write error during relocation process */
10180         { PR_1_RELOC_WRITE_ERR,
10181           N_("Warning: could not write @b %b for %s: %m\n"),
10182           PROMPT_NONE, PR_PREEN_OK },
10183
10184         /* Error allocating inode bitmap */
10185         { PR_1_ALLOCATE_IBITMAP_ERROR,
10186           N_("@A @i @B (%N): %m\n"),
10187           PROMPT_NONE, PR_FATAL },
10188
10189         /* Error allocating block bitmap */
10190         { PR_1_ALLOCATE_BBITMAP_ERROR,
10191           N_("@A @b @B (%N): %m\n"),
10192           PROMPT_NONE, PR_FATAL },
10193
10194         /* Error allocating icount structure */
10195         { PR_1_ALLOCATE_ICOUNT,
10196           N_("@A icount link information: %m\n"),
10197           PROMPT_NONE, PR_FATAL },
10198
10199         /* Error allocating dbcount */
10200         { PR_1_ALLOCATE_DBCOUNT,
10201           N_("@A @d @b array: %m\n"),
10202           PROMPT_NONE, PR_FATAL },
10203
10204         /* Error while scanning inodes */
10205         { PR_1_ISCAN_ERROR,
10206           N_("Error while scanning @is (%i): %m\n"),
10207           PROMPT_NONE, PR_FATAL },
10208
10209         /* Error while iterating over blocks */
10210         { PR_1_BLOCK_ITERATE,
10211           N_("Error while iterating over @bs in @i %i: %m\n"),
10212           PROMPT_NONE, PR_FATAL },
10213
10214         /* Error while storing inode count information */
10215         { PR_1_ICOUNT_STORE,
10216           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10217           PROMPT_NONE, PR_FATAL },
10218
10219         /* Error while storing directory block information */
10220         { PR_1_ADD_DBLOCK,
10221           N_("Error storing @d @b information "
10222           "(@i=%i, @b=%b, num=%N): %m\n"),
10223           PROMPT_NONE, PR_FATAL },
10224
10225         /* Error while reading inode (for clearing) */
10226         { PR_1_READ_INODE,
10227           N_("Error reading @i %i: %m\n"),
10228           PROMPT_NONE, PR_FATAL },
10229
10230         /* Suppress messages prompt */
10231         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10232
10233         /* Imagic flag set on an inode when filesystem doesn't support it */
10234         { PR_1_SET_IMAGIC,
10235           N_("@i %i has imagic flag set.  "),
10236           PROMPT_CLEAR, 0 },
10237
10238         /* Immutable flag set on a device or socket inode */
10239         { PR_1_SET_IMMUTABLE,
10240           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10241              "or append-only flag set.  "),
10242           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10243
10244         /* Compression flag set on an inode when filesystem doesn't support it */
10245         { PR_1_COMPR_SET,
10246           N_("@i %i has @cion flag set on @f without @cion support.  "),
10247           PROMPT_CLEAR, 0 },
10248
10249         /* Non-zero size for device, fifo or socket inode */
10250         { PR_1_SET_NONZSIZE,
10251           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
10252           PROMPT_FIX, PR_PREEN_OK },
10253
10254         /* Filesystem revision is 0, but feature flags are set */
10255         { PR_1_FS_REV_LEVEL,
10256           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
10257           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10258
10259         /* Journal inode is not in use, but contains data */
10260         { PR_1_JOURNAL_INODE_NOT_CLEAR,
10261           N_("@j @i is not in use, but contains data.  "),
10262           PROMPT_CLEAR, PR_PREEN_OK },
10263
10264         /* Journal has bad mode */
10265         { PR_1_JOURNAL_BAD_MODE,
10266           N_("@j is not regular file.  "),
10267           PROMPT_FIX, PR_PREEN_OK },
10268
10269         /* Deal with inodes that were part of orphan linked list */
10270         { PR_1_LOW_DTIME,
10271           N_("@i %i was part of the @o @i list.  "),
10272           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10273
10274         /* Deal with inodes that were part of corrupted orphan linked
10275            list (latch question) */
10276         { PR_1_ORPHAN_LIST_REFUGEES,
10277           N_("@is that were part of a corrupted orphan linked list found.  "),
10278           PROMPT_FIX, 0 },
10279
10280         /* Error allocating refcount structure */
10281         { PR_1_ALLOCATE_REFCOUNT,
10282           N_("@A refcount structure (%N): %m\n"),
10283           PROMPT_NONE, PR_FATAL },
10284
10285         /* Error reading extended attribute block */
10286         { PR_1_READ_EA_BLOCK,
10287           N_("Error reading @a @b %b for @i %i.  "),
10288           PROMPT_CLEAR, 0 },
10289
10290         /* Invalid extended attribute block */
10291         { PR_1_BAD_EA_BLOCK,
10292           N_("@i %i has a bad @a @b %b.  "),
10293           PROMPT_CLEAR, 0 },
10294
10295         /* Error reading Extended Attribute block while fixing refcount */
10296         { PR_1_EXTATTR_READ_ABORT,
10297           N_("Error reading @a @b %b (%m).  "),
10298           PROMPT_ABORT, 0 },
10299
10300         /* Extended attribute reference count incorrect */
10301         { PR_1_EXTATTR_REFCOUNT,
10302           N_("@a @b %b has reference count %B, @s %N.  "),
10303           PROMPT_FIX, 0 },
10304
10305         /* Error writing Extended Attribute block while fixing refcount */
10306         { PR_1_EXTATTR_WRITE,
10307           N_("Error writing @a @b %b (%m).  "),
10308           PROMPT_ABORT, 0 },
10309
10310         /* Multiple EA blocks not supported */
10311         { PR_1_EA_MULTI_BLOCK,
10312           N_("@a @b %b has h_@bs > 1.  "),
10313           PROMPT_CLEAR, 0},
10314
10315         /* Error allocating EA region allocation structure */
10316         { PR_1_EA_ALLOC_REGION,
10317           N_("@A @a @b %b.  "),
10318           PROMPT_ABORT, 0},
10319
10320         /* Error EA allocation collision */
10321         { PR_1_EA_ALLOC_COLLISION,
10322           N_("@a @b %b is corrupt (allocation collision).  "),
10323           PROMPT_CLEAR, 0},
10324
10325         /* Bad extended attribute name */
10326         { PR_1_EA_BAD_NAME,
10327           N_("@a @b %b is corrupt (@n name).  "),
10328           PROMPT_CLEAR, 0},
10329
10330         /* Bad extended attribute value */
10331         { PR_1_EA_BAD_VALUE,
10332           N_("@a @b %b is corrupt (@n value).  "),
10333           PROMPT_CLEAR, 0},
10334
10335         /* Inode too big (latch question) */
10336         { PR_1_INODE_TOOBIG,
10337           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
10338
10339         /* Directory too big */
10340         { PR_1_TOOBIG_DIR,
10341           N_("@b #%B (%b) causes @d to be too big.  "),
10342           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10343
10344         /* Regular file too big */
10345         { PR_1_TOOBIG_REG,
10346           N_("@b #%B (%b) causes file to be too big.  "),
10347           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10348
10349         /* Symlink too big */
10350         { PR_1_TOOBIG_SYMLINK,
10351           N_("@b #%B (%b) causes symlink to be too big.  "),
10352           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10353
10354         /* INDEX_FL flag set on a non-HTREE filesystem */
10355         { PR_1_HTREE_SET,
10356           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10357           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10358
10359         /* INDEX_FL flag set on a non-directory */
10360         { PR_1_HTREE_NODIR,
10361           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10362           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10363
10364         /* Invalid root node in HTREE directory */
10365         { PR_1_HTREE_BADROOT,
10366           N_("@h %i has an @n root node.\n"),
10367           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10368
10369         /* Unsupported hash version in HTREE directory */
10370         { PR_1_HTREE_HASHV,
10371           N_("@h %i has an unsupported hash version (%N)\n"),
10372           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10373
10374         /* Incompatible flag in HTREE root node */
10375         { PR_1_HTREE_INCOMPAT,
10376           N_("@h %i uses an incompatible htree root node flag.\n"),
10377           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10378
10379         /* HTREE too deep */
10380         { PR_1_HTREE_DEPTH,
10381           N_("@h %i has a tree depth (%N) which is too big\n"),
10382           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10383
10384         /* Bad block has indirect block that conflicts with filesystem block */
10385         { PR_1_BB_FS_BLOCK,
10386           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10387              "@f metadata.  "),
10388           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10389
10390         /* Resize inode failed */
10391         { PR_1_RESIZE_INODE_CREATE,
10392           N_("Resize @i (re)creation failed: %m."),
10393           PROMPT_ABORT, 0 },
10394
10395         /* invalid inode->i_extra_isize */
10396         { PR_1_EXTRA_ISIZE,
10397           N_("@i %i has a extra size (%IS) which is @n\n"),
10398           PROMPT_FIX, PR_PREEN_OK },
10399
10400         /* invalid ea entry->e_name_len */
10401         { PR_1_ATTR_NAME_LEN,
10402           N_("@a in @i %i has a namelen (%N) which is @n\n"),
10403           PROMPT_CLEAR, PR_PREEN_OK },
10404
10405         /* invalid ea entry->e_value_size */
10406         { PR_1_ATTR_VALUE_SIZE,
10407           N_("@a in @i %i has a value size (%N) which is @n\n"),
10408           PROMPT_CLEAR, PR_PREEN_OK },
10409
10410         /* invalid ea entry->e_value_offs */
10411         { PR_1_ATTR_VALUE_OFFSET,
10412           N_("@a in @i %i has a value offset (%N) which is @n\n"),
10413           PROMPT_CLEAR, PR_PREEN_OK },
10414
10415         /* invalid ea entry->e_value_block */
10416         { PR_1_ATTR_VALUE_BLOCK,
10417           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
10418           PROMPT_CLEAR, PR_PREEN_OK },
10419
10420         /* invalid ea entry->e_hash */
10421         { PR_1_ATTR_HASH,
10422           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
10423           PROMPT_CLEAR, PR_PREEN_OK },
10424
10425         /* Pass 1b errors */
10426
10427         /* Pass 1B: Rescan for duplicate/bad blocks */
10428         { PR_1B_PASS_HEADER,
10429           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
10430           "Pass 1B: Rescanning for @m @bs\n"),
10431           PROMPT_NONE, 0 },
10432
10433         /* Duplicate/bad block(s) header */
10434         { PR_1B_DUP_BLOCK_HEADER,
10435           N_("@m @b(s) in @i %i:"),
10436           PROMPT_NONE, 0 },
10437
10438         /* Duplicate/bad block(s) in inode */
10439         { PR_1B_DUP_BLOCK,
10440           " %b",
10441           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10442
10443         /* Duplicate/bad block(s) end */
10444         { PR_1B_DUP_BLOCK_END,
10445           "\n",
10446           PROMPT_NONE, PR_PREEN_NOHDR },
10447
10448         /* Error while scanning inodes */
10449         { PR_1B_ISCAN_ERROR,
10450           N_("Error while scanning inodes (%i): %m\n"),
10451           PROMPT_NONE, PR_FATAL },
10452
10453         /* Error allocating inode bitmap */
10454         { PR_1B_ALLOCATE_IBITMAP_ERROR,
10455           N_("@A @i @B (@i_dup_map): %m\n"),
10456           PROMPT_NONE, PR_FATAL },
10457
10458         /* Error while iterating over blocks */
10459         { PR_1B_BLOCK_ITERATE,
10460           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10461           PROMPT_NONE, 0 },
10462
10463         /* Error adjusting EA refcount */
10464         { PR_1B_ADJ_EA_REFCOUNT,
10465           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
10466           PROMPT_NONE, 0 },
10467
10468
10469         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
10470         { PR_1C_PASS_HEADER,
10471           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
10472           PROMPT_NONE, 0 },
10473
10474
10475         /* Pass 1D: Reconciling multiply-claimed blocks */
10476         { PR_1D_PASS_HEADER,
10477           N_("Pass 1D: Reconciling @m @bs\n"),
10478           PROMPT_NONE, 0 },
10479
10480         /* File has duplicate blocks */
10481         { PR_1D_DUP_FILE,
10482           N_("File %Q (@i #%i, mod time %IM) \n"
10483           "  has %B @m @b(s), shared with %N file(s):\n"),
10484           PROMPT_NONE, 0 },
10485
10486         /* List of files sharing duplicate blocks */
10487         { PR_1D_DUP_FILE_LIST,
10488           N_("\t%Q (@i #%i, mod time %IM)\n"),
10489           PROMPT_NONE, 0 },
10490
10491         /* File sharing blocks with filesystem metadata  */
10492         { PR_1D_SHARE_METADATA,
10493           N_("\t<@f metadata>\n"),
10494           PROMPT_NONE, 0 },
10495
10496         /* Report of how many duplicate/bad inodes */
10497         { PR_1D_NUM_DUP_INODES,
10498           N_("(There are %N @is containing @m @bs.)\n\n"),
10499           PROMPT_NONE, 0 },
10500
10501         /* Duplicated blocks already reassigned or cloned. */
10502         { PR_1D_DUP_BLOCKS_DEALT,
10503           N_("@m @bs already reassigned or cloned.\n\n"),
10504           PROMPT_NONE, 0 },
10505
10506         /* Clone duplicate/bad blocks? */
10507         { PR_1D_CLONE_QUESTION,
10508           "", PROMPT_CLONE, PR_NO_OK },
10509
10510         /* Delete file? */
10511         { PR_1D_DELETE_QUESTION,
10512           "", PROMPT_DELETE, 0 },
10513
10514         /* Couldn't clone file (error) */
10515         { PR_1D_CLONE_ERROR,
10516           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10517
10518         /* Pass 2 errors */
10519
10520         /* Pass 2: Checking directory structure */
10521         { PR_2_PASS_HEADER,
10522           N_("Pass 2: Checking @d structure\n"),
10523           PROMPT_NONE, 0 },
10524
10525         /* Bad inode number for '.' */
10526         { PR_2_BAD_INODE_DOT,
10527           N_("@n @i number for '.' in @d @i %i.\n"),
10528           PROMPT_FIX, 0 },
10529
10530         /* Directory entry has bad inode number */
10531         { PR_2_BAD_INO,
10532           N_("@E has @n @i #: %Di.\n"),
10533           PROMPT_CLEAR, 0 },
10534
10535         /* Directory entry has deleted or unused inode */
10536         { PR_2_UNUSED_INODE,
10537           N_("@E has @D/unused @i %Di.  "),
10538           PROMPT_CLEAR, PR_PREEN_OK },
10539
10540         /* Directry entry is link to '.' */
10541         { PR_2_LINK_DOT,
10542           N_("@E @L to '.'  "),
10543           PROMPT_CLEAR, 0 },
10544
10545         /* Directory entry points to inode now located in a bad block */
10546         { PR_2_BB_INODE,
10547           N_("@E points to @i (%Di) located in a bad @b.\n"),
10548           PROMPT_CLEAR, 0 },
10549
10550         /* Directory entry contains a link to a directory */
10551         { PR_2_LINK_DIR,
10552           N_("@E @L to @d %P (%Di).\n"),
10553           PROMPT_CLEAR, 0 },
10554
10555         /* Directory entry contains a link to the root directry */
10556         { PR_2_LINK_ROOT,
10557           N_("@E @L to the @r.\n"),
10558           PROMPT_CLEAR, 0 },
10559
10560         /* Directory entry has illegal characters in its name */
10561         { PR_2_BAD_NAME,
10562           N_("@E has illegal characters in its name.\n"),
10563           PROMPT_FIX, 0 },
10564
10565         /* Missing '.' in directory inode */
10566         { PR_2_MISSING_DOT,
10567           N_("Missing '.' in @d @i %i.\n"),
10568           PROMPT_FIX, 0 },
10569
10570         /* Missing '..' in directory inode */
10571         { PR_2_MISSING_DOT_DOT,
10572           N_("Missing '..' in @d @i %i.\n"),
10573           PROMPT_FIX, 0 },
10574
10575         /* First entry in directory inode doesn't contain '.' */
10576         { PR_2_1ST_NOT_DOT,
10577           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
10578           PROMPT_FIX, 0 },
10579
10580         /* Second entry in directory inode doesn't contain '..' */
10581         { PR_2_2ND_NOT_DOT_DOT,
10582           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
10583           PROMPT_FIX, 0 },
10584
10585         /* i_faddr should be zero */
10586         { PR_2_FADDR_ZERO,
10587           N_("i_faddr @F %IF, @s zero.\n"),
10588           PROMPT_CLEAR, 0 },
10589
10590         /* i_file_acl should be zero */
10591         { PR_2_FILE_ACL_ZERO,
10592           N_("i_file_acl @F %If, @s zero.\n"),
10593           PROMPT_CLEAR, 0 },
10594
10595         /* i_dir_acl should be zero */
10596         { PR_2_DIR_ACL_ZERO,
10597           N_("i_dir_acl @F %Id, @s zero.\n"),
10598           PROMPT_CLEAR, 0 },
10599
10600         /* i_frag should be zero */
10601         { PR_2_FRAG_ZERO,
10602           N_("i_frag @F %N, @s zero.\n"),
10603           PROMPT_CLEAR, 0 },
10604
10605         /* i_fsize should be zero */
10606         { PR_2_FSIZE_ZERO,
10607           N_("i_fsize @F %N, @s zero.\n"),
10608           PROMPT_CLEAR, 0 },
10609
10610         /* inode has bad mode */
10611         { PR_2_BAD_MODE,
10612           N_("@i %i (%Q) has @n mode (%Im).\n"),
10613           PROMPT_CLEAR, 0 },
10614
10615         /* directory corrupted */
10616         { PR_2_DIR_CORRUPTED,
10617           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
10618           PROMPT_SALVAGE, 0 },
10619
10620         /* filename too long */
10621         { PR_2_FILENAME_LONG,
10622           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
10623           PROMPT_TRUNCATE, 0 },
10624
10625         /* Directory inode has a missing block (hole) */
10626         { PR_2_DIRECTORY_HOLE,
10627           N_("@d @i %i has an unallocated @b #%B.  "),
10628           PROMPT_ALLOCATE, 0 },
10629
10630         /* '.' is not NULL terminated */
10631         { PR_2_DOT_NULL_TERM,
10632           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
10633           PROMPT_FIX, 0 },
10634
10635         /* '..' is not NULL terminated */
10636         { PR_2_DOT_DOT_NULL_TERM,
10637           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
10638           PROMPT_FIX, 0 },
10639
10640         /* Illegal character device inode */
10641         { PR_2_BAD_CHAR_DEV,
10642           N_("@i %i (%Q) is an @I character @v.\n"),
10643           PROMPT_CLEAR, 0 },
10644
10645         /* Illegal block device inode */
10646         { PR_2_BAD_BLOCK_DEV,
10647           N_("@i %i (%Q) is an @I @b @v.\n"),
10648           PROMPT_CLEAR, 0 },
10649
10650         /* Duplicate '.' entry */
10651         { PR_2_DUP_DOT,
10652           N_("@E is duplicate '.' @e.\n"),
10653           PROMPT_FIX, 0 },
10654
10655         /* Duplicate '..' entry */
10656         { PR_2_DUP_DOT_DOT,
10657           N_("@E is duplicate '..' @e.\n"),
10658           PROMPT_FIX, 0 },
10659
10660         /* Internal error: couldn't find dir_info */
10661         { PR_2_NO_DIRINFO,
10662           N_("Internal error: couldn't find dir_info for %i.\n"),
10663           PROMPT_NONE, PR_FATAL },
10664
10665         /* Final rec_len is wrong */
10666         { PR_2_FINAL_RECLEN,
10667           N_("@E has rec_len of %Dr, @s %N.\n"),
10668           PROMPT_FIX, 0 },
10669
10670         /* Error allocating icount structure */
10671         { PR_2_ALLOCATE_ICOUNT,
10672           N_("@A icount structure: %m\n"),
10673           PROMPT_NONE, PR_FATAL },
10674
10675         /* Error iterating over directory blocks */
10676         { PR_2_DBLIST_ITERATE,
10677           N_("Error iterating over @d @bs: %m\n"),
10678           PROMPT_NONE, PR_FATAL },
10679
10680         /* Error reading directory block */
10681         { PR_2_READ_DIRBLOCK,
10682           N_("Error reading @d @b %b (@i %i): %m\n"),
10683           PROMPT_CONTINUE, 0 },
10684
10685         /* Error writing directory block */
10686         { PR_2_WRITE_DIRBLOCK,
10687           N_("Error writing @d @b %b (@i %i): %m\n"),
10688           PROMPT_CONTINUE, 0 },
10689
10690         /* Error allocating new directory block */
10691         { PR_2_ALLOC_DIRBOCK,
10692           N_("@A new @d @b for @i %i (%s): %m\n"),
10693           PROMPT_NONE, 0 },
10694
10695         /* Error deallocating inode */
10696         { PR_2_DEALLOC_INODE,
10697           N_("Error deallocating @i %i: %m\n"),
10698           PROMPT_NONE, PR_FATAL },
10699
10700         /* Directory entry for '.' is big.  Split? */
10701         { PR_2_SPLIT_DOT,
10702           N_("@d @e for '.' is big.  "),
10703           PROMPT_SPLIT, PR_NO_OK },
10704
10705         /* Illegal FIFO inode */
10706         { PR_2_BAD_FIFO,
10707           N_("@i %i (%Q) is an @I FIFO.\n"),
10708           PROMPT_CLEAR, 0 },
10709
10710         /* Illegal socket inode */
10711         { PR_2_BAD_SOCKET,
10712           N_("@i %i (%Q) is an @I socket.\n"),
10713           PROMPT_CLEAR, 0 },
10714
10715         /* Directory filetype not set */
10716         { PR_2_SET_FILETYPE,
10717           N_("Setting filetype for @E to %N.\n"),
10718           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
10719
10720         /* Directory filetype incorrect */
10721         { PR_2_BAD_FILETYPE,
10722           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
10723           PROMPT_FIX, 0 },
10724
10725         /* Directory filetype set on filesystem */
10726         { PR_2_CLEAR_FILETYPE,
10727           N_("@E has filetype set.\n"),
10728           PROMPT_CLEAR, PR_PREEN_OK },
10729
10730         /* Directory filename is null */
10731         { PR_2_NULL_NAME,
10732           N_("@E has a @z name.\n"),
10733           PROMPT_CLEAR, 0 },
10734
10735         /* Invalid symlink */
10736         { PR_2_INVALID_SYMLINK,
10737           N_("Symlink %Q (@i #%i) is @n.\n"),
10738           PROMPT_CLEAR, 0 },
10739
10740         /* i_file_acl (extended attribute block) is bad */
10741         { PR_2_FILE_ACL_BAD,
10742           N_("@a @b @F @n (%If).\n"),
10743           PROMPT_CLEAR, 0 },
10744
10745         /* Filesystem contains large files, but has no such flag in sb */
10746         { PR_2_FEATURE_LARGE_FILES,
10747           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
10748           PROMPT_FIX, 0 },
10749
10750         /* Node in HTREE directory not referenced */
10751         { PR_2_HTREE_NOTREF,
10752           N_("@p @h %d: node (%B) not referenced\n"),
10753           PROMPT_NONE, 0 },
10754
10755         /* Node in HTREE directory referenced twice */
10756         { PR_2_HTREE_DUPREF,
10757           N_("@p @h %d: node (%B) referenced twice\n"),
10758           PROMPT_NONE, 0 },
10759
10760         /* Node in HTREE directory has bad min hash */
10761         { PR_2_HTREE_MIN_HASH,
10762           N_("@p @h %d: node (%B) has bad min hash\n"),
10763           PROMPT_NONE, 0 },
10764
10765         /* Node in HTREE directory has bad max hash */
10766         { PR_2_HTREE_MAX_HASH,
10767           N_("@p @h %d: node (%B) has bad max hash\n"),
10768           PROMPT_NONE, 0 },
10769
10770         /* Clear invalid HTREE directory */
10771         { PR_2_HTREE_CLEAR,
10772           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
10773
10774         /* Bad block in htree interior node */
10775         { PR_2_HTREE_BADBLK,
10776           N_("@p @h %d (%q): bad @b number %b.\n"),
10777           PROMPT_CLEAR_HTREE, 0 },
10778
10779         /* Error adjusting EA refcount */
10780         { PR_2_ADJ_EA_REFCOUNT,
10781           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
10782           PROMPT_NONE, PR_FATAL },
10783
10784         /* Invalid HTREE root node */
10785         { PR_2_HTREE_BAD_ROOT,
10786           N_("@p @h %d: root node is @n\n"),
10787           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10788
10789         /* Invalid HTREE limit */
10790         { PR_2_HTREE_BAD_LIMIT,
10791           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
10792           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10793
10794         /* Invalid HTREE count */
10795         { PR_2_HTREE_BAD_COUNT,
10796           N_("@p @h %d: node (%B) has @n count (%N)\n"),
10797           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10798
10799         /* HTREE interior node has out-of-order hashes in table */
10800         { PR_2_HTREE_HASH_ORDER,
10801           N_("@p @h %d: node (%B) has an unordered hash table\n"),
10802           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10803
10804         /* Node in HTREE directory has invalid depth */
10805         { PR_2_HTREE_BAD_DEPTH,
10806           N_("@p @h %d: node (%B) has @n depth\n"),
10807           PROMPT_NONE, 0 },
10808
10809         /* Duplicate directory entry found */
10810         { PR_2_DUPLICATE_DIRENT,
10811           N_("Duplicate @E found.  "),
10812           PROMPT_CLEAR, 0 },
10813
10814         /* Non-unique filename found */
10815         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
10816           N_("@E has a non-unique filename.\nRename to %s"),
10817           PROMPT_NULL, 0 },
10818
10819         /* Duplicate directory entry found */
10820         { PR_2_REPORT_DUP_DIRENT,
10821           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
10822           PROMPT_NONE, 0 },
10823
10824         /* Pass 3 errors */
10825
10826         /* Pass 3: Checking directory connectivity */
10827         { PR_3_PASS_HEADER,
10828           N_("Pass 3: Checking @d connectivity\n"),
10829           PROMPT_NONE, 0 },
10830
10831         /* Root inode not allocated */
10832         { PR_3_NO_ROOT_INODE,
10833           N_("@r not allocated.  "),
10834           PROMPT_ALLOCATE, 0 },
10835
10836         /* No room in lost+found */
10837         { PR_3_EXPAND_LF_DIR,
10838           N_("No room in @l @d.  "),
10839           PROMPT_EXPAND, 0 },
10840
10841         /* Unconnected directory inode */
10842         { PR_3_UNCONNECTED_DIR,
10843           N_("Unconnected @d @i %i (%p)\n"),
10844           PROMPT_CONNECT, 0 },
10845
10846         /* /lost+found not found */
10847         { PR_3_NO_LF_DIR,
10848           N_("/@l not found.  "),
10849           PROMPT_CREATE, PR_PREEN_OK },
10850
10851         /* .. entry is incorrect */
10852         { PR_3_BAD_DOT_DOT,
10853           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
10854           PROMPT_FIX, 0 },
10855
10856         /* Bad or non-existent /lost+found.  Cannot reconnect */
10857         { PR_3_NO_LPF,
10858           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
10859           PROMPT_NONE, 0 },
10860
10861         /* Could not expand /lost+found */
10862         { PR_3_CANT_EXPAND_LPF,
10863           N_("Could not expand /@l: %m\n"),
10864           PROMPT_NONE, 0 },
10865
10866         /* Could not reconnect inode */
10867         { PR_3_CANT_RECONNECT,
10868           N_("Could not reconnect %i: %m\n"),
10869           PROMPT_NONE, 0 },
10870
10871         /* Error while trying to find /lost+found */
10872         { PR_3_ERR_FIND_LPF,
10873           N_("Error while trying to find /@l: %m\n"),
10874           PROMPT_NONE, 0 },
10875
10876         /* Error in ext2fs_new_block while creating /lost+found */
10877         { PR_3_ERR_LPF_NEW_BLOCK,
10878           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
10879           PROMPT_NONE, 0 },
10880
10881         /* Error in ext2fs_new_inode while creating /lost+found */
10882         { PR_3_ERR_LPF_NEW_INODE,
10883           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
10884           PROMPT_NONE, 0 },
10885
10886         /* Error in ext2fs_new_dir_block while creating /lost+found */
10887         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
10888           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
10889           PROMPT_NONE, 0 },
10890
10891         /* Error while writing directory block for /lost+found */
10892         { PR_3_ERR_LPF_WRITE_BLOCK,
10893           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
10894           PROMPT_NONE, 0 },
10895
10896         /* Error while adjusting inode count */
10897         { PR_3_ADJUST_INODE,
10898           N_("Error while adjusting @i count on @i %i\n"),
10899           PROMPT_NONE, 0 },
10900
10901         /* Couldn't fix parent directory -- error */
10902         { PR_3_FIX_PARENT_ERR,
10903           N_("Couldn't fix parent of @i %i: %m\n\n"),
10904           PROMPT_NONE, 0 },
10905
10906         /* Couldn't fix parent directory -- couldn't find it */
10907         { PR_3_FIX_PARENT_NOFIND,
10908           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
10909           PROMPT_NONE, 0 },
10910
10911         /* Error allocating inode bitmap */
10912         { PR_3_ALLOCATE_IBITMAP_ERROR,
10913           N_("@A @i @B (%N): %m\n"),
10914           PROMPT_NONE, PR_FATAL },
10915
10916         /* Error creating root directory */
10917         { PR_3_CREATE_ROOT_ERROR,
10918           N_("Error creating root @d (%s): %m\n"),
10919           PROMPT_NONE, PR_FATAL },
10920
10921         /* Error creating lost and found directory */
10922         { PR_3_CREATE_LPF_ERROR,
10923           N_("Error creating /@l @d (%s): %m\n"),
10924           PROMPT_NONE, PR_FATAL },
10925
10926         /* Root inode is not directory; aborting */
10927         { PR_3_ROOT_NOT_DIR_ABORT,
10928           N_("@r is not a @d; aborting.\n"),
10929           PROMPT_NONE, PR_FATAL },
10930
10931         /* Cannot proceed without a root inode. */
10932         { PR_3_NO_ROOT_INODE_ABORT,
10933           N_("Cannot proceed without a @r.\n"),
10934           PROMPT_NONE, PR_FATAL },
10935
10936         /* Internal error: couldn't find dir_info */
10937         { PR_3_NO_DIRINFO,
10938           N_("Internal error: couldn't find dir_info for %i.\n"),
10939           PROMPT_NONE, PR_FATAL },
10940
10941         /* Lost+found not a directory */
10942         { PR_3_LPF_NOTDIR,
10943           N_("/@l is not a @d (ino=%i)\n"),
10944           PROMPT_UNLINK, 0 },
10945
10946         /* Pass 3A Directory Optimization       */
10947
10948         /* Pass 3A: Optimizing directories */
10949         { PR_3A_PASS_HEADER,
10950           N_("Pass 3A: Optimizing directories\n"),
10951           PROMPT_NONE, PR_PREEN_NOMSG },
10952
10953         /* Error iterating over directories */
10954         { PR_3A_OPTIMIZE_ITER,
10955           N_("Failed to create dirs_to_hash iterator: %m"),
10956           PROMPT_NONE, 0 },
10957
10958         /* Error rehash directory */
10959         { PR_3A_OPTIMIZE_DIR_ERR,
10960           N_("Failed to optimize directory %q (%d): %m"),
10961           PROMPT_NONE, 0 },
10962
10963         /* Rehashing dir header */
10964         { PR_3A_OPTIMIZE_DIR_HEADER,
10965           N_("Optimizing directories: "),
10966           PROMPT_NONE, PR_MSG_ONLY },
10967
10968         /* Rehashing directory %d */
10969         { PR_3A_OPTIMIZE_DIR,
10970           " %d",
10971           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
10972
10973         /* Rehashing dir end */
10974         { PR_3A_OPTIMIZE_DIR_END,
10975           "\n",
10976           PROMPT_NONE, PR_PREEN_NOHDR },
10977
10978         /* Pass 4 errors */
10979
10980         /* Pass 4: Checking reference counts */
10981         { PR_4_PASS_HEADER,
10982           N_("Pass 4: Checking reference counts\n"),
10983           PROMPT_NONE, 0 },
10984
10985         /* Unattached zero-length inode */
10986         { PR_4_ZERO_LEN_INODE,
10987           N_("@u @z @i %i.  "),
10988           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
10989
10990         /* Unattached inode */
10991         { PR_4_UNATTACHED_INODE,
10992           N_("@u @i %i\n"),
10993           PROMPT_CONNECT, 0 },
10994
10995         /* Inode ref count wrong */
10996         { PR_4_BAD_REF_COUNT,
10997           N_("@i %i ref count is %Il, @s %N.  "),
10998           PROMPT_FIX, PR_PREEN_OK },
10999
11000         { PR_4_INCONSISTENT_COUNT,
11001           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11002           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11003           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
11004           "They @s the same!\n"),
11005           PROMPT_NONE, 0 },
11006
11007         /* Pass 5 errors */
11008
11009         /* Pass 5: Checking group summary information */
11010         { PR_5_PASS_HEADER,
11011           N_("Pass 5: Checking @g summary information\n"),
11012           PROMPT_NONE, 0 },
11013
11014         /* Padding at end of inode bitmap is not set. */
11015         { PR_5_INODE_BMAP_PADDING,
11016           N_("Padding at end of @i @B is not set. "),
11017           PROMPT_FIX, PR_PREEN_OK },
11018
11019         /* Padding at end of block bitmap is not set. */
11020         { PR_5_BLOCK_BMAP_PADDING,
11021           N_("Padding at end of @b @B is not set. "),
11022           PROMPT_FIX, PR_PREEN_OK },
11023
11024         /* Block bitmap differences header */
11025         { PR_5_BLOCK_BITMAP_HEADER,
11026           N_("@b @B differences: "),
11027           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11028
11029         /* Block not used, but marked in bitmap */
11030         { PR_5_BLOCK_UNUSED,
11031           " -%b",
11032           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11033
11034         /* Block used, but not marked used in bitmap */
11035         { PR_5_BLOCK_USED,
11036           " +%b",
11037           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11038
11039         /* Block bitmap differences end */
11040         { PR_5_BLOCK_BITMAP_END,
11041           "\n",
11042           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11043
11044         /* Inode bitmap differences header */
11045         { PR_5_INODE_BITMAP_HEADER,
11046           N_("@i @B differences: "),
11047           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11048
11049         /* Inode not used, but marked in bitmap */
11050         { PR_5_INODE_UNUSED,
11051           " -%i",
11052           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11053
11054         /* Inode used, but not marked used in bitmap */
11055         { PR_5_INODE_USED,
11056           " +%i",
11057           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11058
11059         /* Inode bitmap differences end */
11060         { PR_5_INODE_BITMAP_END,
11061           "\n",
11062           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11063
11064         /* Free inodes count for group wrong */
11065         { PR_5_FREE_INODE_COUNT_GROUP,
11066           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11067           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11068
11069         /* Directories count for group wrong */
11070         { PR_5_FREE_DIR_COUNT_GROUP,
11071           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11072           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11073
11074         /* Free inodes count wrong */
11075         { PR_5_FREE_INODE_COUNT,
11076           N_("Free @is count wrong (%i, counted=%j).\n"),
11077           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11078
11079         /* Free blocks count for group wrong */
11080         { PR_5_FREE_BLOCK_COUNT_GROUP,
11081           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11082           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11083
11084         /* Free blocks count wrong */
11085         { PR_5_FREE_BLOCK_COUNT,
11086           N_("Free @bs count wrong (%b, counted=%c).\n"),
11087           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11088
11089         /* Programming error: bitmap endpoints don't match */
11090         { PR_5_BMAP_ENDPOINTS,
11091           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11092           "match calculated @B endpoints (%i, %j)\n"),
11093           PROMPT_NONE, PR_FATAL },
11094
11095         /* Internal error: fudging end of bitmap */
11096         { PR_5_FUDGE_BITMAP_ERROR,
11097           N_("Internal error: fudging end of bitmap (%N)\n"),
11098           PROMPT_NONE, PR_FATAL },
11099
11100         /* Error copying in replacement inode bitmap */
11101         { PR_5_COPY_IBITMAP_ERROR,
11102           N_("Error copying in replacement @i @B: %m\n"),
11103           PROMPT_NONE, PR_FATAL },
11104
11105         /* Error copying in replacement block bitmap */
11106         { PR_5_COPY_BBITMAP_ERROR,
11107           N_("Error copying in replacement @b @B: %m\n"),
11108           PROMPT_NONE, PR_FATAL },
11109
11110         /* Block range not used, but marked in bitmap */
11111         { PR_5_BLOCK_RANGE_UNUSED,
11112           " -(%b--%c)",
11113           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11114
11115         /* Block range used, but not marked used in bitmap */
11116         { PR_5_BLOCK_RANGE_USED,
11117           " +(%b--%c)",
11118           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11119
11120         /* Inode range not used, but marked in bitmap */
11121         { PR_5_INODE_RANGE_UNUSED,
11122           " -(%i--%j)",
11123           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11124
11125         /* Inode range used, but not marked used in bitmap */
11126         { PR_5_INODE_RANGE_USED,
11127           " +(%i--%j)",
11128           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11129
11130         { 0 }
11131 };
11132
11133 /*
11134  * This is the latch flags register.  It allows several problems to be
11135  * "latched" together.  This means that the user has to answer but one
11136  * question for the set of problems, and all of the associated
11137  * problems will be either fixed or not fixed.
11138  */
11139 static struct latch_descr pr_latch_info[] = {
11140         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11141         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11142         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11143         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11144         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11145         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11146         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11147         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11148         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11149         { -1, 0, 0 },
11150 };
11151
11152 static const struct e2fsck_problem *find_problem(problem_t code)
11153 {
11154         int     i;
11155
11156         for (i=0; problem_table[i].e2p_code; i++) {
11157                 if (problem_table[i].e2p_code == code)
11158                         return &problem_table[i];
11159         }
11160         return 0;
11161 }
11162
11163 static struct latch_descr *find_latch(int code)
11164 {
11165         int     i;
11166
11167         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11168                 if (pr_latch_info[i].latch_code == code)
11169                         return &pr_latch_info[i];
11170         }
11171         return 0;
11172 }
11173
11174 int end_problem_latch(e2fsck_t ctx, int mask)
11175 {
11176         struct latch_descr *ldesc;
11177         struct problem_context pctx;
11178         int answer = -1;
11179
11180         ldesc = find_latch(mask);
11181         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11182                 clear_problem_context(&pctx);
11183                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11184         }
11185         ldesc->flags &= ~(PRL_VARIABLE);
11186         return answer;
11187 }
11188
11189 int set_latch_flags(int mask, int setflags, int clearflags)
11190 {
11191         struct latch_descr *ldesc;
11192
11193         ldesc = find_latch(mask);
11194         if (!ldesc)
11195                 return -1;
11196         ldesc->flags |= setflags;
11197         ldesc->flags &= ~clearflags;
11198         return 0;
11199 }
11200
11201 void clear_problem_context(struct problem_context *ctx)
11202 {
11203         memset(ctx, 0, sizeof(struct problem_context));
11204         ctx->blkcount = -1;
11205         ctx->group = -1;
11206 }
11207
11208 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11209 {
11210         ext2_filsys fs = ctx->fs;
11211         const struct e2fsck_problem *ptr;
11212         struct latch_descr *ldesc = 0;
11213         const char *message;
11214         int             def_yn, answer, ans;
11215         int             print_answer = 0;
11216         int             suppress = 0;
11217
11218         ptr = find_problem(code);
11219         if (!ptr) {
11220                 printf(_("Unhandled error code (0x%x)!\n"), code);
11221                 return 0;
11222         }
11223         def_yn = 1;
11224         if ((ptr->flags & PR_NO_DEFAULT) ||
11225             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11226             (ctx->options & E2F_OPT_NO))
11227                 def_yn= 0;
11228
11229         /*
11230          * Do special latch processing.  This is where we ask the
11231          * latch question, if it exists
11232          */
11233         if (ptr->flags & PR_LATCH_MASK) {
11234                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11235                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11236                         ans = fix_problem(ctx, ldesc->question, pctx);
11237                         if (ans == 1)
11238                                 ldesc->flags |= PRL_YES;
11239                         if (ans == 0)
11240                                 ldesc->flags |= PRL_NO;
11241                         ldesc->flags |= PRL_LATCHED;
11242                 }
11243                 if (ldesc->flags & PRL_SUPPRESS)
11244                         suppress++;
11245         }
11246         if ((ptr->flags & PR_PREEN_NOMSG) &&
11247             (ctx->options & E2F_OPT_PREEN))
11248                 suppress++;
11249         if ((ptr->flags & PR_NO_NOMSG) &&
11250             (ctx->options & E2F_OPT_NO))
11251                 suppress++;
11252         if (!suppress) {
11253                 message = ptr->e2p_description;
11254                 if ((ctx->options & E2F_OPT_PREEN) &&
11255                     !(ptr->flags & PR_PREEN_NOHDR)) {
11256                         printf("%s: ", ctx->device_name ?
11257                                ctx->device_name : ctx->filesystem_name);
11258                 }
11259                 if (*message)
11260                         print_e2fsck_message(ctx, _(message), pctx, 1);
11261         }
11262         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11263                 preenhalt(ctx);
11264
11265         if (ptr->flags & PR_FATAL)
11266                 fatal_error(ctx, 0);
11267
11268         if (ptr->prompt == PROMPT_NONE) {
11269                 if (ptr->flags & PR_NOCOLLATE)
11270                         answer = -1;
11271                 else
11272                         answer = def_yn;
11273         } else {
11274                 if (ctx->options & E2F_OPT_PREEN) {
11275                         answer = def_yn;
11276                         if (!(ptr->flags & PR_PREEN_NOMSG))
11277                                 print_answer = 1;
11278                 } else if ((ptr->flags & PR_LATCH_MASK) &&
11279                            (ldesc->flags & (PRL_YES | PRL_NO))) {
11280                         if (!suppress)
11281                                 print_answer = 1;
11282                         if (ldesc->flags & PRL_YES)
11283                                 answer = 1;
11284                         else
11285                                 answer = 0;
11286                 } else
11287                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11288                 if (!answer && !(ptr->flags & PR_NO_OK))
11289                         ext2fs_unmark_valid(fs);
11290
11291                 if (print_answer)
11292                         printf("%s.\n", answer ?
11293                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11294
11295         }
11296
11297         if ((ptr->prompt == PROMPT_ABORT) && answer)
11298                 fatal_error(ctx, 0);
11299
11300         if (ptr->flags & PR_AFTER_CODE)
11301                 answer = fix_problem(ctx, ptr->second_code, pctx);
11302
11303         return answer;
11304 }
11305
11306 /*
11307  * linux/fs/recovery.c
11308  *
11309  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11310  */
11311
11312 /*
11313  * Maintain information about the progress of the recovery job, so that
11314  * the different passes can carry information between them.
11315  */
11316 struct recovery_info
11317 {
11318         tid_t           start_transaction;
11319         tid_t           end_transaction;
11320
11321         int             nr_replays;
11322         int             nr_revokes;
11323         int             nr_revoke_hits;
11324 };
11325
11326 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11327 static int do_one_pass(journal_t *journal,
11328                                 struct recovery_info *info, enum passtype pass);
11329 static int scan_revoke_records(journal_t *, struct buffer_head *,
11330                                 tid_t, struct recovery_info *);
11331
11332 /*
11333  * Read a block from the journal
11334  */
11335
11336 static int jread(struct buffer_head **bhp, journal_t *journal,
11337                  unsigned int offset)
11338 {
11339         int err;
11340         unsigned long blocknr;
11341         struct buffer_head *bh;
11342
11343         *bhp = NULL;
11344
11345         err = journal_bmap(journal, offset, &blocknr);
11346
11347         if (err) {
11348                 printf ("JBD: bad block at offset %u\n", offset);
11349                 return err;
11350         }
11351
11352         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11353         if (!bh)
11354                 return -ENOMEM;
11355
11356         if (!buffer_uptodate(bh)) {
11357                 /* If this is a brand new buffer, start readahead.
11358                    Otherwise, we assume we are already reading it.  */
11359                 if (!buffer_req(bh))
11360                         do_readahead(journal, offset);
11361                 wait_on_buffer(bh);
11362         }
11363
11364         if (!buffer_uptodate(bh)) {
11365                 printf ("JBD: Failed to read block at offset %u\n", offset);
11366                 brelse(bh);
11367                 return -EIO;
11368         }
11369
11370         *bhp = bh;
11371         return 0;
11372 }
11373
11374
11375 /*
11376  * Count the number of in-use tags in a journal descriptor block.
11377  */
11378
11379 static int count_tags(struct buffer_head *bh, int size)
11380 {
11381         char *                  tagp;
11382         journal_block_tag_t *   tag;
11383         int                     nr = 0;
11384
11385         tagp = &bh->b_data[sizeof(journal_header_t)];
11386
11387         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11388                 tag = (journal_block_tag_t *) tagp;
11389
11390                 nr++;
11391                 tagp += sizeof(journal_block_tag_t);
11392                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11393                         tagp += 16;
11394
11395                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11396                         break;
11397         }
11398
11399         return nr;
11400 }
11401
11402
11403 /* Make sure we wrap around the log correctly! */
11404 #define wrap(journal, var)                                            \
11405 do {                                                                \
11406         if (var >= (journal)->j_last)                                   \
11407                 var -= ((journal)->j_last - (journal)->j_first);        \
11408 } while (0)
11409
11410 /**
11411  * int journal_recover(journal_t *journal) - recovers a on-disk journal
11412  * @journal: the journal to recover
11413  *
11414  * The primary function for recovering the log contents when mounting a
11415  * journaled device.
11416  *
11417  * Recovery is done in three passes.  In the first pass, we look for the
11418  * end of the log.  In the second, we assemble the list of revoke
11419  * blocks.  In the third and final pass, we replay any un-revoked blocks
11420  * in the log.
11421  */
11422 int journal_recover(journal_t *journal)
11423 {
11424         int                     err;
11425         journal_superblock_t *  sb;
11426
11427         struct recovery_info    info;
11428
11429         memset(&info, 0, sizeof(info));
11430         sb = journal->j_superblock;
11431
11432         /*
11433          * The journal superblock's s_start field (the current log head)
11434          * is always zero if, and only if, the journal was cleanly
11435          * unmounted.
11436          */
11437
11438         if (!sb->s_start) {
11439                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11440                 return 0;
11441         }
11442
11443         err = do_one_pass(journal, &info, PASS_SCAN);
11444         if (!err)
11445                 err = do_one_pass(journal, &info, PASS_REVOKE);
11446         if (!err)
11447                 err = do_one_pass(journal, &info, PASS_REPLAY);
11448
11449         /* Restart the log at the next transaction ID, thus invalidating
11450          * any existing commit records in the log. */
11451         journal->j_transaction_sequence = ++info.end_transaction;
11452
11453         journal_clear_revoke(journal);
11454         sync_blockdev(journal->j_fs_dev);
11455         return err;
11456 }
11457
11458 static int do_one_pass(journal_t *journal,
11459                         struct recovery_info *info, enum passtype pass)
11460 {
11461         unsigned int            first_commit_ID, next_commit_ID;
11462         unsigned long           next_log_block;
11463         int                     err, success = 0;
11464         journal_superblock_t *  sb;
11465         journal_header_t *      tmp;
11466         struct buffer_head *    bh;
11467         unsigned int            sequence;
11468         int                     blocktype;
11469
11470         /* Precompute the maximum metadata descriptors in a descriptor block */
11471         int                     MAX_BLOCKS_PER_DESC;
11472         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11473                                / sizeof(journal_block_tag_t));
11474
11475         /*
11476          * First thing is to establish what we expect to find in the log
11477          * (in terms of transaction IDs), and where (in terms of log
11478          * block offsets): query the superblock.
11479          */
11480
11481         sb = journal->j_superblock;
11482         next_commit_ID = ntohl(sb->s_sequence);
11483         next_log_block = ntohl(sb->s_start);
11484
11485         first_commit_ID = next_commit_ID;
11486         if (pass == PASS_SCAN)
11487                 info->start_transaction = first_commit_ID;
11488
11489         /*
11490          * Now we walk through the log, transaction by transaction,
11491          * making sure that each transaction has a commit block in the
11492          * expected place.  Each complete transaction gets replayed back
11493          * into the main filesystem.
11494          */
11495
11496         while (1) {
11497                 int                     flags;
11498                 char *                  tagp;
11499                 journal_block_tag_t *   tag;
11500                 struct buffer_head *    obh;
11501                 struct buffer_head *    nbh;
11502
11503                 /* If we already know where to stop the log traversal,
11504                  * check right now that we haven't gone past the end of
11505                  * the log. */
11506
11507                 if (pass != PASS_SCAN)
11508                         if (tid_geq(next_commit_ID, info->end_transaction))
11509                                 break;
11510
11511                 /* Skip over each chunk of the transaction looking
11512                  * either the next descriptor block or the final commit
11513                  * record. */
11514
11515                 err = jread(&bh, journal, next_log_block);
11516                 if (err)
11517                         goto failed;
11518
11519                 next_log_block++;
11520                 wrap(journal, next_log_block);
11521
11522                 /* What kind of buffer is it?
11523                  *
11524                  * If it is a descriptor block, check that it has the
11525                  * expected sequence number.  Otherwise, we're all done
11526                  * here. */
11527
11528                 tmp = (journal_header_t *)bh->b_data;
11529
11530                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11531                         brelse(bh);
11532                         break;
11533                 }
11534
11535                 blocktype = ntohl(tmp->h_blocktype);
11536                 sequence = ntohl(tmp->h_sequence);
11537
11538                 if (sequence != next_commit_ID) {
11539                         brelse(bh);
11540                         break;
11541                 }
11542
11543                 /* OK, we have a valid descriptor block which matches
11544                  * all of the sequence number checks.  What are we going
11545                  * to do with it?  That depends on the pass... */
11546
11547                 switch(blocktype) {
11548                 case JFS_DESCRIPTOR_BLOCK:
11549                         /* If it is a valid descriptor block, replay it
11550                          * in pass REPLAY; otherwise, just skip over the
11551                          * blocks it describes. */
11552                         if (pass != PASS_REPLAY) {
11553                                 next_log_block +=
11554                                         count_tags(bh, journal->j_blocksize);
11555                                 wrap(journal, next_log_block);
11556                                 brelse(bh);
11557                                 continue;
11558                         }
11559
11560                         /* A descriptor block: we can now write all of
11561                          * the data blocks.  Yay, useful work is finally
11562                          * getting done here! */
11563
11564                         tagp = &bh->b_data[sizeof(journal_header_t)];
11565                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11566                                <= journal->j_blocksize) {
11567                                 unsigned long io_block;
11568
11569                                 tag = (journal_block_tag_t *) tagp;
11570                                 flags = ntohl(tag->t_flags);
11571
11572                                 io_block = next_log_block++;
11573                                 wrap(journal, next_log_block);
11574                                 err = jread(&obh, journal, io_block);
11575                                 if (err) {
11576                                         /* Recover what we can, but
11577                                          * report failure at the end. */
11578                                         success = err;
11579                                         printf ("JBD: IO error %d recovering "
11580                                                 "block %ld in log\n",
11581                                                 err, io_block);
11582                                 } else {
11583                                         unsigned long blocknr;
11584
11585                                         blocknr = ntohl(tag->t_blocknr);
11586
11587                                         /* If the block has been
11588                                          * revoked, then we're all done
11589                                          * here. */
11590                                         if (journal_test_revoke
11591                                             (journal, blocknr,
11592                                              next_commit_ID)) {
11593                                                 brelse(obh);
11594                                                 ++info->nr_revoke_hits;
11595                                                 goto skip_write;
11596                                         }
11597
11598                                         /* Find a buffer for the new
11599                                          * data being restored */
11600                                         nbh = getblk(journal->j_fs_dev,
11601                                                        blocknr,
11602                                                      journal->j_blocksize);
11603                                         if (nbh == NULL) {
11604                                                 printf ("JBD: Out of memory "
11605                                                        "during recovery.\n");
11606                                                 err = -ENOMEM;
11607                                                 brelse(bh);
11608                                                 brelse(obh);
11609                                                 goto failed;
11610                                         }
11611
11612                                         lock_buffer(nbh);
11613                                         memcpy(nbh->b_data, obh->b_data,
11614                                                         journal->j_blocksize);
11615                                         if (flags & JFS_FLAG_ESCAPE) {
11616                                                 *((unsigned int *)bh->b_data) =
11617                                                         htonl(JFS_MAGIC_NUMBER);
11618                                         }
11619
11620                                         mark_buffer_uptodate(nbh, 1);
11621                                         mark_buffer_dirty(nbh);
11622                                         ++info->nr_replays;
11623                                         /* ll_rw_block(WRITE, 1, &nbh); */
11624                                         unlock_buffer(nbh);
11625                                         brelse(obh);
11626                                         brelse(nbh);
11627                                 }
11628
11629                         skip_write:
11630                                 tagp += sizeof(journal_block_tag_t);
11631                                 if (!(flags & JFS_FLAG_SAME_UUID))
11632                                         tagp += 16;
11633
11634                                 if (flags & JFS_FLAG_LAST_TAG)
11635                                         break;
11636                         }
11637
11638                         brelse(bh);
11639                         continue;
11640
11641                 case JFS_COMMIT_BLOCK:
11642                         /* Found an expected commit block: not much to
11643                          * do other than move on to the next sequence
11644                          * number. */
11645                         brelse(bh);
11646                         next_commit_ID++;
11647                         continue;
11648
11649                 case JFS_REVOKE_BLOCK:
11650                         /* If we aren't in the REVOKE pass, then we can
11651                          * just skip over this block. */
11652                         if (pass != PASS_REVOKE) {
11653                                 brelse(bh);
11654                                 continue;
11655                         }
11656
11657                         err = scan_revoke_records(journal, bh,
11658                                                   next_commit_ID, info);
11659                         brelse(bh);
11660                         if (err)
11661                                 goto failed;
11662                         continue;
11663
11664                 default:
11665                         goto done;
11666                 }
11667         }
11668
11669  done:
11670         /*
11671          * We broke out of the log scan loop: either we came to the
11672          * known end of the log or we found an unexpected block in the
11673          * log.  If the latter happened, then we know that the "current"
11674          * transaction marks the end of the valid log.
11675          */
11676
11677         if (pass == PASS_SCAN)
11678                 info->end_transaction = next_commit_ID;
11679         else {
11680                 /* It's really bad news if different passes end up at
11681                  * different places (but possible due to IO errors). */
11682                 if (info->end_transaction != next_commit_ID) {
11683                         printf ("JBD: recovery pass %d ended at "
11684                                 "transaction %u, expected %u\n",
11685                                 pass, next_commit_ID, info->end_transaction);
11686                         if (!success)
11687                                 success = -EIO;
11688                 }
11689         }
11690
11691         return success;
11692
11693  failed:
11694         return err;
11695 }
11696
11697
11698 /* Scan a revoke record, marking all blocks mentioned as revoked. */
11699
11700 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
11701                                tid_t sequence, struct recovery_info *info)
11702 {
11703         journal_revoke_header_t *header;
11704         int offset, max;
11705
11706         header = (journal_revoke_header_t *) bh->b_data;
11707         offset = sizeof(journal_revoke_header_t);
11708         max = ntohl(header->r_count);
11709
11710         while (offset < max) {
11711                 unsigned long blocknr;
11712                 int err;
11713
11714                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
11715                 offset += 4;
11716                 err = journal_set_revoke(journal, blocknr, sequence);
11717                 if (err)
11718                         return err;
11719                 ++info->nr_revokes;
11720         }
11721         return 0;
11722 }
11723
11724
11725 /*
11726  * rehash.c --- rebuild hash tree directories
11727  *
11728  * This algorithm is designed for simplicity of implementation and to
11729  * pack the directory as much as possible.  It however requires twice
11730  * as much memory as the size of the directory.  The maximum size
11731  * directory supported using a 4k blocksize is roughly a gigabyte, and
11732  * so there may very well be problems with machines that don't have
11733  * virtual memory, and obscenely large directories.
11734  *
11735  * An alternate algorithm which is much more disk intensive could be
11736  * written, and probably will need to be written in the future.  The
11737  * design goals of such an algorithm are: (a) use (roughly) constant
11738  * amounts of memory, no matter how large the directory, (b) the
11739  * directory must be safe at all times, even if e2fsck is interrupted
11740  * in the middle, (c) we must use minimal amounts of extra disk
11741  * blocks.  This pretty much requires an incremental approach, where
11742  * we are reading from one part of the directory, and inserting into
11743  * the front half.  So the algorithm will have to keep track of a
11744  * moving block boundary between the new tree and the old tree, and
11745  * files will need to be moved from the old directory and inserted
11746  * into the new tree.  If the new directory requires space which isn't
11747  * yet available, blocks from the beginning part of the old directory
11748  * may need to be moved to the end of the directory to make room for
11749  * the new tree:
11750  *
11751  *    --------------------------------------------------------
11752  *    |  new tree   |        | old tree                      |
11753  *    --------------------------------------------------------
11754  *                  ^ ptr    ^ptr
11755  *                tail new   head old
11756  *
11757  * This is going to be a pain in the tuckus to implement, and will
11758  * require a lot more disk accesses.  So I'm going to skip it for now;
11759  * it's only really going to be an issue for really, really big
11760  * filesystems (when we reach the level of tens of millions of files
11761  * in a single directory).  It will probably be easier to simply
11762  * require that e2fsck use VM first.
11763  */
11764
11765 struct fill_dir_struct {
11766         char *buf;
11767         struct ext2_inode *inode;
11768         int err;
11769         e2fsck_t ctx;
11770         struct hash_entry *harray;
11771         int max_array, num_array;
11772         int dir_size;
11773         int compress;
11774         ino_t parent;
11775 };
11776
11777 struct hash_entry {
11778         ext2_dirhash_t  hash;
11779         ext2_dirhash_t  minor_hash;
11780         struct ext2_dir_entry   *dir;
11781 };
11782
11783 struct out_dir {
11784         int             num;
11785         int             max;
11786         char            *buf;
11787         ext2_dirhash_t  *hashes;
11788 };
11789
11790 static int fill_dir_block(ext2_filsys fs,
11791                           blk_t *block_nr,
11792                           e2_blkcnt_t blockcnt,
11793                           blk_t ref_block FSCK_ATTR((unused)),
11794                           int ref_offset FSCK_ATTR((unused)),
11795                           void *priv_data)
11796 {
11797         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
11798         struct hash_entry       *new_array, *ent;
11799         struct ext2_dir_entry   *dirent;
11800         char                    *dir;
11801         unsigned int            offset, dir_offset;
11802
11803         if (blockcnt < 0)
11804                 return 0;
11805
11806         offset = blockcnt * fs->blocksize;
11807         if (offset + fs->blocksize > fd->inode->i_size) {
11808                 fd->err = EXT2_ET_DIR_CORRUPTED;
11809                 return BLOCK_ABORT;
11810         }
11811         dir = (fd->buf+offset);
11812         if (HOLE_BLKADDR(*block_nr)) {
11813                 memset(dir, 0, fs->blocksize);
11814                 dirent = (struct ext2_dir_entry *) dir;
11815                 dirent->rec_len = fs->blocksize;
11816         } else {
11817                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
11818                 if (fd->err)
11819                         return BLOCK_ABORT;
11820         }
11821         /* While the directory block is "hot", index it. */
11822         dir_offset = 0;
11823         while (dir_offset < fs->blocksize) {
11824                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
11825                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
11826                     (dirent->rec_len < 8) ||
11827                     ((dirent->rec_len % 4) != 0) ||
11828                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
11829                         fd->err = EXT2_ET_DIR_CORRUPTED;
11830                         return BLOCK_ABORT;
11831                 }
11832                 dir_offset += dirent->rec_len;
11833                 if (dirent->inode == 0)
11834                         continue;
11835                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
11836                     (dirent->name[0] == '.'))
11837                         continue;
11838                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
11839                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
11840                         fd->parent = dirent->inode;
11841                         continue;
11842                 }
11843                 if (fd->num_array >= fd->max_array) {
11844                         new_array = realloc(fd->harray,
11845                             sizeof(struct hash_entry) * (fd->max_array+500));
11846                         if (!new_array) {
11847                                 fd->err = ENOMEM;
11848                                 return BLOCK_ABORT;
11849                         }
11850                         fd->harray = new_array;
11851                         fd->max_array += 500;
11852                 }
11853                 ent = fd->harray + fd->num_array++;
11854                 ent->dir = dirent;
11855                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
11856                 if (fd->compress)
11857                         ent->hash = ent->minor_hash = 0;
11858                 else {
11859                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
11860                                                  dirent->name,
11861                                                  dirent->name_len & 0xFF,
11862                                                  fs->super->s_hash_seed,
11863                                                  &ent->hash, &ent->minor_hash);
11864                         if (fd->err)
11865                                 return BLOCK_ABORT;
11866                 }
11867         }
11868
11869         return 0;
11870 }
11871
11872 /* Used for sorting the hash entry */
11873 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
11874 {
11875         const struct hash_entry *he_a = (const struct hash_entry *) a;
11876         const struct hash_entry *he_b = (const struct hash_entry *) b;
11877         int     ret;
11878         int     min_len;
11879
11880         min_len = he_a->dir->name_len;
11881         if (min_len > he_b->dir->name_len)
11882                 min_len = he_b->dir->name_len;
11883
11884         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
11885         if (ret == 0) {
11886                 if (he_a->dir->name_len > he_b->dir->name_len)
11887                         ret = 1;
11888                 else if (he_a->dir->name_len < he_b->dir->name_len)
11889                         ret = -1;
11890                 else
11891                         ret = he_b->dir->inode - he_a->dir->inode;
11892         }
11893         return ret;
11894 }
11895
11896 /* Used for sorting the hash entry */
11897 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
11898 {
11899         const struct hash_entry *he_a = (const struct hash_entry *) a;
11900         const struct hash_entry *he_b = (const struct hash_entry *) b;
11901         int     ret;
11902
11903         if (he_a->hash > he_b->hash)
11904                 ret = 1;
11905         else if (he_a->hash < he_b->hash)
11906                 ret = -1;
11907         else {
11908                 if (he_a->minor_hash > he_b->minor_hash)
11909                         ret = 1;
11910                 else if (he_a->minor_hash < he_b->minor_hash)
11911                         ret = -1;
11912                 else
11913                         ret = name_cmp(a, b);
11914         }
11915         return ret;
11916 }
11917
11918 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
11919                                 int blocks)
11920 {
11921         void                    *new_mem;
11922
11923         if (outdir->max) {
11924                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
11925                 if (!new_mem)
11926                         return ENOMEM;
11927                 outdir->buf = new_mem;
11928                 new_mem = realloc(outdir->hashes,
11929                                   blocks * sizeof(ext2_dirhash_t));
11930                 if (!new_mem)
11931                         return ENOMEM;
11932                 outdir->hashes = new_mem;
11933         } else {
11934                 outdir->buf = malloc(blocks * fs->blocksize);
11935                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
11936                 outdir->num = 0;
11937         }
11938         outdir->max = blocks;
11939         return 0;
11940 }
11941
11942 static void free_out_dir(struct out_dir *outdir)
11943 {
11944         free(outdir->buf);
11945         free(outdir->hashes);
11946         outdir->max = 0;
11947         outdir->num =0;
11948 }
11949
11950 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
11951                          char ** ret)
11952 {
11953         errcode_t       retval;
11954
11955         if (outdir->num >= outdir->max) {
11956                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
11957                 if (retval)
11958                         return retval;
11959         }
11960         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
11961         memset(*ret, 0, fs->blocksize);
11962         return 0;
11963 }
11964
11965 /*
11966  * This function is used to make a unique filename.  We do this by
11967  * appending ~0, and then incrementing the number.  However, we cannot
11968  * expand the length of the filename beyond the padding available in
11969  * the directory entry.
11970  */
11971 static void mutate_name(char *str, __u16 *len)
11972 {
11973         int     i;
11974         __u16   l = *len & 0xFF, h = *len & 0xff00;
11975
11976         /*
11977          * First check to see if it looks the name has been mutated
11978          * already
11979          */
11980         for (i = l-1; i > 0; i--) {
11981                 if (!isdigit(str[i]))
11982                         break;
11983         }
11984         if ((i == l-1) || (str[i] != '~')) {
11985                 if (((l-1) & 3) < 2)
11986                         l += 2;
11987                 else
11988                         l = (l+3) & ~3;
11989                 str[l-2] = '~';
11990                 str[l-1] = '0';
11991                 *len = l | h;
11992                 return;
11993         }
11994         for (i = l-1; i >= 0; i--) {
11995                 if (isdigit(str[i])) {
11996                         if (str[i] == '9')
11997                                 str[i] = '0';
11998                         else {
11999                                 str[i]++;
12000                                 return;
12001                         }
12002                         continue;
12003                 }
12004                 if (i == 1) {
12005                         if (str[0] == 'z')
12006                                 str[0] = 'A';
12007                         else if (str[0] == 'Z') {
12008                                 str[0] = '~';
12009                                 str[1] = '0';
12010                         } else
12011                                 str[0]++;
12012                 } else if (i > 0) {
12013                         str[i] = '1';
12014                         str[i-1] = '~';
12015                 } else {
12016                         if (str[0] == '~')
12017                                 str[0] = 'a';
12018                         else
12019                                 str[0]++;
12020                 }
12021                 break;
12022         }
12023 }
12024
12025 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12026                                     ext2_ino_t ino,
12027                                     struct fill_dir_struct *fd)
12028 {
12029         struct problem_context  pctx;
12030         struct hash_entry       *ent, *prev;
12031         int                     i, j;
12032         int                     fixed = 0;
12033         char                    new_name[256];
12034         __u16                   new_len;
12035
12036         clear_problem_context(&pctx);
12037         pctx.ino = ino;
12038
12039         for (i=1; i < fd->num_array; i++) {
12040                 ent = fd->harray + i;
12041                 prev = ent - 1;
12042                 if (!ent->dir->inode ||
12043                     ((ent->dir->name_len & 0xFF) !=
12044                      (prev->dir->name_len & 0xFF)) ||
12045                     (strncmp(ent->dir->name, prev->dir->name,
12046                              ent->dir->name_len & 0xFF)))
12047                         continue;
12048                 pctx.dirent = ent->dir;
12049                 if ((ent->dir->inode == prev->dir->inode) &&
12050                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12051                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12052                         ent->dir->inode = 0;
12053                         fixed++;
12054                         continue;
12055                 }
12056                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12057                 new_len = ent->dir->name_len;
12058                 mutate_name(new_name, &new_len);
12059                 for (j=0; j < fd->num_array; j++) {
12060                         if ((i==j) ||
12061                             ((ent->dir->name_len & 0xFF) !=
12062                              (fd->harray[j].dir->name_len & 0xFF)) ||
12063                             (strncmp(new_name, fd->harray[j].dir->name,
12064                                      new_len & 0xFF)))
12065                                 continue;
12066                         mutate_name(new_name, &new_len);
12067
12068                         j = -1;
12069                 }
12070                 new_name[new_len & 0xFF] = 0;
12071                 pctx.str = new_name;
12072                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12073                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
12074                         ent->dir->name_len = new_len;
12075                         ext2fs_dirhash(fs->super->s_def_hash_version,
12076                                        ent->dir->name,
12077                                        ent->dir->name_len & 0xFF,
12078                                        fs->super->s_hash_seed,
12079                                        &ent->hash, &ent->minor_hash);
12080                         fixed++;
12081                 }
12082         }
12083         return fixed;
12084 }
12085
12086
12087 static errcode_t copy_dir_entries(ext2_filsys fs,
12088                                   struct fill_dir_struct *fd,
12089                                   struct out_dir *outdir)
12090 {
12091         errcode_t               retval;
12092         char                    *block_start;
12093         struct hash_entry       *ent;
12094         struct ext2_dir_entry   *dirent;
12095         int                     i, rec_len, left;
12096         ext2_dirhash_t          prev_hash;
12097         int                     offset;
12098
12099         outdir->max = 0;
12100         retval = alloc_size_dir(fs, outdir,
12101                                 (fd->dir_size / fs->blocksize) + 2);
12102         if (retval)
12103                 return retval;
12104         outdir->num = fd->compress ? 0 : 1;
12105         offset = 0;
12106         outdir->hashes[0] = 0;
12107         prev_hash = 1;
12108         if ((retval = get_next_block(fs, outdir, &block_start)))
12109                 return retval;
12110         dirent = (struct ext2_dir_entry *) block_start;
12111         left = fs->blocksize;
12112         for (i=0; i < fd->num_array; i++) {
12113                 ent = fd->harray + i;
12114                 if (ent->dir->inode == 0)
12115                         continue;
12116                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12117                 if (rec_len > left) {
12118                         if (left)
12119                                 dirent->rec_len += left;
12120                         if ((retval = get_next_block(fs, outdir,
12121                                                       &block_start)))
12122                                 return retval;
12123                         offset = 0;
12124                 }
12125                 left = fs->blocksize - offset;
12126                 dirent = (struct ext2_dir_entry *) (block_start + offset);
12127                 if (offset == 0) {
12128                         if (ent->hash == prev_hash)
12129                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
12130                         else
12131                                 outdir->hashes[outdir->num-1] = ent->hash;
12132                 }
12133                 dirent->inode = ent->dir->inode;
12134                 dirent->name_len = ent->dir->name_len;
12135                 dirent->rec_len = rec_len;
12136                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12137                 offset += rec_len;
12138                 left -= rec_len;
12139                 if (left < 12) {
12140                         dirent->rec_len += left;
12141                         offset += left;
12142                         left = 0;
12143                 }
12144                 prev_hash = ent->hash;
12145         }
12146         if (left)
12147                 dirent->rec_len += left;
12148
12149         return 0;
12150 }
12151
12152
12153 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12154                                     ext2_ino_t ino, ext2_ino_t parent)
12155 {
12156         struct ext2_dir_entry           *dir;
12157         struct ext2_dx_root_info        *root;
12158         struct ext2_dx_countlimit       *limits;
12159         int                             filetype = 0;
12160
12161         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12162                 filetype = EXT2_FT_DIR << 8;
12163
12164         memset(buf, 0, fs->blocksize);
12165         dir = (struct ext2_dir_entry *) buf;
12166         dir->inode = ino;
12167         dir->name[0] = '.';
12168         dir->name_len = 1 | filetype;
12169         dir->rec_len = 12;
12170         dir = (struct ext2_dir_entry *) (buf + 12);
12171         dir->inode = parent;
12172         dir->name[0] = '.';
12173         dir->name[1] = '.';
12174         dir->name_len = 2 | filetype;
12175         dir->rec_len = fs->blocksize - 12;
12176
12177         root = (struct ext2_dx_root_info *) (buf+24);
12178         root->reserved_zero = 0;
12179         root->hash_version = fs->super->s_def_hash_version;
12180         root->info_length = 8;
12181         root->indirect_levels = 0;
12182         root->unused_flags = 0;
12183
12184         limits = (struct ext2_dx_countlimit *) (buf+32);
12185         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12186         limits->count = 0;
12187
12188         return root;
12189 }
12190
12191
12192 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12193 {
12194         struct ext2_dir_entry           *dir;
12195         struct ext2_dx_countlimit       *limits;
12196
12197         memset(buf, 0, fs->blocksize);
12198         dir = (struct ext2_dir_entry *) buf;
12199         dir->inode = 0;
12200         dir->rec_len = fs->blocksize;
12201
12202         limits = (struct ext2_dx_countlimit *) (buf+8);
12203         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12204         limits->count = 0;
12205
12206         return (struct ext2_dx_entry *) limits;
12207 }
12208
12209 /*
12210  * This function takes the leaf nodes which have been written in
12211  * outdir, and populates the root node and any necessary interior nodes.
12212  */
12213 static errcode_t calculate_tree(ext2_filsys fs,
12214                                 struct out_dir *outdir,
12215                                 ext2_ino_t ino,
12216                                 ext2_ino_t parent)
12217 {
12218         struct ext2_dx_root_info        *root_info;
12219         struct ext2_dx_entry            *root, *dx_ent = 0;
12220         struct ext2_dx_countlimit       *root_limit, *limit;
12221         errcode_t                       retval;
12222         char                            * block_start;
12223         int                             i, c1, c2, nblks;
12224         int                             limit_offset, root_offset;
12225
12226         root_info = set_root_node(fs, outdir->buf, ino, parent);
12227         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12228                 root_info->info_length;
12229         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12230         c1 = root_limit->limit;
12231         nblks = outdir->num;
12232
12233         /* Write out the pointer blocks */
12234         if (nblks-1 <= c1) {
12235                 /* Just write out the root block, and we're done */
12236                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12237                 for (i=1; i < nblks; i++) {
12238                         root->block = ext2fs_cpu_to_le32(i);
12239                         if (i != 1)
12240                                 root->hash =
12241                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12242                         root++;
12243                         c1--;
12244                 }
12245         } else {
12246                 c2 = 0;
12247                 limit = 0;
12248                 root_info->indirect_levels = 1;
12249                 for (i=1; i < nblks; i++) {
12250                         if (c1 == 0)
12251                                 return ENOSPC;
12252                         if (c2 == 0) {
12253                                 if (limit)
12254                                         limit->limit = limit->count =
12255                 ext2fs_cpu_to_le16(limit->limit);
12256                                 root = (struct ext2_dx_entry *)
12257                                         (outdir->buf + root_offset);
12258                                 root->block = ext2fs_cpu_to_le32(outdir->num);
12259                                 if (i != 1)
12260                                         root->hash =
12261                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12262                                 if ((retval =  get_next_block(fs, outdir,
12263                                                               &block_start)))
12264                                         return retval;
12265                                 dx_ent = set_int_node(fs, block_start);
12266                                 limit = (struct ext2_dx_countlimit *) dx_ent;
12267                                 c2 = limit->limit;
12268                                 root_offset += sizeof(struct ext2_dx_entry);
12269                                 c1--;
12270                         }
12271                         dx_ent->block = ext2fs_cpu_to_le32(i);
12272                         if (c2 != limit->limit)
12273                                 dx_ent->hash =
12274                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12275                         dx_ent++;
12276                         c2--;
12277                 }
12278                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12279                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12280         }
12281         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12282         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12283         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12284
12285         return 0;
12286 }
12287
12288 struct write_dir_struct {
12289         struct out_dir *outdir;
12290         errcode_t       err;
12291         e2fsck_t        ctx;
12292         int             cleared;
12293 };
12294
12295 /*
12296  * Helper function which writes out a directory block.
12297  */
12298 static int write_dir_block(ext2_filsys fs,
12299                            blk_t        *block_nr,
12300                            e2_blkcnt_t blockcnt,
12301                            blk_t ref_block FSCK_ATTR((unused)),
12302                            int ref_offset FSCK_ATTR((unused)),
12303                            void *priv_data)
12304 {
12305         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12306         blk_t   blk;
12307         char    *dir;
12308
12309         if (*block_nr == 0)
12310                 return 0;
12311         if (blockcnt >= wd->outdir->num) {
12312                 e2fsck_read_bitmaps(wd->ctx);
12313                 blk = *block_nr;
12314                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12315                 ext2fs_block_alloc_stats(fs, blk, -1);
12316                 *block_nr = 0;
12317                 wd->cleared++;
12318                 return BLOCK_CHANGED;
12319         }
12320         if (blockcnt < 0)
12321                 return 0;
12322
12323         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12324         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12325         if (wd->err)
12326                 return BLOCK_ABORT;
12327         return 0;
12328 }
12329
12330 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12331                                  struct out_dir *outdir,
12332                                  ext2_ino_t ino, int compress)
12333 {
12334         struct write_dir_struct wd;
12335         errcode_t       retval;
12336         struct ext2_inode       inode;
12337
12338         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12339         if (retval)
12340                 return retval;
12341
12342         wd.outdir = outdir;
12343         wd.err = 0;
12344         wd.ctx = ctx;
12345         wd.cleared = 0;
12346
12347         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12348                                        write_dir_block, &wd);
12349         if (retval)
12350                 return retval;
12351         if (wd.err)
12352                 return wd.err;
12353
12354         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12355         if (compress)
12356                 inode.i_flags &= ~EXT2_INDEX_FL;
12357         else
12358                 inode.i_flags |= EXT2_INDEX_FL;
12359         inode.i_size = outdir->num * fs->blocksize;
12360         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12361         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12362
12363         return 0;
12364 }
12365
12366 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12367 {
12368         ext2_filsys             fs = ctx->fs;
12369         errcode_t               retval;
12370         struct ext2_inode       inode;
12371         char                    *dir_buf = 0;
12372         struct fill_dir_struct  fd;
12373         struct out_dir          outdir;
12374
12375         outdir.max = outdir.num = 0;
12376         outdir.buf = 0;
12377         outdir.hashes = 0;
12378         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12379
12380         retval = ENOMEM;
12381         fd.harray = 0;
12382         dir_buf = malloc(inode.i_size);
12383         if (!dir_buf)
12384                 goto errout;
12385
12386         fd.max_array = inode.i_size / 32;
12387         fd.num_array = 0;
12388         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12389         if (!fd.harray)
12390                 goto errout;
12391
12392         fd.ctx = ctx;
12393         fd.buf = dir_buf;
12394         fd.inode = &inode;
12395         fd.err = 0;
12396         fd.dir_size = 0;
12397         fd.compress = 0;
12398         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12399             (inode.i_size / fs->blocksize) < 2)
12400                 fd.compress = 1;
12401         fd.parent = 0;
12402
12403         /* Read in the entire directory into memory */
12404         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12405                                        fill_dir_block, &fd);
12406         if (fd.err) {
12407                 retval = fd.err;
12408                 goto errout;
12409         }
12410
12411 #if 0
12412         printf("%d entries (%d bytes) found in inode %d\n",
12413                fd.num_array, fd.dir_size, ino);
12414 #endif
12415
12416         /* Sort the list */
12417 resort:
12418         if (fd.compress)
12419                 qsort(fd.harray+2, fd.num_array-2,
12420                       sizeof(struct hash_entry), name_cmp);
12421         else
12422                 qsort(fd.harray, fd.num_array,
12423                       sizeof(struct hash_entry), hash_cmp);
12424
12425         /*
12426          * Look for duplicates
12427          */
12428         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12429                 goto resort;
12430
12431         if (ctx->options & E2F_OPT_NO) {
12432                 retval = 0;
12433                 goto errout;
12434         }
12435
12436         /*
12437          * Copy the directory entries.  In a htree directory these
12438          * will become the leaf nodes.
12439          */
12440         retval = copy_dir_entries(fs, &fd, &outdir);
12441         if (retval)
12442                 goto errout;
12443
12444         free(dir_buf); dir_buf = 0;
12445
12446         if (!fd.compress) {
12447                 /* Calculate the interior nodes */
12448                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12449                 if (retval)
12450                         goto errout;
12451         }
12452
12453         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12454
12455 errout:
12456         free(dir_buf);
12457         free(fd.harray);
12458
12459         free_out_dir(&outdir);
12460         return retval;
12461 }
12462
12463 void e2fsck_rehash_directories(e2fsck_t ctx)
12464 {
12465         struct problem_context  pctx;
12466 #ifdef RESOURCE_TRACK
12467         struct resource_track   rtrack;
12468 #endif
12469         struct dir_info         *dir;
12470         ext2_u32_iterate        iter;
12471         ext2_ino_t              ino;
12472         errcode_t               retval;
12473         int                     i, cur, max, all_dirs, dir_index, first = 1;
12474
12475 #ifdef RESOURCE_TRACK
12476         init_resource_track(&rtrack);
12477 #endif
12478
12479         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12480
12481         if (!ctx->dirs_to_hash && !all_dirs)
12482                 return;
12483
12484         e2fsck_get_lost_and_found(ctx, 0);
12485
12486         clear_problem_context(&pctx);
12487
12488         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12489         cur = 0;
12490         if (all_dirs) {
12491                 i = 0;
12492                 max = e2fsck_get_num_dirinfo(ctx);
12493         } else {
12494                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12495                                                        &iter);
12496                 if (retval) {
12497                         pctx.errcode = retval;
12498                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12499                         return;
12500                 }
12501                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12502         }
12503         while (1) {
12504                 if (all_dirs) {
12505                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12506                                 break;
12507                         ino = dir->ino;
12508                 } else {
12509                         if (!ext2fs_u32_list_iterate(iter, &ino))
12510                                 break;
12511                 }
12512                 if (ino == ctx->lost_and_found)
12513                         continue;
12514                 pctx.dir = ino;
12515                 if (first) {
12516                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12517                         first = 0;
12518                 }
12519 #if 0
12520                 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12521 #endif
12522                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12523                 if (pctx.errcode) {
12524                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12525                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12526                 }
12527                 if (ctx->progress && !ctx->progress_fd)
12528                         e2fsck_simple_progress(ctx, "Rebuilding directory",
12529                                100.0 * (float) (++cur) / (float) max, ino);
12530         }
12531         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12532         if (!all_dirs)
12533                 ext2fs_u32_list_iterate_end(iter);
12534
12535         ext2fs_u32_list_free(ctx->dirs_to_hash);
12536         ctx->dirs_to_hash = 0;
12537
12538 #ifdef RESOURCE_TRACK
12539         if (ctx->options & E2F_OPT_TIME2) {
12540                 e2fsck_clear_progbar(ctx);
12541                 print_resource_track("Pass 3A", &rtrack);
12542         }
12543 #endif
12544 }
12545
12546 /*
12547  * linux/fs/revoke.c
12548  *
12549  * Journal revoke routines for the generic filesystem journaling code;
12550  * part of the ext2fs journaling system.
12551  *
12552  * Revoke is the mechanism used to prevent old log records for deleted
12553  * metadata from being replayed on top of newer data using the same
12554  * blocks.  The revoke mechanism is used in two separate places:
12555  *
12556  * + Commit: during commit we write the entire list of the current
12557  *   transaction's revoked blocks to the journal
12558  *
12559  * + Recovery: during recovery we record the transaction ID of all
12560  *   revoked blocks.  If there are multiple revoke records in the log
12561  *   for a single block, only the last one counts, and if there is a log
12562  *   entry for a block beyond the last revoke, then that log entry still
12563  *   gets replayed.
12564  *
12565  * We can get interactions between revokes and new log data within a
12566  * single transaction:
12567  *
12568  * Block is revoked and then journaled:
12569  *   The desired end result is the journaling of the new block, so we
12570  *   cancel the revoke before the transaction commits.
12571  *
12572  * Block is journaled and then revoked:
12573  *   The revoke must take precedence over the write of the block, so we
12574  *   need either to cancel the journal entry or to write the revoke
12575  *   later in the log than the log block.  In this case, we choose the
12576  *   latter: journaling a block cancels any revoke record for that block
12577  *   in the current transaction, so any revoke for that block in the
12578  *   transaction must have happened after the block was journaled and so
12579  *   the revoke must take precedence.
12580  *
12581  * Block is revoked and then written as data:
12582  *   The data write is allowed to succeed, but the revoke is _not_
12583  *   cancelled.  We still need to prevent old log records from
12584  *   overwriting the new data.  We don't even need to clear the revoke
12585  *   bit here.
12586  *
12587  * Revoke information on buffers is a tri-state value:
12588  *
12589  * RevokeValid clear:   no cached revoke status, need to look it up
12590  * RevokeValid set, Revoked clear:
12591  *                      buffer has not been revoked, and cancel_revoke
12592  *                      need do nothing.
12593  * RevokeValid set, Revoked set:
12594  *                      buffer has been revoked.
12595  */
12596
12597 static kmem_cache_t *revoke_record_cache;
12598 static kmem_cache_t *revoke_table_cache;
12599
12600 /* Each revoke record represents one single revoked block.  During
12601    journal replay, this involves recording the transaction ID of the
12602    last transaction to revoke this block. */
12603
12604 struct jbd_revoke_record_s
12605 {
12606         struct list_head  hash;
12607         tid_t             sequence;     /* Used for recovery only */
12608         unsigned long     blocknr;
12609 };
12610
12611
12612 /* The revoke table is just a simple hash table of revoke records. */
12613 struct jbd_revoke_table_s
12614 {
12615         /* It is conceivable that we might want a larger hash table
12616          * for recovery.  Must be a power of two. */
12617         int               hash_size;
12618         int               hash_shift;
12619         struct list_head *hash_table;
12620 };
12621
12622
12623 /* Utility functions to maintain the revoke table */
12624
12625 /* Borrowed from buffer.c: this is a tried and tested block hash function */
12626 static inline int hash(journal_t *journal, unsigned long block)
12627 {
12628         struct jbd_revoke_table_s *table = journal->j_revoke;
12629         int hash_shift = table->hash_shift;
12630
12631         return ((block << (hash_shift - 6)) ^
12632                 (block >> 13) ^
12633                 (block << (hash_shift - 12))) & (table->hash_size - 1);
12634 }
12635
12636 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
12637                               tid_t seq)
12638 {
12639         struct list_head *hash_list;
12640         struct jbd_revoke_record_s *record;
12641
12642         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
12643         if (!record)
12644                 goto oom;
12645
12646         record->sequence = seq;
12647         record->blocknr = blocknr;
12648         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
12649         list_add(&record->hash, hash_list);
12650         return 0;
12651
12652 oom:
12653         return -ENOMEM;
12654 }
12655
12656 /* Find a revoke record in the journal's hash table. */
12657
12658 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
12659                                                       unsigned long blocknr)
12660 {
12661         struct list_head *hash_list;
12662         struct jbd_revoke_record_s *record;
12663
12664         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
12665
12666         record = (struct jbd_revoke_record_s *) hash_list->next;
12667         while (&(record->hash) != hash_list) {
12668                 if (record->blocknr == blocknr)
12669                         return record;
12670                 record = (struct jbd_revoke_record_s *) record->hash.next;
12671         }
12672         return NULL;
12673 }
12674
12675 int journal_init_revoke_caches(void)
12676 {
12677         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
12678         if (revoke_record_cache == 0)
12679                 return -ENOMEM;
12680
12681         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
12682         if (revoke_table_cache == 0) {
12683                 do_cache_destroy(revoke_record_cache);
12684                 revoke_record_cache = NULL;
12685                 return -ENOMEM;
12686         }
12687         return 0;
12688 }
12689
12690 void journal_destroy_revoke_caches(void)
12691 {
12692         do_cache_destroy(revoke_record_cache);
12693         revoke_record_cache = 0;
12694         do_cache_destroy(revoke_table_cache);
12695         revoke_table_cache = 0;
12696 }
12697
12698 /* Initialise the revoke table for a given journal to a given size. */
12699
12700 int journal_init_revoke(journal_t *journal, int hash_size)
12701 {
12702         int shift, tmp;
12703
12704         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
12705         if (!journal->j_revoke)
12706                 return -ENOMEM;
12707
12708         /* Check that the hash_size is a power of two */
12709         journal->j_revoke->hash_size = hash_size;
12710
12711         shift = 0;
12712         tmp = hash_size;
12713         while((tmp >>= 1UL) != 0UL)
12714                 shift++;
12715         journal->j_revoke->hash_shift = shift;
12716
12717         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
12718         if (!journal->j_revoke->hash_table) {
12719                 free(journal->j_revoke);
12720                 journal->j_revoke = NULL;
12721                 return -ENOMEM;
12722         }
12723
12724         for (tmp = 0; tmp < hash_size; tmp++)
12725                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
12726
12727         return 0;
12728 }
12729
12730 /* Destoy a journal's revoke table.  The table must already be empty! */
12731
12732 void journal_destroy_revoke(journal_t *journal)
12733 {
12734         struct jbd_revoke_table_s *table;
12735         struct list_head *hash_list;
12736         int i;
12737
12738         table = journal->j_revoke;
12739         if (!table)
12740                 return;
12741
12742         for (i=0; i<table->hash_size; i++) {
12743                 hash_list = &table->hash_table[i];
12744         }
12745
12746         free(table->hash_table);
12747         free(table);
12748         journal->j_revoke = NULL;
12749 }
12750
12751 /*
12752  * Revoke support for recovery.
12753  *
12754  * Recovery needs to be able to:
12755  *
12756  *  record all revoke records, including the tid of the latest instance
12757  *  of each revoke in the journal
12758  *
12759  *  check whether a given block in a given transaction should be replayed
12760  *  (ie. has not been revoked by a revoke record in that or a subsequent
12761  *  transaction)
12762  *
12763  *  empty the revoke table after recovery.
12764  */
12765
12766 /*
12767  * First, setting revoke records.  We create a new revoke record for
12768  * every block ever revoked in the log as we scan it for recovery, and
12769  * we update the existing records if we find multiple revokes for a
12770  * single block.
12771  */
12772
12773 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
12774                        tid_t sequence)
12775 {
12776         struct jbd_revoke_record_s *record;
12777
12778         record = find_revoke_record(journal, blocknr);
12779         if (record) {
12780                 /* If we have multiple occurences, only record the
12781                  * latest sequence number in the hashed record */
12782                 if (tid_gt(sequence, record->sequence))
12783                         record->sequence = sequence;
12784                 return 0;
12785         }
12786         return insert_revoke_hash(journal, blocknr, sequence);
12787 }
12788
12789 /*
12790  * Test revoke records.  For a given block referenced in the log, has
12791  * that block been revoked?  A revoke record with a given transaction
12792  * sequence number revokes all blocks in that transaction and earlier
12793  * ones, but later transactions still need replayed.
12794  */
12795
12796 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
12797                         tid_t sequence)
12798 {
12799         struct jbd_revoke_record_s *record;
12800
12801         record = find_revoke_record(journal, blocknr);
12802         if (!record)
12803                 return 0;
12804         if (tid_gt(sequence, record->sequence))
12805                 return 0;
12806         return 1;
12807 }
12808
12809 /*
12810  * Finally, once recovery is over, we need to clear the revoke table so
12811  * that it can be reused by the running filesystem.
12812  */
12813
12814 void journal_clear_revoke(journal_t *journal)
12815 {
12816         int i;
12817         struct list_head *hash_list;
12818         struct jbd_revoke_record_s *record;
12819         struct jbd_revoke_table_s *revoke_var;
12820
12821         revoke_var = journal->j_revoke;
12822
12823         for (i = 0; i < revoke_var->hash_size; i++) {
12824                 hash_list = &revoke_var->hash_table[i];
12825                 while (!list_empty(hash_list)) {
12826                         record = (struct jbd_revoke_record_s*) hash_list->next;
12827                         list_del(&record->hash);
12828                         free(record);
12829                 }
12830         }
12831 }
12832
12833 /*
12834  * e2fsck.c - superblock checks
12835  */
12836
12837 #define MIN_CHECK 1
12838 #define MAX_CHECK 2
12839
12840 static void check_super_value(e2fsck_t ctx, const char *descr,
12841                               unsigned long value, int flags,
12842                               unsigned long min_val, unsigned long max_val)
12843 {
12844         struct          problem_context pctx;
12845
12846         if (((flags & MIN_CHECK) && (value < min_val)) ||
12847             ((flags & MAX_CHECK) && (value > max_val))) {
12848                 clear_problem_context(&pctx);
12849                 pctx.num = value;
12850                 pctx.str = descr;
12851                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
12852                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
12853         }
12854 }
12855
12856 /*
12857  * This routine may get stubbed out in special compilations of the
12858  * e2fsck code..
12859  */
12860 #ifndef EXT2_SPECIAL_DEVICE_SIZE
12861 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
12862 {
12863         return (ext2fs_get_device_size(ctx->filesystem_name,
12864                                        EXT2_BLOCK_SIZE(ctx->fs->super),
12865                                        &ctx->num_blocks));
12866 }
12867 #endif
12868
12869 /*
12870  * helper function to release an inode
12871  */
12872 struct process_block_struct {
12873         e2fsck_t        ctx;
12874         char            *buf;
12875         struct problem_context *pctx;
12876         int             truncating;
12877         int             truncate_offset;
12878         e2_blkcnt_t     truncate_block;
12879         int             truncated_blocks;
12880         int             abort;
12881         errcode_t       errcode;
12882 };
12883
12884 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
12885                                e2_blkcnt_t blockcnt,
12886                                blk_t    ref_blk FSCK_ATTR((unused)),
12887                                int      ref_offset FSCK_ATTR((unused)),
12888                                void *priv_data)
12889 {
12890         struct process_block_struct *pb;
12891         e2fsck_t                ctx;
12892         struct problem_context  *pctx;
12893         blk_t                   blk = *block_nr;
12894         int                     retval = 0;
12895
12896         pb = (struct process_block_struct *) priv_data;
12897         ctx = pb->ctx;
12898         pctx = pb->pctx;
12899
12900         pctx->blk = blk;
12901         pctx->blkcount = blockcnt;
12902
12903         if (HOLE_BLKADDR(blk))
12904                 return 0;
12905
12906         if ((blk < fs->super->s_first_data_block) ||
12907             (blk >= fs->super->s_blocks_count)) {
12908                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
12909         return_abort:
12910                 pb->abort = 1;
12911                 return BLOCK_ABORT;
12912         }
12913
12914         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
12915                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
12916                 goto return_abort;
12917         }
12918
12919         /*
12920          * If we are deleting an orphan, then we leave the fields alone.
12921          * If we are truncating an orphan, then update the inode fields
12922          * and clean up any partial block data.
12923          */
12924         if (pb->truncating) {
12925                 /*
12926                  * We only remove indirect blocks if they are
12927                  * completely empty.
12928                  */
12929                 if (blockcnt < 0) {
12930                         int     i, limit;
12931                         blk_t   *bp;
12932
12933                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
12934                                                         pb->buf);
12935                         if (pb->errcode)
12936                                 goto return_abort;
12937
12938                         limit = fs->blocksize >> 2;
12939                         for (i = 0, bp = (blk_t *) pb->buf;
12940                              i < limit;  i++, bp++)
12941                                 if (*bp)
12942                                         return 0;
12943                 }
12944                 /*
12945                  * We don't remove direct blocks until we've reached
12946                  * the truncation block.
12947                  */
12948                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
12949                         return 0;
12950                 /*
12951                  * If part of the last block needs truncating, we do
12952                  * it here.
12953                  */
12954                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
12955                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
12956                                                         pb->buf);
12957                         if (pb->errcode)
12958                                 goto return_abort;
12959                         memset(pb->buf + pb->truncate_offset, 0,
12960                                fs->blocksize - pb->truncate_offset);
12961                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
12962                                                          pb->buf);
12963                         if (pb->errcode)
12964                                 goto return_abort;
12965                 }
12966                 pb->truncated_blocks++;
12967                 *block_nr = 0;
12968                 retval |= BLOCK_CHANGED;
12969         }
12970
12971         ext2fs_block_alloc_stats(fs, blk, -1);
12972         return retval;
12973 }
12974
12975 /*
12976  * This function releases an inode.  Returns 1 if an inconsistency was
12977  * found.  If the inode has a link count, then it is being truncated and
12978  * not deleted.
12979  */
12980 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
12981                                 struct ext2_inode *inode, char *block_buf,
12982                                 struct problem_context *pctx)
12983 {
12984         struct process_block_struct     pb;
12985         ext2_filsys                     fs = ctx->fs;
12986         errcode_t                       retval;
12987         __u32                           count;
12988
12989         if (!ext2fs_inode_has_valid_blocks(inode))
12990                 return 0;
12991
12992         pb.buf = block_buf + 3 * ctx->fs->blocksize;
12993         pb.ctx = ctx;
12994         pb.abort = 0;
12995         pb.errcode = 0;
12996         pb.pctx = pctx;
12997         if (inode->i_links_count) {
12998                 pb.truncating = 1;
12999                 pb.truncate_block = (e2_blkcnt_t)
13000                         ((((long long)inode->i_size_high << 32) +
13001                           inode->i_size + fs->blocksize - 1) /
13002                          fs->blocksize);
13003                 pb.truncate_offset = inode->i_size % fs->blocksize;
13004         } else {
13005                 pb.truncating = 0;
13006                 pb.truncate_block = 0;
13007                 pb.truncate_offset = 0;
13008         }
13009         pb.truncated_blocks = 0;
13010         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13011                                       block_buf, release_inode_block, &pb);
13012         if (retval) {
13013                 com_err("release_inode_blocks", retval,
13014                         _("while calling ext2fs_block_iterate for inode %d"),
13015                         ino);
13016                 return 1;
13017         }
13018         if (pb.abort)
13019                 return 1;
13020
13021         /* Refresh the inode since ext2fs_block_iterate may have changed it */
13022         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13023
13024         if (pb.truncated_blocks)
13025                 inode->i_blocks -= pb.truncated_blocks *
13026                         (fs->blocksize / 512);
13027
13028         if (inode->i_file_acl) {
13029                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13030                                                    block_buf, -1, &count);
13031                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13032                         retval = 0;
13033                         count = 1;
13034                 }
13035                 if (retval) {
13036                         com_err("release_inode_blocks", retval,
13037                 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13038                                 ino);
13039                         return 1;
13040                 }
13041                 if (count == 0)
13042                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13043                 inode->i_file_acl = 0;
13044         }
13045         return 0;
13046 }
13047
13048 /*
13049  * This function releases all of the orphan inodes.  It returns 1 if
13050  * it hit some error, and 0 on success.
13051  */
13052 static int release_orphan_inodes(e2fsck_t ctx)
13053 {
13054         ext2_filsys fs = ctx->fs;
13055         ext2_ino_t      ino, next_ino;
13056         struct ext2_inode inode;
13057         struct problem_context pctx;
13058         char *block_buf;
13059
13060         if ((ino = fs->super->s_last_orphan) == 0)
13061                 return 0;
13062
13063         /*
13064          * Win or lose, we won't be using the head of the orphan inode
13065          * list again.
13066          */
13067         fs->super->s_last_orphan = 0;
13068         ext2fs_mark_super_dirty(fs);
13069
13070         /*
13071          * If the filesystem contains errors, don't run the orphan
13072          * list, since the orphan list can't be trusted; and we're
13073          * going to be running a full e2fsck run anyway...
13074          */
13075         if (fs->super->s_state & EXT2_ERROR_FS)
13076                 return 0;
13077
13078         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13079             (ino > fs->super->s_inodes_count)) {
13080                 clear_problem_context(&pctx);
13081                 pctx.ino = ino;
13082                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13083                 return 1;
13084         }
13085
13086         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13087                                                     "block iterate buffer");
13088         e2fsck_read_bitmaps(ctx);
13089
13090         while (ino) {
13091                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13092                 clear_problem_context(&pctx);
13093                 pctx.ino = ino;
13094                 pctx.inode = &inode;
13095                 pctx.str = inode.i_links_count ? _("Truncating") :
13096                         _("Clearing");
13097
13098                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13099
13100                 next_ino = inode.i_dtime;
13101                 if (next_ino &&
13102                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13103                      (next_ino > fs->super->s_inodes_count))) {
13104                         pctx.ino = next_ino;
13105                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13106                         goto return_abort;
13107                 }
13108
13109                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13110                         goto return_abort;
13111
13112                 if (!inode.i_links_count) {
13113                         ext2fs_inode_alloc_stats2(fs, ino, -1,
13114                                                   LINUX_S_ISDIR(inode.i_mode));
13115                         inode.i_dtime = time(0);
13116                 } else {
13117                         inode.i_dtime = 0;
13118                 }
13119                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13120                 ino = next_ino;
13121         }
13122         ext2fs_free_mem(&block_buf);
13123         return 0;
13124 return_abort:
13125         ext2fs_free_mem(&block_buf);
13126         return 1;
13127 }
13128
13129 /*
13130  * Check the resize inode to make sure it is sane.  We check both for
13131  * the case where on-line resizing is not enabled (in which case the
13132  * resize inode should be cleared) as well as the case where on-line
13133  * resizing is enabled.
13134  */
13135 static void check_resize_inode(e2fsck_t ctx)
13136 {
13137         ext2_filsys fs = ctx->fs;
13138         struct ext2_inode inode;
13139         struct problem_context  pctx;
13140         int             i, j, gdt_off, ind_off;
13141         blk_t           blk, pblk, expect;
13142         __u32           *dind_buf = 0, *ind_buf;
13143         errcode_t       retval;
13144
13145         clear_problem_context(&pctx);
13146
13147         /*
13148          * If the resize inode feature isn't set, then
13149          * s_reserved_gdt_blocks must be zero.
13150          */
13151         if (!(fs->super->s_feature_compat &
13152               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13153                 if (fs->super->s_reserved_gdt_blocks) {
13154                         pctx.num = fs->super->s_reserved_gdt_blocks;
13155                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13156                                         &pctx)) {
13157                                 fs->super->s_reserved_gdt_blocks = 0;
13158                                 ext2fs_mark_super_dirty(fs);
13159                         }
13160                 }
13161         }
13162
13163         /* Read the resize inode */
13164         pctx.ino = EXT2_RESIZE_INO;
13165         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13166         if (retval) {
13167                 if (fs->super->s_feature_compat &
13168                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
13169                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13170                 return;
13171         }
13172
13173         /*
13174          * If the resize inode feature isn't set, check to make sure
13175          * the resize inode is cleared; then we're done.
13176          */
13177         if (!(fs->super->s_feature_compat &
13178               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13179                 for (i=0; i < EXT2_N_BLOCKS; i++) {
13180                         if (inode.i_block[i])
13181                                 break;
13182                 }
13183                 if ((i < EXT2_N_BLOCKS) &&
13184                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13185                         memset(&inode, 0, sizeof(inode));
13186                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13187                                            "clear_resize");
13188                 }
13189                 return;
13190         }
13191
13192         /*
13193          * The resize inode feature is enabled; check to make sure the
13194          * only block in use is the double indirect block
13195          */
13196         blk = inode.i_block[EXT2_DIND_BLOCK];
13197         for (i=0; i < EXT2_N_BLOCKS; i++) {
13198                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13199                         break;
13200         }
13201         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13202             !(inode.i_mode & LINUX_S_IFREG) ||
13203             (blk < fs->super->s_first_data_block ||
13204              blk >= fs->super->s_blocks_count)) {
13205         resize_inode_invalid:
13206                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13207                         memset(&inode, 0, sizeof(inode));
13208                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13209                                            "clear_resize");
13210                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13211                 }
13212                 if (!(ctx->options & E2F_OPT_READONLY)) {
13213                         fs->super->s_state &= ~EXT2_VALID_FS;
13214                         ext2fs_mark_super_dirty(fs);
13215                 }
13216                 goto cleanup;
13217         }
13218         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13219                                                     "resize dind buffer");
13220         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13221
13222         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13223         if (retval)
13224                 goto resize_inode_invalid;
13225
13226         gdt_off = fs->desc_blocks;
13227         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13228         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13229              i++, gdt_off++, pblk++) {
13230                 gdt_off %= fs->blocksize/4;
13231                 if (dind_buf[gdt_off] != pblk)
13232                         goto resize_inode_invalid;
13233                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13234                 if (retval)
13235                         goto resize_inode_invalid;
13236                 ind_off = 0;
13237                 for (j = 1; j < fs->group_desc_count; j++) {
13238                         if (!ext2fs_bg_has_super(fs, j))
13239                                 continue;
13240                         expect = pblk + (j * fs->super->s_blocks_per_group);
13241                         if (ind_buf[ind_off] != expect)
13242                                 goto resize_inode_invalid;
13243                         ind_off++;
13244                 }
13245         }
13246
13247 cleanup:
13248         ext2fs_free_mem(&dind_buf);
13249
13250  }
13251
13252 static void check_super_block(e2fsck_t ctx)
13253 {
13254         ext2_filsys fs = ctx->fs;
13255         blk_t   first_block, last_block;
13256         struct ext2_super_block *sb = fs->super;
13257         struct ext2_group_desc *gd;
13258         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
13259         blk_t   bpg_max;
13260         int     inodes_per_block;
13261         int     ipg_max;
13262         int     inode_size;
13263         dgrp_t  i;
13264         blk_t   should_be;
13265         struct problem_context  pctx;
13266         __u32   free_blocks = 0, free_inodes = 0;
13267
13268         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13269         ipg_max = inodes_per_block * (blocks_per_group - 4);
13270         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13271                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13272         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13273         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13274                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13275
13276         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13277                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13278         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13279                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13280         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13281                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13282
13283         clear_problem_context(&pctx);
13284
13285         /*
13286          * Verify the super block constants...
13287          */
13288         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13289                           MIN_CHECK, 1, 0);
13290         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13291                           MIN_CHECK, 1, 0);
13292         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13293                           MAX_CHECK, 0, sb->s_blocks_count);
13294         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13295                           MIN_CHECK | MAX_CHECK, 0,
13296                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13297         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13298                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13299         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13300                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13301                           bpg_max);
13302         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13303                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
13304         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13305                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13306         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13307                           MAX_CHECK, 0, sb->s_blocks_count / 2);
13308         check_super_value(ctx, "reserved_gdt_blocks",
13309                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13310                           fs->blocksize/4);
13311         inode_size = EXT2_INODE_SIZE(sb);
13312         check_super_value(ctx, "inode_size",
13313                           inode_size, MIN_CHECK | MAX_CHECK,
13314                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13315         if (inode_size & (inode_size - 1)) {
13316                 pctx.num = inode_size;
13317                 pctx.str = "inode_size";
13318                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13319                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13320                 return;
13321         }
13322
13323         if (!ctx->num_blocks) {
13324                 pctx.errcode = e2fsck_get_device_size(ctx);
13325                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13326                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13327                         ctx->flags |= E2F_FLAG_ABORT;
13328                         return;
13329                 }
13330                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13331                     (ctx->num_blocks < sb->s_blocks_count)) {
13332                         pctx.blk = sb->s_blocks_count;
13333                         pctx.blk2 = ctx->num_blocks;
13334                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13335                                 ctx->flags |= E2F_FLAG_ABORT;
13336                                 return;
13337                         }
13338                 }
13339         }
13340
13341         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13342                 pctx.blk = EXT2_BLOCK_SIZE(sb);
13343                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13344                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13345                 ctx->flags |= E2F_FLAG_ABORT;
13346                 return;
13347         }
13348
13349         should_be = sb->s_frags_per_group >>
13350                 (sb->s_log_block_size - sb->s_log_frag_size);
13351         if (sb->s_blocks_per_group != should_be) {
13352                 pctx.blk = sb->s_blocks_per_group;
13353                 pctx.blk2 = should_be;
13354                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13355                 ctx->flags |= E2F_FLAG_ABORT;
13356                 return;
13357         }
13358
13359         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13360         if (sb->s_first_data_block != should_be) {
13361                 pctx.blk = sb->s_first_data_block;
13362                 pctx.blk2 = should_be;
13363                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13364                 ctx->flags |= E2F_FLAG_ABORT;
13365                 return;
13366         }
13367
13368         should_be = sb->s_inodes_per_group * fs->group_desc_count;
13369         if (sb->s_inodes_count != should_be) {
13370                 pctx.ino = sb->s_inodes_count;
13371                 pctx.ino2 = should_be;
13372                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13373                         sb->s_inodes_count = should_be;
13374                         ext2fs_mark_super_dirty(fs);
13375                 }
13376         }
13377
13378         /*
13379          * Verify the group descriptors....
13380          */
13381         first_block =  sb->s_first_data_block;
13382         last_block = first_block + blocks_per_group;
13383
13384         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13385                 pctx.group = i;
13386
13387                 if (i == fs->group_desc_count - 1)
13388                         last_block = sb->s_blocks_count;
13389                 if ((gd->bg_block_bitmap < first_block) ||
13390                     (gd->bg_block_bitmap >= last_block)) {
13391                         pctx.blk = gd->bg_block_bitmap;
13392                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13393                                 gd->bg_block_bitmap = 0;
13394                 }
13395                 if (gd->bg_block_bitmap == 0) {
13396                         ctx->invalid_block_bitmap_flag[i]++;
13397                         ctx->invalid_bitmaps++;
13398                 }
13399                 if ((gd->bg_inode_bitmap < first_block) ||
13400                     (gd->bg_inode_bitmap >= last_block)) {
13401                         pctx.blk = gd->bg_inode_bitmap;
13402                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13403                                 gd->bg_inode_bitmap = 0;
13404                 }
13405                 if (gd->bg_inode_bitmap == 0) {
13406                         ctx->invalid_inode_bitmap_flag[i]++;
13407                         ctx->invalid_bitmaps++;
13408                 }
13409                 if ((gd->bg_inode_table < first_block) ||
13410                     ((gd->bg_inode_table +
13411                       fs->inode_blocks_per_group - 1) >= last_block)) {
13412                         pctx.blk = gd->bg_inode_table;
13413                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13414                                 gd->bg_inode_table = 0;
13415                 }
13416                 if (gd->bg_inode_table == 0) {
13417                         ctx->invalid_inode_table_flag[i]++;
13418                         ctx->invalid_bitmaps++;
13419                 }
13420                 free_blocks += gd->bg_free_blocks_count;
13421                 free_inodes += gd->bg_free_inodes_count;
13422                 first_block += sb->s_blocks_per_group;
13423                 last_block += sb->s_blocks_per_group;
13424
13425                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13426                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13427                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13428                         ext2fs_unmark_valid(fs);
13429
13430         }
13431
13432         /*
13433          * Update the global counts from the block group counts.  This
13434          * is needed for an experimental patch which eliminates
13435          * locking the entire filesystem when allocating blocks or
13436          * inodes; if the filesystem is not unmounted cleanly, the
13437          * global counts may not be accurate.
13438          */
13439         if ((free_blocks != sb->s_free_blocks_count) ||
13440             (free_inodes != sb->s_free_inodes_count)) {
13441                 if (ctx->options & E2F_OPT_READONLY)
13442                         ext2fs_unmark_valid(fs);
13443                 else {
13444                         sb->s_free_blocks_count = free_blocks;
13445                         sb->s_free_inodes_count = free_inodes;
13446                         ext2fs_mark_super_dirty(fs);
13447                 }
13448         }
13449
13450         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13451             (sb->s_free_inodes_count > sb->s_inodes_count))
13452                 ext2fs_unmark_valid(fs);
13453
13454
13455         /*
13456          * If we have invalid bitmaps, set the error state of the
13457          * filesystem.
13458          */
13459         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13460                 sb->s_state &= ~EXT2_VALID_FS;
13461                 ext2fs_mark_super_dirty(fs);
13462         }
13463
13464         clear_problem_context(&pctx);
13465
13466 #ifndef EXT2_SKIP_UUID
13467         /*
13468          * If the UUID field isn't assigned, assign it.
13469          */
13470         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13471                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13472                         uuid_generate(sb->s_uuid);
13473                         ext2fs_mark_super_dirty(fs);
13474                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13475                 }
13476         }
13477 #endif
13478
13479         /*
13480          * For the Hurd, check to see if the filetype option is set,
13481          * since it doesn't support it.
13482          */
13483         if (!(ctx->options & E2F_OPT_READONLY) &&
13484             fs->super->s_creator_os == EXT2_OS_HURD &&
13485             (fs->super->s_feature_incompat &
13486              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13487                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13488                         fs->super->s_feature_incompat &=
13489                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13490                         ext2fs_mark_super_dirty(fs);
13491
13492                 }
13493         }
13494
13495         /*
13496          * If we have any of the compatibility flags set, we need to have a
13497          * revision 1 filesystem.  Most kernels will not check the flags on
13498          * a rev 0 filesystem and we may have corruption issues because of
13499          * the incompatible changes to the filesystem.
13500          */
13501         if (!(ctx->options & E2F_OPT_READONLY) &&
13502             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13503             (fs->super->s_feature_compat ||
13504              fs->super->s_feature_ro_compat ||
13505              fs->super->s_feature_incompat) &&
13506             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13507                 ext2fs_update_dynamic_rev(fs);
13508                 ext2fs_mark_super_dirty(fs);
13509         }
13510
13511         check_resize_inode(ctx);
13512
13513         /*
13514          * Clean up any orphan inodes, if present.
13515          */
13516         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13517                 fs->super->s_state &= ~EXT2_VALID_FS;
13518                 ext2fs_mark_super_dirty(fs);
13519         }
13520
13521         /*
13522          * Move the ext3 journal file, if necessary.
13523          */
13524         e2fsck_move_ext3_journal(ctx);
13525         return;
13526 }
13527
13528 /*
13529  * swapfs.c --- byte-swap an ext2 filesystem
13530  */
13531
13532 #ifdef ENABLE_SWAPFS
13533
13534 struct swap_block_struct {
13535         ext2_ino_t      ino;
13536         int             isdir;
13537         errcode_t       errcode;
13538         char            *dir_buf;
13539         struct ext2_inode *inode;
13540 };
13541
13542 /*
13543  * This is a helper function for block_iterate.  We mark all of the
13544  * indirect and direct blocks as changed, so that block_iterate will
13545  * write them out.
13546  */
13547 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13548                       void *priv_data)
13549 {
13550         errcode_t       retval;
13551
13552         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13553
13554         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13555                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13556                 if (retval) {
13557                         sb->errcode = retval;
13558                         return BLOCK_ABORT;
13559                 }
13560                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13561                 if (retval) {
13562                         sb->errcode = retval;
13563                         return BLOCK_ABORT;
13564                 }
13565         }
13566         if (blockcnt >= 0) {
13567                 if (blockcnt < EXT2_NDIR_BLOCKS)
13568                         return 0;
13569                 return BLOCK_CHANGED;
13570         }
13571         if (blockcnt == BLOCK_COUNT_IND) {
13572                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
13573                         return 0;
13574                 return BLOCK_CHANGED;
13575         }
13576         if (blockcnt == BLOCK_COUNT_DIND) {
13577                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
13578                         return 0;
13579                 return BLOCK_CHANGED;
13580         }
13581         if (blockcnt == BLOCK_COUNT_TIND) {
13582                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
13583                         return 0;
13584                 return BLOCK_CHANGED;
13585         }
13586         return BLOCK_CHANGED;
13587 }
13588
13589 /*
13590  * This function is responsible for byte-swapping all of the indirect,
13591  * block pointers.  It is also responsible for byte-swapping directories.
13592  */
13593 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
13594                               struct ext2_inode *inode)
13595 {
13596         errcode_t                       retval;
13597         struct swap_block_struct        sb;
13598
13599         sb.ino = ino;
13600         sb.inode = inode;
13601         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
13602         sb.errcode = 0;
13603         sb.isdir = 0;
13604         if (LINUX_S_ISDIR(inode->i_mode))
13605                 sb.isdir = 1;
13606
13607         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
13608                                       swap_block, &sb);
13609         if (retval) {
13610                 com_err("swap_inode_blocks", retval,
13611                         _("while calling ext2fs_block_iterate"));
13612                 ctx->flags |= E2F_FLAG_ABORT;
13613                 return;
13614         }
13615         if (sb.errcode) {
13616                 com_err("swap_inode_blocks", sb.errcode,
13617                         _("while calling iterator function"));
13618                 ctx->flags |= E2F_FLAG_ABORT;
13619                 return;
13620         }
13621 }
13622
13623 static void swap_inodes(e2fsck_t ctx)
13624 {
13625         ext2_filsys fs = ctx->fs;
13626         dgrp_t                  group;
13627         unsigned int            i;
13628         ext2_ino_t              ino = 1;
13629         char                    *buf, *block_buf;
13630         errcode_t               retval;
13631         struct ext2_inode *     inode;
13632
13633         e2fsck_use_inode_shortcuts(ctx, 1);
13634
13635         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
13636                                 &buf);
13637         if (retval) {
13638                 com_err("swap_inodes", retval,
13639                         _("while allocating inode buffer"));
13640                 ctx->flags |= E2F_FLAG_ABORT;
13641                 return;
13642         }
13643         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13644                                                     "block interate buffer");
13645         for (group = 0; group < fs->group_desc_count; group++) {
13646                 retval = io_channel_read_blk(fs->io,
13647                       fs->group_desc[group].bg_inode_table,
13648                       fs->inode_blocks_per_group, buf);
13649                 if (retval) {
13650                         com_err("swap_inodes", retval,
13651                                 _("while reading inode table (group %d)"),
13652                                 group);
13653                         ctx->flags |= E2F_FLAG_ABORT;
13654                         return;
13655                 }
13656                 inode = (struct ext2_inode *) buf;
13657                 for (i=0; i < fs->super->s_inodes_per_group;
13658                      i++, ino++, inode++) {
13659                         ctx->stashed_ino = ino;
13660                         ctx->stashed_inode = inode;
13661
13662                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
13663                                 ext2fs_swap_inode(fs, inode, inode, 0);
13664
13665                         /*
13666                          * Skip deleted files.
13667                          */
13668                         if (inode->i_links_count == 0)
13669                                 continue;
13670
13671                         if (LINUX_S_ISDIR(inode->i_mode) ||
13672                             ((inode->i_block[EXT2_IND_BLOCK] ||
13673                               inode->i_block[EXT2_DIND_BLOCK] ||
13674                               inode->i_block[EXT2_TIND_BLOCK]) &&
13675                              ext2fs_inode_has_valid_blocks(inode)))
13676                                 swap_inode_blocks(ctx, ino, block_buf, inode);
13677
13678                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13679                                 return;
13680
13681                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
13682                                 ext2fs_swap_inode(fs, inode, inode, 1);
13683                 }
13684                 retval = io_channel_write_blk(fs->io,
13685                       fs->group_desc[group].bg_inode_table,
13686                       fs->inode_blocks_per_group, buf);
13687                 if (retval) {
13688                         com_err("swap_inodes", retval,
13689                                 _("while writing inode table (group %d)"),
13690                                 group);
13691                         ctx->flags |= E2F_FLAG_ABORT;
13692                         return;
13693                 }
13694         }
13695         ext2fs_free_mem(&buf);
13696         ext2fs_free_mem(&block_buf);
13697         e2fsck_use_inode_shortcuts(ctx, 0);
13698         ext2fs_flush_icache(fs);
13699 }
13700
13701 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
13702 /*
13703  * On the PowerPC, the big-endian variant of the ext2 filesystem
13704  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
13705  * of each word.  Thus a bitmap with only bit 0 set would be, as
13706  * a string of bytes, 00 00 00 01 00 ...
13707  * To cope with this, we byte-reverse each word of a bitmap if
13708  * we have a big-endian filesystem, that is, if we are *not*
13709  * byte-swapping other word-sized numbers.
13710  */
13711 #define EXT2_BIG_ENDIAN_BITMAPS
13712 #endif
13713
13714 #ifdef EXT2_BIG_ENDIAN_BITMAPS
13715 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
13716 {
13717         __u32 *p = (__u32 *) bmap->bitmap;
13718         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
13719
13720         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
13721                 *p = ext2fs_swab32(*p);
13722 }
13723 #endif
13724
13725
13726 #ifdef ENABLE_SWAPFS
13727 static void swap_filesys(e2fsck_t ctx)
13728 {
13729         ext2_filsys fs = ctx->fs;
13730 #ifdef RESOURCE_TRACK
13731         struct resource_track   rtrack;
13732
13733         init_resource_track(&rtrack);
13734 #endif
13735
13736         if (!(ctx->options & E2F_OPT_PREEN))
13737                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
13738
13739 #ifdef MTRACE
13740         mtrace_print("Byte swap");
13741 #endif
13742
13743         if (fs->super->s_mnt_count) {
13744                 fprintf(stderr, _("%s: the filesystem must be freshly "
13745                         "checked using fsck\n"
13746                         "and not mounted before trying to "
13747                         "byte-swap it.\n"), ctx->device_name);
13748                 ctx->flags |= E2F_FLAG_ABORT;
13749                 return;
13750         }
13751         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
13752                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
13753                                EXT2_FLAG_SWAP_BYTES_WRITE);
13754                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
13755         } else {
13756                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
13757                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
13758         }
13759         swap_inodes(ctx);
13760         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13761                 return;
13762         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
13763                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
13764         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
13765                        EXT2_FLAG_SWAP_BYTES_WRITE);
13766
13767 #ifdef EXT2_BIG_ENDIAN_BITMAPS
13768         e2fsck_read_bitmaps(ctx);
13769         ext2fs_swap_bitmap(fs->inode_map);
13770         ext2fs_swap_bitmap(fs->block_map);
13771         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
13772 #endif
13773         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13774         ext2fs_flush(fs);
13775         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13776
13777 #ifdef RESOURCE_TRACK
13778         if (ctx->options & E2F_OPT_TIME2)
13779                 print_resource_track(_("Byte swap"), &rtrack);
13780 #endif
13781 }
13782 #endif  /* ENABLE_SWAPFS */
13783
13784 #endif
13785
13786 /*
13787  * util.c --- miscellaneous utilities
13788  */
13789
13790
13791 #if 0
13792 void fatal_error(e2fsck_t ctx, const char *msg)
13793 {
13794         if (msg)
13795                 fprintf (stderr, "e2fsck: %s\n", msg);
13796         if (ctx->fs && ctx->fs->io) {
13797                 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
13798                         io_channel_flush(ctx->fs->io);
13799                 else
13800                         fprintf(stderr, "e2fsck: io manager magic bad!\n");
13801         }
13802         ctx->flags |= E2F_FLAG_ABORT;
13803         if (ctx->flags & E2F_FLAG_SETJMP_OK)
13804                 longjmp(ctx->abort_loc, 1);
13805         exit(EXIT_ERROR);
13806 }
13807 #endif
13808
13809 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
13810                              const char *description)
13811 {
13812         void *ret;
13813         char buf[256];
13814
13815 #ifdef DEBUG_ALLOCATE_MEMORY
13816         printf("Allocating %d bytes for %s...\n", size, description);
13817 #endif
13818         ret = malloc(size);
13819         if (!ret) {
13820                 sprintf(buf, "Can't allocate %s\n", description);
13821                 fatal_error(ctx, buf);
13822         }
13823         memset(ret, 0, size);
13824         return ret;
13825 }
13826
13827 static char *string_copy(const char *str, int len)
13828 {
13829         char    *ret;
13830
13831         if (!str)
13832                 return NULL;
13833         if (!len)
13834                 len = strlen(str);
13835         ret = malloc(len+1);
13836         if (ret) {
13837                 strncpy(ret, str, len);
13838                 ret[len] = 0;
13839         }
13840         return ret;
13841 }
13842
13843 #ifndef HAVE_CONIO_H
13844 static int read_a_char(void)
13845 {
13846         char    c;
13847         int     r;
13848         int     fail = 0;
13849
13850         while(1) {
13851                 if (e2fsck_global_ctx &&
13852                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
13853                         return 3;
13854                 }
13855                 r = read(0, &c, 1);
13856                 if (r == 1)
13857                         return c;
13858                 if (fail++ > 100)
13859                         break;
13860         }
13861         return EOF;
13862 }
13863 #endif
13864
13865 static int ask_yn(const char * string, int def)
13866 {
13867         int             c;
13868         const char      *defstr;
13869         static const char short_yes[] = "yY";
13870         static const char short_no[] = "nN";
13871
13872 #ifdef HAVE_TERMIOS_H
13873         struct termios  termios, tmp;
13874
13875         tcgetattr (0, &termios);
13876         tmp = termios;
13877         tmp.c_lflag &= ~(ICANON | ECHO);
13878         tmp.c_cc[VMIN] = 1;
13879         tmp.c_cc[VTIME] = 0;
13880         tcsetattr (0, TCSANOW, &tmp);
13881 #endif
13882
13883         if (def == 1)
13884                 defstr = "<y>";
13885         else if (def == 0)
13886                 defstr = "<n>";
13887         else
13888                 defstr = " (y/n)";
13889         printf("%s%s? ", string, defstr);
13890         while (1) {
13891                 fflush (stdout);
13892                 if ((c = read_a_char()) == EOF)
13893                         break;
13894                 if (c == 3) {
13895 #ifdef HAVE_TERMIOS_H
13896                         tcsetattr (0, TCSANOW, &termios);
13897 #endif
13898                         if (e2fsck_global_ctx &&
13899                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
13900                                 puts("\n");
13901                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
13902                         }
13903                         puts(_("cancelled!\n"));
13904                         return 0;
13905                 }
13906                 if (strchr(short_yes, (char) c)) {
13907                         def = 1;
13908                         break;
13909                 }
13910                 else if (strchr(short_no, (char) c)) {
13911                         def = 0;
13912                         break;
13913                 }
13914                 else if ((c == ' ' || c == '\n') && (def != -1))
13915                         break;
13916         }
13917         if (def)
13918                 puts("yes\n");
13919         else
13920                 puts ("no\n");
13921 #ifdef HAVE_TERMIOS_H
13922         tcsetattr (0, TCSANOW, &termios);
13923 #endif
13924         return def;
13925 }
13926
13927 int ask (e2fsck_t ctx, const char * string, int def)
13928 {
13929         if (ctx->options & E2F_OPT_NO) {
13930                 printf (_("%s? no\n\n"), string);
13931                 return 0;
13932         }
13933         if (ctx->options & E2F_OPT_YES) {
13934                 printf (_("%s? yes\n\n"), string);
13935                 return 1;
13936         }
13937         if (ctx->options & E2F_OPT_PREEN) {
13938                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
13939                 return def;
13940         }
13941         return ask_yn(string, def);
13942 }
13943
13944 void e2fsck_read_bitmaps(e2fsck_t ctx)
13945 {
13946         ext2_filsys fs = ctx->fs;
13947         errcode_t       retval;
13948
13949         if (ctx->invalid_bitmaps) {
13950                 com_err(ctx->program_name, 0,
13951                     _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
13952                         ctx->device_name);
13953                 fatal_error(ctx, 0);
13954         }
13955
13956         ehandler_operation(_("reading inode and block bitmaps"));
13957         retval = ext2fs_read_bitmaps(fs);
13958         ehandler_operation(0);
13959         if (retval) {
13960                 com_err(ctx->program_name, retval,
13961                         _("while retrying to read bitmaps for %s"),
13962                         ctx->device_name);
13963                 fatal_error(ctx, 0);
13964         }
13965 }
13966
13967 static void e2fsck_write_bitmaps(e2fsck_t ctx)
13968 {
13969         ext2_filsys fs = ctx->fs;
13970         errcode_t       retval;
13971
13972         if (ext2fs_test_bb_dirty(fs)) {
13973                 ehandler_operation(_("writing block bitmaps"));
13974                 retval = ext2fs_write_block_bitmap(fs);
13975                 ehandler_operation(0);
13976                 if (retval) {
13977                         com_err(ctx->program_name, retval,
13978                             _("while retrying to write block bitmaps for %s"),
13979                                 ctx->device_name);
13980                         fatal_error(ctx, 0);
13981                 }
13982         }
13983
13984         if (ext2fs_test_ib_dirty(fs)) {
13985                 ehandler_operation(_("writing inode bitmaps"));
13986                 retval = ext2fs_write_inode_bitmap(fs);
13987                 ehandler_operation(0);
13988                 if (retval) {
13989                         com_err(ctx->program_name, retval,
13990                             _("while retrying to write inode bitmaps for %s"),
13991                                 ctx->device_name);
13992                         fatal_error(ctx, 0);
13993                 }
13994         }
13995 }
13996
13997 void preenhalt(e2fsck_t ctx)
13998 {
13999         ext2_filsys fs = ctx->fs;
14000
14001         if (!(ctx->options & E2F_OPT_PREEN))
14002                 return;
14003         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14004                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14005                ctx->device_name);
14006         if (fs != NULL) {
14007                 fs->super->s_state |= EXT2_ERROR_FS;
14008                 ext2fs_mark_super_dirty(fs);
14009                 ext2fs_close(fs);
14010         }
14011         exit(EXIT_UNCORRECTED);
14012 }
14013
14014 #ifdef RESOURCE_TRACK
14015 void init_resource_track(struct resource_track *track)
14016 {
14017 #ifdef HAVE_GETRUSAGE
14018         struct rusage r;
14019 #endif
14020
14021         track->brk_start = sbrk(0);
14022         gettimeofday(&track->time_start, 0);
14023 #ifdef HAVE_GETRUSAGE
14024 #ifdef sun
14025         memset(&r, 0, sizeof(struct rusage));
14026 #endif
14027         getrusage(RUSAGE_SELF, &r);
14028         track->user_start = r.ru_utime;
14029         track->system_start = r.ru_stime;
14030 #else
14031         track->user_start.tv_sec = track->user_start.tv_usec = 0;
14032         track->system_start.tv_sec = track->system_start.tv_usec = 0;
14033 #endif
14034 }
14035
14036 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14037                                        struct timeval *tv2)
14038 {
14039         return ((tv1->tv_sec - tv2->tv_sec) +
14040                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14041 }
14042
14043 void print_resource_track(const char *desc, struct resource_track *track)
14044 {
14045 #ifdef HAVE_GETRUSAGE
14046         struct rusage r;
14047 #endif
14048 #ifdef HAVE_MALLINFO
14049         struct mallinfo malloc_info;
14050 #endif
14051         struct timeval time_end;
14052
14053         gettimeofday(&time_end, 0);
14054
14055         if (desc)
14056                 printf("%s: ", desc);
14057
14058 #ifdef HAVE_MALLINFO
14059 #define kbytes(x)       (((x) + 1023) / 1024)
14060
14061         malloc_info = mallinfo();
14062         printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14063                kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14064                kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14065 #else
14066         printf(_("Memory used: %d, "),
14067                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14068 #endif
14069 #ifdef HAVE_GETRUSAGE
14070         getrusage(RUSAGE_SELF, &r);
14071
14072         printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14073                timeval_subtract(&time_end, &track->time_start),
14074                timeval_subtract(&r.ru_utime, &track->user_start),
14075                timeval_subtract(&r.ru_stime, &track->system_start));
14076 #else
14077         printf(_("elapsed time: %6.3f\n"),
14078                timeval_subtract(&time_end, &track->time_start));
14079 #endif
14080 }
14081 #endif /* RESOURCE_TRACK */
14082
14083 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14084                               struct ext2_inode * inode, const char *proc)
14085 {
14086         int retval;
14087
14088         retval = ext2fs_read_inode(ctx->fs, ino, inode);
14089         if (retval) {
14090                 com_err("ext2fs_read_inode", retval,
14091                         _("while reading inode %ld in %s"), ino, proc);
14092                 fatal_error(ctx, 0);
14093         }
14094 }
14095
14096 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14097                                struct ext2_inode * inode, int bufsize,
14098                                const char *proc)
14099 {
14100         int retval;
14101
14102         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14103         if (retval) {
14104                 com_err("ext2fs_write_inode", retval,
14105                         _("while writing inode %ld in %s"), ino, proc);
14106                 fatal_error(ctx, 0);
14107         }
14108 }
14109
14110 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14111                                struct ext2_inode * inode, const char *proc)
14112 {
14113         int retval;
14114
14115         retval = ext2fs_write_inode(ctx->fs, ino, inode);
14116         if (retval) {
14117                 com_err("ext2fs_write_inode", retval,
14118                         _("while writing inode %ld in %s"), ino, proc);
14119                 fatal_error(ctx, 0);
14120         }
14121 }
14122
14123 #ifdef MTRACE
14124 void mtrace_print(char *mesg)
14125 {
14126         FILE    *malloc_get_mallstream();
14127         FILE    *f = malloc_get_mallstream();
14128
14129         if (f)
14130                 fprintf(f, "============= %s\n", mesg);
14131 }
14132 #endif
14133
14134 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14135                    io_manager manager)
14136 {
14137         struct ext2_super_block *sb;
14138         io_channel              io = NULL;
14139         void                    *buf = NULL;
14140         int                     blocksize;
14141         blk_t                   superblock, ret_sb = 8193;
14142
14143         if (fs && fs->super) {
14144                 ret_sb = (fs->super->s_blocks_per_group +
14145                           fs->super->s_first_data_block);
14146                 if (ctx) {
14147                         ctx->superblock = ret_sb;
14148                         ctx->blocksize = fs->blocksize;
14149                 }
14150                 return ret_sb;
14151         }
14152
14153         if (ctx) {
14154                 if (ctx->blocksize) {
14155                         ret_sb = ctx->blocksize * 8;
14156                         if (ctx->blocksize == 1024)
14157                                 ret_sb++;
14158                         ctx->superblock = ret_sb;
14159                         return ret_sb;
14160                 }
14161                 ctx->superblock = ret_sb;
14162                 ctx->blocksize = 1024;
14163         }
14164
14165         if (!name || !manager)
14166                 goto cleanup;
14167
14168         if (manager->open(name, 0, &io) != 0)
14169                 goto cleanup;
14170
14171         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14172                 goto cleanup;
14173         sb = (struct ext2_super_block *) buf;
14174
14175         for (blocksize = EXT2_MIN_BLOCK_SIZE;
14176              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14177                 superblock = blocksize*8;
14178                 if (blocksize == 1024)
14179                         superblock++;
14180                 io_channel_set_blksize(io, blocksize);
14181                 if (io_channel_read_blk(io, superblock,
14182                                         -SUPERBLOCK_SIZE, buf))
14183                         continue;
14184 #ifdef EXT2FS_ENABLE_SWAPFS
14185                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14186                         ext2fs_swap_super(sb);
14187 #endif
14188                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14189                         ret_sb = superblock;
14190                         if (ctx) {
14191                                 ctx->superblock = superblock;
14192                                 ctx->blocksize = blocksize;
14193                         }
14194                         break;
14195                 }
14196         }
14197
14198 cleanup:
14199         if (io)
14200                 io_channel_close(io);
14201         ext2fs_free_mem(&buf);
14202         return (ret_sb);
14203 }
14204
14205
14206 /*
14207  * This function runs through the e2fsck passes and calls them all,
14208  * returning restart, abort, or cancel as necessary...
14209  */
14210 typedef void (*pass_t)(e2fsck_t ctx);
14211
14212 static const pass_t e2fsck_passes[] = {
14213         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14214         e2fsck_pass5, 0 };
14215
14216 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14217
14218 static int e2fsck_run(e2fsck_t ctx)
14219 {
14220         int     i;
14221         pass_t  e2fsck_pass;
14222
14223         if (setjmp(ctx->abort_loc)) {
14224                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14225                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14226         }
14227         ctx->flags |= E2F_FLAG_SETJMP_OK;
14228
14229         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14230                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14231                         break;
14232                 e2fsck_pass(ctx);
14233                 if (ctx->progress)
14234                         (void) (ctx->progress)(ctx, 0, 0, 0);
14235         }
14236         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14237
14238         if (ctx->flags & E2F_FLAG_RUN_RETURN)
14239                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14240         return 0;
14241 }
14242
14243
14244 /*
14245  * unix.c - The unix-specific code for e2fsck
14246  */
14247
14248
14249 /* Command line options */
14250 static int swapfs;
14251 #ifdef ENABLE_SWAPFS
14252 static int normalize_swapfs;
14253 #endif
14254 static int cflag;               /* check disk */
14255 static int show_version_only;
14256 static int verbose;
14257
14258 static int replace_bad_blocks;
14259 static int keep_bad_blocks;
14260 static char *bad_blocks_file;
14261
14262 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
14263 int journal_enable_debug = -1;
14264 #endif
14265
14266 #if 0
14267 static void usage(e2fsck_t ctx)
14268 {
14269         fprintf(stderr,
14270                 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14271                 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14272                 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
14273                 "\t\t[-E extended-options] device\n"),
14274                 ctx->program_name);
14275
14276         fprintf(stderr, _("\nEmergency help:\n"
14277                 " -p                   Automatic repair (no questions)\n"
14278                 " -n                   Make no changes to the filesystem\n"
14279                 " -y                   Assume \"yes\" to all questions\n"
14280                 " -c                   Check for bad blocks and add them to the badblock list\n"
14281                 " -f                   Force checking even if filesystem is marked clean\n"));
14282         fprintf(stderr, _(""
14283                 " -v                   Be verbose\n"
14284                 " -b superblock        Use alternative superblock\n"
14285                 " -B blocksize         Force blocksize when looking for superblock\n"
14286                 " -j external_journal  Set location of the external journal\n"
14287                 " -l bad_blocks_file   Add to badblocks list\n"
14288                 " -L bad_blocks_file   Set badblocks list\n"
14289                 ));
14290
14291         exit(EXIT_USAGE);
14292 }
14293 #endif
14294
14295 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
14296
14297 static void show_stats(e2fsck_t ctx)
14298 {
14299         ext2_filsys fs = ctx->fs;
14300         int inodes, inodes_used, blocks, blocks_used;
14301         int dir_links;
14302         int num_files, num_links;
14303         int frag_percent;
14304
14305         dir_links = 2 * ctx->fs_directory_count - 1;
14306         num_files = ctx->fs_total_count - dir_links;
14307         num_links = ctx->fs_links_count - dir_links;
14308         inodes = fs->super->s_inodes_count;
14309         inodes_used = (fs->super->s_inodes_count -
14310                        fs->super->s_free_inodes_count);
14311         blocks = fs->super->s_blocks_count;
14312         blocks_used = (fs->super->s_blocks_count -
14313                        fs->super->s_free_blocks_count);
14314
14315         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14316         frag_percent = (frag_percent + 5) / 10;
14317
14318         if (!verbose) {
14319                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14320                        ctx->device_name, inodes_used, inodes,
14321                        frag_percent / 10, frag_percent % 10,
14322                        blocks_used, blocks);
14323                 return;
14324         }
14325         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14326                 100 * inodes_used / inodes);
14327         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14328                 P_E2("", "s", ctx->fs_fragmented),
14329                 frag_percent / 10, frag_percent % 10);
14330         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14331                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14332         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14333                 (int) ((long long) 100 * blocks_used / blocks));
14334         printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14335         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14336         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14337         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14338         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14339         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14340         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14341         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14342         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14343         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14344         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14345         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14346 }
14347
14348 static void check_mount(e2fsck_t ctx)
14349 {
14350         errcode_t       retval;
14351         int             cont;
14352
14353         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14354                                          &ctx->mount_flags);
14355         if (retval) {
14356                 com_err("ext2fs_check_if_mount", retval,
14357                         _("while determining whether %s is mounted."),
14358                         ctx->filesystem_name);
14359                 return;
14360         }
14361
14362         /*
14363          * If the filesystem isn't mounted, or it's the root filesystem
14364          * and it's mounted read-only, then everything's fine.
14365          */
14366         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14367             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14368              (ctx->mount_flags & EXT2_MF_READONLY)))
14369                 return;
14370
14371         if (ctx->options & E2F_OPT_READONLY) {
14372                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
14373                 return;
14374         }
14375
14376         printf(_("%s is mounted.  "), ctx->filesystem_name);
14377         if (!ctx->interactive)
14378                 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14379         printf(_("\n\n\007\007\007\007WARNING!!!  "
14380                "Running e2fsck on a mounted filesystem may cause\n"
14381                "SEVERE filesystem damage.\007\007\007\n\n"));
14382         cont = ask_yn(_("Do you really want to continue"), -1);
14383         if (!cont) {
14384                 printf (_("check aborted.\n"));
14385                 exit (0);
14386         }
14387         return;
14388 }
14389
14390 static int is_on_batt(void)
14391 {
14392         FILE    *f;
14393         DIR     *d;
14394         char    tmp[80], tmp2[80], fname[80];
14395         unsigned int    acflag;
14396         struct dirent*  de;
14397
14398         f = fopen("/proc/apm", "r");
14399         if (f) {
14400                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14401                         acflag = 1;
14402                 fclose(f);
14403                 return (acflag != 1);
14404         }
14405         d = opendir("/proc/acpi/ac_adapter");
14406         if (d) {
14407                 while ((de=readdir(d)) != NULL) {
14408                         if (!strncmp(".", de->d_name, 1))
14409                                 continue;
14410                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14411                                  de->d_name);
14412                         f = fopen(fname, "r");
14413                         if (!f)
14414                                 continue;
14415                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14416                                 tmp[0] = 0;
14417                         fclose(f);
14418                         if (strncmp(tmp, "off-line", 8) == 0) {
14419                                 closedir(d);
14420                                 return 1;
14421                         }
14422                 }
14423                 closedir(d);
14424         }
14425         return 0;
14426 }
14427
14428 /*
14429  * This routine checks to see if a filesystem can be skipped; if so,
14430  * it will exit with EXIT_OK.  Under some conditions it will print a
14431  * message explaining why a check is being forced.
14432  */
14433 static void check_if_skip(e2fsck_t ctx)
14434 {
14435         ext2_filsys fs = ctx->fs;
14436         const char *reason = NULL;
14437         unsigned int reason_arg = 0;
14438         long next_check;
14439         int batt = is_on_batt();
14440         time_t now = time(0);
14441
14442         if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14443             cflag || swapfs)
14444                 return;
14445
14446         if ((fs->super->s_state & EXT2_ERROR_FS) ||
14447             !ext2fs_test_valid(fs))
14448                 reason = _(" contains a file system with errors");
14449         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14450                 reason = _(" was not cleanly unmounted");
14451         else if ((fs->super->s_max_mnt_count > 0) &&
14452                  (fs->super->s_mnt_count >=
14453                   (unsigned) fs->super->s_max_mnt_count)) {
14454                 reason = _(" has been mounted %u times without being checked");
14455                 reason_arg = fs->super->s_mnt_count;
14456                 if (batt && (fs->super->s_mnt_count <
14457                              (unsigned) fs->super->s_max_mnt_count*2))
14458                         reason = 0;
14459         } else if (fs->super->s_checkinterval &&
14460                    ((now - fs->super->s_lastcheck) >=
14461                     fs->super->s_checkinterval)) {
14462                 reason = _(" has gone %u days without being checked");
14463                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14464                 if (batt && ((now - fs->super->s_lastcheck) <
14465                              fs->super->s_checkinterval*2))
14466                         reason = 0;
14467         }
14468         if (reason) {
14469                 fputs(ctx->device_name, stdout);
14470                 printf(reason, reason_arg);
14471                 fputs(_(", check forced.\n"), stdout);
14472                 return;
14473         }
14474         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14475                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14476                fs->super->s_inodes_count,
14477                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14478                fs->super->s_blocks_count);
14479         next_check = 100000;
14480         if (fs->super->s_max_mnt_count > 0) {
14481                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14482                 if (next_check <= 0)
14483                         next_check = 1;
14484         }
14485         if (fs->super->s_checkinterval &&
14486             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14487                 next_check = 1;
14488         if (next_check <= 5) {
14489                 if (next_check == 1)
14490                         fputs(_(" (check after next mount)"), stdout);
14491                 else
14492                         printf(_(" (check in %ld mounts)"), next_check);
14493         }
14494         fputc('\n', stdout);
14495         ext2fs_close(fs);
14496         ctx->fs = NULL;
14497         e2fsck_free_context(ctx);
14498         exit(EXIT_OK);
14499 }
14500
14501 /*
14502  * For completion notice
14503  */
14504 struct percent_tbl {
14505         int     max_pass;
14506         int     table[32];
14507 };
14508 static const struct percent_tbl e2fsck_tbl = {
14509         5, { 0, 70, 90, 92,  95, 100 }
14510 };
14511
14512 static char bar[128], spaces[128];
14513
14514 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14515                           int max)
14516 {
14517         float   percent;
14518
14519         if (pass <= 0)
14520                 return 0.0;
14521         if (pass > tbl->max_pass || max == 0)
14522                 return 100.0;
14523         percent = ((float) curr) / ((float) max);
14524         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14525                 + tbl->table[pass-1]);
14526 }
14527
14528 void e2fsck_clear_progbar(e2fsck_t ctx)
14529 {
14530         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14531                 return;
14532
14533         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14534                ctx->stop_meta);
14535         fflush(stdout);
14536         ctx->flags &= ~E2F_FLAG_PROG_BAR;
14537 }
14538
14539 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14540                            unsigned int dpynum)
14541 {
14542         static const char spinner[] = "\\|/-";
14543         int     i;
14544         unsigned int    tick;
14545         struct timeval  tv;
14546         int dpywidth;
14547         int fixed_percent;
14548
14549         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14550                 return 0;
14551
14552         /*
14553          * Calculate the new progress position.  If the
14554          * percentage hasn't changed, then we skip out right
14555          * away.
14556          */
14557         fixed_percent = (int) ((10 * percent) + 0.5);
14558         if (ctx->progress_last_percent == fixed_percent)
14559                 return 0;
14560         ctx->progress_last_percent = fixed_percent;
14561
14562         /*
14563          * If we've already updated the spinner once within
14564          * the last 1/8th of a second, no point doing it
14565          * again.
14566          */
14567         gettimeofday(&tv, NULL);
14568         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
14569         if ((tick == ctx->progress_last_time) &&
14570             (fixed_percent != 0) && (fixed_percent != 1000))
14571                 return 0;
14572         ctx->progress_last_time = tick;
14573
14574         /*
14575          * Advance the spinner, and note that the progress bar
14576          * will be on the screen
14577          */
14578         ctx->progress_pos = (ctx->progress_pos+1) & 3;
14579         ctx->flags |= E2F_FLAG_PROG_BAR;
14580
14581         dpywidth = 66 - strlen(label);
14582         dpywidth = 8 * (dpywidth / 8);
14583         if (dpynum)
14584                 dpywidth -= 8;
14585
14586         i = ((percent * dpywidth) + 50) / 100;
14587         printf("%s%s: |%s%s", ctx->start_meta, label,
14588                bar + (sizeof(bar) - (i+1)),
14589                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
14590         if (fixed_percent == 1000)
14591                 fputc('|', stdout);
14592         else
14593                 fputc(spinner[ctx->progress_pos & 3], stdout);
14594         printf(" %4.1f%%  ", percent);
14595         if (dpynum)
14596                 printf("%u\r", dpynum);
14597         else
14598                 fputs(" \r", stdout);
14599         fputs(ctx->stop_meta, stdout);
14600
14601         if (fixed_percent == 1000)
14602                 e2fsck_clear_progbar(ctx);
14603         fflush(stdout);
14604
14605         return 0;
14606 }
14607
14608 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
14609                                   unsigned long cur, unsigned long max)
14610 {
14611         char buf[80];
14612         float percent;
14613
14614         if (pass == 0)
14615                 return 0;
14616
14617         if (ctx->progress_fd) {
14618                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
14619                 write(ctx->progress_fd, buf, strlen(buf));
14620         } else {
14621                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
14622                 e2fsck_simple_progress(ctx, ctx->device_name,
14623                                        percent, 0);
14624         }
14625         return 0;
14626 }
14627
14628 static void reserve_stdio_fds(void)
14629 {
14630         int     fd;
14631
14632         while (1) {
14633                 fd = open(bb_dev_null, O_RDWR);
14634                 if (fd > 2)
14635                         break;
14636                 if (fd < 0) {
14637                         fprintf(stderr, _("ERROR: Couldn't open "
14638                                 "/dev/null (%s)\n"),
14639                                 strerror(errno));
14640                         break;
14641                 }
14642         }
14643         close(fd);
14644 }
14645
14646 static void signal_progress_on(int sig FSCK_ATTR((unused)))
14647 {
14648         e2fsck_t ctx = e2fsck_global_ctx;
14649
14650         if (!ctx)
14651                 return;
14652
14653         ctx->progress = e2fsck_update_progress;
14654         ctx->progress_fd = 0;
14655 }
14656
14657 static void signal_progress_off(int sig FSCK_ATTR((unused)))
14658 {
14659         e2fsck_t ctx = e2fsck_global_ctx;
14660
14661         if (!ctx)
14662                 return;
14663
14664         e2fsck_clear_progbar(ctx);
14665         ctx->progress = 0;
14666 }
14667
14668 static void signal_cancel(int sig FSCK_ATTR((unused)))
14669 {
14670         e2fsck_t ctx = e2fsck_global_ctx;
14671
14672         if (!ctx)
14673                 exit(FSCK_CANCELED);
14674
14675         ctx->flags |= E2F_FLAG_CANCEL;
14676 }
14677
14678 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
14679 {
14680         char    *buf, *token, *next, *p, *arg;
14681         int     ea_ver;
14682         int     extended_usage = 0;
14683
14684         buf = string_copy(opts, 0);
14685         for (token = buf; token && *token; token = next) {
14686                 p = strchr(token, ',');
14687                 next = 0;
14688                 if (p) {
14689                         *p = 0;
14690                         next = p+1;
14691                 }
14692                 arg = strchr(token, '=');
14693                 if (arg) {
14694                         *arg = 0;
14695                         arg++;
14696                 }
14697                 if (strcmp(token, "ea_ver") == 0) {
14698                         if (!arg) {
14699                                 extended_usage++;
14700                                 continue;
14701                         }
14702                         ea_ver = strtoul(arg, &p, 0);
14703                         if (*p ||
14704                             ((ea_ver != 1) && (ea_ver != 2))) {
14705                                 fprintf(stderr,
14706                                         _("Invalid EA version.\n"));
14707                                 extended_usage++;
14708                                 continue;
14709                         }
14710                         ctx->ext_attr_ver = ea_ver;
14711                 } else {
14712                         fprintf(stderr, _("Unknown extended option: %s\n"),
14713                                 token);
14714                         extended_usage++;
14715                 }
14716         }
14717         if (extended_usage) {
14718                 bb_error_msg_and_die(
14719                         "Extended options are separated by commas, "
14720                         "and may take an argument which\n"
14721                         "is set off by an equals ('=') sign.  "
14722                         "Valid extended options are:\n"
14723                         "\tea_ver=<ea_version (1 or 2)>\n\n");
14724         }
14725 }
14726
14727
14728 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
14729 {
14730         int             flush = 0;
14731         int             c, fd;
14732 #ifdef MTRACE
14733         extern void     *mallwatch;
14734 #endif
14735         e2fsck_t        ctx;
14736         errcode_t       retval;
14737         struct sigaction        sa;
14738         char            *extended_opts = 0;
14739
14740         retval = e2fsck_allocate_context(&ctx);
14741         if (retval)
14742                 return retval;
14743
14744         *ret_ctx = ctx;
14745
14746         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
14747         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
14748         if (isatty(0) && isatty(1)) {
14749                 ctx->interactive = 1;
14750         } else {
14751                 ctx->start_meta[0] = '\001';
14752                 ctx->stop_meta[0] = '\002';
14753         }
14754         memset(bar, '=', sizeof(bar)-1);
14755         memset(spaces, ' ', sizeof(spaces)-1);
14756         blkid_get_cache(&ctx->blkid, NULL);
14757
14758         if (argc && *argv)
14759                 ctx->program_name = *argv;
14760         else
14761                 ctx->program_name = "e2fsck";
14762         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
14763                 switch (c) {
14764                 case 'C':
14765                         ctx->progress = e2fsck_update_progress;
14766                         ctx->progress_fd = atoi(optarg);
14767                         if (!ctx->progress_fd)
14768                                 break;
14769                         /* Validate the file descriptor to avoid disasters */
14770                         fd = dup(ctx->progress_fd);
14771                         if (fd < 0) {
14772                                 fprintf(stderr,
14773                                 _("Error validating file descriptor %d: %s\n"),
14774                                         ctx->progress_fd,
14775                                         error_message(errno));
14776                                 fatal_error(ctx,
14777                         _("Invalid completion information file descriptor"));
14778                         } else
14779                                 close(fd);
14780                         break;
14781                 case 'D':
14782                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
14783                         break;
14784                 case 'E':
14785                         extended_opts = optarg;
14786                         break;
14787                 case 'p':
14788                 case 'a':
14789                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
14790                         conflict_opt:
14791                                 fatal_error(ctx,
14792         _("Only one the options -p/-a, -n or -y may be specified."));
14793                         }
14794                         ctx->options |= E2F_OPT_PREEN;
14795                         break;
14796                 case 'n':
14797                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
14798                                 goto conflict_opt;
14799                         ctx->options |= E2F_OPT_NO;
14800                         break;
14801                 case 'y':
14802                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
14803                                 goto conflict_opt;
14804                         ctx->options |= E2F_OPT_YES;
14805                         break;
14806                 case 't':
14807 #ifdef RESOURCE_TRACK
14808                         if (ctx->options & E2F_OPT_TIME)
14809                                 ctx->options |= E2F_OPT_TIME2;
14810                         else
14811                                 ctx->options |= E2F_OPT_TIME;
14812 #else
14813                         fprintf(stderr, _("The -t option is not "
14814                                 "supported on this version of e2fsck.\n"));
14815 #endif
14816                         break;
14817                 case 'c':
14818                         if (cflag++)
14819                                 ctx->options |= E2F_OPT_WRITECHECK;
14820                         ctx->options |= E2F_OPT_CHECKBLOCKS;
14821                         break;
14822                 case 'r':
14823                         /* What we do by default, anyway! */
14824                         break;
14825                 case 'b':
14826                         ctx->use_superblock = atoi(optarg);
14827                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
14828                         break;
14829                 case 'B':
14830                         ctx->blocksize = atoi(optarg);
14831                         break;
14832                 case 'I':
14833                         ctx->inode_buffer_blocks = atoi(optarg);
14834                         break;
14835                 case 'j':
14836                         ctx->journal_name = string_copy(optarg, 0);
14837                         break;
14838                 case 'P':
14839                         ctx->process_inode_size = atoi(optarg);
14840                         break;
14841                 case 'L':
14842                         replace_bad_blocks++;
14843                 case 'l':
14844                         bad_blocks_file = string_copy(optarg, 0);
14845                         break;
14846                 case 'd':
14847                         ctx->options |= E2F_OPT_DEBUG;
14848                         break;
14849                 case 'f':
14850                         ctx->options |= E2F_OPT_FORCE;
14851                         break;
14852                 case 'F':
14853                         flush = 1;
14854                         break;
14855                 case 'v':
14856                         verbose = 1;
14857                         break;
14858                 case 'V':
14859                         show_version_only = 1;
14860                         break;
14861 #ifdef MTRACE
14862                 case 'M':
14863                         mallwatch = (void *) strtol(optarg, NULL, 0);
14864                         break;
14865 #endif
14866                 case 'N':
14867                         ctx->device_name = optarg;
14868                         break;
14869 #ifdef ENABLE_SWAPFS
14870                 case 's':
14871                         normalize_swapfs = 1;
14872                 case 'S':
14873                         swapfs = 1;
14874                         break;
14875 #else
14876                 case 's':
14877                 case 'S':
14878                         fprintf(stderr, _("Byte-swapping filesystems "
14879                                           "not compiled in this version "
14880                                           "of e2fsck\n"));
14881                         exit(1);
14882 #endif
14883                 case 'k':
14884                         keep_bad_blocks++;
14885                         break;
14886                 default:
14887                         usage();
14888                 }
14889         if (show_version_only)
14890                 return 0;
14891         if (optind != argc - 1)
14892                 usage();
14893         if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
14894             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
14895                 ctx->options |= E2F_OPT_READONLY;
14896         ctx->io_options = strchr(argv[optind], '?');
14897         if (ctx->io_options)
14898                 *ctx->io_options++ = 0;
14899         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
14900         if (!ctx->filesystem_name) {
14901                 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
14902                         argv[optind]);
14903                 fatal_error(ctx, 0);
14904         }
14905         if (extended_opts)
14906                 parse_extended_opts(ctx, extended_opts);
14907
14908         if (flush) {
14909                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
14910                 if (fd < 0) {
14911                         com_err("open", errno,
14912                                 _("while opening %s for flushing"),
14913                                 ctx->filesystem_name);
14914                         fatal_error(ctx, 0);
14915                 }
14916                 if ((retval = ext2fs_sync_device(fd, 1))) {
14917                         com_err("ext2fs_sync_device", retval,
14918                                 _("while trying to flush %s"),
14919                                 ctx->filesystem_name);
14920                         fatal_error(ctx, 0);
14921                 }
14922                 close(fd);
14923         }
14924 #ifdef ENABLE_SWAPFS
14925         if (swapfs) {
14926                 if (cflag || bad_blocks_file) {
14927                         fprintf(stderr, _("Incompatible options not "
14928                                           "allowed when byte-swapping.\n"));
14929                         exit(EXIT_USAGE);
14930                 }
14931         }
14932 #endif
14933         if (cflag && bad_blocks_file) {
14934                 fprintf(stderr, _("The -c and the -l/-L options may "
14935                                   "not be both used at the same time.\n"));
14936                 exit(EXIT_USAGE);
14937         }
14938         /*
14939          * Set up signal action
14940          */
14941         memset(&sa, 0, sizeof(struct sigaction));
14942         sa.sa_handler = signal_cancel;
14943         sigaction(SIGINT, &sa, 0);
14944         sigaction(SIGTERM, &sa, 0);
14945 #ifdef SA_RESTART
14946         sa.sa_flags = SA_RESTART;
14947 #endif
14948         e2fsck_global_ctx = ctx;
14949         sa.sa_handler = signal_progress_on;
14950         sigaction(SIGUSR1, &sa, 0);
14951         sa.sa_handler = signal_progress_off;
14952         sigaction(SIGUSR2, &sa, 0);
14953
14954         /* Update our PATH to include /sbin if we need to run badblocks  */
14955         if (cflag)
14956                 e2fs_set_sbin_path();
14957 #ifdef __CONFIG_JBD_DEBUG__E2FS
14958         if (getenv("E2FSCK_JBD_DEBUG"))
14959                 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
14960 #endif
14961         return 0;
14962 }
14963
14964 static const char my_ver_string[] = E2FSPROGS_VERSION;
14965 static const char my_ver_date[] = E2FSPROGS_DATE;
14966
14967 int e2fsck_main (int argc, char *argv[])
14968 {
14969         errcode_t       retval;
14970         int             exit_value = EXIT_OK;
14971         ext2_filsys     fs = 0;
14972         io_manager      io_ptr;
14973         struct ext2_super_block *sb;
14974         const char      *lib_ver_date;
14975         int             my_ver, lib_ver;
14976         e2fsck_t        ctx;
14977         struct problem_context pctx;
14978         int flags, run_result;
14979
14980         clear_problem_context(&pctx);
14981 #ifdef MTRACE
14982         mtrace();
14983 #endif
14984 #ifdef MCHECK
14985         mcheck(0);
14986 #endif
14987 #ifdef ENABLE_NLS
14988         setlocale(LC_MESSAGES, "");
14989         setlocale(LC_CTYPE, "");
14990         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
14991         textdomain(NLS_CAT_NAME);
14992 #endif
14993         my_ver = ext2fs_parse_version_string(my_ver_string);
14994         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
14995         if (my_ver > lib_ver) {
14996                 fprintf( stderr, _("Error: ext2fs library version "
14997                         "out of date!\n"));
14998                 show_version_only++;
14999         }
15000
15001         retval = PRS(argc, argv, &ctx);
15002         if (retval) {
15003                 com_err("e2fsck", retval,
15004                         _("while trying to initialize program"));
15005                 exit(EXIT_ERROR);
15006         }
15007         reserve_stdio_fds();
15008
15009 #ifdef RESOURCE_TRACK
15010         init_resource_track(&ctx->global_rtrack);
15011 #endif
15012
15013         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15014                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15015                          my_ver_date);
15016
15017         if (show_version_only) {
15018                 fprintf(stderr, _("\tUsing %s, %s\n"),
15019                         error_message(EXT2_ET_BASE), lib_ver_date);
15020                 exit(EXIT_OK);
15021         }
15022
15023         check_mount(ctx);
15024
15025         if (!(ctx->options & E2F_OPT_PREEN) &&
15026             !(ctx->options & E2F_OPT_NO) &&
15027             !(ctx->options & E2F_OPT_YES)) {
15028                 if (!ctx->interactive)
15029                         fatal_error(ctx,
15030                                     _("need terminal for interactive repairs"));
15031         }
15032         ctx->superblock = ctx->use_superblock;
15033 restart:
15034 #ifdef CONFIG_TESTIO_DEBUG
15035         io_ptr = test_io_manager;
15036         test_io_backing_manager = unix_io_manager;
15037 #else
15038         io_ptr = unix_io_manager;
15039 #endif
15040         flags = 0;
15041         if ((ctx->options & E2F_OPT_READONLY) == 0)
15042                 flags |= EXT2_FLAG_RW;
15043
15044         if (ctx->superblock && ctx->blocksize) {
15045                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15046                                       flags, ctx->superblock, ctx->blocksize,
15047                                       io_ptr, &fs);
15048         } else if (ctx->superblock) {
15049                 int blocksize;
15050                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15051                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15052                         retval = ext2fs_open2(ctx->filesystem_name,
15053                                               ctx->io_options, flags,
15054                                               ctx->superblock, blocksize,
15055                                               io_ptr, &fs);
15056                         if (!retval)
15057                                 break;
15058                 }
15059         } else
15060                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15061                                       flags, 0, 0, io_ptr, &fs);
15062         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15063             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15064             ((retval == EXT2_ET_BAD_MAGIC) ||
15065              ((retval == 0) && ext2fs_check_desc(fs)))) {
15066                 if (!fs || (fs->group_desc_count > 1)) {
15067                         printf(_("%s trying backup blocks...\n"),
15068                                retval ? _("Couldn't find ext2 superblock,") :
15069                                _("Group descriptors look bad..."));
15070                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15071                         if (fs)
15072                                 ext2fs_close(fs);
15073                         goto restart;
15074                 }
15075         }
15076         if (retval) {
15077                 com_err(ctx->program_name, retval, _("while trying to open %s"),
15078                         ctx->filesystem_name);
15079                 if (retval == EXT2_ET_REV_TOO_HIGH) {
15080                         printf(_("The filesystem revision is apparently "
15081                                "too high for this version of e2fsck.\n"
15082                                "(Or the filesystem superblock "
15083                                "is corrupt)\n\n"));
15084                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15085                 } else if (retval == EXT2_ET_SHORT_READ)
15086                         printf(_("Could this be a zero-length partition?\n"));
15087                 else if ((retval == EPERM) || (retval == EACCES))
15088                         printf(_("You must have %s access to the "
15089                                "filesystem or be root\n"),
15090                                (ctx->options & E2F_OPT_READONLY) ?
15091                                "r/o" : "r/w");
15092                 else if (retval == ENXIO)
15093                         printf(_("Possibly non-existent or swap device?\n"));
15094 #ifdef EROFS
15095                 else if (retval == EROFS)
15096                         printf(_("Disk write-protected; use the -n option "
15097                                "to do a read-only\n"
15098                                "check of the device.\n"));
15099 #endif
15100                 else
15101                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15102                 fatal_error(ctx, 0);
15103         }
15104         ctx->fs = fs;
15105         fs->priv_data = ctx;
15106         sb = fs->super;
15107         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15108                 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15109                         _("while trying to open %s"),
15110                         ctx->filesystem_name);
15111         get_newer:
15112                 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15113         }
15114
15115         /*
15116          * Set the device name, which is used whenever we print error
15117          * or informational messages to the user.
15118          */
15119         if (ctx->device_name == 0 &&
15120             (sb->s_volume_name[0] != 0)) {
15121                 ctx->device_name = string_copy(sb->s_volume_name,
15122                                                sizeof(sb->s_volume_name));
15123         }
15124         if (ctx->device_name == 0)
15125                 ctx->device_name = ctx->filesystem_name;
15126
15127         /*
15128          * Make sure the ext3 superblock fields are consistent.
15129          */
15130         retval = e2fsck_check_ext3_journal(ctx);
15131         if (retval) {
15132                 com_err(ctx->program_name, retval,
15133                         _("while checking ext3 journal for %s"),
15134                         ctx->device_name);
15135                 fatal_error(ctx, 0);
15136         }
15137
15138         /*
15139          * Check to see if we need to do ext3-style recovery.  If so,
15140          * do it, and then restart the fsck.
15141          */
15142         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15143                 if (ctx->options & E2F_OPT_READONLY) {
15144                         printf(_("Warning: skipping journal recovery "
15145                                  "because doing a read-only filesystem "
15146                                  "check.\n"));
15147                         io_channel_flush(ctx->fs->io);
15148                 } else {
15149                         if (ctx->flags & E2F_FLAG_RESTARTED) {
15150                                 /*
15151                                  * Whoops, we attempted to run the
15152                                  * journal twice.  This should never
15153                                  * happen, unless the hardware or
15154                                  * device driver is being bogus.
15155                                  */
15156                                 com_err(ctx->program_name, 0,
15157                                         _("unable to set superblock flags on %s\n"), ctx->device_name);
15158                                 fatal_error(ctx, 0);
15159                         }
15160                         retval = e2fsck_run_ext3_journal(ctx);
15161                         if (retval) {
15162                                 com_err(ctx->program_name, retval,
15163                                 _("while recovering ext3 journal of %s"),
15164                                         ctx->device_name);
15165                                 fatal_error(ctx, 0);
15166                         }
15167                         ext2fs_close(ctx->fs);
15168                         ctx->fs = 0;
15169                         ctx->flags |= E2F_FLAG_RESTARTED;
15170                         goto restart;
15171                 }
15172         }
15173
15174         /*
15175          * Check for compatibility with the feature sets.  We need to
15176          * be more stringent than ext2fs_open().
15177          */
15178         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15179             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15180                 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15181                         "(%s)", ctx->device_name);
15182                 goto get_newer;
15183         }
15184         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15185                 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15186                         "(%s)", ctx->device_name);
15187                 goto get_newer;
15188         }
15189 #ifdef ENABLE_COMPRESSION
15190         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15191                 com_err(ctx->program_name, 0,
15192                         _("Warning: compression support is experimental.\n"));
15193 #endif
15194 #ifndef ENABLE_HTREE
15195         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15196                 com_err(ctx->program_name, 0,
15197                         _("E2fsck not compiled with HTREE support,\n\t"
15198                           "but filesystem %s has HTREE directories.\n"),
15199                         ctx->device_name);
15200                 goto get_newer;
15201         }
15202 #endif
15203
15204         /*
15205          * If the user specified a specific superblock, presumably the
15206          * master superblock has been trashed.  So we mark the
15207          * superblock as dirty, so it can be written out.
15208          */
15209         if (ctx->superblock &&
15210             !(ctx->options & E2F_OPT_READONLY))
15211                 ext2fs_mark_super_dirty(fs);
15212
15213         /*
15214          * We only update the master superblock because (a) paranoia;
15215          * we don't want to corrupt the backup superblocks, and (b) we
15216          * don't need to update the mount count and last checked
15217          * fields in the backup superblock (the kernel doesn't
15218          * update the backup superblocks anyway).
15219          */
15220         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15221
15222         ehandler_init(fs->io);
15223
15224         if (ctx->superblock)
15225                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15226         ext2fs_mark_valid(fs);
15227         check_super_block(ctx);
15228         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15229                 fatal_error(ctx, 0);
15230         check_if_skip(ctx);
15231         if (bad_blocks_file)
15232                 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15233         else if (cflag)
15234                 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15235         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15236                 fatal_error(ctx, 0);
15237 #ifdef ENABLE_SWAPFS
15238
15239 #ifdef WORDS_BIGENDIAN
15240 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
15241 #else
15242 #define NATIVE_FLAG 0
15243 #endif
15244
15245
15246         if (normalize_swapfs) {
15247                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
15248                         fprintf(stderr, _("%s: Filesystem byte order "
15249                                 "already normalized.\n"), ctx->device_name);
15250                         fatal_error(ctx, 0);
15251                 }
15252         }
15253         if (swapfs) {
15254                 swap_filesys(ctx);
15255                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15256                         fatal_error(ctx, 0);
15257         }
15258 #endif
15259
15260         /*
15261          * Mark the system as valid, 'til proven otherwise
15262          */
15263         ext2fs_mark_valid(fs);
15264
15265         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15266         if (retval) {
15267                 com_err(ctx->program_name, retval,
15268                         _("while reading bad blocks inode"));
15269                 preenhalt(ctx);
15270                 printf(_("This doesn't bode well,"
15271                          " but we'll try to go on...\n"));
15272         }
15273
15274         run_result = e2fsck_run(ctx);
15275         e2fsck_clear_progbar(ctx);
15276         if (run_result == E2F_FLAG_RESTART) {
15277                 printf(_("Restarting e2fsck from the beginning...\n"));
15278                 retval = e2fsck_reset_context(ctx);
15279                 if (retval) {
15280                         com_err(ctx->program_name, retval,
15281                                 _("while resetting context"));
15282                         fatal_error(ctx, 0);
15283                 }
15284                 ext2fs_close(fs);
15285                 goto restart;
15286         }
15287         if (run_result & E2F_FLAG_CANCEL) {
15288                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15289                        ctx->device_name : ctx->filesystem_name);
15290                 exit_value |= FSCK_CANCELED;
15291         }
15292         if (run_result & E2F_FLAG_ABORT)
15293                 fatal_error(ctx, _("aborted"));
15294
15295 #ifdef MTRACE
15296         mtrace_print("Cleanup");
15297 #endif
15298         if (ext2fs_test_changed(fs)) {
15299                 exit_value |= EXIT_NONDESTRUCT;
15300                 if (!(ctx->options & E2F_OPT_PREEN))
15301                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15302                                ctx->device_name);
15303                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15304                         printf(_("%s: ***** REBOOT LINUX *****\n"),
15305                                ctx->device_name);
15306                         exit_value |= EXIT_DESTRUCT;
15307                 }
15308         }
15309         if (!ext2fs_test_valid(fs)) {
15310                 printf(_("\n%s: ********** WARNING: Filesystem still has "
15311                          "errors **********\n\n"), ctx->device_name);
15312                 exit_value |= EXIT_UNCORRECTED;
15313                 exit_value &= ~EXIT_NONDESTRUCT;
15314         }
15315         if (exit_value & FSCK_CANCELED)
15316                 exit_value &= ~EXIT_NONDESTRUCT;
15317         else {
15318                 show_stats(ctx);
15319                 if (!(ctx->options & E2F_OPT_READONLY)) {
15320                         if (ext2fs_test_valid(fs)) {
15321                                 if (!(sb->s_state & EXT2_VALID_FS))
15322                                         exit_value |= EXIT_NONDESTRUCT;
15323                                 sb->s_state = EXT2_VALID_FS;
15324                         } else
15325                                 sb->s_state &= ~EXT2_VALID_FS;
15326                         sb->s_mnt_count = 0;
15327                         sb->s_lastcheck = time(NULL);
15328                         ext2fs_mark_super_dirty(fs);
15329                 }
15330         }
15331
15332         e2fsck_write_bitmaps(ctx);
15333
15334         ext2fs_close(fs);
15335         ctx->fs = NULL;
15336         free(ctx->filesystem_name);
15337         free(ctx->journal_name);
15338         e2fsck_free_context(ctx);
15339
15340 #ifdef RESOURCE_TRACK
15341         if (ctx->options & E2F_OPT_TIME)
15342                 print_resource_track(NULL, &ctx->global_rtrack);
15343 #endif
15344
15345         return exit_value;
15346 }