Convert a chunk of usage.h to USE_ and SKIP_ (more to do there), and fix a
[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 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
80                               struct ext2_inode * inode, const char * proc);
81 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
82                                struct ext2_inode * inode, const char * proc);
83 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
84                            const char *name, io_manager manager);
85
86 /* unix.c */
87 static void e2fsck_clear_progbar(e2fsck_t ctx);
88 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
89                                   float percent, unsigned int dpynum);
90
91
92 /*
93  * problem.h --- e2fsck problem error codes
94  */
95
96 typedef __u32 problem_t;
97
98 struct problem_context {
99         errcode_t       errcode;
100         ext2_ino_t ino, ino2, dir;
101         struct ext2_inode *inode;
102         struct ext2_dir_entry *dirent;
103         blk_t   blk, blk2;
104         e2_blkcnt_t     blkcount;
105         int             group;
106         __u64   num;
107         const char *str;
108 };
109
110 /*
111  * We define a set of "latch groups"; these are problems which are
112  * handled as a set.  The user answers once for a particular latch
113  * group.
114  */
115 #define PR_LATCH_MASK         0x0ff0 /* Latch mask */
116 #define PR_LATCH_BLOCK        0x0010 /* Latch for illegal blocks (pass 1) */
117 #define PR_LATCH_BBLOCK       0x0020 /* Latch for bad block inode blocks (pass 1) */
118 #define PR_LATCH_IBITMAP      0x0030 /* Latch for pass 5 inode bitmap proc. */
119 #define PR_LATCH_BBITMAP      0x0040 /* Latch for pass 5 inode bitmap proc. */
120 #define PR_LATCH_RELOC        0x0050 /* Latch for superblock relocate hint */
121 #define PR_LATCH_DBLOCK       0x0060 /* Latch for pass 1b dup block headers */
122 #define PR_LATCH_LOW_DTIME    0x0070 /* Latch for pass1 orphaned list refugees */
123 #define PR_LATCH_TOOBIG       0x0080 /* Latch for file to big errors */
124 #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
125
126 #define PR_LATCH(x)     ((((x) & PR_LATCH_MASK) >> 4) - 1)
127
128 /*
129  * Latch group descriptor flags
130  */
131 #define PRL_YES         0x0001  /* Answer yes */
132 #define PRL_NO          0x0002  /* Answer no */
133 #define PRL_LATCHED     0x0004  /* The latch group is latched */
134 #define PRL_SUPPRESS    0x0008  /* Suppress all latch group questions */
135
136 #define PRL_VARIABLE    0x000f  /* All the flags that need to be reset */
137
138 /*
139  * Pre-Pass 1 errors
140  */
141
142 /* Block bitmap not in group */
143 #define PR_0_BB_NOT_GROUP       0x000001
144
145 /* Inode bitmap not in group */
146 #define PR_0_IB_NOT_GROUP       0x000002
147
148 /* Inode table not in group */
149 #define PR_0_ITABLE_NOT_GROUP   0x000003
150
151 /* Superblock corrupt */
152 #define PR_0_SB_CORRUPT         0x000004
153
154 /* Filesystem size is wrong */
155 #define PR_0_FS_SIZE_WRONG      0x000005
156
157 /* Fragments not supported */
158 #define PR_0_NO_FRAGMENTS       0x000006
159
160 /* Bad blocks_per_group */
161 #define PR_0_BLOCKS_PER_GROUP   0x000007
162
163 /* Bad first_data_block */
164 #define PR_0_FIRST_DATA_BLOCK   0x000008
165
166 /* Adding UUID to filesystem */
167 #define PR_0_ADD_UUID           0x000009
168
169 /* Relocate hint */
170 #define PR_0_RELOCATE_HINT      0x00000A
171
172 /* Miscellaneous superblock corruption */
173 #define PR_0_MISC_CORRUPT_SUPER 0x00000B
174
175 /* Error determing physical device size of filesystem */
176 #define PR_0_GETSIZE_ERROR      0x00000C
177
178 /* Inode count in the superblock incorrect */
179 #define PR_0_INODE_COUNT_WRONG  0x00000D
180
181 /* The Hurd does not support the filetype feature */
182 #define PR_0_HURD_CLEAR_FILETYPE 0x00000E
183
184 /* Journal inode is invalid */
185 #define PR_0_JOURNAL_BAD_INODE  0x00000F
186
187 /* The external journal has multiple filesystems (which we can't handle yet) */
188 #define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010
189
190 /* Can't find external journal */
191 #define PR_0_CANT_FIND_JOURNAL  0x000011
192
193 /* External journal has bad superblock */
194 #define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012
195
196 /* Superblock has a bad journal UUID */
197 #define PR_0_JOURNAL_BAD_UUID   0x000013
198
199 /* Journal has an unknown superblock type */
200 #define PR_0_JOURNAL_UNSUPP_SUPER 0x000014
201
202 /* Journal superblock is corrupt */
203 #define PR_0_JOURNAL_BAD_SUPER  0x000015
204
205 /* Journal superblock is corrupt */
206 #define PR_0_JOURNAL_HAS_JOURNAL 0x000016
207
208 /* Superblock has recovery flag set but no journal */
209 #define PR_0_JOURNAL_RECOVER_SET 0x000017
210
211 /* Journal has data, but recovery flag is clear */
212 #define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018
213
214 /* Ask if we should clear the journal */
215 #define PR_0_JOURNAL_RESET_JOURNAL 0x000019
216
217 /* Filesystem revision is 0, but feature flags are set */
218 #define PR_0_FS_REV_LEVEL       0x00001A
219
220 /* Clearing orphan inode */
221 #define PR_0_ORPHAN_CLEAR_INODE                 0x000020
222
223 /* Illegal block found in orphaned inode */
224 #define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM           0x000021
225
226 /* Already cleared block found in orphaned inode */
227 #define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK       0x000022
228
229 /* Illegal orphan inode in superblock */
230 #define PR_0_ORPHAN_ILLEGAL_HEAD_INODE          0x000023
231
232 /* Illegal inode in orphaned inode list */
233 #define PR_0_ORPHAN_ILLEGAL_INODE               0x000024
234
235 /* Journal has unsupported read-only feature - abort */
236 #define PR_0_JOURNAL_UNSUPP_ROCOMPAT            0x000025
237
238 /* Journal has unsupported incompatible feature - abort */
239 #define PR_0_JOURNAL_UNSUPP_INCOMPAT            0x000026
240
241 /* Journal has unsupported version number */
242 #define PR_0_JOURNAL_UNSUPP_VERSION             0x000027
243
244 /* Moving journal to hidden file */
245 #define PR_0_MOVE_JOURNAL                       0x000028
246
247 /* Error moving journal */
248 #define PR_0_ERR_MOVE_JOURNAL                   0x000029
249
250 /* Clearing V2 journal superblock */
251 #define PR_0_CLEAR_V2_JOURNAL                   0x00002A
252
253 /* Run journal anyway */
254 #define PR_0_JOURNAL_RUN                        0x00002B
255
256 /* Run journal anyway by default */
257 #define PR_0_JOURNAL_RUN_DEFAULT                0x00002C
258
259 /* Backup journal inode blocks */
260 #define PR_0_BACKUP_JNL                         0x00002D
261
262 /* Reserved blocks w/o resize_inode */
263 #define PR_0_NONZERO_RESERVED_GDT_BLOCKS        0x00002E
264
265 /* Resize_inode not enabled, but resize inode is non-zero */
266 #define PR_0_CLEAR_RESIZE_INODE                 0x00002F
267
268 /* Resize inode invalid */
269 #define PR_0_RESIZE_INODE_INVALID               0x000030
270
271 /*
272  * Pass 1 errors
273  */
274
275 /* Pass 1: Checking inodes, blocks, and sizes */
276 #define PR_1_PASS_HEADER                0x010000
277
278 /* Root directory is not an inode */
279 #define PR_1_ROOT_NO_DIR                0x010001
280
281 /* Root directory has dtime set */
282 #define PR_1_ROOT_DTIME                 0x010002
283
284 /* Reserved inode has bad mode */
285 #define PR_1_RESERVED_BAD_MODE          0x010003
286
287 /* Deleted inode has zero dtime */
288 #define PR_1_ZERO_DTIME                 0x010004
289
290 /* Inode in use, but dtime set */
291 #define PR_1_SET_DTIME                  0x010005
292
293 /* Zero-length directory */
294 #define PR_1_ZERO_LENGTH_DIR            0x010006
295
296 /* Block bitmap conflicts with some other fs block */
297 #define PR_1_BB_CONFLICT                0x010007
298
299 /* Inode bitmap conflicts with some other fs block */
300 #define PR_1_IB_CONFLICT                0x010008
301
302 /* Inode table conflicts with some other fs block */
303 #define PR_1_ITABLE_CONFLICT            0x010009
304
305 /* Block bitmap is on a bad block */
306 #define PR_1_BB_BAD_BLOCK               0x01000A
307
308 /* Inode bitmap is on a bad block */
309 #define PR_1_IB_BAD_BLOCK               0x01000B
310
311 /* Inode has incorrect i_size */
312 #define PR_1_BAD_I_SIZE                 0x01000C
313
314 /* Inode has incorrect i_blocks */
315 #define PR_1_BAD_I_BLOCKS               0x01000D
316
317 /* Illegal block number in inode */
318 #define PR_1_ILLEGAL_BLOCK_NUM          0x01000E
319
320 /* Block number overlaps fs metadata */
321 #define PR_1_BLOCK_OVERLAPS_METADATA    0x01000F
322
323 /* Inode has illegal blocks (latch question) */
324 #define PR_1_INODE_BLOCK_LATCH          0x010010
325
326 /* Too many bad blocks in inode */
327 #define PR_1_TOO_MANY_BAD_BLOCKS        0x010011
328
329 /* Illegal block number in bad block inode */
330 #define PR_1_BB_ILLEGAL_BLOCK_NUM       0x010012
331
332 /* Bad block inode has illegal blocks (latch question) */
333 #define PR_1_INODE_BBLOCK_LATCH         0x010013
334
335 /* Duplicate or bad blocks in use! */
336 #define PR_1_DUP_BLOCKS_PREENSTOP       0x010014
337
338 /* Bad block used as bad block indirect block */
339 #define PR_1_BBINODE_BAD_METABLOCK      0x010015
340
341 /* Inconsistency can't be fixed prompt */
342 #define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
343
344 /* Bad primary block */
345 #define PR_1_BAD_PRIMARY_BLOCK          0x010017
346
347 /* Bad primary block prompt */
348 #define PR_1_BAD_PRIMARY_BLOCK_PROMPT   0x010018
349
350 /* Bad primary superblock */
351 #define PR_1_BAD_PRIMARY_SUPERBLOCK     0x010019
352
353 /* Bad primary block group descriptors */
354 #define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A
355
356 /* Bad superblock in group */
357 #define PR_1_BAD_SUPERBLOCK             0x01001B
358
359 /* Bad block group descriptors in group */
360 #define PR_1_BAD_GROUP_DESCRIPTORS      0x01001C
361
362 /* Block claimed for no reason */
363 #define PR_1_PROGERR_CLAIMED_BLOCK      0x01001D
364
365 /* Error allocating blocks for relocating metadata */
366 #define PR_1_RELOC_BLOCK_ALLOCATE       0x01001E
367
368 /* Error allocating block buffer during relocation process */
369 #define PR_1_RELOC_MEMORY_ALLOCATE      0x01001F
370
371 /* Relocating metadata group information from X to Y */
372 #define PR_1_RELOC_FROM_TO              0x010020
373
374 /* Relocating metatdata group information to X */
375 #define PR_1_RELOC_TO                   0x010021
376
377 /* Block read error during relocation process */
378 #define PR_1_RELOC_READ_ERR             0x010022
379
380 /* Block write error during relocation process */
381 #define PR_1_RELOC_WRITE_ERR            0x010023
382
383 /* Error allocating inode bitmap */
384 #define PR_1_ALLOCATE_IBITMAP_ERROR     0x010024
385
386 /* Error allocating block bitmap */
387 #define PR_1_ALLOCATE_BBITMAP_ERROR     0x010025
388
389 /* Error allocating icount structure */
390 #define PR_1_ALLOCATE_ICOUNT            0x010026
391
392 /* Error allocating dbcount */
393 #define PR_1_ALLOCATE_DBCOUNT           0x010027
394
395 /* Error while scanning inodes */
396 #define PR_1_ISCAN_ERROR                0x010028
397
398 /* Error while iterating over blocks */
399 #define PR_1_BLOCK_ITERATE              0x010029
400
401 /* Error while storing inode count information */
402 #define PR_1_ICOUNT_STORE               0x01002A
403
404 /* Error while storing directory block information */
405 #define PR_1_ADD_DBLOCK                 0x01002B
406
407 /* Error while reading inode (for clearing) */
408 #define PR_1_READ_INODE                 0x01002C
409
410 /* Suppress messages prompt */
411 #define PR_1_SUPPRESS_MESSAGES          0x01002D
412
413 /* Imagic flag set on an inode when filesystem doesn't support it */
414 #define PR_1_SET_IMAGIC                 0x01002F
415
416 /* Immutable flag set on a device or socket inode */
417 #define PR_1_SET_IMMUTABLE              0x010030
418
419 /* Compression flag set on a non-compressed filesystem */
420 #define PR_1_COMPR_SET                  0x010031
421
422 /* Non-zero size on on device, fifo or socket inode */
423 #define PR_1_SET_NONZSIZE               0x010032
424
425 /* Filesystem revision is 0, but feature flags are set */
426 #define PR_1_FS_REV_LEVEL               0x010033
427
428 /* Journal inode not in use, needs clearing */
429 #define PR_1_JOURNAL_INODE_NOT_CLEAR    0x010034
430
431 /* Journal inode has wrong mode */
432 #define PR_1_JOURNAL_BAD_MODE           0x010035
433
434 /* Inode that was part of orphan linked list */
435 #define PR_1_LOW_DTIME                  0x010036
436
437 /* Latch question which asks how to deal with low dtime inodes */
438 #define PR_1_ORPHAN_LIST_REFUGEES       0x010037
439
440 /* Error allocating refcount structure */
441 #define PR_1_ALLOCATE_REFCOUNT          0x010038
442
443 /* Error reading Extended Attribute block */
444 #define PR_1_READ_EA_BLOCK              0x010039
445
446 /* Invalid Extended Attribute block */
447 #define PR_1_BAD_EA_BLOCK               0x01003A
448
449 /* Error reading Extended Attribute block while fixing refcount -- abort */
450 #define PR_1_EXTATTR_READ_ABORT         0x01003B
451
452 /* Extended attribute reference count incorrect */
453 #define PR_1_EXTATTR_REFCOUNT           0x01003C
454
455 /* Error writing Extended Attribute block while fixing refcount */
456 #define PR_1_EXTATTR_WRITE              0x01003D
457
458 /* Multiple EA blocks not supported */
459 #define PR_1_EA_MULTI_BLOCK             0x01003E
460
461 /* Error allocating EA region allocation structure */
462 #define PR_1_EA_ALLOC_REGION            0x01003F
463
464 /* Error EA allocation collision */
465 #define PR_1_EA_ALLOC_COLLISION         0x010040
466
467 /* Bad extended attribute name */
468 #define PR_1_EA_BAD_NAME                0x010041
469
470 /* Bad extended attribute value */
471 #define PR_1_EA_BAD_VALUE               0x010042
472
473 /* Inode too big (latch question) */
474 #define PR_1_INODE_TOOBIG               0x010043
475
476 /* Directory too big */
477 #define PR_1_TOOBIG_DIR                 0x010044
478
479 /* Regular file too big */
480 #define PR_1_TOOBIG_REG                 0x010045
481
482 /* Symlink too big */
483 #define PR_1_TOOBIG_SYMLINK             0x010046
484
485 /* INDEX_FL flag set on a non-HTREE filesystem */
486 #define PR_1_HTREE_SET                  0x010047
487
488 /* INDEX_FL flag set on a non-directory */
489 #define PR_1_HTREE_NODIR                0x010048
490
491 /* Invalid root node in HTREE directory */
492 #define PR_1_HTREE_BADROOT              0x010049
493
494 /* Unsupported hash version in HTREE directory */
495 #define PR_1_HTREE_HASHV                0x01004A
496
497 /* Incompatible flag in HTREE root node */
498 #define PR_1_HTREE_INCOMPAT             0x01004B
499
500 /* HTREE too deep */
501 #define PR_1_HTREE_DEPTH                0x01004C
502
503 /* Bad block has indirect block that conflicts with filesystem block */
504 #define PR_1_BB_FS_BLOCK                0x01004D
505
506 /* Resize inode failed */
507 #define PR_1_RESIZE_INODE_CREATE        0x01004E
508
509 /* inode->i_size is too long */
510 #define PR_1_EXTRA_ISIZE                0x01004F
511
512 /* attribute name is too long */
513 #define PR_1_ATTR_NAME_LEN              0x010050
514
515 /* wrong EA value offset */
516 #define PR_1_ATTR_VALUE_OFFSET          0x010051
517
518 /* wrong EA blocknumber */
519 #define PR_1_ATTR_VALUE_BLOCK           0x010052
520
521 /* wrong EA value size */
522 #define PR_1_ATTR_VALUE_SIZE            0x010053
523
524 /* wrong EA hash value */
525 #define PR_1_ATTR_HASH                  0x010054
526
527 /*
528  * Pass 1b errors
529  */
530
531 /* Pass 1B: Rescan for duplicate/bad blocks */
532 #define PR_1B_PASS_HEADER       0x011000
533
534 /* Duplicate/bad block(s) header */
535 #define PR_1B_DUP_BLOCK_HEADER  0x011001
536
537 /* Duplicate/bad block(s) in inode */
538 #define PR_1B_DUP_BLOCK         0x011002
539
540 /* Duplicate/bad block(s) end */
541 #define PR_1B_DUP_BLOCK_END     0x011003
542
543 /* Error while scanning inodes */
544 #define PR_1B_ISCAN_ERROR       0x011004
545
546 /* Error allocating inode bitmap */
547 #define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
548
549 /* Error while iterating over blocks */
550 #define PR_1B_BLOCK_ITERATE     0x0110006
551
552 /* Error adjusting EA refcount */
553 #define PR_1B_ADJ_EA_REFCOUNT   0x0110007
554
555
556 /* Pass 1C: Scan directories for inodes with dup blocks. */
557 #define PR_1C_PASS_HEADER       0x012000
558
559
560 /* Pass 1D: Reconciling duplicate blocks */
561 #define PR_1D_PASS_HEADER       0x013000
562
563 /* File has duplicate blocks */
564 #define PR_1D_DUP_FILE          0x013001
565
566 /* List of files sharing duplicate blocks */
567 #define PR_1D_DUP_FILE_LIST     0x013002
568
569 /* File sharing blocks with filesystem metadata  */
570 #define PR_1D_SHARE_METADATA    0x013003
571
572 /* Report of how many duplicate/bad inodes */
573 #define PR_1D_NUM_DUP_INODES    0x013004
574
575 /* Duplicated blocks already reassigned or cloned. */
576 #define PR_1D_DUP_BLOCKS_DEALT  0x013005
577
578 /* Clone duplicate/bad blocks? */
579 #define PR_1D_CLONE_QUESTION    0x013006
580
581 /* Delete file? */
582 #define PR_1D_DELETE_QUESTION   0x013007
583
584 /* Couldn't clone file (error) */
585 #define PR_1D_CLONE_ERROR       0x013008
586
587 /*
588  * Pass 2 errors
589  */
590
591 /* Pass 2: Checking directory structure */
592 #define PR_2_PASS_HEADER        0x020000
593
594 /* Bad inode number for '.' */
595 #define PR_2_BAD_INODE_DOT      0x020001
596
597 /* Directory entry has bad inode number */
598 #define PR_2_BAD_INO            0x020002
599
600 /* Directory entry has deleted or unused inode */
601 #define PR_2_UNUSED_INODE       0x020003
602
603 /* Directry entry is link to '.' */
604 #define PR_2_LINK_DOT           0x020004
605
606 /* Directory entry points to inode now located in a bad block */
607 #define PR_2_BB_INODE           0x020005
608
609 /* Directory entry contains a link to a directory */
610 #define PR_2_LINK_DIR           0x020006
611
612 /* Directory entry contains a link to the root directry */
613 #define PR_2_LINK_ROOT          0x020007
614
615 /* Directory entry has illegal characters in its name */
616 #define PR_2_BAD_NAME           0x020008
617
618 /* Missing '.' in directory inode */
619 #define PR_2_MISSING_DOT        0x020009
620
621 /* Missing '..' in directory inode */
622 #define PR_2_MISSING_DOT_DOT    0x02000A
623
624 /* First entry in directory inode doesn't contain '.' */
625 #define PR_2_1ST_NOT_DOT        0x02000B
626
627 /* Second entry in directory inode doesn't contain '..' */
628 #define PR_2_2ND_NOT_DOT_DOT    0x02000C
629
630 /* i_faddr should be zero */
631 #define PR_2_FADDR_ZERO         0x02000D
632
633 /* i_file_acl should be zero */
634 #define PR_2_FILE_ACL_ZERO      0x02000E
635
636 /* i_dir_acl should be zero */
637 #define PR_2_DIR_ACL_ZERO       0x02000F
638
639 /* i_frag should be zero */
640 #define PR_2_FRAG_ZERO          0x020010
641
642 /* i_fsize should be zero */
643 #define PR_2_FSIZE_ZERO         0x020011
644
645 /* inode has bad mode */
646 #define PR_2_BAD_MODE           0x020012
647
648 /* directory corrupted */
649 #define PR_2_DIR_CORRUPTED      0x020013
650
651 /* filename too long */
652 #define PR_2_FILENAME_LONG      0x020014
653
654 /* Directory inode has a missing block (hole) */
655 #define PR_2_DIRECTORY_HOLE     0x020015
656
657 /* '.' is not NULL terminated */
658 #define PR_2_DOT_NULL_TERM      0x020016
659
660 /* '..' is not NULL terminated */
661 #define PR_2_DOT_DOT_NULL_TERM  0x020017
662
663 /* Illegal character device in inode */
664 #define PR_2_BAD_CHAR_DEV       0x020018
665
666 /* Illegal block device in inode */
667 #define PR_2_BAD_BLOCK_DEV      0x020019
668
669 /* Duplicate '.' entry */
670 #define PR_2_DUP_DOT            0x02001A
671
672 /* Duplicate '..' entry */
673 #define PR_2_DUP_DOT_DOT        0x02001B
674
675 /* Internal error: couldn't find dir_info */
676 #define PR_2_NO_DIRINFO         0x02001C
677
678 /* Final rec_len is wrong */
679 #define PR_2_FINAL_RECLEN       0x02001D
680
681 /* Error allocating icount structure */
682 #define PR_2_ALLOCATE_ICOUNT    0x02001E
683
684 /* Error iterating over directory blocks */
685 #define PR_2_DBLIST_ITERATE     0x02001F
686
687 /* Error reading directory block */
688 #define PR_2_READ_DIRBLOCK      0x020020
689
690 /* Error writing directory block */
691 #define PR_2_WRITE_DIRBLOCK     0x020021
692
693 /* Error allocating new directory block */
694 #define PR_2_ALLOC_DIRBOCK      0x020022
695
696 /* Error deallocating inode */
697 #define PR_2_DEALLOC_INODE      0x020023
698
699 /* Directory entry for '.' is big.  Split? */
700 #define PR_2_SPLIT_DOT          0x020024
701
702 /* Illegal FIFO */
703 #define PR_2_BAD_FIFO           0x020025
704
705 /* Illegal socket */
706 #define PR_2_BAD_SOCKET         0x020026
707
708 /* Directory filetype not set */
709 #define PR_2_SET_FILETYPE       0x020027
710
711 /* Directory filetype incorrect */
712 #define PR_2_BAD_FILETYPE       0x020028
713
714 /* Directory filetype set when it shouldn't be */
715 #define PR_2_CLEAR_FILETYPE     0x020029
716
717 /* Directory filename can't be zero-length  */
718 #define PR_2_NULL_NAME          0x020030
719
720 /* Invalid symlink */
721 #define PR_2_INVALID_SYMLINK    0x020031
722
723 /* i_file_acl (extended attribute) is bad */
724 #define PR_2_FILE_ACL_BAD       0x020032
725
726 /* Filesystem contains large files, but has no such flag in sb */
727 #define PR_2_FEATURE_LARGE_FILES 0x020033
728
729 /* Node in HTREE directory not referenced */
730 #define PR_2_HTREE_NOTREF       0x020034
731
732 /* Node in HTREE directory referenced twice */
733 #define PR_2_HTREE_DUPREF       0x020035
734
735 /* Node in HTREE directory has bad min hash */
736 #define PR_2_HTREE_MIN_HASH     0x020036
737
738 /* Node in HTREE directory has bad max hash */
739 #define PR_2_HTREE_MAX_HASH     0x020037
740
741 /* Clear invalid HTREE directory */
742 #define PR_2_HTREE_CLEAR        0x020038
743
744 /* Clear the htree flag forcibly */
745 /* #define PR_2_HTREE_FCLR      0x020039 */
746
747 /* Bad block in htree interior node */
748 #define PR_2_HTREE_BADBLK       0x02003A
749
750 /* Error adjusting EA refcount */
751 #define PR_2_ADJ_EA_REFCOUNT    0x02003B
752
753 /* Invalid HTREE root node */
754 #define PR_2_HTREE_BAD_ROOT     0x02003C
755
756 /* Invalid HTREE limit */
757 #define PR_2_HTREE_BAD_LIMIT    0x02003D
758
759 /* Invalid HTREE count */
760 #define PR_2_HTREE_BAD_COUNT    0x02003E
761
762 /* HTREE interior node has out-of-order hashes in table */
763 #define PR_2_HTREE_HASH_ORDER   0x02003F
764
765 /* Node in HTREE directory has bad depth */
766 #define PR_2_HTREE_BAD_DEPTH    0x020040
767
768 /* Duplicate directory entry found */
769 #define PR_2_DUPLICATE_DIRENT   0x020041
770
771 /* Non-unique filename found */
772 #define PR_2_NON_UNIQUE_FILE    0x020042
773
774 /* Duplicate directory entry found */
775 #define PR_2_REPORT_DUP_DIRENT  0x020043
776
777 /*
778  * Pass 3 errors
779  */
780
781 /* Pass 3: Checking directory connectivity */
782 #define PR_3_PASS_HEADER                0x030000
783
784 /* Root inode not allocated */
785 #define PR_3_NO_ROOT_INODE              0x030001
786
787 /* No room in lost+found */
788 #define PR_3_EXPAND_LF_DIR              0x030002
789
790 /* Unconnected directory inode */
791 #define PR_3_UNCONNECTED_DIR            0x030003
792
793 /* /lost+found not found */
794 #define PR_3_NO_LF_DIR                  0x030004
795
796 /* .. entry is incorrect */
797 #define PR_3_BAD_DOT_DOT                0x030005
798
799 /* Bad or non-existent /lost+found.  Cannot reconnect */
800 #define PR_3_NO_LPF                     0x030006
801
802 /* Could not expand /lost+found */
803 #define PR_3_CANT_EXPAND_LPF            0x030007
804
805 /* Could not reconnect inode */
806 #define PR_3_CANT_RECONNECT             0x030008
807
808 /* Error while trying to find /lost+found */
809 #define PR_3_ERR_FIND_LPF               0x030009
810
811 /* Error in ext2fs_new_block while creating /lost+found */
812 #define PR_3_ERR_LPF_NEW_BLOCK          0x03000A
813
814 /* Error in ext2fs_new_inode while creating /lost+found */
815 #define PR_3_ERR_LPF_NEW_INODE          0x03000B
816
817 /* Error in ext2fs_new_dir_block while creating /lost+found */
818 #define PR_3_ERR_LPF_NEW_DIR_BLOCK      0x03000C
819
820 /* Error while writing directory block for /lost+found */
821 #define PR_3_ERR_LPF_WRITE_BLOCK        0x03000D
822
823 /* Error while adjusting inode count */
824 #define PR_3_ADJUST_INODE               0x03000E
825
826 /* Couldn't fix parent directory -- error */
827 #define PR_3_FIX_PARENT_ERR             0x03000F
828
829 /* Couldn't fix parent directory -- couldn't find it */
830 #define PR_3_FIX_PARENT_NOFIND          0x030010
831
832 /* Error allocating inode bitmap */
833 #define PR_3_ALLOCATE_IBITMAP_ERROR     0x030011
834
835 /* Error creating root directory */
836 #define PR_3_CREATE_ROOT_ERROR          0x030012
837
838 /* Error creating lost and found directory */
839 #define PR_3_CREATE_LPF_ERROR           0x030013
840
841 /* Root inode is not directory; aborting */
842 #define PR_3_ROOT_NOT_DIR_ABORT         0x030014
843
844 /* Cannot proceed without a root inode. */
845 #define PR_3_NO_ROOT_INODE_ABORT        0x030015
846
847 /* Internal error: couldn't find dir_info */
848 #define PR_3_NO_DIRINFO                 0x030016
849
850 /* Lost+found is not a directory */
851 #define PR_3_LPF_NOTDIR                 0x030017
852
853 /*
854  * Pass 3a --- rehashing diretories
855  */
856 /* Pass 3a: Reindexing directories */
857 #define PR_3A_PASS_HEADER               0x031000
858
859 /* Error iterating over directories */
860 #define PR_3A_OPTIMIZE_ITER             0x031001
861
862 /* Error rehash directory */
863 #define PR_3A_OPTIMIZE_DIR_ERR          0x031002
864
865 /* Rehashing dir header */
866 #define PR_3A_OPTIMIZE_DIR_HEADER               0x031003
867
868 /* Rehashing directory %d */
869 #define PR_3A_OPTIMIZE_DIR              0x031004
870
871 /* Rehashing dir end */
872 #define PR_3A_OPTIMIZE_DIR_END          0x031005
873
874 /*
875  * Pass 4 errors
876  */
877
878 /* Pass 4: Checking reference counts */
879 #define PR_4_PASS_HEADER        0x040000
880
881 /* Unattached zero-length inode */
882 #define PR_4_ZERO_LEN_INODE     0x040001
883
884 /* Unattached inode */
885 #define PR_4_UNATTACHED_INODE   0x040002
886
887 /* Inode ref count wrong */
888 #define PR_4_BAD_REF_COUNT      0x040003
889
890 /* Inconsistent inode count information cached */
891 #define PR_4_INCONSISTENT_COUNT 0x040004
892
893 /*
894  * Pass 5 errors
895  */
896
897 /* Pass 5: Checking group summary information */
898 #define PR_5_PASS_HEADER                0x050000
899
900 /* Padding at end of inode bitmap is not set. */
901 #define PR_5_INODE_BMAP_PADDING         0x050001
902
903 /* Padding at end of block bitmap is not set. */
904 #define PR_5_BLOCK_BMAP_PADDING         0x050002
905
906 /* Block bitmap differences header */
907 #define PR_5_BLOCK_BITMAP_HEADER        0x050003
908
909 /* Block not used, but marked in bitmap */
910 #define PR_5_BLOCK_UNUSED               0x050004
911
912 /* Block used, but not marked used in bitmap */
913 #define PR_5_BLOCK_USED                 0x050005
914
915 /* Block bitmap differences end */
916 #define PR_5_BLOCK_BITMAP_END           0x050006
917
918 /* Inode bitmap differences header */
919 #define PR_5_INODE_BITMAP_HEADER        0x050007
920
921 /* Inode not used, but marked in bitmap */
922 #define PR_5_INODE_UNUSED               0x050008
923
924 /* Inode used, but not marked used in bitmap */
925 #define PR_5_INODE_USED                 0x050009
926
927 /* Inode bitmap differences end */
928 #define PR_5_INODE_BITMAP_END           0x05000A
929
930 /* Free inodes count for group wrong */
931 #define PR_5_FREE_INODE_COUNT_GROUP     0x05000B
932
933 /* Directories count for group wrong */
934 #define PR_5_FREE_DIR_COUNT_GROUP       0x05000C
935
936 /* Free inodes count wrong */
937 #define PR_5_FREE_INODE_COUNT   0x05000D
938
939 /* Free blocks count for group wrong */
940 #define PR_5_FREE_BLOCK_COUNT_GROUP     0x05000E
941
942 /* Free blocks count wrong */
943 #define PR_5_FREE_BLOCK_COUNT           0x05000F
944
945 /* Programming error: bitmap endpoints don't match */
946 #define PR_5_BMAP_ENDPOINTS             0x050010
947
948 /* Internal error: fudging end of bitmap */
949 #define PR_5_FUDGE_BITMAP_ERROR         0x050011
950
951 /* Error copying in replacement inode bitmap */
952 #define PR_5_COPY_IBITMAP_ERROR         0x050012
953
954 /* Error copying in replacement block bitmap */
955 #define PR_5_COPY_BBITMAP_ERROR         0x050013
956
957 /* Block range not used, but marked in bitmap */
958 #define PR_5_BLOCK_RANGE_UNUSED         0x050014
959
960 /* Block range used, but not marked used in bitmap */
961 #define PR_5_BLOCK_RANGE_USED           0x050015
962
963 /* Inode range not used, but marked in bitmap */
964 #define PR_5_INODE_RANGE_UNUSED         0x050016
965
966 /* Inode rangeused, but not marked used in bitmap */
967 #define PR_5_INODE_RANGE_USED           0x050017
968
969 /*
970  * Function declarations
971  */
972 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
973 static int end_problem_latch(e2fsck_t ctx, int mask);
974 static int set_latch_flags(int mask, int setflags, int clearflags);
975 static void clear_problem_context(struct problem_context *ctx);
976
977 /*
978  * Dictionary Abstract Data Type
979  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
980  *
981  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
982  * kazlib_1_20
983  */
984
985 #ifndef DICT_H
986 #define DICT_H
987
988 /*
989  * Blurb for inclusion into C++ translation units
990  */
991
992 typedef unsigned long dictcount_t;
993 #define DICTCOUNT_T_MAX ULONG_MAX
994
995 /*
996  * The dictionary is implemented as a red-black tree
997  */
998
999 typedef enum { dnode_red, dnode_black } dnode_color_t;
1000
1001 typedef struct dnode_t {
1002     struct dnode_t *dict_left;
1003     struct dnode_t *dict_right;
1004     struct dnode_t *dict_parent;
1005     dnode_color_t dict_color;
1006     const void *dict_key;
1007     void *dict_data;
1008 } dnode_t;
1009
1010 typedef int (*dict_comp_t)(const void *, const void *);
1011 typedef void (*dnode_free_t)(dnode_t *);
1012
1013 typedef struct dict_t {
1014     dnode_t dict_nilnode;
1015     dictcount_t dict_nodecount;
1016     dictcount_t dict_maxcount;
1017     dict_comp_t dict_compare;
1018     dnode_free_t dict_freenode;
1019     int dict_dupes;
1020 } dict_t;
1021
1022 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
1023
1024 typedef struct dict_load_t {
1025     dict_t *dict_dictptr;
1026     dnode_t dict_nilnode;
1027 } dict_load_t;
1028
1029 #define dict_count(D) ((D)->dict_nodecount)
1030 #define dnode_get(N) ((N)->dict_data)
1031 #define dnode_getkey(N) ((N)->dict_key)
1032
1033 #endif
1034
1035 /*
1036  * Compatibility header file for e2fsck which should be included
1037  * instead of linux/jfs.h
1038  *
1039  * Copyright (C) 2000 Stephen C. Tweedie
1040  */
1041
1042 /*
1043  * Pull in the definition of the e2fsck context structure
1044  */
1045
1046 struct buffer_head {
1047         char            b_data[8192];
1048         e2fsck_t        b_ctx;
1049         io_channel      b_io;
1050         int             b_size;
1051         blk_t           b_blocknr;
1052         int             b_dirty;
1053         int             b_uptodate;
1054         int             b_err;
1055 };
1056
1057
1058 #define K_DEV_FS        1
1059 #define K_DEV_JOURNAL   2
1060
1061 #define lock_buffer(bh) do {} while(0)
1062 #define unlock_buffer(bh) do {} while(0)
1063 #define buffer_req(bh) 1
1064 #define do_readahead(journal, start) do {} while(0)
1065
1066 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
1067
1068 typedef struct {
1069         int     object_length;
1070 } kmem_cache_t;
1071
1072 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1073
1074 /*
1075  * We use the standard libext2fs portability tricks for inline
1076  * functions.
1077  */
1078
1079 static _INLINE_ kmem_cache_t * do_cache_create(int len)
1080 {
1081         kmem_cache_t *new_cache;
1082
1083         new_cache = malloc(sizeof(*new_cache));
1084         if (new_cache)
1085                 new_cache->object_length = len;
1086         return new_cache;
1087 }
1088
1089 static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1090 {
1091         free(cache);
1092 }
1093
1094 /*
1095  * badblocks.c --- replace/append bad blocks to the bad block inode
1096  */
1097
1098 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
1099                                  void *priv_data);
1100
1101
1102 static void invalid_block(ext2_filsys fs FSCK_ATTR((unused)), blk_t blk)
1103 {
1104         printf(_("Bad block %u out of range; ignored.\n"), blk);
1105         return;
1106 }
1107
1108 static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1109                           int replace_bad_blocks)
1110 {
1111         ext2_filsys fs = ctx->fs;
1112         errcode_t       retval;
1113         badblocks_list  bb_list = 0;
1114         FILE            *f;
1115         char            buf[1024];
1116
1117         e2fsck_read_bitmaps(ctx);
1118
1119         /*
1120          * Make sure the bad block inode is sane.  If there are any
1121          * illegal blocks, clear them.
1122          */
1123         retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
1124                                       check_bb_inode_blocks, 0);
1125         if (retval) {
1126                 com_err("ext2fs_block_iterate", retval,
1127                         _("while sanity checking the bad blocks inode"));
1128                 goto fatal;
1129         }
1130
1131         /*
1132          * If we're appending to the bad blocks inode, read in the
1133          * current bad blocks.
1134          */
1135         if (!replace_bad_blocks) {
1136                 retval = ext2fs_read_bb_inode(fs, &bb_list);
1137                 if (retval) {
1138                         com_err("ext2fs_read_bb_inode", retval,
1139                                 _("while reading the bad blocks inode"));
1140                         goto fatal;
1141                 }
1142         }
1143
1144         /*
1145          * Now read in the bad blocks from the file; if
1146          * bad_blocks_file is null, then try to run the badblocks
1147          * command.
1148          */
1149         if (bad_blocks_file) {
1150                 f = fopen(bad_blocks_file, "r");
1151                 if (!f) {
1152                         com_err("read_bad_blocks_file", errno,
1153                                 _("while trying to open %s"), bad_blocks_file);
1154                         goto fatal;
1155                 }
1156         } else {
1157                 sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
1158                         (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
1159                         (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
1160                         fs->device_name, fs->super->s_blocks_count);
1161                 f = popen(buf, "r");
1162                 if (!f) {
1163                         com_err("read_bad_blocks_file", errno,
1164                                 _("while trying popen '%s'"), buf);
1165                         goto fatal;
1166                 }
1167         }
1168         retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
1169         if (bad_blocks_file)
1170                 fclose(f);
1171         else
1172                 pclose(f);
1173         if (retval) {
1174                 com_err("ext2fs_read_bb_FILE", retval,
1175                         _("while reading in list of bad blocks from file"));
1176                 goto fatal;
1177         }
1178
1179         /*
1180          * Finally, update the bad blocks from the bad_block_map
1181          */
1182         retval = ext2fs_update_bb_inode(fs, bb_list);
1183         if (retval) {
1184                 com_err("ext2fs_update_bb_inode", retval,
1185                         _("while updating bad block inode"));
1186                 goto fatal;
1187         }
1188
1189         ext2fs_badblocks_list_free(bb_list);
1190         return;
1191
1192 fatal:
1193         ctx->flags |= E2F_FLAG_ABORT;
1194         return;
1195
1196 }
1197
1198 static int check_bb_inode_blocks(ext2_filsys fs,
1199                                  blk_t *block_nr,
1200                                  int blockcnt FSCK_ATTR((unused)),
1201                                  void *priv_data FSCK_ATTR((unused)))
1202 {
1203         if (!*block_nr)
1204                 return 0;
1205
1206         /*
1207          * If the block number is outrageous, clear it and ignore it.
1208          */
1209         if (*block_nr >= fs->super->s_blocks_count ||
1210             *block_nr < fs->super->s_first_data_block) {
1211                 printf(_("Warning illegal block %u found in bad block inode.  Cleared.\n"), *block_nr);
1212                 *block_nr = 0;
1213                 return BLOCK_CHANGED;
1214         }
1215
1216         return 0;
1217 }
1218
1219 /*
1220  * Dictionary Abstract Data Type
1221  */
1222
1223
1224 /*
1225  * These macros provide short convenient names for structure members,
1226  * which are embellished with dict_ prefixes so that they are
1227  * properly confined to the documented namespace. It's legal for a
1228  * program which uses dict to define, for instance, a macro called ``parent''.
1229  * Such a macro would interfere with the dnode_t struct definition.
1230  * In general, highly portable and reusable C modules which expose their
1231  * structures need to confine structure member names to well-defined spaces.
1232  * The resulting identifiers aren't necessarily convenient to use, nor
1233  * readable, in the implementation, however!
1234  */
1235
1236 #define left dict_left
1237 #define right dict_right
1238 #define parent dict_parent
1239 #define color dict_color
1240 #define key dict_key
1241 #define data dict_data
1242
1243 #define nilnode dict_nilnode
1244 #define maxcount dict_maxcount
1245 #define compare dict_compare
1246 #define dupes dict_dupes
1247
1248 #define dict_root(D) ((D)->nilnode.left)
1249 #define dict_nil(D) (&(D)->nilnode)
1250 #define DICT_DEPTH_MAX 64
1251
1252 static void dnode_free(dnode_t *node);
1253
1254 /*
1255  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
1256  * its right child C are rearranged so that the P instead becomes the left
1257  * child of C.   The left subtree of C is inherited as the new right subtree
1258  * for P.  The ordering of the keys within the tree is thus preserved.
1259  */
1260
1261 static void rotate_left(dnode_t *upper)
1262 {
1263     dnode_t *lower, *lowleft, *upparent;
1264
1265     lower = upper->right;
1266     upper->right = lowleft = lower->left;
1267     lowleft->parent = upper;
1268
1269     lower->parent = upparent = upper->parent;
1270
1271     /* don't need to check for root node here because root->parent is
1272        the sentinel nil node, and root->parent->left points back to root */
1273
1274     if (upper == upparent->left) {
1275         upparent->left = lower;
1276     } else {
1277         assert (upper == upparent->right);
1278         upparent->right = lower;
1279     }
1280
1281     lower->left = upper;
1282     upper->parent = lower;
1283 }
1284
1285 /*
1286  * This operation is the ``mirror'' image of rotate_left. It is
1287  * the same procedure, but with left and right interchanged.
1288  */
1289
1290 static void rotate_right(dnode_t *upper)
1291 {
1292     dnode_t *lower, *lowright, *upparent;
1293
1294     lower = upper->left;
1295     upper->left = lowright = lower->right;
1296     lowright->parent = upper;
1297
1298     lower->parent = upparent = upper->parent;
1299
1300     if (upper == upparent->right) {
1301         upparent->right = lower;
1302     } else {
1303         assert (upper == upparent->left);
1304         upparent->left = lower;
1305     }
1306
1307     lower->right = upper;
1308     upper->parent = lower;
1309 }
1310
1311 /*
1312  * Do a postorder traversal of the tree rooted at the specified
1313  * node and free everything under it.  Used by dict_free().
1314  */
1315
1316 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1317 {
1318     if (node == nil)
1319         return;
1320     free_nodes(dict, node->left, nil);
1321     free_nodes(dict, node->right, nil);
1322     dict->dict_freenode(node);
1323 }
1324
1325 /*
1326  * Verify that the tree contains the given node. This is done by
1327  * traversing all of the nodes and comparing their pointers to the
1328  * given pointer. Returns 1 if the node is found, otherwise
1329  * returns zero. It is intended for debugging purposes.
1330  */
1331
1332 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1333 {
1334     if (root != nil) {
1335         return root == node
1336                 || verify_dict_has_node(nil, root->left, node)
1337                 || verify_dict_has_node(nil, root->right, node);
1338     }
1339     return 0;
1340 }
1341
1342
1343 /*
1344  * Select a different set of node allocator routines.
1345  */
1346
1347 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1348 {
1349     assert (dict_count(dict) == 0);
1350     dict->dict_freenode = fr;
1351 }
1352
1353 /*
1354  * Free all the nodes in the dictionary by using the dictionary's
1355  * installed free routine. The dictionary is emptied.
1356  */
1357
1358 static void dict_free_nodes(dict_t *dict)
1359 {
1360     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1361     free_nodes(dict, root, nil);
1362     dict->dict_nodecount = 0;
1363     dict->nilnode.left = &dict->nilnode;
1364     dict->nilnode.right = &dict->nilnode;
1365 }
1366
1367 /*
1368  * Initialize a user-supplied dictionary object.
1369  */
1370
1371 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1372 {
1373     dict->compare = comp;
1374     dict->dict_freenode = dnode_free;
1375     dict->dict_nodecount = 0;
1376     dict->maxcount = maxcount;
1377     dict->nilnode.left = &dict->nilnode;
1378     dict->nilnode.right = &dict->nilnode;
1379     dict->nilnode.parent = &dict->nilnode;
1380     dict->nilnode.color = dnode_black;
1381     dict->dupes = 0;
1382     return dict;
1383 }
1384
1385 /*
1386  * Locate a node in the dictionary having the given key.
1387  * If the node is not found, a null a pointer is returned (rather than
1388  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
1389  * located node is returned.
1390  */
1391
1392 static dnode_t *dict_lookup(dict_t *dict, const void *key)
1393 {
1394     dnode_t *root = dict_root(dict);
1395     dnode_t *nil = dict_nil(dict);
1396     dnode_t *saved;
1397     int result;
1398
1399     /* simple binary search adapted for trees that contain duplicate keys */
1400
1401     while (root != nil) {
1402         result = dict->compare(key, root->key);
1403         if (result < 0)
1404             root = root->left;
1405         else if (result > 0)
1406             root = root->right;
1407         else {
1408             if (!dict->dupes) { /* no duplicates, return match          */
1409                 return root;
1410             } else {            /* could be dupes, find leftmost one    */
1411                 do {
1412                     saved = root;
1413                     root = root->left;
1414                     while (root != nil && dict->compare(key, root->key))
1415                         root = root->right;
1416                 } while (root != nil);
1417                 return saved;
1418             }
1419         }
1420     }
1421
1422     return NULL;
1423 }
1424
1425 /*
1426  * Insert a node into the dictionary. The node should have been
1427  * initialized with a data field. All other fields are ignored.
1428  * The behavior is undefined if the user attempts to insert into
1429  * a dictionary that is already full (for which the dict_isfull()
1430  * function returns true).
1431  */
1432
1433 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1434 {
1435     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1436     dnode_t *parent = nil, *uncle, *grandpa;
1437     int result = -1;
1438
1439     node->key = key;
1440
1441     /* basic binary tree insert */
1442
1443     while (where != nil) {
1444         parent = where;
1445         result = dict->compare(key, where->key);
1446         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
1447         assert (dict->dupes || result != 0);
1448         if (result < 0)
1449             where = where->left;
1450         else
1451             where = where->right;
1452     }
1453
1454     assert (where == nil);
1455
1456     if (result < 0)
1457         parent->left = node;
1458     else
1459         parent->right = node;
1460
1461     node->parent = parent;
1462     node->left = nil;
1463     node->right = nil;
1464
1465     dict->dict_nodecount++;
1466
1467     /* red black adjustments */
1468
1469     node->color = dnode_red;
1470
1471     while (parent->color == dnode_red) {
1472         grandpa = parent->parent;
1473         if (parent == grandpa->left) {
1474             uncle = grandpa->right;
1475             if (uncle->color == dnode_red) {    /* red parent, red uncle */
1476                 parent->color = dnode_black;
1477                 uncle->color = dnode_black;
1478                 grandpa->color = dnode_red;
1479                 node = grandpa;
1480                 parent = grandpa->parent;
1481             } else {                            /* red parent, black uncle */
1482                 if (node == parent->right) {
1483                     rotate_left(parent);
1484                     parent = node;
1485                     assert (grandpa == parent->parent);
1486                     /* rotation between parent and child preserves grandpa */
1487                 }
1488                 parent->color = dnode_black;
1489                 grandpa->color = dnode_red;
1490                 rotate_right(grandpa);
1491                 break;
1492             }
1493         } else {        /* symmetric cases: parent == parent->parent->right */
1494             uncle = grandpa->left;
1495             if (uncle->color == dnode_red) {
1496                 parent->color = dnode_black;
1497                 uncle->color = dnode_black;
1498                 grandpa->color = dnode_red;
1499                 node = grandpa;
1500                 parent = grandpa->parent;
1501             } else {
1502                 if (node == parent->left) {
1503                     rotate_right(parent);
1504                     parent = node;
1505                     assert (grandpa == parent->parent);
1506                 }
1507                 parent->color = dnode_black;
1508                 grandpa->color = dnode_red;
1509                 rotate_left(grandpa);
1510                 break;
1511             }
1512         }
1513     }
1514
1515     dict_root(dict)->color = dnode_black;
1516
1517 }
1518
1519 /*
1520  * Allocate a node using the dictionary's allocator routine, give it
1521  * the data item.
1522  */
1523
1524 static dnode_t *dnode_init(dnode_t *dnode, void *data)
1525 {
1526     dnode->data = data;
1527     dnode->parent = NULL;
1528     dnode->left = NULL;
1529     dnode->right = NULL;
1530     return dnode;
1531 }
1532
1533 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1534 {
1535     dnode_t *node = malloc(sizeof(dnode_t));
1536
1537     if (node) {
1538         dnode_init(node, data);
1539         dict_insert(dict, node, key);
1540         return 1;
1541     }
1542     return 0;
1543 }
1544
1545 /*
1546  * Return the node with the lowest (leftmost) key. If the dictionary is empty
1547  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
1548  */
1549
1550 static dnode_t *dict_first(dict_t *dict)
1551 {
1552     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
1553
1554     if (root != nil)
1555         while ((left = root->left) != nil)
1556             root = left;
1557
1558     return (root == nil) ? NULL : root;
1559 }
1560
1561 /*
1562  * Return the given node's successor node---the node which has the
1563  * next key in the the left to right ordering. If the node has
1564  * no successor, a null pointer is returned rather than a pointer to
1565  * the nil node.
1566  */
1567
1568 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
1569 {
1570     dnode_t *nil = dict_nil(dict), *parent, *left;
1571
1572     if (curr->right != nil) {
1573         curr = curr->right;
1574         while ((left = curr->left) != nil)
1575             curr = left;
1576         return curr;
1577     }
1578
1579     parent = curr->parent;
1580
1581     while (parent != nil && curr == parent->right) {
1582         curr = parent;
1583         parent = curr->parent;
1584     }
1585
1586     return (parent == nil) ? NULL : parent;
1587 }
1588
1589
1590 static void dnode_free(dnode_t *node)
1591 {
1592     free(node);
1593 }
1594
1595
1596 #undef left
1597 #undef right
1598 #undef parent
1599 #undef color
1600 #undef key
1601 #undef data
1602
1603 #undef nilnode
1604 #undef maxcount
1605 #undef compare
1606 #undef dupes
1607
1608
1609 /*
1610  * dirinfo.c --- maintains the directory information table for e2fsck.
1611  */
1612
1613 /*
1614  * This subroutine is called during pass1 to create a directory info
1615  * entry.  During pass1, the passed-in parent is 0; it will get filled
1616  * in during pass2.
1617  */
1618 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
1619 {
1620         struct dir_info *dir;
1621         int             i, j;
1622         ext2_ino_t      num_dirs;
1623         errcode_t       retval;
1624         unsigned long   old_size;
1625
1626         if (!ctx->dir_info) {
1627                 ctx->dir_info_count = 0;
1628                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
1629                 if (retval)
1630                         num_dirs = 1024;        /* Guess */
1631                 ctx->dir_info_size = num_dirs + 10;
1632                 ctx->dir_info  = (struct dir_info *)
1633                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
1634                                                * sizeof (struct dir_info),
1635                                                "directory map");
1636         }
1637
1638         if (ctx->dir_info_count >= ctx->dir_info_size) {
1639                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
1640                 ctx->dir_info_size += 10;
1641                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
1642                                            sizeof(struct dir_info),
1643                                            &ctx->dir_info);
1644                 if (retval) {
1645                         ctx->dir_info_size -= 10;
1646                         return;
1647                 }
1648         }
1649
1650         /*
1651          * Normally, add_dir_info is called with each inode in
1652          * sequential order; but once in a while (like when pass 3
1653          * needs to recreate the root directory or lost+found
1654          * directory) it is called out of order.  In those cases, we
1655          * need to move the dir_info entries down to make room, since
1656          * the dir_info array needs to be sorted by inode number for
1657          * get_dir_info()'s sake.
1658          */
1659         if (ctx->dir_info_count &&
1660             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
1661                 for (i = ctx->dir_info_count-1; i > 0; i--)
1662                         if (ctx->dir_info[i-1].ino < ino)
1663                                 break;
1664                 dir = &ctx->dir_info[i];
1665                 if (dir->ino != ino)
1666                         for (j = ctx->dir_info_count++; j > i; j--)
1667                                 ctx->dir_info[j] = ctx->dir_info[j-1];
1668         } else
1669                 dir = &ctx->dir_info[ctx->dir_info_count++];
1670
1671         dir->ino = ino;
1672         dir->dotdot = parent;
1673         dir->parent = parent;
1674 }
1675
1676 /*
1677  * get_dir_info() --- given an inode number, try to find the directory
1678  * information entry for it.
1679  */
1680 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
1681 {
1682         int     low, high, mid;
1683
1684         low = 0;
1685         high = ctx->dir_info_count-1;
1686         if (!ctx->dir_info)
1687                 return 0;
1688         if (ino == ctx->dir_info[low].ino)
1689                 return &ctx->dir_info[low];
1690         if  (ino == ctx->dir_info[high].ino)
1691                 return &ctx->dir_info[high];
1692
1693         while (low < high) {
1694                 mid = (low+high)/2;
1695                 if (mid == low || mid == high)
1696                         break;
1697                 if (ino == ctx->dir_info[mid].ino)
1698                         return &ctx->dir_info[mid];
1699                 if (ino < ctx->dir_info[mid].ino)
1700                         high = mid;
1701                 else
1702                         low = mid;
1703         }
1704         return 0;
1705 }
1706
1707 /*
1708  * Free the dir_info structure when it isn't needed any more.
1709  */
1710 static void e2fsck_free_dir_info(e2fsck_t ctx)
1711 {
1712         ext2fs_free_mem(&ctx->dir_info);
1713         ctx->dir_info_size = 0;
1714         ctx->dir_info_count = 0;
1715 }
1716
1717 /*
1718  * Return the count of number of directories in the dir_info structure
1719  */
1720 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
1721 {
1722         return ctx->dir_info_count;
1723 }
1724
1725 /*
1726  * A simple interator function
1727  */
1728 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
1729 {
1730         if (*control >= ctx->dir_info_count)
1731                 return 0;
1732
1733         return(ctx->dir_info + (*control)++);
1734 }
1735
1736 /*
1737  * dirinfo.c --- maintains the directory information table for e2fsck.
1738  *
1739  */
1740
1741 #ifdef ENABLE_HTREE
1742
1743 /*
1744  * This subroutine is called during pass1 to create a directory info
1745  * entry.  During pass1, the passed-in parent is 0; it will get filled
1746  * in during pass2.
1747  */
1748 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
1749 {
1750         struct dx_dir_info *dir;
1751         int             i, j;
1752         errcode_t       retval;
1753         unsigned long   old_size;
1754
1755         if (!ctx->dx_dir_info) {
1756                 ctx->dx_dir_info_count = 0;
1757                 ctx->dx_dir_info_size = 100; /* Guess */
1758                 ctx->dx_dir_info  = (struct dx_dir_info *)
1759                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
1760                                                * sizeof (struct dx_dir_info),
1761                                                "directory map");
1762         }
1763
1764         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
1765                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
1766                 ctx->dx_dir_info_size += 10;
1767                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
1768                                            sizeof(struct dx_dir_info),
1769                                            &ctx->dx_dir_info);
1770                 if (retval) {
1771                         ctx->dx_dir_info_size -= 10;
1772                         return;
1773                 }
1774         }
1775
1776         /*
1777          * Normally, add_dx_dir_info is called with each inode in
1778          * sequential order; but once in a while (like when pass 3
1779          * needs to recreate the root directory or lost+found
1780          * directory) it is called out of order.  In those cases, we
1781          * need to move the dx_dir_info entries down to make room, since
1782          * the dx_dir_info array needs to be sorted by inode number for
1783          * get_dx_dir_info()'s sake.
1784          */
1785         if (ctx->dx_dir_info_count &&
1786             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
1787                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
1788                         if (ctx->dx_dir_info[i-1].ino < ino)
1789                                 break;
1790                 dir = &ctx->dx_dir_info[i];
1791                 if (dir->ino != ino)
1792                         for (j = ctx->dx_dir_info_count++; j > i; j--)
1793                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
1794         } else
1795                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
1796
1797         dir->ino = ino;
1798         dir->numblocks = num_blocks;
1799         dir->hashversion = 0;
1800         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
1801                                        * sizeof (struct dx_dirblock_info),
1802                                        "dx_block info array");
1803
1804 }
1805
1806 /*
1807  * get_dx_dir_info() --- given an inode number, try to find the directory
1808  * information entry for it.
1809  */
1810 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
1811 {
1812         int     low, high, mid;
1813
1814         low = 0;
1815         high = ctx->dx_dir_info_count-1;
1816         if (!ctx->dx_dir_info)
1817                 return 0;
1818         if (ino == ctx->dx_dir_info[low].ino)
1819                 return &ctx->dx_dir_info[low];
1820         if  (ino == ctx->dx_dir_info[high].ino)
1821                 return &ctx->dx_dir_info[high];
1822
1823         while (low < high) {
1824                 mid = (low+high)/2;
1825                 if (mid == low || mid == high)
1826                         break;
1827                 if (ino == ctx->dx_dir_info[mid].ino)
1828                         return &ctx->dx_dir_info[mid];
1829                 if (ino < ctx->dx_dir_info[mid].ino)
1830                         high = mid;
1831                 else
1832                         low = mid;
1833         }
1834         return 0;
1835 }
1836
1837 /*
1838  * Free the dx_dir_info structure when it isn't needed any more.
1839  */
1840 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
1841 {
1842         int     i;
1843         struct dx_dir_info *dir;
1844
1845         if (ctx->dx_dir_info) {
1846                 dir = ctx->dx_dir_info;
1847                 for (i=0; i < ctx->dx_dir_info_count; i++) {
1848                         ext2fs_free_mem(&dir->dx_block);
1849                 }
1850                 ext2fs_free_mem(&ctx->dx_dir_info);
1851         }
1852         ctx->dx_dir_info_size = 0;
1853         ctx->dx_dir_info_count = 0;
1854 }
1855
1856 /*
1857  * A simple interator function
1858  */
1859 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
1860 {
1861         if (*control >= ctx->dx_dir_info_count)
1862                 return 0;
1863
1864         return(ctx->dx_dir_info + (*control)++);
1865 }
1866
1867 #endif /* ENABLE_HTREE */
1868 /*
1869  * e2fsck.c - a consistency checker for the new extended file system.
1870  *
1871  */
1872
1873 /*
1874  * This function allocates an e2fsck context
1875  */
1876 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
1877 {
1878         e2fsck_t        context;
1879         errcode_t       retval;
1880
1881         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
1882         if (retval)
1883                 return retval;
1884
1885         memset(context, 0, sizeof(struct e2fsck_struct));
1886
1887         context->process_inode_size = 256;
1888         context->ext_attr_ver = 2;
1889
1890         *ret = context;
1891         return 0;
1892 }
1893
1894 struct ea_refcount_el {
1895         blk_t   ea_blk;
1896         int     ea_count;
1897 };
1898
1899 struct ea_refcount {
1900         blk_t           count;
1901         blk_t           size;
1902         blk_t           cursor;
1903         struct ea_refcount_el   *list;
1904 };
1905
1906 static void ea_refcount_free(ext2_refcount_t refcount)
1907 {
1908         if (!refcount)
1909                 return;
1910
1911         ext2fs_free_mem(&refcount->list);
1912         ext2fs_free_mem(&refcount);
1913 }
1914
1915 /*
1916  * This function resets an e2fsck context; it is called when e2fsck
1917  * needs to be restarted.
1918  */
1919 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
1920 {
1921         ctx->flags = 0;
1922         ctx->lost_and_found = 0;
1923         ctx->bad_lost_and_found = 0;
1924         ext2fs_free_inode_bitmap(ctx->inode_used_map);
1925         ctx->inode_used_map = 0;
1926         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
1927         ctx->inode_dir_map = 0;
1928         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
1929         ctx->inode_reg_map = 0;
1930         ext2fs_free_block_bitmap(ctx->block_found_map);
1931         ctx->block_found_map = 0;
1932         ext2fs_free_icount(ctx->inode_link_info);
1933         ctx->inode_link_info = 0;
1934         if (ctx->journal_io) {
1935                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
1936                         io_channel_close(ctx->journal_io);
1937                 ctx->journal_io = 0;
1938         }
1939         if (ctx->fs) {
1940                 ext2fs_free_dblist(ctx->fs->dblist);
1941                 ctx->fs->dblist = 0;
1942         }
1943         e2fsck_free_dir_info(ctx);
1944 #ifdef ENABLE_HTREE
1945         e2fsck_free_dx_dir_info(ctx);
1946 #endif
1947         ea_refcount_free(ctx->refcount);
1948         ctx->refcount = 0;
1949         ea_refcount_free(ctx->refcount_extra);
1950         ctx->refcount_extra = 0;
1951         ext2fs_free_block_bitmap(ctx->block_dup_map);
1952         ctx->block_dup_map = 0;
1953         ext2fs_free_block_bitmap(ctx->block_ea_map);
1954         ctx->block_ea_map = 0;
1955         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
1956         ctx->inode_bb_map = 0;
1957         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
1958         ctx->inode_bad_map = 0;
1959         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
1960         ctx->inode_imagic_map = 0;
1961         ext2fs_u32_list_free(ctx->dirs_to_hash);
1962         ctx->dirs_to_hash = 0;
1963
1964         /*
1965          * Clear the array of invalid meta-data flags
1966          */
1967         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
1968         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
1969         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
1970
1971         /* Clear statistic counters */
1972         ctx->fs_directory_count = 0;
1973         ctx->fs_regular_count = 0;
1974         ctx->fs_blockdev_count = 0;
1975         ctx->fs_chardev_count = 0;
1976         ctx->fs_links_count = 0;
1977         ctx->fs_symlinks_count = 0;
1978         ctx->fs_fast_symlinks_count = 0;
1979         ctx->fs_fifo_count = 0;
1980         ctx->fs_total_count = 0;
1981         ctx->fs_badblocks_count = 0;
1982         ctx->fs_sockets_count = 0;
1983         ctx->fs_ind_count = 0;
1984         ctx->fs_dind_count = 0;
1985         ctx->fs_tind_count = 0;
1986         ctx->fs_fragmented = 0;
1987         ctx->large_files = 0;
1988
1989         /* Reset the superblock to the user's requested value */
1990         ctx->superblock = ctx->use_superblock;
1991
1992         return 0;
1993 }
1994
1995 static void e2fsck_free_context(e2fsck_t ctx)
1996 {
1997         if (!ctx)
1998                 return;
1999
2000         e2fsck_reset_context(ctx);
2001         if (ctx->blkid)
2002                 blkid_put_cache(ctx->blkid);
2003
2004         ext2fs_free_mem(&ctx);
2005 }
2006
2007 /*
2008  * ea_refcount.c
2009  */
2010
2011 /*
2012  * The strategy we use for keeping track of EA refcounts is as
2013  * follows.  We keep a sorted array of first EA blocks and its
2014  * reference counts.  Once the refcount has dropped to zero, it is
2015  * removed from the array to save memory space.  Once the EA block is
2016  * checked, its bit is set in the block_ea_map bitmap.
2017  */
2018
2019
2020 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2021 {
2022         ext2_refcount_t refcount;
2023         errcode_t       retval;
2024         size_t          bytes;
2025
2026         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2027         if (retval)
2028                 return retval;
2029         memset(refcount, 0, sizeof(struct ea_refcount));
2030
2031         if (!size)
2032                 size = 500;
2033         refcount->size = size;
2034         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2035 #ifdef DEBUG
2036         printf("Refcount allocated %d entries, %d bytes.\n",
2037                refcount->size, bytes);
2038 #endif
2039         retval = ext2fs_get_mem(bytes, &refcount->list);
2040         if (retval)
2041                 goto errout;
2042         memset(refcount->list, 0, bytes);
2043
2044         refcount->count = 0;
2045         refcount->cursor = 0;
2046
2047         *ret = refcount;
2048         return 0;
2049
2050 errout:
2051         ea_refcount_free(refcount);
2052         return(retval);
2053 }
2054
2055 /*
2056  * collapse_refcount() --- go through the refcount array, and get rid
2057  * of any count == zero entries
2058  */
2059 static void refcount_collapse(ext2_refcount_t refcount)
2060 {
2061         unsigned int    i, j;
2062         struct ea_refcount_el   *list;
2063
2064         list = refcount->list;
2065         for (i = 0, j = 0; i < refcount->count; i++) {
2066                 if (list[i].ea_count) {
2067                         if (i != j)
2068                                 list[j] = list[i];
2069                         j++;
2070                 }
2071         }
2072 #if defined(DEBUG) || defined(TEST_PROGRAM)
2073         printf("Refcount_collapse: size was %d, now %d\n",
2074                refcount->count, j);
2075 #endif
2076         refcount->count = j;
2077 }
2078
2079
2080 /*
2081  * insert_refcount_el() --- Insert a new entry into the sorted list at a
2082  *      specified position.
2083  */
2084 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2085                                                  blk_t blk, int pos)
2086 {
2087         struct ea_refcount_el   *el;
2088         errcode_t               retval;
2089         blk_t                   new_size = 0;
2090         int                     num;
2091
2092         if (refcount->count >= refcount->size) {
2093                 new_size = refcount->size + 100;
2094 #ifdef DEBUG
2095                 printf("Reallocating refcount %d entries...\n", new_size);
2096 #endif
2097                 retval = ext2fs_resize_mem((size_t) refcount->size *
2098                                            sizeof(struct ea_refcount_el),
2099                                            (size_t) new_size *
2100                                            sizeof(struct ea_refcount_el),
2101                                            &refcount->list);
2102                 if (retval)
2103                         return 0;
2104                 refcount->size = new_size;
2105         }
2106         num = (int) refcount->count - pos;
2107         if (num < 0)
2108                 return 0;       /* should never happen */
2109         if (num) {
2110                 memmove(&refcount->list[pos+1], &refcount->list[pos],
2111                         sizeof(struct ea_refcount_el) * num);
2112         }
2113         refcount->count++;
2114         el = &refcount->list[pos];
2115         el->ea_count = 0;
2116         el->ea_blk = blk;
2117         return el;
2118 }
2119
2120
2121 /*
2122  * get_refcount_el() --- given an block number, try to find refcount
2123  *      information in the sorted list.  If the create flag is set,
2124  *      and we can't find an entry, create one in the sorted list.
2125  */
2126 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2127                                               blk_t blk, int create)
2128 {
2129         float   range;
2130         int     low, high, mid;
2131         blk_t   lowval, highval;
2132
2133         if (!refcount || !refcount->list)
2134                 return 0;
2135 retry:
2136         low = 0;
2137         high = (int) refcount->count-1;
2138         if (create && ((refcount->count == 0) ||
2139                        (blk > refcount->list[high].ea_blk))) {
2140                 if (refcount->count >= refcount->size)
2141                         refcount_collapse(refcount);
2142
2143                 return insert_refcount_el(refcount, blk,
2144                                           (unsigned) refcount->count);
2145         }
2146         if (refcount->count == 0)
2147                 return 0;
2148
2149         if (refcount->cursor >= refcount->count)
2150                 refcount->cursor = 0;
2151         if (blk == refcount->list[refcount->cursor].ea_blk)
2152                 return &refcount->list[refcount->cursor++];
2153 #ifdef DEBUG
2154         printf("Non-cursor get_refcount_el: %u\n", blk);
2155 #endif
2156         while (low <= high) {
2157                 if (low == high)
2158                         mid = low;
2159                 else {
2160                         /* Interpolate for efficiency */
2161                         lowval = refcount->list[low].ea_blk;
2162                         highval = refcount->list[high].ea_blk;
2163
2164                         if (blk < lowval)
2165                                 range = 0;
2166                         else if (blk > highval)
2167                                 range = 1;
2168                         else
2169                                 range = ((float) (blk - lowval)) /
2170                                         (highval - lowval);
2171                         mid = low + ((int) (range * (high-low)));
2172                 }
2173
2174                 if (blk == refcount->list[mid].ea_blk) {
2175                         refcount->cursor = mid+1;
2176                         return &refcount->list[mid];
2177                 }
2178                 if (blk < refcount->list[mid].ea_blk)
2179                         high = mid-1;
2180                 else
2181                         low = mid+1;
2182         }
2183         /*
2184          * If we need to create a new entry, it should be right at
2185          * low (where high will be left at low-1).
2186          */
2187         if (create) {
2188                 if (refcount->count >= refcount->size) {
2189                         refcount_collapse(refcount);
2190                         if (refcount->count < refcount->size)
2191                                 goto retry;
2192                 }
2193                 return insert_refcount_el(refcount, blk, low);
2194         }
2195         return 0;
2196 }
2197
2198 static errcode_t
2199 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2200 {
2201         struct ea_refcount_el   *el;
2202
2203         el = get_refcount_el(refcount, blk, 1);
2204         if (!el)
2205                 return EXT2_ET_NO_MEMORY;
2206         el->ea_count++;
2207
2208         if (ret)
2209                 *ret = el->ea_count;
2210         return 0;
2211 }
2212
2213 static errcode_t
2214 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2215 {
2216         struct ea_refcount_el   *el;
2217
2218         el = get_refcount_el(refcount, blk, 0);
2219         if (!el || el->ea_count == 0)
2220                 return EXT2_ET_INVALID_ARGUMENT;
2221
2222         el->ea_count--;
2223
2224         if (ret)
2225                 *ret = el->ea_count;
2226         return 0;
2227 }
2228
2229 static errcode_t
2230 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2231 {
2232         struct ea_refcount_el   *el;
2233
2234         /*
2235          * Get the refcount element
2236          */
2237         el = get_refcount_el(refcount, blk, count ? 1 : 0);
2238         if (!el)
2239                 return count ? EXT2_ET_NO_MEMORY : 0;
2240         el->ea_count = count;
2241         return 0;
2242 }
2243
2244 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2245 {
2246         refcount->cursor = 0;
2247 }
2248
2249
2250 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2251 {
2252         struct ea_refcount_el   *list;
2253
2254         while (1) {
2255                 if (refcount->cursor >= refcount->count)
2256                         return 0;
2257                 list = refcount->list;
2258                 if (list[refcount->cursor].ea_count) {
2259                         if (ret)
2260                                 *ret = list[refcount->cursor].ea_count;
2261                         return list[refcount->cursor++].ea_blk;
2262                 }
2263                 refcount->cursor++;
2264         }
2265 }
2266
2267
2268 /*
2269  * ehandler.c --- handle bad block errors which come up during the
2270  *      course of an e2fsck session.
2271  */
2272
2273
2274 static const char *operation;
2275
2276 static errcode_t
2277 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2278                          void *data, size_t size FSCK_ATTR((unused)),
2279                          int actual FSCK_ATTR((unused)), errcode_t error)
2280 {
2281         int     i;
2282         char    *p;
2283         ext2_filsys fs = (ext2_filsys) channel->app_data;
2284         e2fsck_t ctx;
2285
2286         ctx = (e2fsck_t) fs->priv_data;
2287
2288         /*
2289          * If more than one block was read, try reading each block
2290          * separately.  We could use the actual bytes read to figure
2291          * out where to start, but we don't bother.
2292          */
2293         if (count > 1) {
2294                 p = (char *) data;
2295                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2296                         error = io_channel_read_blk(channel, block,
2297                                                     1, p);
2298                         if (error)
2299                                 return error;
2300                 }
2301                 return 0;
2302         }
2303         if (operation)
2304                 printf(_("Error reading block %lu (%s) while %s.  "), block,
2305                        error_message(error), operation);
2306         else
2307                 printf(_("Error reading block %lu (%s).  "), block,
2308                        error_message(error));
2309         preenhalt(ctx);
2310         if (ask(ctx, _("Ignore error"), 1)) {
2311                 if (ask(ctx, _("Force rewrite"), 1))
2312                         io_channel_write_blk(channel, block, 1, data);
2313                 return 0;
2314         }
2315
2316         return error;
2317 }
2318
2319 static errcode_t
2320 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2321                         const void *data, size_t size FSCK_ATTR((unused)),
2322                         int actual FSCK_ATTR((unused)), errcode_t error)
2323 {
2324         int             i;
2325         const char      *p;
2326         ext2_filsys fs = (ext2_filsys) channel->app_data;
2327         e2fsck_t ctx;
2328
2329         ctx = (e2fsck_t) fs->priv_data;
2330
2331         /*
2332          * If more than one block was written, try writing each block
2333          * separately.  We could use the actual bytes read to figure
2334          * out where to start, but we don't bother.
2335          */
2336         if (count > 1) {
2337                 p = (const char *) data;
2338                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2339                         error = io_channel_write_blk(channel, block,
2340                                                      1, p);
2341                         if (error)
2342                                 return error;
2343                 }
2344                 return 0;
2345         }
2346
2347         if (operation)
2348                 printf(_("Error writing block %lu (%s) while %s.  "), block,
2349                        error_message(error), operation);
2350         else
2351                 printf(_("Error writing block %lu (%s).  "), block,
2352                        error_message(error));
2353         preenhalt(ctx);
2354         if (ask(ctx, _("Ignore error"), 1))
2355                 return 0;
2356
2357         return error;
2358 }
2359
2360 static inline const char *ehandler_operation(const char *op)
2361 {
2362         const char *ret = operation;
2363
2364         operation = op;
2365         return ret;
2366 }
2367
2368 static void ehandler_init(io_channel channel)
2369 {
2370         channel->read_error = e2fsck_handle_read_error;
2371         channel->write_error = e2fsck_handle_write_error;
2372 }
2373
2374 /*
2375  * journal.c --- code for handling the "ext3" journal
2376  *
2377  * Copyright (C) 2000 Andreas Dilger
2378  * Copyright (C) 2000 Theodore Ts'o
2379  *
2380  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2381  * Copyright (C) 1999 Red Hat Software
2382  *
2383  * This file may be redistributed under the terms of the
2384  * GNU General Public License version 2 or at your discretion
2385  * any later version.
2386  */
2387
2388 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2389
2390 /*
2391  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2392  * This creates a larger static binary, and a smaller binary using
2393  * shared libraries.  It's also probably slightly less CPU-efficient,
2394  * which is why it's not on by default.  But, it's a good way of
2395  * testing the functions in inode_io.c and fileio.c.
2396  */
2397 #undef USE_INODE_IO
2398
2399 /* Kernel compatibility functions for handling the journal.  These allow us
2400  * to use the recovery.c file virtually unchanged from the kernel, so we
2401  * don't have to do much to keep kernel and user recovery in sync.
2402  */
2403 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2404 {
2405 #ifdef USE_INODE_IO
2406         *phys = block;
2407         return 0;
2408 #else
2409         struct inode    *inode = journal->j_inode;
2410         errcode_t       retval;
2411         blk_t           pblk;
2412
2413         if (!inode) {
2414                 *phys = block;
2415                 return 0;
2416         }
2417
2418         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2419                             &inode->i_ext2, NULL, 0, block, &pblk);
2420         *phys = pblk;
2421         return (retval);
2422 #endif
2423 }
2424
2425 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2426 {
2427         struct buffer_head *bh;
2428
2429         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2430         if (!bh)
2431                 return NULL;
2432
2433         bh->b_ctx = kdev->k_ctx;
2434         if (kdev->k_dev == K_DEV_FS)
2435                 bh->b_io = kdev->k_ctx->fs->io;
2436         else
2437                 bh->b_io = kdev->k_ctx->journal_io;
2438         bh->b_size = blocksize;
2439         bh->b_blocknr = blocknr;
2440
2441         return bh;
2442 }
2443
2444 static void sync_blockdev(kdev_t kdev)
2445 {
2446         io_channel      io;
2447
2448         if (kdev->k_dev == K_DEV_FS)
2449                 io = kdev->k_ctx->fs->io;
2450         else
2451                 io = kdev->k_ctx->journal_io;
2452
2453         io_channel_flush(io);
2454 }
2455
2456 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2457 {
2458         int retval;
2459         struct buffer_head *bh;
2460
2461         for (; nr > 0; --nr) {
2462                 bh = *bhp++;
2463                 if (rw == READ && !bh->b_uptodate) {
2464                         retval = io_channel_read_blk(bh->b_io,
2465                                                      bh->b_blocknr,
2466                                                      1, bh->b_data);
2467                         if (retval) {
2468                                 com_err(bh->b_ctx->device_name, retval,
2469                                         "while reading block %lu\n",
2470                                         (unsigned long) bh->b_blocknr);
2471                                 bh->b_err = retval;
2472                                 continue;
2473                         }
2474                         bh->b_uptodate = 1;
2475                 } else if (rw == WRITE && bh->b_dirty) {
2476                         retval = io_channel_write_blk(bh->b_io,
2477                                                       bh->b_blocknr,
2478                                                       1, bh->b_data);
2479                         if (retval) {
2480                                 com_err(bh->b_ctx->device_name, retval,
2481                                         "while writing block %lu\n",
2482                                         (unsigned long) bh->b_blocknr);
2483                                 bh->b_err = retval;
2484                                 continue;
2485                         }
2486                         bh->b_dirty = 0;
2487                         bh->b_uptodate = 1;
2488                 }
2489         }
2490 }
2491
2492 static inline void mark_buffer_dirty(struct buffer_head *bh)
2493 {
2494         bh->b_dirty = 1;
2495 }
2496
2497 static inline void mark_buffer_clean(struct buffer_head * bh)
2498 {
2499         bh->b_dirty = 0;
2500 }
2501
2502 static void brelse(struct buffer_head *bh)
2503 {
2504         if (bh->b_dirty)
2505                 ll_rw_block(WRITE, 1, &bh);
2506         ext2fs_free_mem(&bh);
2507 }
2508
2509 static inline int buffer_uptodate(struct buffer_head *bh)
2510 {
2511         return bh->b_uptodate;
2512 }
2513
2514 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2515 {
2516         bh->b_uptodate = val;
2517 }
2518
2519 static void wait_on_buffer(struct buffer_head *bh)
2520 {
2521         if (!bh->b_uptodate)
2522                 ll_rw_block(READ, 1, &bh);
2523 }
2524
2525
2526 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2527 {
2528         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2529
2530         /* if we had an error doing journal recovery, we need a full fsck */
2531         if (error)
2532                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2533         ext2fs_mark_super_dirty(ctx->fs);
2534 }
2535
2536 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2537 {
2538         struct ext2_super_block *sb = ctx->fs->super;
2539         struct ext2_super_block jsuper;
2540         struct problem_context  pctx;
2541         struct buffer_head      *bh;
2542         struct inode            *j_inode = NULL;
2543         struct kdev_s           *dev_fs = NULL, *dev_journal;
2544         const char              *journal_name = 0;
2545         journal_t               *journal = NULL;
2546         errcode_t               retval = 0;
2547         io_manager              io_ptr = 0;
2548         unsigned long           start = 0;
2549         blk_t                   blk;
2550         int                     ext_journal = 0;
2551         int                     tried_backup_jnl = 0;
2552         int                     i;
2553
2554         clear_problem_context(&pctx);
2555
2556         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2557         if (!journal) {
2558                 return EXT2_ET_NO_MEMORY;
2559         }
2560
2561         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2562         if (!dev_fs) {
2563                 retval = EXT2_ET_NO_MEMORY;
2564                 goto errout;
2565         }
2566         dev_journal = dev_fs+1;
2567
2568         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2569         dev_fs->k_dev = K_DEV_FS;
2570         dev_journal->k_dev = K_DEV_JOURNAL;
2571
2572         journal->j_dev = dev_journal;
2573         journal->j_fs_dev = dev_fs;
2574         journal->j_inode = NULL;
2575         journal->j_blocksize = ctx->fs->blocksize;
2576
2577         if (uuid_is_null(sb->s_journal_uuid)) {
2578                 if (!sb->s_journal_inum)
2579                         return EXT2_ET_BAD_INODE_NUM;
2580                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2581                                                  "journal inode");
2582                 if (!j_inode) {
2583                         retval = EXT2_ET_NO_MEMORY;
2584                         goto errout;
2585                 }
2586
2587                 j_inode->i_ctx = ctx;
2588                 j_inode->i_ino = sb->s_journal_inum;
2589
2590                 if ((retval = ext2fs_read_inode(ctx->fs,
2591                                                 sb->s_journal_inum,
2592                                                 &j_inode->i_ext2))) {
2593                 try_backup_journal:
2594                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
2595                             tried_backup_jnl)
2596                                 goto errout;
2597                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
2598                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
2599                                EXT2_N_BLOCKS*4);
2600                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
2601                         j_inode->i_ext2.i_links_count = 1;
2602                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
2603                         tried_backup_jnl++;
2604                 }
2605                 if (!j_inode->i_ext2.i_links_count ||
2606                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
2607                         retval = EXT2_ET_NO_JOURNAL;
2608                         goto try_backup_journal;
2609                 }
2610                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
2611                     JFS_MIN_JOURNAL_BLOCKS) {
2612                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
2613                         goto try_backup_journal;
2614                 }
2615                 for (i=0; i < EXT2_N_BLOCKS; i++) {
2616                         blk = j_inode->i_ext2.i_block[i];
2617                         if (!blk) {
2618                                 if (i < EXT2_NDIR_BLOCKS) {
2619                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
2620                                         goto try_backup_journal;
2621                                 }
2622                                 continue;
2623                         }
2624                         if (blk < sb->s_first_data_block ||
2625                             blk >= sb->s_blocks_count) {
2626                                 retval = EXT2_ET_BAD_BLOCK_NUM;
2627                                 goto try_backup_journal;
2628                         }
2629                 }
2630                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
2631
2632 #ifdef USE_INODE_IO
2633                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
2634                                                  &j_inode->i_ext2,
2635                                                  &journal_name);
2636                 if (retval)
2637                         goto errout;
2638
2639                 io_ptr = inode_io_manager;
2640 #else
2641                 journal->j_inode = j_inode;
2642                 ctx->journal_io = ctx->fs->io;
2643                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
2644                         goto errout;
2645 #endif
2646         } else {
2647                 ext_journal = 1;
2648                 if (!ctx->journal_name) {
2649                         char uuid[37];
2650
2651                         uuid_unparse(sb->s_journal_uuid, uuid);
2652                         ctx->journal_name = blkid_get_devname(ctx->blkid,
2653                                                               "UUID", uuid);
2654                         if (!ctx->journal_name)
2655                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
2656                 }
2657                 journal_name = ctx->journal_name;
2658
2659                 if (!journal_name) {
2660                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
2661                         return EXT2_ET_LOAD_EXT_JOURNAL;
2662                 }
2663
2664                 io_ptr = unix_io_manager;
2665         }
2666
2667 #ifndef USE_INODE_IO
2668         if (ext_journal)
2669 #endif
2670                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
2671                                       &ctx->journal_io);
2672         if (retval)
2673                 goto errout;
2674
2675         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
2676
2677         if (ext_journal) {
2678                 if (ctx->fs->blocksize == 1024)
2679                         start = 1;
2680                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
2681                 if (!bh) {
2682                         retval = EXT2_ET_NO_MEMORY;
2683                         goto errout;
2684                 }
2685                 ll_rw_block(READ, 1, &bh);
2686                 if ((retval = bh->b_err) != 0)
2687                         goto errout;
2688                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
2689                        sizeof(jsuper));
2690                 brelse(bh);
2691 #ifdef EXT2FS_ENABLE_SWAPFS
2692                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
2693                         ext2fs_swap_super(&jsuper);
2694 #endif
2695                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
2696                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
2697                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
2698                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
2699                         goto errout;
2700                 }
2701                 /* Make sure the journal UUID is correct */
2702                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
2703                            sizeof(jsuper.s_uuid))) {
2704                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
2705                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
2706                         goto errout;
2707                 }
2708
2709                 journal->j_maxlen = jsuper.s_blocks_count;
2710                 start++;
2711         }
2712
2713         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
2714                 retval = EXT2_ET_NO_MEMORY;
2715                 goto errout;
2716         }
2717
2718         journal->j_sb_buffer = bh;
2719         journal->j_superblock = (journal_superblock_t *)bh->b_data;
2720
2721 #ifdef USE_INODE_IO
2722         ext2fs_free_mem(&j_inode);
2723 #endif
2724
2725         *ret_journal = journal;
2726         return 0;
2727
2728 errout:
2729         ext2fs_free_mem(&dev_fs);
2730         ext2fs_free_mem(&j_inode);
2731         ext2fs_free_mem(&journal);
2732         return retval;
2733
2734 }
2735
2736 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
2737                                               struct problem_context *pctx)
2738 {
2739         struct ext2_super_block *sb = ctx->fs->super;
2740         int recover = ctx->fs->super->s_feature_incompat &
2741                 EXT3_FEATURE_INCOMPAT_RECOVER;
2742         int has_journal = ctx->fs->super->s_feature_compat &
2743                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2744
2745         if (has_journal || sb->s_journal_inum) {
2746                 /* The journal inode is bogus, remove and force full fsck */
2747                 pctx->ino = sb->s_journal_inum;
2748                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
2749                         if (has_journal && sb->s_journal_inum)
2750                                 printf("*** ext3 journal has been deleted - "
2751                                        "filesystem is now ext2 only ***\n\n");
2752                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2753                         sb->s_journal_inum = 0;
2754                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
2755                         e2fsck_clear_recover(ctx, 1);
2756                         return 0;
2757                 }
2758                 return EXT2_ET_BAD_INODE_NUM;
2759         } else if (recover) {
2760                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
2761                         e2fsck_clear_recover(ctx, 1);
2762                         return 0;
2763                 }
2764                 return EXT2_ET_UNSUPP_FEATURE;
2765         }
2766         return 0;
2767 }
2768
2769 #define V1_SB_SIZE      0x0024
2770 static void clear_v2_journal_fields(journal_t *journal)
2771 {
2772         e2fsck_t ctx = journal->j_dev->k_ctx;
2773         struct problem_context pctx;
2774
2775         clear_problem_context(&pctx);
2776
2777         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
2778                 return;
2779
2780         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
2781                ctx->fs->blocksize-V1_SB_SIZE);
2782         mark_buffer_dirty(journal->j_sb_buffer);
2783 }
2784
2785
2786 static errcode_t e2fsck_journal_load(journal_t *journal)
2787 {
2788         e2fsck_t ctx = journal->j_dev->k_ctx;
2789         journal_superblock_t *jsb;
2790         struct buffer_head *jbh = journal->j_sb_buffer;
2791         struct problem_context pctx;
2792
2793         clear_problem_context(&pctx);
2794
2795         ll_rw_block(READ, 1, &jbh);
2796         if (jbh->b_err) {
2797                 com_err(ctx->device_name, jbh->b_err,
2798                         _("reading journal superblock\n"));
2799                 return jbh->b_err;
2800         }
2801
2802         jsb = journal->j_superblock;
2803         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
2804         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
2805                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2806
2807         switch (ntohl(jsb->s_header.h_blocktype)) {
2808         case JFS_SUPERBLOCK_V1:
2809                 journal->j_format_version = 1;
2810                 if (jsb->s_feature_compat ||
2811                     jsb->s_feature_incompat ||
2812                     jsb->s_feature_ro_compat ||
2813                     jsb->s_nr_users)
2814                         clear_v2_journal_fields(journal);
2815                 break;
2816
2817         case JFS_SUPERBLOCK_V2:
2818                 journal->j_format_version = 2;
2819                 if (ntohl(jsb->s_nr_users) > 1 &&
2820                     uuid_is_null(ctx->fs->super->s_journal_uuid))
2821                         clear_v2_journal_fields(journal);
2822                 if (ntohl(jsb->s_nr_users) > 1) {
2823                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
2824                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
2825                 }
2826                 break;
2827
2828         /*
2829          * These should never appear in a journal super block, so if
2830          * they do, the journal is badly corrupted.
2831          */
2832         case JFS_DESCRIPTOR_BLOCK:
2833         case JFS_COMMIT_BLOCK:
2834         case JFS_REVOKE_BLOCK:
2835                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2836
2837         /* If we don't understand the superblock major type, but there
2838          * is a magic number, then it is likely to be a new format we
2839          * just don't understand, so leave it alone. */
2840         default:
2841                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
2842         }
2843
2844         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
2845                 return EXT2_ET_UNSUPP_FEATURE;
2846
2847         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
2848                 return EXT2_ET_RO_UNSUPP_FEATURE;
2849
2850         /* We have now checked whether we know enough about the journal
2851          * format to be able to proceed safely, so any other checks that
2852          * fail we should attempt to recover from. */
2853         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
2854                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
2855                         _("%s: no valid journal superblock found\n"),
2856                         ctx->device_name);
2857                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2858         }
2859
2860         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
2861                 journal->j_maxlen = ntohl(jsb->s_maxlen);
2862         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
2863                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
2864                         _("%s: journal too short\n"),
2865                         ctx->device_name);
2866                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2867         }
2868
2869         journal->j_tail_sequence = ntohl(jsb->s_sequence);
2870         journal->j_transaction_sequence = journal->j_tail_sequence;
2871         journal->j_tail = ntohl(jsb->s_start);
2872         journal->j_first = ntohl(jsb->s_first);
2873         journal->j_last = ntohl(jsb->s_maxlen);
2874
2875         return 0;
2876 }
2877
2878 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
2879                                        journal_t *journal)
2880 {
2881         char *p;
2882         union {
2883                 uuid_t uuid;
2884                 __u32 val[4];
2885         } u;
2886         __u32 new_seq = 0;
2887         int i;
2888
2889         /* Leave a valid existing V1 superblock signature alone.
2890          * Anything unrecognisable we overwrite with a new V2
2891          * signature. */
2892
2893         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
2894             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
2895                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
2896                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
2897         }
2898
2899         /* Zero out everything else beyond the superblock header */
2900
2901         p = ((char *) jsb) + sizeof(journal_header_t);
2902         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
2903
2904         jsb->s_blocksize = htonl(ctx->fs->blocksize);
2905         jsb->s_maxlen = htonl(journal->j_maxlen);
2906         jsb->s_first = htonl(1);
2907
2908         /* Initialize the journal sequence number so that there is "no"
2909          * chance we will find old "valid" transactions in the journal.
2910          * This avoids the need to zero the whole journal (slow to do,
2911          * and risky when we are just recovering the filesystem).
2912          */
2913         uuid_generate(u.uuid);
2914         for (i = 0; i < 4; i ++)
2915                 new_seq ^= u.val[i];
2916         jsb->s_sequence = htonl(new_seq);
2917
2918         mark_buffer_dirty(journal->j_sb_buffer);
2919         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
2920 }
2921
2922 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
2923                                                   journal_t *journal,
2924                                                   struct problem_context *pctx)
2925 {
2926         struct ext2_super_block *sb = ctx->fs->super;
2927         int recover = ctx->fs->super->s_feature_incompat &
2928                 EXT3_FEATURE_INCOMPAT_RECOVER;
2929
2930         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
2931                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
2932                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
2933                                                    journal);
2934                         journal->j_transaction_sequence = 1;
2935                         e2fsck_clear_recover(ctx, recover);
2936                         return 0;
2937                 }
2938                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2939         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
2940                 return EXT2_ET_CORRUPT_SUPERBLOCK;
2941
2942         return 0;
2943 }
2944
2945 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
2946                                    int reset, int drop)
2947 {
2948         journal_superblock_t *jsb;
2949
2950         if (drop)
2951                 mark_buffer_clean(journal->j_sb_buffer);
2952         else if (!(ctx->options & E2F_OPT_READONLY)) {
2953                 jsb = journal->j_superblock;
2954                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
2955                 if (reset)
2956                         jsb->s_start = 0; /* this marks the journal as empty */
2957                 mark_buffer_dirty(journal->j_sb_buffer);
2958         }
2959         brelse(journal->j_sb_buffer);
2960
2961         if (ctx->journal_io) {
2962                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2963                         io_channel_close(ctx->journal_io);
2964                 ctx->journal_io = 0;
2965         }
2966
2967 #ifndef USE_INODE_IO
2968         ext2fs_free_mem(&journal->j_inode);
2969 #endif
2970         ext2fs_free_mem(&journal->j_fs_dev);
2971         ext2fs_free_mem(&journal);
2972 }
2973
2974 /*
2975  * This function makes sure that the superblock fields regarding the
2976  * journal are consistent.
2977  */
2978 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
2979 {
2980         struct ext2_super_block *sb = ctx->fs->super;
2981         journal_t *journal;
2982         int recover = ctx->fs->super->s_feature_incompat &
2983                 EXT3_FEATURE_INCOMPAT_RECOVER;
2984         struct problem_context pctx;
2985         problem_t problem;
2986         int reset = 0, force_fsck = 0;
2987         int retval;
2988
2989         /* If we don't have any journal features, don't do anything more */
2990         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
2991             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
2992             uuid_is_null(sb->s_journal_uuid))
2993                 return 0;
2994
2995         clear_problem_context(&pctx);
2996         pctx.num = sb->s_journal_inum;
2997
2998         retval = e2fsck_get_journal(ctx, &journal);
2999         if (retval) {
3000                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3001                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3002                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3003                     (retval == EXT2_ET_NO_JOURNAL))
3004                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3005                 return retval;
3006         }
3007
3008         retval = e2fsck_journal_load(journal);
3009         if (retval) {
3010                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3011                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3012                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3013                                   &pctx))) ||
3014                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3015                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3016                                   &pctx))) ||
3017                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3018                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3019                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3020                                                                   &pctx);
3021                 e2fsck_journal_release(ctx, journal, 0, 1);
3022                 return retval;
3023         }
3024
3025         /*
3026          * We want to make the flags consistent here.  We will not leave with
3027          * needs_recovery set but has_journal clear.  We can't get in a loop
3028          * with -y, -n, or -p, only if a user isn't making up their mind.
3029          */
3030 no_has_journal:
3031         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3032                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3033                 pctx.str = "inode";
3034                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3035                         if (recover &&
3036                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3037                                 goto no_has_journal;
3038                         /*
3039                          * Need a full fsck if we are releasing a
3040                          * journal stored on a reserved inode.
3041                          */
3042                         force_fsck = recover ||
3043                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3044                         /* Clear all of the journal fields */
3045                         sb->s_journal_inum = 0;
3046                         sb->s_journal_dev = 0;
3047                         memset(sb->s_journal_uuid, 0,
3048                                sizeof(sb->s_journal_uuid));
3049                         e2fsck_clear_recover(ctx, force_fsck);
3050                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3051                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3052                         ext2fs_mark_super_dirty(ctx->fs);
3053                 }
3054         }
3055
3056         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3057             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3058             journal->j_superblock->s_start != 0) {
3059                 /* Print status information */
3060                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3061                 if (ctx->superblock)
3062                         problem = PR_0_JOURNAL_RUN_DEFAULT;
3063                 else
3064                         problem = PR_0_JOURNAL_RUN;
3065                 if (fix_problem(ctx, problem, &pctx)) {
3066                         ctx->options |= E2F_OPT_FORCE;
3067                         sb->s_feature_incompat |=
3068                                 EXT3_FEATURE_INCOMPAT_RECOVER;
3069                         ext2fs_mark_super_dirty(ctx->fs);
3070                 } else if (fix_problem(ctx,
3071                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3072                         reset = 1;
3073                         sb->s_state &= ~EXT2_VALID_FS;
3074                         ext2fs_mark_super_dirty(ctx->fs);
3075                 }
3076                 /*
3077                  * If the user answers no to the above question, we
3078                  * ignore the fact that journal apparently has data;
3079                  * accidentally replaying over valid data would be far
3080                  * worse than skipping a questionable recovery.
3081                  *
3082                  * XXX should we abort with a fatal error here?  What
3083                  * will the ext3 kernel code do if a filesystem with
3084                  * !NEEDS_RECOVERY but with a non-zero
3085                  * journal->j_superblock->s_start is mounted?
3086                  */
3087         }
3088
3089         e2fsck_journal_release(ctx, journal, reset, 0);
3090         return retval;
3091 }
3092
3093 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3094 {
3095         journal_t *journal;
3096         int retval;
3097
3098         journal_init_revoke_caches();
3099         retval = e2fsck_get_journal(ctx, &journal);
3100         if (retval)
3101                 return retval;
3102
3103         retval = e2fsck_journal_load(journal);
3104         if (retval)
3105                 goto errout;
3106
3107         retval = journal_init_revoke(journal, 1024);
3108         if (retval)
3109                 goto errout;
3110
3111         retval = -journal_recover(journal);
3112         if (retval)
3113                 goto errout;
3114
3115         if (journal->j_superblock->s_errno) {
3116                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3117                 ext2fs_mark_super_dirty(ctx->fs);
3118                 journal->j_superblock->s_errno = 0;
3119                 mark_buffer_dirty(journal->j_sb_buffer);
3120         }
3121
3122 errout:
3123         journal_destroy_revoke(journal);
3124         journal_destroy_revoke_caches();
3125         e2fsck_journal_release(ctx, journal, 1, 0);
3126         return retval;
3127 }
3128
3129 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3130 {
3131         io_manager io_ptr = ctx->fs->io->manager;
3132         int blocksize = ctx->fs->blocksize;
3133         errcode_t       retval, recover_retval;
3134
3135         printf(_("%s: recovering journal\n"), ctx->device_name);
3136         if (ctx->options & E2F_OPT_READONLY) {
3137                 printf(_("%s: won't do journal recovery while read-only\n"),
3138                        ctx->device_name);
3139                 return EXT2_ET_FILE_RO;
3140         }
3141
3142         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3143                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
3144
3145         recover_retval = recover_ext3_journal(ctx);
3146
3147         /*
3148          * Reload the filesystem context to get up-to-date data from disk
3149          * because journal recovery will change the filesystem under us.
3150          */
3151         ext2fs_close(ctx->fs);
3152         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3153                              ctx->superblock, blocksize, io_ptr,
3154                              &ctx->fs);
3155
3156         if (retval) {
3157                 com_err(ctx->program_name, retval,
3158                         _("while trying to re-open %s"),
3159                         ctx->device_name);
3160                 fatal_error(ctx, 0);
3161         }
3162         ctx->fs->priv_data = ctx;
3163
3164         /* Set the superblock flags */
3165         e2fsck_clear_recover(ctx, recover_retval);
3166         return recover_retval;
3167 }
3168
3169 /*
3170  * This function will move the journal inode from a visible file in
3171  * the filesystem directory hierarchy to the reserved inode if necessary.
3172  */
3173 static const char * const journal_names[] = {
3174         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3175
3176 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3177 {
3178         struct ext2_super_block *sb = ctx->fs->super;
3179         struct problem_context  pctx;
3180         struct ext2_inode       inode;
3181         ext2_filsys             fs = ctx->fs;
3182         ext2_ino_t              ino;
3183         errcode_t               retval;
3184         const char * const *    cpp;
3185         int                     group, mount_flags;
3186
3187         clear_problem_context(&pctx);
3188
3189         /*
3190          * If the filesystem is opened read-only, or there is no
3191          * journal, then do nothing.
3192          */
3193         if ((ctx->options & E2F_OPT_READONLY) ||
3194             (sb->s_journal_inum == 0) ||
3195             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3196                 return;
3197
3198         /*
3199          * Read in the journal inode
3200          */
3201         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3202                 return;
3203
3204         /*
3205          * If it's necessary to backup the journal inode, do so.
3206          */
3207         if ((sb->s_jnl_backup_type == 0) ||
3208             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3209              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3210                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3211                         memcpy(sb->s_jnl_blocks, inode.i_block,
3212                                EXT2_N_BLOCKS*4);
3213                         sb->s_jnl_blocks[16] = inode.i_size;
3214                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3215                         ext2fs_mark_super_dirty(fs);
3216                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3217                 }
3218         }
3219
3220         /*
3221          * If the journal is already the hidden inode, then do nothing
3222          */
3223         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3224                 return;
3225
3226         /*
3227          * The journal inode had better have only one link and not be readable.
3228          */
3229         if (inode.i_links_count != 1)
3230                 return;
3231
3232         /*
3233          * If the filesystem is mounted, or we can't tell whether
3234          * or not it's mounted, do nothing.
3235          */
3236         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3237         if (retval || (mount_flags & EXT2_MF_MOUNTED))
3238                 return;
3239
3240         /*
3241          * If we can't find the name of the journal inode, then do
3242          * nothing.
3243          */
3244         for (cpp = journal_names; *cpp; cpp++) {
3245                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3246                                        strlen(*cpp), 0, &ino);
3247                 if ((retval == 0) && (ino == sb->s_journal_inum))
3248                         break;
3249         }
3250         if (*cpp == 0)
3251                 return;
3252
3253         /* We need the inode bitmap to be loaded */
3254         retval = ext2fs_read_bitmaps(fs);
3255         if (retval)
3256                 return;
3257
3258         pctx.str = *cpp;
3259         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3260                 return;
3261
3262         /*
3263          * OK, we've done all the checks, let's actually move the
3264          * journal inode.  Errors at this point mean we need to force
3265          * an ext2 filesystem check.
3266          */
3267         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3268                 goto err_out;
3269         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3270                 goto err_out;
3271         sb->s_journal_inum = EXT2_JOURNAL_INO;
3272         ext2fs_mark_super_dirty(fs);
3273         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3274         inode.i_links_count = 0;
3275         inode.i_dtime = time(0);
3276         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3277                 goto err_out;
3278
3279         group = ext2fs_group_of_ino(fs, ino);
3280         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3281         ext2fs_mark_ib_dirty(fs);
3282         fs->group_desc[group].bg_free_inodes_count++;
3283         fs->super->s_free_inodes_count++;
3284         return;
3285
3286 err_out:
3287         pctx.errcode = retval;
3288         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3289         fs->super->s_state &= ~EXT2_VALID_FS;
3290         ext2fs_mark_super_dirty(fs);
3291         return;
3292 }
3293
3294 /*
3295  * message.c --- print e2fsck messages (with compression)
3296  *
3297  * print_e2fsck_message() prints a message to the user, using
3298  * compression techniques and expansions of abbreviations.
3299  *
3300  * The following % expansions are supported:
3301  *
3302  *      %b      <blk>                   block number
3303  *      %B      <blkcount>              integer
3304  *      %c      <blk2>                  block number
3305  *      %Di     <dirent>->ino           inode number
3306  *      %Dn     <dirent>->name          string
3307  *      %Dr     <dirent>->rec_len
3308  *      %Dl     <dirent>->name_len
3309  *      %Dt     <dirent>->filetype
3310  *      %d      <dir>                   inode number
3311  *      %g      <group>                 integer
3312  *      %i      <ino>                   inode number
3313  *      %Is     <inode> -> i_size
3314  *      %IS     <inode> -> i_extra_isize
3315  *      %Ib     <inode> -> i_blocks
3316  *      %Il     <inode> -> i_links_count
3317  *      %Im     <inode> -> i_mode
3318  *      %IM     <inode> -> i_mtime
3319  *      %IF     <inode> -> i_faddr
3320  *      %If     <inode> -> i_file_acl
3321  *      %Id     <inode> -> i_dir_acl
3322  *      %Iu     <inode> -> i_uid
3323  *      %Ig     <inode> -> i_gid
3324  *      %j      <ino2>                  inode number
3325  *      %m      <com_err error message>
3326  *      %N      <num>
3327  *      %p      ext2fs_get_pathname of directory <ino>
3328  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
3329  *                      the containing directory.  (If dirent is NULL
3330  *                      then return the pathname of directory <ino2>)
3331  *      %q      ext2fs_get_pathname of directory <dir>
3332  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
3333  *                      the containing directory.
3334  *      %s      <str>                   miscellaneous string
3335  *      %S      backup superblock
3336  *      %X      <num> hexadecimal format
3337  *
3338  * The following '@' expansions are supported:
3339  *
3340  *      @a      extended attribute
3341  *      @A      error allocating
3342  *      @b      block
3343  *      @B      bitmap
3344  *      @c      compress
3345  *      @C      conflicts with some other fs block
3346  *      @D      deleted
3347  *      @d      directory
3348  *      @e      entry
3349  *      @E      Entry '%Dn' in %p (%i)
3350  *      @f      filesystem
3351  *      @F      for @i %i (%Q) is
3352  *      @g      group
3353  *      @h      HTREE directory inode
3354  *      @i      inode
3355  *      @I      illegal
3356  *      @j      journal
3357  *      @l      lost+found
3358  *      @L      is a link
3359  *      @m      multiply-claimed
3360  *      @n      invalid
3361  *      @o      orphaned
3362  *      @p      problem in
3363  *      @r      root inode
3364  *      @s      should be
3365  *      @S      superblock
3366  *      @u      unattached
3367  *      @v      device
3368  *      @z      zero-length
3369  */
3370
3371
3372 /*
3373  * This structure defines the abbreviations used by the text strings
3374  * below.  The first character in the string is the index letter.  An
3375  * abbreviation of the form '@<i>' is expanded by looking up the index
3376  * letter <i> in the table below.
3377  */
3378 static const char * const abbrevs[] = {
3379         N_("aextended attribute"),
3380         N_("Aerror allocating"),
3381         N_("bblock"),
3382         N_("Bbitmap"),
3383         N_("ccompress"),
3384         N_("Cconflicts with some other fs @b"),
3385         N_("iinode"),
3386         N_("Iillegal"),
3387         N_("jjournal"),
3388         N_("Ddeleted"),
3389         N_("ddirectory"),
3390         N_("eentry"),
3391         N_("E@e '%Dn' in %p (%i)"),
3392         N_("ffilesystem"),
3393         N_("Ffor @i %i (%Q) is"),
3394         N_("ggroup"),
3395         N_("hHTREE @d @i"),
3396         N_("llost+found"),
3397         N_("Lis a link"),
3398     N_("mmultiply-claimed"),
3399     N_("ninvalid"),
3400         N_("oorphaned"),
3401         N_("pproblem in"),
3402         N_("rroot @i"),
3403         N_("sshould be"),
3404         N_("Ssuper@b"),
3405         N_("uunattached"),
3406         N_("vdevice"),
3407         N_("zzero-length"),
3408         "@@",
3409         0
3410         };
3411
3412 /*
3413  * Give more user friendly names to the "special" inodes.
3414  */
3415 #define num_special_inodes      11
3416 static const char * const special_inode_name[] =
3417 {
3418         N_("<The NULL inode>"),                 /* 0 */
3419         N_("<The bad blocks inode>"),           /* 1 */
3420         "/",                                    /* 2 */
3421         N_("<The ACL index inode>"),            /* 3 */
3422         N_("<The ACL data inode>"),             /* 4 */
3423         N_("<The boot loader inode>"),          /* 5 */
3424         N_("<The undelete directory inode>"),   /* 6 */
3425         N_("<The group descriptor inode>"),     /* 7 */
3426         N_("<The journal inode>"),              /* 8 */
3427         N_("<Reserved inode 9>"),               /* 9 */
3428         N_("<Reserved inode 10>"),              /* 10 */
3429 };
3430
3431 /*
3432  * This function does "safe" printing.  It will convert non-printable
3433  * ASCII characters using '^' and M- notation.
3434  */
3435 static void safe_print(const char *cp, int len)
3436 {
3437         unsigned char   ch;
3438
3439         if (len < 0)
3440                 len = strlen(cp);
3441
3442         while (len--) {
3443                 ch = *cp++;
3444                 if (ch > 128) {
3445                         fputs("M-", stdout);
3446                         ch -= 128;
3447                 }
3448                 if ((ch < 32) || (ch == 0x7f)) {
3449                         fputc('^', stdout);
3450                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3451                 }
3452                 fputc(ch, stdout);
3453         }
3454 }
3455
3456
3457 /*
3458  * This function prints a pathname, using the ext2fs_get_pathname
3459  * function
3460  */
3461 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3462 {
3463         errcode_t       retval;
3464         char            *path;
3465
3466         if (!dir && (ino < num_special_inodes)) {
3467                 fputs(_(special_inode_name[ino]), stdout);
3468                 return;
3469         }
3470
3471         retval = ext2fs_get_pathname(fs, dir, ino, &path);
3472         if (retval)
3473                 fputs("???", stdout);
3474         else {
3475                 safe_print(path, -1);
3476                 ext2fs_free_mem(&path);
3477         }
3478 }
3479
3480 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3481                           struct problem_context *pctx, int first);
3482 /*
3483  * This function handles the '@' expansion.  We allow recursive
3484  * expansion; an @ expression can contain further '@' and '%'
3485  * expressions.
3486  */
3487 static void expand_at_expression(e2fsck_t ctx, char ch,
3488                                           struct problem_context *pctx,
3489                                           int *first)
3490 {
3491         const char * const *cpp;
3492         const char *str;
3493
3494         /* Search for the abbreviation */
3495         for (cpp = abbrevs; *cpp; cpp++) {
3496                 if (ch == *cpp[0])
3497                         break;
3498         }
3499         if (*cpp) {
3500                 str = _(*cpp) + 1;
3501                 if (*first && islower(*str)) {
3502                         *first = 0;
3503                         fputc(toupper(*str++), stdout);
3504                 }
3505                 print_e2fsck_message(ctx, str, pctx, *first);
3506         } else
3507                 printf("@%c", ch);
3508 }
3509
3510 /*
3511  * This function expands '%IX' expressions
3512  */
3513 static void expand_inode_expression(char ch,
3514                                              struct problem_context *ctx)
3515 {
3516         struct ext2_inode       *inode;
3517         struct ext2_inode_large *large_inode;
3518         char *                  time_str;
3519         time_t                  t;
3520         int                     do_gmt = -1;
3521
3522         if (!ctx || !ctx->inode)
3523                 goto no_inode;
3524
3525         inode = ctx->inode;
3526         large_inode = (struct ext2_inode_large *) inode;
3527
3528         switch (ch) {
3529         case 's':
3530                 if (LINUX_S_ISDIR(inode->i_mode))
3531                         printf("%u", inode->i_size);
3532                 else {
3533 #ifdef EXT2_NO_64_TYPE
3534                         if (inode->i_size_high)
3535                                 printf("0x%x%08x", inode->i_size_high,
3536                                        inode->i_size);
3537                         else
3538                                 printf("%u", inode->i_size);
3539 #else
3540                         printf("%llu", (inode->i_size |
3541                                         ((__u64) inode->i_size_high << 32)));
3542 #endif
3543                 }
3544                 break;
3545         case 'S':
3546                 printf("%u", large_inode->i_extra_isize);
3547                 break;
3548         case 'b':
3549                 printf("%u", inode->i_blocks);
3550                 break;
3551         case 'l':
3552                 printf("%d", inode->i_links_count);
3553                 break;
3554         case 'm':
3555                 printf("0%o", inode->i_mode);
3556                 break;
3557         case 'M':
3558                 /* The diet libc doesn't respect the TZ environemnt variable */
3559                 if (do_gmt == -1) {
3560                         time_str = getenv("TZ");
3561                         if (!time_str)
3562                                 time_str = "";
3563                         do_gmt = !strcmp(time_str, "GMT");
3564                 }
3565                 t = inode->i_mtime;
3566                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3567                 printf("%.24s", time_str);
3568                 break;
3569         case 'F':
3570                 printf("%u", inode->i_faddr);
3571                 break;
3572         case 'f':
3573                 printf("%u", inode->i_file_acl);
3574                 break;
3575         case 'd':
3576                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3577                               inode->i_dir_acl : 0));
3578                 break;
3579         case 'u':
3580                 printf("%d", (inode->i_uid |
3581                               (inode->osd2.linux2.l_i_uid_high << 16)));
3582                 break;
3583         case 'g':
3584                 printf("%d", (inode->i_gid |
3585                               (inode->osd2.linux2.l_i_gid_high << 16)));
3586                 break;
3587         default:
3588         no_inode:
3589                 printf("%%I%c", ch);
3590                 break;
3591         }
3592 }
3593
3594 /*
3595  * This function expands '%dX' expressions
3596  */
3597 static _INLINE_ void expand_dirent_expression(char ch,
3598                                               struct problem_context *ctx)
3599 {
3600         struct ext2_dir_entry   *dirent;
3601         int     len;
3602
3603         if (!ctx || !ctx->dirent)
3604                 goto no_dirent;
3605
3606         dirent = ctx->dirent;
3607
3608         switch (ch) {
3609         case 'i':
3610                 printf("%u", dirent->inode);
3611                 break;
3612         case 'n':
3613                 len = dirent->name_len & 0xFF;
3614                 if (len > EXT2_NAME_LEN)
3615                         len = EXT2_NAME_LEN;
3616                 if (len > dirent->rec_len)
3617                         len = dirent->rec_len;
3618                 safe_print(dirent->name, len);
3619                 break;
3620         case 'r':
3621                 printf("%u", dirent->rec_len);
3622                 break;
3623         case 'l':
3624                 printf("%u", dirent->name_len & 0xFF);
3625                 break;
3626         case 't':
3627                 printf("%u", dirent->name_len >> 8);
3628                 break;
3629         default:
3630         no_dirent:
3631                 printf("%%D%c", ch);
3632                 break;
3633         }
3634 }
3635
3636 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
3637                                                struct problem_context *ctx)
3638 {
3639         if (!ctx)
3640                 goto no_context;
3641
3642         switch (ch) {
3643         case '%':
3644                 fputc('%', stdout);
3645                 break;
3646         case 'b':
3647                 printf("%u", ctx->blk);
3648                 break;
3649         case 'B':
3650 #ifdef EXT2_NO_64_TYPE
3651                 printf("%d", ctx->blkcount);
3652 #else
3653                 printf("%lld", ctx->blkcount);
3654 #endif
3655                 break;
3656         case 'c':
3657                 printf("%u", ctx->blk2);
3658                 break;
3659         case 'd':
3660                 printf("%u", ctx->dir);
3661                 break;
3662         case 'g':
3663                 printf("%d", ctx->group);
3664                 break;
3665         case 'i':
3666                 printf("%u", ctx->ino);
3667                 break;
3668         case 'j':
3669                 printf("%u", ctx->ino2);
3670                 break;
3671         case 'm':
3672                 printf("%s", error_message(ctx->errcode));
3673                 break;
3674         case 'N':
3675 #ifdef EXT2_NO_64_TYPE
3676                 printf("%u", ctx->num);
3677 #else
3678                 printf("%llu", ctx->num);
3679 #endif
3680                 break;
3681         case 'p':
3682                 print_pathname(fs, ctx->ino, 0);
3683                 break;
3684         case 'P':
3685                 print_pathname(fs, ctx->ino2,
3686                                ctx->dirent ? ctx->dirent->inode : 0);
3687                 break;
3688         case 'q':
3689                 print_pathname(fs, ctx->dir, 0);
3690                 break;
3691         case 'Q':
3692                 print_pathname(fs, ctx->dir, ctx->ino);
3693                 break;
3694         case 'S':
3695                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
3696                 break;
3697         case 's':
3698                 printf("%s", ctx->str ? ctx->str : "NULL");
3699                 break;
3700         case 'X':
3701 #ifdef EXT2_NO_64_TYPE
3702                 printf("0x%x", ctx->num);
3703 #else
3704                 printf("0x%llx", ctx->num);
3705 #endif
3706                 break;
3707         default:
3708         no_context:
3709                 printf("%%%c", ch);
3710                 break;
3711         }
3712 }
3713
3714
3715 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3716                           struct problem_context *pctx, int first)
3717 {
3718         ext2_filsys fs = ctx->fs;
3719         const char *    cp;
3720         int             i;
3721
3722         e2fsck_clear_progbar(ctx);
3723         for (cp = msg; *cp; cp++) {
3724                 if (cp[0] == '@') {
3725                         cp++;
3726                         expand_at_expression(ctx, *cp, pctx, &first);
3727                 } else if (cp[0] == '%' && cp[1] == 'I') {
3728                         cp += 2;
3729                         expand_inode_expression(*cp, pctx);
3730                 } else if (cp[0] == '%' && cp[1] == 'D') {
3731                         cp += 2;
3732                         expand_dirent_expression(*cp, pctx);
3733                 } else if ((cp[0] == '%')) {
3734                         cp++;
3735                         expand_percent_expression(fs, *cp, pctx);
3736                 } else {
3737                         for (i=0; cp[i]; i++)
3738                                 if ((cp[i] == '@') || cp[i] == '%')
3739                                         break;
3740                         printf("%.*s", i, cp);
3741                         cp += i-1;
3742                 }
3743                 first = 0;
3744         }
3745 }
3746
3747
3748 /*
3749  * region.c --- code which manages allocations within a region.
3750  */
3751
3752 struct region_el {
3753         region_addr_t   start;
3754         region_addr_t   end;
3755         struct region_el *next;
3756 };
3757
3758 struct region_struct {
3759         region_addr_t   min;
3760         region_addr_t   max;
3761         struct region_el *allocated;
3762 };
3763
3764 static region_t region_create(region_addr_t min, region_addr_t max)
3765 {
3766         region_t        region;
3767
3768         region = malloc(sizeof(struct region_struct));
3769         if (!region)
3770                 return NULL;
3771         memset(region, 0, sizeof(struct region_struct));
3772         region->min = min;
3773         region->max = max;
3774         return region;
3775 }
3776
3777 static void region_free(region_t region)
3778 {
3779         struct region_el        *r, *next;
3780
3781         for (r = region->allocated; r; r = next) {
3782                 next = r->next;
3783                 free(r);
3784         }
3785         memset(region, 0, sizeof(struct region_struct));
3786         free(region);
3787 }
3788
3789 static int region_allocate(region_t region, region_addr_t start, int n)
3790 {
3791         struct region_el        *r, *new_region, *prev, *next;
3792         region_addr_t end;
3793
3794         end = start+n;
3795         if ((start < region->min) || (end > region->max))
3796                 return -1;
3797         if (n == 0)
3798                 return 1;
3799
3800         /*
3801          * Search through the linked list.  If we find that it
3802          * conflicts witih something that's already allocated, return
3803          * 1; if we can find an existing region which we can grow, do
3804          * so.  Otherwise, stop when we find the appropriate place
3805          * insert a new region element into the linked list.
3806          */
3807         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
3808                 if (((start >= r->start) && (start < r->end)) ||
3809                     ((end > r->start) && (end <= r->end)) ||
3810                     ((start <= r->start) && (end >= r->end)))
3811                         return 1;
3812                 if (end == r->start) {
3813                         r->start = start;
3814                         return 0;
3815                 }
3816                 if (start == r->end) {
3817                         if ((next = r->next)) {
3818                                 if (end > next->start)
3819                                         return 1;
3820                                 if (end == next->start) {
3821                                         r->end = next->end;
3822                                         r->next = next->next;
3823                                         free(next);
3824                                         return 0;
3825                                 }
3826                         }
3827                         r->end = end;
3828                         return 0;
3829                 }
3830                 if (start < r->start)
3831                         break;
3832         }
3833         /*
3834          * Insert a new region element structure into the linked list
3835          */
3836         new_region = malloc(sizeof(struct region_el));
3837         if (!new_region)
3838                 return -1;
3839         new_region->start = start;
3840         new_region->end = start + n;
3841         new_region->next = r;
3842         if (prev)
3843                 prev->next = new_region;
3844         else
3845                 region->allocated = new_region;
3846         return 0;
3847 }
3848
3849 /*
3850  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
3851  *
3852  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
3853  * and applies the following tests to each inode:
3854  *
3855  *      - The mode field of the inode must be legal.
3856  *      - The size and block count fields of the inode are correct.
3857  *      - A data block must not be used by another inode
3858  *
3859  * Pass 1 also gathers the collects the following information:
3860  *
3861  *      - A bitmap of which inodes are in use.          (inode_used_map)
3862  *      - A bitmap of which inodes are directories.     (inode_dir_map)
3863  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
3864  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
3865  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
3866  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
3867  *      - A bitmap of which blocks are in use.          (block_found_map)
3868  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
3869  *      - The data blocks of the directory inodes.      (dir_map)
3870  *
3871  * Pass 1 is designed to stash away enough information so that the
3872  * other passes should not need to read in the inode information
3873  * during the normal course of a filesystem check.  (Althogh if an
3874  * inconsistency is detected, other passes may need to read in an
3875  * inode to fix it.)
3876  *
3877  * Note that pass 1B will be invoked if there are any duplicate blocks
3878  * found.
3879  */
3880
3881
3882 static int process_block(ext2_filsys fs, blk_t  *blocknr,
3883                          e2_blkcnt_t blockcnt, blk_t ref_blk,
3884                          int ref_offset, void *priv_data);
3885 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
3886                              e2_blkcnt_t blockcnt, blk_t ref_blk,
3887                              int ref_offset, void *priv_data);
3888 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
3889                          char *block_buf);
3890 static void mark_table_blocks(e2fsck_t ctx);
3891 static void alloc_bb_map(e2fsck_t ctx);
3892 static void alloc_imagic_map(e2fsck_t ctx);
3893 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
3894 static void handle_fs_bad_blocks(e2fsck_t ctx);
3895 static void process_inodes(e2fsck_t ctx, char *block_buf);
3896 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
3897 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
3898                                   dgrp_t group, void * priv_data);
3899 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3900                                     char *block_buf, int adjust_sign);
3901 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
3902
3903 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
3904                                struct ext2_inode * inode, int bufsize,
3905                                const char *proc);
3906
3907 struct process_block_struct_1 {
3908         ext2_ino_t      ino;
3909         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
3910                                 fragmented:1, compressed:1, bbcheck:1;
3911         blk_t           num_blocks;
3912         blk_t           max_blocks;
3913         e2_blkcnt_t     last_block;
3914         int             num_illegal_blocks;
3915         blk_t           previous_block;
3916         struct ext2_inode *inode;
3917         struct problem_context *pctx;
3918         ext2fs_block_bitmap fs_meta_blocks;
3919         e2fsck_t        ctx;
3920 };
3921
3922 struct process_inode_block {
3923         ext2_ino_t ino;
3924         struct ext2_inode inode;
3925 };
3926
3927 struct scan_callback_struct {
3928         e2fsck_t        ctx;
3929         char            *block_buf;
3930 };
3931
3932 /*
3933  * For the inodes to process list.
3934  */
3935 static struct process_inode_block *inodes_to_process;
3936 static int process_inode_count;
3937
3938 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
3939                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
3940
3941 /*
3942  * Free all memory allocated by pass1 in preparation for restarting
3943  * things.
3944  */
3945 static void unwind_pass1(void)
3946 {
3947         ext2fs_free_mem(&inodes_to_process);
3948 }
3949
3950 /*
3951  * Check to make sure a device inode is real.  Returns 1 if the device
3952  * checks out, 0 if not.
3953  *
3954  * Note: this routine is now also used to check FIFO's and Sockets,
3955  * since they have the same requirement; the i_block fields should be
3956  * zero.
3957  */
3958 static int
3959 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
3960 {
3961         int     i;
3962
3963         /*
3964          * If i_blocks is non-zero, or the index flag is set, then
3965          * this is a bogus device/fifo/socket
3966          */
3967         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
3968             (inode->i_flags & EXT2_INDEX_FL))
3969                 return 0;
3970
3971         /*
3972          * We should be able to do the test below all the time, but
3973          * because the kernel doesn't forcibly clear the device
3974          * inode's additional i_block fields, there are some rare
3975          * occasions when a legitimate device inode will have non-zero
3976          * additional i_block fields.  So for now, we only complain
3977          * when the immutable flag is set, which should never happen
3978          * for devices.  (And that's when the problem is caused, since
3979          * you can't set or clear immutable flags for devices.)  Once
3980          * the kernel has been fixed we can change this...
3981          */
3982         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
3983                 for (i=4; i < EXT2_N_BLOCKS; i++)
3984                         if (inode->i_block[i])
3985                                 return 0;
3986         }
3987         return 1;
3988 }
3989
3990 /*
3991  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
3992  * checks out, 0 if not.
3993  */
3994 static int
3995 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
3996 {
3997         unsigned int len;
3998         int i;
3999         blk_t   blocks;
4000
4001         if ((inode->i_size_high || inode->i_size == 0) ||
4002             (inode->i_flags & EXT2_INDEX_FL))
4003                 return 0;
4004
4005         blocks = ext2fs_inode_data_blocks(fs, inode);
4006         if (blocks) {
4007                 if ((inode->i_size >= fs->blocksize) ||
4008                     (blocks != fs->blocksize >> 9) ||
4009                     (inode->i_block[0] < fs->super->s_first_data_block) ||
4010                     (inode->i_block[0] >= fs->super->s_blocks_count))
4011                         return 0;
4012
4013                 for (i = 1; i < EXT2_N_BLOCKS; i++)
4014                         if (inode->i_block[i])
4015                                 return 0;
4016
4017                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4018                         return 0;
4019
4020                 len = strnlen(buf, fs->blocksize);
4021                 if (len == fs->blocksize)
4022                         return 0;
4023         } else {
4024                 if (inode->i_size >= sizeof(inode->i_block))
4025                         return 0;
4026
4027                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4028                 if (len == sizeof(inode->i_block))
4029                         return 0;
4030         }
4031         if (len != inode->i_size)
4032                 return 0;
4033         return 1;
4034 }
4035
4036 /*
4037  * If the immutable (or append-only) flag is set on the inode, offer
4038  * to clear it.
4039  */
4040 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4041 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4042 {
4043         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4044                 return;
4045
4046         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4047                 return;
4048
4049         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4050         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4051 }
4052
4053 /*
4054  * If device, fifo or socket, check size is zero -- if not offer to
4055  * clear it
4056  */
4057 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4058 {
4059         struct ext2_inode *inode = pctx->inode;
4060
4061         if ((inode->i_size == 0) && (inode->i_size_high == 0))
4062                 return;
4063
4064         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4065                 return;
4066
4067         inode->i_size = 0;
4068         inode->i_size_high = 0;
4069         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4070 }
4071
4072 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4073 {
4074         struct ext2_super_block *sb = ctx->fs->super;
4075         struct ext2_inode_large *inode;
4076         struct ext2_ext_attr_entry *entry;
4077         char *start, *end;
4078         int storage_size, remain, offs;
4079         int problem = 0;
4080
4081         inode = (struct ext2_inode_large *) pctx->inode;
4082         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4083                 inode->i_extra_isize;
4084         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4085                 inode->i_extra_isize + sizeof(__u32);
4086         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4087         entry = (struct ext2_ext_attr_entry *) start;
4088
4089         /* scan all entry's headers first */
4090
4091         /* take finish entry 0UL into account */
4092         remain = storage_size - sizeof(__u32);
4093         offs = end - start;
4094
4095         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4096
4097                 /* header eats this space */
4098                 remain -= sizeof(struct ext2_ext_attr_entry);
4099
4100                 /* is attribute name valid? */
4101                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4102                         pctx->num = entry->e_name_len;
4103                         problem = PR_1_ATTR_NAME_LEN;
4104                         goto fix;
4105                 }
4106
4107                 /* attribute len eats this space */
4108                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4109
4110                 /* check value size */
4111                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4112                         pctx->num = entry->e_value_size;
4113                         problem = PR_1_ATTR_VALUE_SIZE;
4114                         goto fix;
4115                 }
4116
4117                 /* check value placement */
4118                 if (entry->e_value_offs +
4119                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4120                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4121                         pctx->num = entry->e_value_offs;
4122                         problem = PR_1_ATTR_VALUE_OFFSET;
4123                         goto fix;
4124                 }
4125
4126                 /* e_value_block must be 0 in inode's ea */
4127                 if (entry->e_value_block != 0) {
4128                         pctx->num = entry->e_value_block;
4129                         problem = PR_1_ATTR_VALUE_BLOCK;
4130                         goto fix;
4131                 }
4132
4133                 /* e_hash must be 0 in inode's ea */
4134                 if (entry->e_hash != 0) {
4135                         pctx->num = entry->e_hash;
4136                         problem = PR_1_ATTR_HASH;
4137                         goto fix;
4138                 }
4139
4140                 remain -= entry->e_value_size;
4141                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4142
4143                 entry = EXT2_EXT_ATTR_NEXT(entry);
4144         }
4145 fix:
4146         /*
4147          * it seems like a corruption. it's very unlikely we could repair
4148          * EA(s) in automatic fashion -bzzz
4149          */
4150         if (problem == 0 || !fix_problem(ctx, problem, pctx))
4151                 return;
4152
4153         /* simple remove all possible EA(s) */
4154         *((__u32 *)start) = 0UL;
4155         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4156                                 EXT2_INODE_SIZE(sb), "pass1");
4157 }
4158
4159 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4160 {
4161         struct ext2_super_block *sb = ctx->fs->super;
4162         struct ext2_inode_large *inode;
4163         __u32 *eamagic;
4164         int min, max;
4165
4166         inode = (struct ext2_inode_large *) pctx->inode;
4167         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4168                 /* this isn't large inode. so, nothing to check */
4169                 return;
4170         }
4171
4172         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4173         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4174         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4175         /*
4176          * For now we will allow i_extra_isize to be 0, but really
4177          * implementations should never allow i_extra_isize to be 0
4178          */
4179         if (inode->i_extra_isize &&
4180             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4181                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4182                         return;
4183                 inode->i_extra_isize = min;
4184                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4185                                         EXT2_INODE_SIZE(sb), "pass1");
4186                 return;
4187         }
4188
4189         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4190                         inode->i_extra_isize);
4191         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4192                 /* it seems inode has an extended attribute(s) in body */
4193                 check_ea_in_inode(ctx, pctx);
4194         }
4195 }
4196
4197 static void e2fsck_pass1(e2fsck_t ctx)
4198 {
4199         int     i;
4200         __u64   max_sizes;
4201         ext2_filsys fs = ctx->fs;
4202         ext2_ino_t      ino;
4203         struct ext2_inode *inode;
4204         ext2_inode_scan scan;
4205         char            *block_buf;
4206         unsigned char   frag, fsize;
4207         struct          problem_context pctx;
4208         struct          scan_callback_struct scan_struct;
4209         struct ext2_super_block *sb = ctx->fs->super;
4210         int             imagic_fs;
4211         int             busted_fs_time = 0;
4212         int             inode_size;
4213
4214         clear_problem_context(&pctx);
4215
4216         if (!(ctx->options & E2F_OPT_PREEN))
4217                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4218
4219         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4220             !(ctx->options & E2F_OPT_NO)) {
4221                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4222                         ctx->dirs_to_hash = 0;
4223         }
4224
4225         /* Pass 1 */
4226
4227 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4228
4229         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4230                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4231                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4232                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4233                 max_sizes = (max_sizes * (1UL << i)) - 1;
4234                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4235         }
4236 #undef EXT2_BPP
4237
4238         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4239
4240         /*
4241          * Allocate bitmaps structures
4242          */
4243         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4244                                               &ctx->inode_used_map);
4245         if (pctx.errcode) {
4246                 pctx.num = 1;
4247                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4248                 ctx->flags |= E2F_FLAG_ABORT;
4249                 return;
4250         }
4251         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4252                                 _("directory inode map"), &ctx->inode_dir_map);
4253         if (pctx.errcode) {
4254                 pctx.num = 2;
4255                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4256                 ctx->flags |= E2F_FLAG_ABORT;
4257                 return;
4258         }
4259         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4260                         _("regular file inode map"), &ctx->inode_reg_map);
4261         if (pctx.errcode) {
4262                 pctx.num = 6;
4263                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4264                 ctx->flags |= E2F_FLAG_ABORT;
4265                 return;
4266         }
4267         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4268                                               &ctx->block_found_map);
4269         if (pctx.errcode) {
4270                 pctx.num = 1;
4271                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4272                 ctx->flags |= E2F_FLAG_ABORT;
4273                 return;
4274         }
4275         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4276                                              &ctx->inode_link_info);
4277         if (pctx.errcode) {
4278                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4279                 ctx->flags |= E2F_FLAG_ABORT;
4280                 return;
4281         }
4282         inode_size = EXT2_INODE_SIZE(fs->super);
4283         inode = (struct ext2_inode *)
4284                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4285
4286         inodes_to_process = (struct process_inode_block *)
4287                 e2fsck_allocate_memory(ctx,
4288                                        (ctx->process_inode_size *
4289                                         sizeof(struct process_inode_block)),
4290                                        "array of inodes to process");
4291         process_inode_count = 0;
4292
4293         pctx.errcode = ext2fs_init_dblist(fs, 0);
4294         if (pctx.errcode) {
4295                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4296                 ctx->flags |= E2F_FLAG_ABORT;
4297                 return;
4298         }
4299
4300         /*
4301          * If the last orphan field is set, clear it, since the pass1
4302          * processing will automatically find and clear the orphans.
4303          * In the future, we may want to try using the last_orphan
4304          * linked list ourselves, but for now, we clear it so that the
4305          * ext3 mount code won't get confused.
4306          */
4307         if (!(ctx->options & E2F_OPT_READONLY)) {
4308                 if (fs->super->s_last_orphan) {
4309                         fs->super->s_last_orphan = 0;
4310                         ext2fs_mark_super_dirty(fs);
4311                 }
4312         }
4313
4314         mark_table_blocks(ctx);
4315         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4316                                                     "block interate buffer");
4317         e2fsck_use_inode_shortcuts(ctx, 1);
4318         ehandler_operation(_("doing inode scan"));
4319         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4320                                               &scan);
4321         if (pctx.errcode) {
4322                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4323                 ctx->flags |= E2F_FLAG_ABORT;
4324                 return;
4325         }
4326         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4327         ctx->stashed_inode = inode;
4328         scan_struct.ctx = ctx;
4329         scan_struct.block_buf = block_buf;
4330         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4331         if (ctx->progress)
4332                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4333                         return;
4334         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
4335             (fs->super->s_mtime < fs->super->s_inodes_count))
4336                 busted_fs_time = 1;
4337
4338         while (1) {
4339                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4340                                                           inode, inode_size);
4341                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4342                         return;
4343                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4344                         if (!ctx->inode_bb_map)
4345                                 alloc_bb_map(ctx);
4346                         ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4347                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4348                         continue;
4349                 }
4350                 if (pctx.errcode) {
4351                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4352                         ctx->flags |= E2F_FLAG_ABORT;
4353                         return;
4354                 }
4355                 if (!ino)
4356                         break;
4357                 pctx.ino = ino;
4358                 pctx.inode = inode;
4359                 ctx->stashed_ino = ino;
4360                 if (inode->i_links_count) {
4361                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4362                                            ino, inode->i_links_count);
4363                         if (pctx.errcode) {
4364                                 pctx.num = inode->i_links_count;
4365                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4366                                 ctx->flags |= E2F_FLAG_ABORT;
4367                                 return;
4368                         }
4369                 }
4370                 if (ino == EXT2_BAD_INO) {
4371                         struct process_block_struct_1 pb;
4372
4373                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4374                                                           &pb.fs_meta_blocks);
4375                         if (pctx.errcode) {
4376                                 pctx.num = 4;
4377                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4378                                 ctx->flags |= E2F_FLAG_ABORT;
4379                                 return;
4380                         }
4381                         pb.ino = EXT2_BAD_INO;
4382                         pb.num_blocks = pb.last_block = 0;
4383                         pb.num_illegal_blocks = 0;
4384                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4385                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4386                         pb.inode = inode;
4387                         pb.pctx = &pctx;
4388                         pb.ctx = ctx;
4389                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4390                                      block_buf, process_bad_block, &pb);
4391                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4392                         if (pctx.errcode) {
4393                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4394                                 ctx->flags |= E2F_FLAG_ABORT;
4395                                 return;
4396                         }
4397                         if (pb.bbcheck)
4398                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4399                                 ctx->flags |= E2F_FLAG_ABORT;
4400                                 return;
4401                         }
4402                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4403                         clear_problem_context(&pctx);
4404                         continue;
4405                 } else if (ino == EXT2_ROOT_INO) {
4406                         /*
4407                          * Make sure the root inode is a directory; if
4408                          * not, offer to clear it.  It will be
4409                          * regnerated in pass #3.
4410                          */
4411                         if (!LINUX_S_ISDIR(inode->i_mode)) {
4412                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4413                                         inode->i_dtime = time(0);
4414                                         inode->i_links_count = 0;
4415                                         ext2fs_icount_store(ctx->inode_link_info,
4416                                                             ino, 0);
4417                                         e2fsck_write_inode(ctx, ino, inode,
4418                                                            "pass1");
4419                                 }
4420
4421                         }
4422                         /*
4423                          * If dtime is set, offer to clear it.  mke2fs
4424                          * version 0.2b created filesystems with the
4425                          * dtime field set for the root and lost+found
4426                          * directories.  We won't worry about
4427                          * /lost+found, since that can be regenerated
4428                          * easily.  But we will fix the root directory
4429                          * as a special case.
4430                          */
4431                         if (inode->i_dtime && inode->i_links_count) {
4432                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4433                                         inode->i_dtime = 0;
4434                                         e2fsck_write_inode(ctx, ino, inode,
4435                                                            "pass1");
4436                                 }
4437                         }
4438                 } else if (ino == EXT2_JOURNAL_INO) {
4439                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4440                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4441                                 if (!LINUX_S_ISREG(inode->i_mode) &&
4442                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4443                                                 &pctx)) {
4444                                         inode->i_mode = LINUX_S_IFREG;
4445                                         e2fsck_write_inode(ctx, ino, inode,
4446                                                            "pass1");
4447                                 }
4448                                 check_blocks(ctx, &pctx, block_buf);
4449                                 continue;
4450                         }
4451                         if ((inode->i_links_count || inode->i_blocks ||
4452                              inode->i_blocks || inode->i_block[0]) &&
4453                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4454                                         &pctx)) {
4455                                 memset(inode, 0, inode_size);
4456                                 ext2fs_icount_store(ctx->inode_link_info,
4457                                                     ino, 0);
4458                                 e2fsck_write_inode_full(ctx, ino, inode,
4459                                                         inode_size, "pass1");
4460                         }
4461                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4462                         int     problem = 0;
4463
4464                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4465                         if (ino == EXT2_BOOT_LOADER_INO) {
4466                                 if (LINUX_S_ISDIR(inode->i_mode))
4467                                         problem = PR_1_RESERVED_BAD_MODE;
4468                         } else if (ino == EXT2_RESIZE_INO) {
4469                                 if (inode->i_mode &&
4470                                     !LINUX_S_ISREG(inode->i_mode))
4471                                         problem = PR_1_RESERVED_BAD_MODE;
4472                         } else {
4473                                 if (inode->i_mode != 0)
4474                                         problem = PR_1_RESERVED_BAD_MODE;
4475                         }
4476                         if (problem) {
4477                                 if (fix_problem(ctx, problem, &pctx)) {
4478                                         inode->i_mode = 0;
4479                                         e2fsck_write_inode(ctx, ino, inode,
4480                                                            "pass1");
4481                                 }
4482                         }
4483                         check_blocks(ctx, &pctx, block_buf);
4484                         continue;
4485                 }
4486                 /*
4487                  * Check for inodes who might have been part of the
4488                  * orphaned list linked list.  They should have gotten
4489                  * dealt with by now, unless the list had somehow been
4490                  * corrupted.
4491                  *
4492                  * FIXME: In the future, inodes which are still in use
4493                  * (and which are therefore) pending truncation should
4494                  * be handled specially.  Right now we just clear the
4495                  * dtime field, and the normal e2fsck handling of
4496                  * inodes where i_size and the inode blocks are
4497                  * inconsistent is to fix i_size, instead of releasing
4498                  * the extra blocks.  This won't catch the inodes that
4499                  * was at the end of the orphan list, but it's better
4500                  * than nothing.  The right answer is that there
4501                  * shouldn't be any bugs in the orphan list handling.  :-)
4502                  */
4503                 if (inode->i_dtime && !busted_fs_time &&
4504                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
4505                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4506                                 inode->i_dtime = inode->i_links_count ?
4507                                         0 : time(0);
4508                                 e2fsck_write_inode(ctx, ino, inode,
4509                                                    "pass1");
4510                         }
4511                 }
4512
4513                 /*
4514                  * This code assumes that deleted inodes have
4515                  * i_links_count set to 0.
4516                  */
4517                 if (!inode->i_links_count) {
4518                         if (!inode->i_dtime && inode->i_mode) {
4519                                 if (fix_problem(ctx,
4520                                             PR_1_ZERO_DTIME, &pctx)) {
4521                                         inode->i_dtime = time(0);
4522                                         e2fsck_write_inode(ctx, ino, inode,
4523                                                            "pass1");
4524                                 }
4525                         }
4526                         continue;
4527                 }
4528                 /*
4529                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
4530                  * deleted files.  Oops.
4531                  *
4532                  * Since all new ext2 implementations get this right,
4533                  * we now assume that the case of non-zero
4534                  * i_links_count and non-zero dtime means that we
4535                  * should keep the file, not delete it.
4536                  *
4537                  */
4538                 if (inode->i_dtime) {
4539                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4540                                 inode->i_dtime = 0;
4541                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
4542                         }
4543                 }
4544
4545                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4546                 switch (fs->super->s_creator_os) {
4547                     case EXT2_OS_LINUX:
4548                         frag = inode->osd2.linux2.l_i_frag;
4549                         fsize = inode->osd2.linux2.l_i_fsize;
4550                         break;
4551                     case EXT2_OS_HURD:
4552                         frag = inode->osd2.hurd2.h_i_frag;
4553                         fsize = inode->osd2.hurd2.h_i_fsize;
4554                         break;
4555                     case EXT2_OS_MASIX:
4556                         frag = inode->osd2.masix2.m_i_frag;
4557                         fsize = inode->osd2.masix2.m_i_fsize;
4558                         break;
4559                     default:
4560                         frag = fsize = 0;
4561                 }
4562
4563                 if (inode->i_faddr || frag || fsize ||
4564                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4565                         mark_inode_bad(ctx, ino);
4566                 if (inode->i_flags & EXT2_IMAGIC_FL) {
4567                         if (imagic_fs) {
4568                                 if (!ctx->inode_imagic_map)
4569                                         alloc_imagic_map(ctx);
4570                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4571                                                          ino);
4572                         } else {
4573                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4574                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
4575                                         e2fsck_write_inode(ctx, ino,
4576                                                            inode, "pass1");
4577                                 }
4578                         }
4579                 }
4580
4581                 check_inode_extra_space(ctx, &pctx);
4582
4583                 if (LINUX_S_ISDIR(inode->i_mode)) {
4584                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
4585                         e2fsck_add_dir_info(ctx, ino, 0);
4586                         ctx->fs_directory_count++;
4587                 } else if (LINUX_S_ISREG (inode->i_mode)) {
4588                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
4589                         ctx->fs_regular_count++;
4590                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
4591                            e2fsck_pass1_check_device_inode(fs, inode)) {
4592                         check_immutable(ctx, &pctx);
4593                         check_size(ctx, &pctx);
4594                         ctx->fs_chardev_count++;
4595                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
4596                            e2fsck_pass1_check_device_inode(fs, inode)) {
4597                         check_immutable(ctx, &pctx);
4598                         check_size(ctx, &pctx);
4599                         ctx->fs_blockdev_count++;
4600                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
4601                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
4602                         check_immutable(ctx, &pctx);
4603                         ctx->fs_symlinks_count++;
4604                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
4605                                 ctx->fs_fast_symlinks_count++;
4606                                 check_blocks(ctx, &pctx, block_buf);
4607                                 continue;
4608                         }
4609                 }
4610                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
4611                          e2fsck_pass1_check_device_inode(fs, inode)) {
4612                         check_immutable(ctx, &pctx);
4613                         check_size(ctx, &pctx);
4614                         ctx->fs_fifo_count++;
4615                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
4616                            e2fsck_pass1_check_device_inode(fs, inode)) {
4617                         check_immutable(ctx, &pctx);
4618                         check_size(ctx, &pctx);
4619                         ctx->fs_sockets_count++;
4620                 } else
4621                         mark_inode_bad(ctx, ino);
4622                 if (inode->i_block[EXT2_IND_BLOCK])
4623                         ctx->fs_ind_count++;
4624                 if (inode->i_block[EXT2_DIND_BLOCK])
4625                         ctx->fs_dind_count++;
4626                 if (inode->i_block[EXT2_TIND_BLOCK])
4627                         ctx->fs_tind_count++;
4628                 if (inode->i_block[EXT2_IND_BLOCK] ||
4629                     inode->i_block[EXT2_DIND_BLOCK] ||
4630                     inode->i_block[EXT2_TIND_BLOCK] ||
4631                     inode->i_file_acl) {
4632                         inodes_to_process[process_inode_count].ino = ino;
4633                         inodes_to_process[process_inode_count].inode = *inode;
4634                         process_inode_count++;
4635                 } else
4636                         check_blocks(ctx, &pctx, block_buf);
4637
4638                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4639                         return;
4640
4641                 if (process_inode_count >= ctx->process_inode_size) {
4642                         process_inodes(ctx, block_buf);
4643
4644                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4645                                 return;
4646                 }
4647         }
4648         process_inodes(ctx, block_buf);
4649         ext2fs_close_inode_scan(scan);
4650         ehandler_operation(0);
4651
4652         /*
4653          * If any extended attribute blocks' reference counts need to
4654          * be adjusted, either up (ctx->refcount_extra), or down
4655          * (ctx->refcount), then fix them.
4656          */
4657         if (ctx->refcount) {
4658                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
4659                 ea_refcount_free(ctx->refcount);
4660                 ctx->refcount = 0;
4661         }
4662         if (ctx->refcount_extra) {
4663                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
4664                                         block_buf, +1);
4665                 ea_refcount_free(ctx->refcount_extra);
4666                 ctx->refcount_extra = 0;
4667         }
4668
4669         if (ctx->invalid_bitmaps)
4670                 handle_fs_bad_blocks(ctx);
4671
4672         /* We don't need the block_ea_map any more */
4673         ext2fs_free_block_bitmap(ctx->block_ea_map);
4674         ctx->block_ea_map = 0;
4675
4676         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
4677                 ext2fs_block_bitmap save_bmap;
4678
4679                 save_bmap = fs->block_map;
4680                 fs->block_map = ctx->block_found_map;
4681                 clear_problem_context(&pctx);
4682                 pctx.errcode = ext2fs_create_resize_inode(fs);
4683                 if (pctx.errcode) {
4684                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
4685                         /* Should never get here */
4686                         ctx->flags |= E2F_FLAG_ABORT;
4687                         return;
4688                 }
4689                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
4690                                   "recreate inode");
4691                 inode->i_mtime = time(0);
4692                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, 
4693                                   "recreate inode");
4694                 fs->block_map = save_bmap;
4695                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
4696         }
4697
4698         if (ctx->flags & E2F_FLAG_RESTART) {
4699                 /*
4700                  * Only the master copy of the superblock and block
4701                  * group descriptors are going to be written during a
4702                  * restart, so set the superblock to be used to be the
4703                  * master superblock.
4704                  */
4705                 ctx->use_superblock = 0;
4706                 unwind_pass1();
4707                 goto endit;
4708         }
4709
4710         if (ctx->block_dup_map) {
4711                 if (ctx->options & E2F_OPT_PREEN) {
4712                         clear_problem_context(&pctx);
4713                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
4714                 }
4715                 e2fsck_pass1_dupblocks(ctx, block_buf);
4716         }
4717         ext2fs_free_mem(&inodes_to_process);
4718 endit:
4719         e2fsck_use_inode_shortcuts(ctx, 0);
4720
4721         ext2fs_free_mem(&block_buf);
4722         ext2fs_free_mem(&inode);
4723
4724 }
4725
4726 /*
4727  * When the inode_scan routines call this callback at the end of the
4728  * glock group, call process_inodes.
4729  */
4730 static errcode_t scan_callback(ext2_filsys fs,
4731                                ext2_inode_scan scan FSCK_ATTR((unused)),
4732                                dgrp_t group, void * priv_data)
4733 {
4734         struct scan_callback_struct *scan_struct;
4735         e2fsck_t ctx;
4736
4737         scan_struct = (struct scan_callback_struct *) priv_data;
4738         ctx = scan_struct->ctx;
4739
4740         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
4741
4742         if (ctx->progress)
4743                 if ((ctx->progress)(ctx, 1, group+1,
4744                                     ctx->fs->group_desc_count))
4745                         return EXT2_ET_CANCEL_REQUESTED;
4746
4747         return 0;
4748 }
4749
4750 /*
4751  * Process the inodes in the "inodes to process" list.
4752  */
4753 static void process_inodes(e2fsck_t ctx, char *block_buf)
4754 {
4755         int                     i;
4756         struct ext2_inode       *old_stashed_inode;
4757         ext2_ino_t              old_stashed_ino;
4758         const char              *old_operation;
4759         char                    buf[80];
4760         struct problem_context  pctx;
4761
4762         /* begin process_inodes */
4763         if (process_inode_count == 0)
4764                 return;
4765         old_operation = ehandler_operation(0);
4766         old_stashed_inode = ctx->stashed_inode;
4767         old_stashed_ino = ctx->stashed_ino;
4768         qsort(inodes_to_process, process_inode_count,
4769                       sizeof(struct process_inode_block), process_inode_cmp);
4770         clear_problem_context(&pctx);
4771         for (i=0; i < process_inode_count; i++) {
4772                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
4773                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
4774                 sprintf(buf, _("reading indirect blocks of inode %u"),
4775                         pctx.ino);
4776                 ehandler_operation(buf);
4777                 check_blocks(ctx, &pctx, block_buf);
4778                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4779                         break;
4780         }
4781         ctx->stashed_inode = old_stashed_inode;
4782         ctx->stashed_ino = old_stashed_ino;
4783         process_inode_count = 0;
4784         /* end process inodes */
4785
4786         ehandler_operation(old_operation);
4787 }
4788
4789 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
4790 {
4791         const struct process_inode_block *ib_a =
4792                 (const struct process_inode_block *) a;
4793         const struct process_inode_block *ib_b =
4794                 (const struct process_inode_block *) b;
4795         int     ret;
4796
4797         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
4798                ib_b->inode.i_block[EXT2_IND_BLOCK]);
4799         if (ret == 0)
4800                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
4801         return ret;
4802 }
4803
4804 /*
4805  * Mark an inode as being bad in some what
4806  */
4807 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
4808 {
4809         struct          problem_context pctx;
4810
4811         if (!ctx->inode_bad_map) {
4812                 clear_problem_context(&pctx);
4813
4814                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
4815                             _("bad inode map"), &ctx->inode_bad_map);
4816                 if (pctx.errcode) {
4817                         pctx.num = 3;
4818                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4819                         /* Should never get here */
4820                         ctx->flags |= E2F_FLAG_ABORT;
4821                         return;
4822                 }
4823         }
4824         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
4825 }
4826
4827
4828 /*
4829  * This procedure will allocate the inode "bb" (badblock) map table
4830  */
4831 static void alloc_bb_map(e2fsck_t ctx)
4832 {
4833         struct          problem_context pctx;
4834
4835         clear_problem_context(&pctx);
4836         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
4837                                               _("inode in bad block map"),
4838                                               &ctx->inode_bb_map);
4839         if (pctx.errcode) {
4840                 pctx.num = 4;
4841                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4842                 /* Should never get here */
4843                 ctx->flags |= E2F_FLAG_ABORT;
4844                 return;
4845         }
4846 }
4847
4848 /*
4849  * This procedure will allocate the inode imagic table
4850  */
4851 static void alloc_imagic_map(e2fsck_t ctx)
4852 {
4853         struct          problem_context pctx;
4854
4855         clear_problem_context(&pctx);
4856         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
4857                                               _("imagic inode map"),
4858                                               &ctx->inode_imagic_map);
4859         if (pctx.errcode) {
4860                 pctx.num = 5;
4861                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4862                 /* Should never get here */
4863                 ctx->flags |= E2F_FLAG_ABORT;
4864                 return;
4865         }
4866 }
4867
4868 /*
4869  * Marks a block as in use, setting the dup_map if it's been set
4870  * already.  Called by process_block and process_bad_block.
4871  *
4872  * WARNING: Assumes checks have already been done to make sure block
4873  * is valid.  This is true in both process_block and process_bad_block.
4874  */
4875 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
4876 {
4877         struct          problem_context pctx;
4878
4879         clear_problem_context(&pctx);
4880
4881         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
4882                 if (!ctx->block_dup_map) {
4883                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
4884                               _("multiply claimed block map"),
4885                               &ctx->block_dup_map);
4886                         if (pctx.errcode) {
4887                                 pctx.num = 3;
4888                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
4889                                             &pctx);
4890                                 /* Should never get here */
4891                                 ctx->flags |= E2F_FLAG_ABORT;
4892                                 return;
4893                         }
4894                 }
4895                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
4896         } else {
4897                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
4898         }
4899 }
4900
4901 /*
4902  * Adjust the extended attribute block's reference counts at the end
4903  * of pass 1, either by subtracting out references for EA blocks that
4904  * are still referenced in ctx->refcount, or by adding references for
4905  * EA blocks that had extra references as accounted for in
4906  * ctx->refcount_extra.
4907  */
4908 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4909                                     char *block_buf, int adjust_sign)
4910 {
4911         struct ext2_ext_attr_header     *header;
4912         struct problem_context          pctx;
4913         ext2_filsys                     fs = ctx->fs;
4914         blk_t                           blk;
4915         __u32                           should_be;
4916         int                             count;
4917
4918         clear_problem_context(&pctx);
4919
4920         ea_refcount_intr_begin(refcount);
4921         while (1) {
4922                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
4923                         break;
4924                 pctx.blk = blk;
4925                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
4926                 if (pctx.errcode) {
4927                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
4928                         return;
4929                 }
4930                 header = (struct ext2_ext_attr_header *) block_buf;
4931                 pctx.blkcount = header->h_refcount;
4932                 should_be = header->h_refcount + adjust_sign * count;
4933                 pctx.num = should_be;
4934                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
4935                         header->h_refcount = should_be;
4936                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
4937                                                              block_buf);
4938                         if (pctx.errcode) {
4939                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
4940                                 continue;
4941                         }
4942                 }
4943         }
4944 }
4945
4946 /*
4947  * Handle processing the extended attribute blocks
4948  */
4949 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
4950                            char *block_buf)
4951 {
4952         ext2_filsys fs = ctx->fs;
4953         ext2_ino_t      ino = pctx->ino;
4954         struct ext2_inode *inode = pctx->inode;
4955         blk_t           blk;
4956         char *          end;
4957         struct ext2_ext_attr_header *header;
4958         struct ext2_ext_attr_entry *entry;
4959         int             count;
4960         region_t        region;
4961
4962         blk = inode->i_file_acl;
4963         if (blk == 0)
4964                 return 0;
4965
4966         /*
4967          * If the Extended attribute flag isn't set, then a non-zero
4968          * file acl means that the inode is corrupted.
4969          *
4970          * Or if the extended attribute block is an invalid block,
4971          * then the inode is also corrupted.
4972          */
4973         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
4974             (blk < fs->super->s_first_data_block) ||
4975             (blk >= fs->super->s_blocks_count)) {
4976                 mark_inode_bad(ctx, ino);
4977                 return 0;
4978         }
4979
4980         /* If ea bitmap hasn't been allocated, create it */
4981         if (!ctx->block_ea_map) {
4982                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
4983                                                       _("ext attr block map"),
4984                                                       &ctx->block_ea_map);
4985                 if (pctx->errcode) {
4986                         pctx->num = 2;
4987                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
4988                         ctx->flags |= E2F_FLAG_ABORT;
4989                         return 0;
4990                 }
4991         }
4992
4993         /* Create the EA refcount structure if necessary */
4994         if (!ctx->refcount) {
4995                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
4996                 if (pctx->errcode) {
4997                         pctx->num = 1;
4998                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
4999                         ctx->flags |= E2F_FLAG_ABORT;
5000                         return 0;
5001                 }
5002         }
5003
5004         /* Have we seen this EA block before? */
5005         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5006                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5007                         return 1;
5008                 /* Ooops, this EA was referenced more than it stated */
5009                 if (!ctx->refcount_extra) {
5010                         pctx->errcode = ea_refcount_create(0,
5011                                            &ctx->refcount_extra);
5012                         if (pctx->errcode) {
5013                                 pctx->num = 2;
5014                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5015                                 ctx->flags |= E2F_FLAG_ABORT;
5016                                 return 0;
5017                         }
5018                 }
5019                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5020                 return 1;
5021         }
5022
5023         /*
5024          * OK, we haven't seen this EA block yet.  So we need to
5025          * validate it
5026          */
5027         pctx->blk = blk;
5028         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5029         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5030                 goto clear_extattr;
5031         header = (struct ext2_ext_attr_header *) block_buf;
5032         pctx->blk = inode->i_file_acl;
5033         if (((ctx->ext_attr_ver == 1) &&
5034              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5035             ((ctx->ext_attr_ver == 2) &&
5036              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5037                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5038                         goto clear_extattr;
5039         }
5040
5041         if (header->h_blocks != 1) {
5042                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5043                         goto clear_extattr;
5044         }
5045
5046         region = region_create(0, fs->blocksize);
5047         if (!region) {
5048                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5049                 ctx->flags |= E2F_FLAG_ABORT;
5050                 return 0;
5051         }
5052         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5053                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5054                         goto clear_extattr;
5055         }
5056
5057         entry = (struct ext2_ext_attr_entry *)(header+1);
5058         end = block_buf + fs->blocksize;
5059         while ((char *)entry < end && *(__u32 *)entry) {
5060                 if (region_allocate(region, (char *)entry - (char *)header,
5061                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5062                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5063                                 goto clear_extattr;
5064                 }
5065                 if ((ctx->ext_attr_ver == 1 &&
5066                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5067                     (ctx->ext_attr_ver == 2 &&
5068                      entry->e_name_index == 0)) {
5069                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5070                                 goto clear_extattr;
5071                 }
5072                 if (entry->e_value_block != 0) {
5073                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5074                                 goto clear_extattr;
5075                 }
5076                 if (entry->e_value_size &&
5077                     region_allocate(region, entry->e_value_offs,
5078                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5079                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5080                                 goto clear_extattr;
5081                 }
5082                 entry = EXT2_EXT_ATTR_NEXT(entry);
5083         }
5084         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5085                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5086                         goto clear_extattr;
5087         }
5088         region_free(region);
5089
5090         count = header->h_refcount - 1;
5091         if (count)
5092                 ea_refcount_store(ctx->refcount, blk, count);
5093         mark_block_used(ctx, blk);
5094         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5095
5096         return 1;
5097
5098 clear_extattr:
5099         inode->i_file_acl = 0;
5100         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5101         return 0;
5102 }
5103
5104 /* Returns 1 if bad htree, 0 if OK */
5105 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5106                         ext2_ino_t ino FSCK_ATTR((unused)),
5107                         struct ext2_inode *inode,
5108                         char *block_buf)
5109 {
5110         struct ext2_dx_root_info        *root;
5111         ext2_filsys                     fs = ctx->fs;
5112         errcode_t                       retval;
5113         blk_t                           blk;
5114
5115         if ((!LINUX_S_ISDIR(inode->i_mode) &&
5116              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5117             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5118              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5119                 return 1;
5120
5121         blk = inode->i_block[0];
5122         if (((blk == 0) ||
5123              (blk < fs->super->s_first_data_block) ||
5124              (blk >= fs->super->s_blocks_count)) &&
5125             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5126                 return 1;
5127
5128         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5129         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5130                 return 1;
5131
5132         /* XXX should check that beginning matches a directory */
5133         root = (struct ext2_dx_root_info *) (block_buf + 24);
5134
5135         if ((root->reserved_zero || root->info_length < 8) &&
5136             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5137                 return 1;
5138
5139         pctx->num = root->hash_version;
5140         if ((root->hash_version != EXT2_HASH_LEGACY) &&
5141             (root->hash_version != EXT2_HASH_HALF_MD4) &&
5142             (root->hash_version != EXT2_HASH_TEA) &&
5143             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5144                 return 1;
5145
5146         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5147             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5148                 return 1;
5149
5150         pctx->num = root->indirect_levels;
5151         if ((root->indirect_levels > 1) &&
5152             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5153                 return 1;
5154
5155         return 0;
5156 }
5157
5158 /*
5159  * This subroutine is called on each inode to account for all of the
5160  * blocks used by that inode.
5161  */
5162 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5163                          char *block_buf)
5164 {
5165         ext2_filsys fs = ctx->fs;
5166         struct process_block_struct_1 pb;
5167         ext2_ino_t      ino = pctx->ino;
5168         struct ext2_inode *inode = pctx->inode;
5169         int             bad_size = 0;
5170         int             dirty_inode = 0;
5171         __u64           size;
5172
5173         pb.ino = ino;
5174         pb.num_blocks = 0;
5175         pb.last_block = -1;
5176         pb.num_illegal_blocks = 0;
5177         pb.suppress = 0; pb.clear = 0;
5178         pb.fragmented = 0;
5179         pb.compressed = 0;
5180         pb.previous_block = 0;
5181         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5182         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5183         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5184         pb.inode = inode;
5185         pb.pctx = pctx;
5186         pb.ctx = ctx;
5187         pctx->ino = ino;
5188         pctx->errcode = 0;
5189
5190         if (inode->i_flags & EXT2_COMPRBLK_FL) {
5191                 if (fs->super->s_feature_incompat &
5192                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
5193                         pb.compressed = 1;
5194                 else {
5195                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5196                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5197                                 dirty_inode++;
5198                         }
5199                 }
5200         }
5201
5202         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5203                 pb.num_blocks++;
5204
5205         if (ext2fs_inode_has_valid_blocks(inode))
5206                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5207                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5208                                        block_buf, process_block, &pb);
5209         end_problem_latch(ctx, PR_LATCH_BLOCK);
5210         end_problem_latch(ctx, PR_LATCH_TOOBIG);
5211         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5212                 goto out;
5213         if (pctx->errcode)
5214                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5215
5216         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5217                 ctx->fs_fragmented++;
5218
5219         if (pb.clear) {
5220                 inode->i_links_count = 0;
5221                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5222                 inode->i_dtime = time(0);
5223                 dirty_inode++;
5224                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5225                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5226                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5227                 /*
5228                  * The inode was probably partially accounted for
5229                  * before processing was aborted, so we need to
5230                  * restart the pass 1 scan.
5231                  */
5232                 ctx->flags |= E2F_FLAG_RESTART;
5233                 goto out;
5234         }
5235
5236         if (inode->i_flags & EXT2_INDEX_FL) {
5237                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5238                         inode->i_flags &= ~EXT2_INDEX_FL;
5239                         dirty_inode++;
5240                 } else {
5241 #ifdef ENABLE_HTREE
5242                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5243 #endif
5244                 }
5245         }
5246         if (ctx->dirs_to_hash && pb.is_dir &&
5247             !(inode->i_flags & EXT2_INDEX_FL) &&
5248             ((inode->i_size / fs->blocksize) >= 3))
5249                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5250
5251         if (!pb.num_blocks && pb.is_dir) {
5252                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5253                         inode->i_links_count = 0;
5254                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5255                         inode->i_dtime = time(0);
5256                         dirty_inode++;
5257                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5258                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5259                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5260                         ctx->fs_directory_count--;
5261                         goto out;
5262                 }
5263         }
5264
5265         pb.num_blocks *= (fs->blocksize / 512);
5266
5267         if (pb.is_dir) {
5268                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5269                 if (nblock > (pb.last_block + 1))
5270                         bad_size = 1;
5271                 else if (nblock < (pb.last_block + 1)) {
5272                         if (((pb.last_block + 1) - nblock) >
5273                             fs->super->s_prealloc_dir_blocks)
5274                                 bad_size = 2;
5275                 }
5276         } else {
5277                 size = EXT2_I_SIZE(inode);
5278                 if ((pb.last_block >= 0) &&
5279                     (size < (__u64) pb.last_block * fs->blocksize))
5280                         bad_size = 3;
5281                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5282                         bad_size = 4;
5283         }
5284         /* i_size for symlinks is checked elsewhere */
5285         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5286                 pctx->num = (pb.last_block+1) * fs->blocksize;
5287                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5288                         inode->i_size = pctx->num;
5289                         if (!LINUX_S_ISDIR(inode->i_mode))
5290                                 inode->i_size_high = pctx->num >> 32;
5291                         dirty_inode++;
5292                 }
5293                 pctx->num = 0;
5294         }
5295         if (LINUX_S_ISREG(inode->i_mode) &&
5296             (inode->i_size_high || inode->i_size & 0x80000000UL))
5297                 ctx->large_files++;
5298         if (pb.num_blocks != inode->i_blocks) {
5299                 pctx->num = pb.num_blocks;
5300                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5301                         inode->i_blocks = pb.num_blocks;
5302                         dirty_inode++;
5303                 }
5304                 pctx->num = 0;
5305         }
5306 out:
5307         if (dirty_inode)
5308                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5309 }
5310
5311
5312 /*
5313  * This is a helper function for check_blocks().
5314  */
5315 static int process_block(ext2_filsys fs,
5316                   blk_t *block_nr,
5317                   e2_blkcnt_t blockcnt,
5318                   blk_t ref_block FSCK_ATTR((unused)),
5319                   int ref_offset FSCK_ATTR((unused)),
5320                   void *priv_data)
5321 {
5322         struct process_block_struct_1 *p;
5323         struct problem_context *pctx;
5324         blk_t   blk = *block_nr;
5325         int     ret_code = 0;
5326         int     problem = 0;
5327         e2fsck_t        ctx;
5328
5329         p = (struct process_block_struct_1 *) priv_data;
5330         pctx = p->pctx;
5331         ctx = p->ctx;
5332
5333         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5334                 /* todo: Check that the comprblk_fl is high, that the
5335                    blkaddr pattern looks right (all non-holes up to
5336                    first EXT2FS_COMPRESSED_BLKADDR, then all
5337                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5338                    that the feature_incompat bit is high, and that the
5339                    inode is a regular file.  If we're doing a "full
5340                    check" (a concept introduced to e2fsck by e2compr,
5341                    meaning that we look at data blocks as well as
5342                    metadata) then call some library routine that
5343                    checks the compressed data.  I'll have to think
5344                    about this, because one particularly important
5345                    problem to be able to fix is to recalculate the
5346                    cluster size if necessary.  I think that perhaps
5347                    we'd better do most/all e2compr-specific checks
5348                    separately, after the non-e2compr checks.  If not
5349                    doing a full check, it may be useful to test that
5350                    the personality is linux; e.g. if it isn't then
5351                    perhaps this really is just an illegal block. */
5352                 return 0;
5353         }
5354
5355         if (blk == 0) {
5356                 if (p->is_dir == 0) {
5357                         /*
5358                          * Should never happen, since only directories
5359                          * get called with BLOCK_FLAG_HOLE
5360                          */
5361 #if DEBUG_E2FSCK
5362                         printf("process_block() called with blk == 0, "
5363                                "blockcnt=%d, inode %lu???\n",
5364                                blockcnt, p->ino);
5365 #endif
5366                         return 0;
5367                 }
5368                 if (blockcnt < 0)
5369                         return 0;
5370                 if (blockcnt * fs->blocksize < p->inode->i_size) {
5371                         goto mark_dir;
5372                 }
5373                 return 0;
5374         }
5375
5376         /*
5377          * Simplistic fragmentation check.  We merely require that the
5378          * file be contiguous.  (Which can never be true for really
5379          * big files that are greater than a block group.)
5380          */
5381         if (!HOLE_BLKADDR(p->previous_block)) {
5382                 if (p->previous_block+1 != blk)
5383                         p->fragmented = 1;
5384         }
5385         p->previous_block = blk;
5386
5387         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5388                 problem = PR_1_TOOBIG_DIR;
5389         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5390                 problem = PR_1_TOOBIG_REG;
5391         if (!p->is_dir && !p->is_reg && blockcnt > 0)
5392                 problem = PR_1_TOOBIG_SYMLINK;
5393
5394         if (blk < fs->super->s_first_data_block ||
5395             blk >= fs->super->s_blocks_count)
5396                 problem = PR_1_ILLEGAL_BLOCK_NUM;
5397
5398         if (problem) {
5399                 p->num_illegal_blocks++;
5400                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5401                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5402                                 p->clear = 1;
5403                                 return BLOCK_ABORT;
5404                         }
5405                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5406                                 p->suppress = 1;
5407                                 set_latch_flags(PR_LATCH_BLOCK,
5408                                                 PRL_SUPPRESS, 0);
5409                         }
5410                 }
5411                 pctx->blk = blk;
5412                 pctx->blkcount = blockcnt;
5413                 if (fix_problem(ctx, problem, pctx)) {
5414                         blk = *block_nr = 0;
5415                         ret_code = BLOCK_CHANGED;
5416                         goto mark_dir;
5417                 } else
5418                         return 0;
5419         }
5420
5421         if (p->ino == EXT2_RESIZE_INO) {
5422                 /*
5423                  * The resize inode has already be sanity checked
5424                  * during pass #0 (the superblock checks).  All we
5425                  * have to do is mark the double indirect block as
5426                  * being in use; all of the other blocks are handled
5427                  * by mark_table_blocks()).
5428                  */
5429                 if (blockcnt == BLOCK_COUNT_DIND)
5430                         mark_block_used(ctx, blk);
5431         } else
5432                 mark_block_used(ctx, blk);
5433         p->num_blocks++;
5434         if (blockcnt >= 0)
5435                 p->last_block = blockcnt;
5436 mark_dir:
5437         if (p->is_dir && (blockcnt >= 0)) {
5438                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5439                                                     blk, blockcnt);
5440                 if (pctx->errcode) {
5441                         pctx->blk = blk;
5442                         pctx->num = blockcnt;
5443                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5444                         /* Should never get here */
5445                         ctx->flags |= E2F_FLAG_ABORT;
5446                         return BLOCK_ABORT;
5447                 }
5448         }
5449         return ret_code;
5450 }
5451
5452 static int process_bad_block(ext2_filsys fs,
5453                       blk_t *block_nr,
5454                       e2_blkcnt_t blockcnt,
5455                       blk_t ref_block FSCK_ATTR((unused)),
5456                       int ref_offset FSCK_ATTR((unused)),
5457                       void *priv_data)
5458 {
5459         struct process_block_struct_1 *p;
5460         blk_t           blk = *block_nr;
5461         blk_t           first_block;
5462         dgrp_t          i;
5463         struct problem_context *pctx;
5464         e2fsck_t        ctx;
5465
5466         /*
5467          * Note: This function processes blocks for the bad blocks
5468          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
5469          */
5470
5471         if (!blk)
5472                 return 0;
5473
5474         p = (struct process_block_struct_1 *) priv_data;
5475         ctx = p->ctx;
5476         pctx = p->pctx;
5477
5478         pctx->ino = EXT2_BAD_INO;
5479         pctx->blk = blk;
5480         pctx->blkcount = blockcnt;
5481
5482         if ((blk < fs->super->s_first_data_block) ||
5483             (blk >= fs->super->s_blocks_count)) {
5484                 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5485                         *block_nr = 0;
5486                         return BLOCK_CHANGED;
5487                 } else
5488                         return 0;
5489         }
5490
5491         if (blockcnt < 0) {
5492                 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5493                         p->bbcheck = 1;
5494                         if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5495                                 *block_nr = 0;
5496                                 return BLOCK_CHANGED;
5497                         }
5498                 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5499                                                     blk)) {
5500                         p->bbcheck = 1;
5501                         if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5502                                         pctx)) {
5503                                 *block_nr = 0;
5504                                 return BLOCK_CHANGED;
5505                         }
5506                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5507                                 return BLOCK_ABORT;
5508                 } else
5509                         mark_block_used(ctx, blk);
5510                 return 0;
5511         }
5512
5513         ctx->fs_badblocks_count++;
5514         /*
5515          * If the block is not used, then mark it as used and return.
5516          * If it is already marked as found, this must mean that
5517          * there's an overlap between the filesystem table blocks
5518          * (bitmaps and inode table) and the bad block list.
5519          */
5520         if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
5521                 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
5522                 return 0;
5523         }
5524         /*
5525          * Try to find the where the filesystem block was used...
5526          */
5527         first_block = fs->super->s_first_data_block;
5528
5529         for (i = 0; i < fs->group_desc_count; i++ ) {
5530                 pctx->group = i;
5531                 pctx->blk = blk;
5532                 if (!ext2fs_bg_has_super(fs, i))
5533                         goto skip_super;
5534                 if (blk == first_block) {
5535                         if (i == 0) {
5536                                 if (fix_problem(ctx,
5537                                                 PR_1_BAD_PRIMARY_SUPERBLOCK,
5538                                                 pctx)) {
5539                                         *block_nr = 0;
5540                                         return BLOCK_CHANGED;
5541                                 }
5542                                 return 0;
5543                         }
5544                         fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
5545                         return 0;
5546                 }
5547                 if ((blk > first_block) &&
5548                     (blk <= first_block + fs->desc_blocks)) {
5549                         if (i == 0) {
5550                                 pctx->blk = *block_nr;
5551                                 if (fix_problem(ctx,
5552                         PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
5553                                         *block_nr = 0;
5554                                         return BLOCK_CHANGED;
5555                                 }
5556                                 return 0;
5557                         }
5558                         fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
5559                         return 0;
5560                 }
5561         skip_super:
5562                 if (blk == fs->group_desc[i].bg_block_bitmap) {
5563                         if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
5564                                 ctx->invalid_block_bitmap_flag[i]++;
5565                                 ctx->invalid_bitmaps++;
5566                         }
5567                         return 0;
5568                 }
5569                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
5570                         if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
5571                                 ctx->invalid_inode_bitmap_flag[i]++;
5572                                 ctx->invalid_bitmaps++;
5573                         }
5574                         return 0;
5575                 }
5576                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
5577                     (blk < (fs->group_desc[i].bg_inode_table +
5578                             fs->inode_blocks_per_group))) {
5579                         /*
5580                          * If there are bad blocks in the inode table,
5581                          * the inode scan code will try to do
5582                          * something reasonable automatically.
5583                          */
5584                         return 0;
5585                 }
5586                 first_block += fs->super->s_blocks_per_group;
5587         }
5588         /*
5589          * If we've gotten to this point, then the only
5590          * possibility is that the bad block inode meta data
5591          * is using a bad block.
5592          */
5593         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
5594             (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
5595             (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
5596                 p->bbcheck = 1;
5597                 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
5598                         *block_nr = 0;
5599                         return BLOCK_CHANGED;
5600                 }
5601                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5602                         return BLOCK_ABORT;
5603                 return 0;
5604         }
5605
5606         pctx->group = -1;
5607
5608         /* Warn user that the block wasn't claimed */
5609         fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
5610
5611         return 0;
5612 }
5613
5614 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
5615                             const char *name, int num, blk_t *new_block)
5616 {
5617         ext2_filsys fs = ctx->fs;
5618         blk_t           old_block = *new_block;
5619         int             i;
5620         char            *buf;
5621         struct problem_context  pctx;
5622
5623         clear_problem_context(&pctx);
5624
5625         pctx.group = group;
5626         pctx.blk = old_block;
5627         pctx.str = name;
5628
5629         pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
5630                         first_block + fs->super->s_blocks_per_group,
5631                                         num, ctx->block_found_map, new_block);
5632         if (pctx.errcode) {
5633                 pctx.num = num;
5634                 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
5635                 ext2fs_unmark_valid(fs);
5636                 return;
5637         }
5638         pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
5639         if (pctx.errcode) {
5640                 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
5641                 ext2fs_unmark_valid(fs);
5642                 return;
5643         }
5644         ext2fs_mark_super_dirty(fs);
5645         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
5646         pctx.blk2 = *new_block;
5647         fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
5648                           PR_1_RELOC_TO), &pctx);
5649         pctx.blk2 = 0;
5650         for (i = 0; i < num; i++) {
5651                 pctx.blk = i;
5652                 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
5653                 if (old_block) {
5654                         pctx.errcode = io_channel_read_blk(fs->io,
5655                                    old_block + i, 1, buf);
5656                         if (pctx.errcode)
5657                                 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
5658                 } else
5659                         memset(buf, 0, fs->blocksize);
5660
5661                 pctx.blk = (*new_block) + i;
5662                 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
5663                                               1, buf);
5664                 if (pctx.errcode)
5665                         fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
5666         }
5667         ext2fs_free_mem(&buf);
5668 }
5669
5670 /*
5671  * This routine gets called at the end of pass 1 if bad blocks are
5672  * detected in the superblock, group descriptors, inode_bitmaps, or
5673  * block bitmaps.  At this point, all of the blocks have been mapped
5674  * out, so we can try to allocate new block(s) to replace the bad
5675  * blocks.
5676  */
5677 static void handle_fs_bad_blocks(e2fsck_t ctx)
5678 {
5679         ext2_filsys fs = ctx->fs;
5680         dgrp_t          i;
5681         int             first_block = fs->super->s_first_data_block;
5682
5683         for (i = 0; i < fs->group_desc_count; i++) {
5684                 if (ctx->invalid_block_bitmap_flag[i]) {
5685                         new_table_block(ctx, first_block, i, _("block bitmap"),
5686                                         1, &fs->group_desc[i].bg_block_bitmap);
5687                 }
5688                 if (ctx->invalid_inode_bitmap_flag[i]) {
5689                         new_table_block(ctx, first_block, i, _("inode bitmap"),
5690                                         1, &fs->group_desc[i].bg_inode_bitmap);
5691                 }
5692                 if (ctx->invalid_inode_table_flag[i]) {
5693                         new_table_block(ctx, first_block, i, _("inode table"),
5694                                         fs->inode_blocks_per_group,
5695                                         &fs->group_desc[i].bg_inode_table);
5696                         ctx->flags |= E2F_FLAG_RESTART;
5697                 }
5698                 first_block += fs->super->s_blocks_per_group;
5699         }
5700         ctx->invalid_bitmaps = 0;
5701 }
5702
5703 /*
5704  * This routine marks all blocks which are used by the superblock,
5705  * group descriptors, inode bitmaps, and block bitmaps.
5706  */
5707 static void mark_table_blocks(e2fsck_t ctx)
5708 {
5709         ext2_filsys fs = ctx->fs;
5710         blk_t   block, b;
5711         dgrp_t  i;
5712         int     j;
5713         struct problem_context pctx;
5714
5715         clear_problem_context(&pctx);
5716
5717         block = fs->super->s_first_data_block;
5718         for (i = 0; i < fs->group_desc_count; i++) {
5719                 pctx.group = i;
5720
5721                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
5722
5723                 /*
5724                  * Mark the blocks used for the inode table
5725                  */
5726                 if (fs->group_desc[i].bg_inode_table) {
5727                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
5728                              j < fs->inode_blocks_per_group;
5729                              j++, b++) {
5730                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
5731                                                              b)) {
5732                                         pctx.blk = b;
5733                                         if (fix_problem(ctx,
5734                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
5735                                                 ctx->invalid_inode_table_flag[i]++;
5736                                                 ctx->invalid_bitmaps++;
5737                                         }
5738                                 } else {
5739                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
5740                                                              b);
5741                                 }
5742                         }
5743                 }
5744
5745                 /*
5746                  * Mark block used for the block bitmap
5747                  */
5748                 if (fs->group_desc[i].bg_block_bitmap) {
5749                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
5750                                      fs->group_desc[i].bg_block_bitmap)) {
5751                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
5752                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
5753                                         ctx->invalid_block_bitmap_flag[i]++;
5754                                         ctx->invalid_bitmaps++;
5755                                 }
5756                         } else {
5757                             ext2fs_mark_block_bitmap(ctx->block_found_map,
5758                                      fs->group_desc[i].bg_block_bitmap);
5759                     }
5760
5761                 }
5762                 /*
5763                  * Mark block used for the inode bitmap
5764                  */
5765                 if (fs->group_desc[i].bg_inode_bitmap) {
5766                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
5767                                      fs->group_desc[i].bg_inode_bitmap)) {
5768                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
5769                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
5770                                         ctx->invalid_inode_bitmap_flag[i]++;
5771                                         ctx->invalid_bitmaps++;
5772                                 }
5773                         } else {
5774                             ext2fs_mark_block_bitmap(ctx->block_found_map,
5775                                      fs->group_desc[i].bg_inode_bitmap);
5776                         }
5777                 }
5778                 block += fs->super->s_blocks_per_group;
5779         }
5780 }
5781
5782 /*
5783  * Thes subroutines short circuits ext2fs_get_blocks and
5784  * ext2fs_check_directory; we use them since we already have the inode
5785  * structure, so there's no point in letting the ext2fs library read
5786  * the inode again.
5787  */
5788 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
5789                                   blk_t *blocks)
5790 {
5791         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5792         int     i;
5793
5794         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
5795                 return EXT2_ET_CALLBACK_NOTHANDLED;
5796
5797         for (i=0; i < EXT2_N_BLOCKS; i++)
5798                 blocks[i] = ctx->stashed_inode->i_block[i];
5799         return 0;
5800 }
5801
5802 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
5803                                   struct ext2_inode *inode)
5804 {
5805         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5806
5807         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
5808                 return EXT2_ET_CALLBACK_NOTHANDLED;
5809         *inode = *ctx->stashed_inode;
5810         return 0;
5811 }
5812
5813 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
5814                             struct ext2_inode *inode)
5815 {
5816         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5817
5818         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
5819                 *ctx->stashed_inode = *inode;
5820         return EXT2_ET_CALLBACK_NOTHANDLED;
5821 }
5822
5823 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
5824 {
5825         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
5826
5827         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
5828                 return EXT2_ET_CALLBACK_NOTHANDLED;
5829
5830         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
5831                 return EXT2_ET_NO_DIRECTORY;
5832         return 0;
5833 }
5834
5835 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
5836 {
5837         ext2_filsys fs = ctx->fs;
5838
5839         if (bool) {
5840                 fs->get_blocks = pass1_get_blocks;
5841                 fs->check_directory = pass1_check_directory;
5842                 fs->read_inode = pass1_read_inode;
5843                 fs->write_inode = pass1_write_inode;
5844                 ctx->stashed_ino = 0;
5845         } else {
5846                 fs->get_blocks = 0;
5847                 fs->check_directory = 0;
5848                 fs->read_inode = 0;
5849                 fs->write_inode = 0;
5850         }
5851 }
5852
5853 /*
5854  * pass1b.c --- Pass #1b of e2fsck
5855  *
5856  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
5857  * only invoked if pass 1 discovered blocks which are in use by more
5858  * than one inode.
5859  *
5860  * Pass1B scans the data blocks of all the inodes again, generating a
5861  * complete list of duplicate blocks and which inodes have claimed
5862  * them.
5863  *
5864  * Pass1C does a tree-traversal of the filesystem, to determine the
5865  * parent directories of these inodes.  This step is necessary so that
5866  * e2fsck can print out the pathnames of affected inodes.
5867  *
5868  * Pass1D is a reconciliation pass.  For each inode with duplicate
5869  * blocks, the user is prompted if s/he would like to clone the file
5870  * (so that the file gets a fresh copy of the duplicated blocks) or
5871  * simply to delete the file.
5872  *
5873  */
5874
5875
5876 /* Needed for architectures where sizeof(int) != sizeof(void *) */
5877 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
5878 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
5879
5880 /* Define an extension to the ext2 library's block count information */
5881 #define BLOCK_COUNT_EXTATTR     (-5)
5882
5883 struct block_el {
5884         blk_t   block;
5885         struct block_el *next;
5886 };
5887
5888 struct inode_el {
5889         ext2_ino_t      inode;
5890         struct inode_el *next;
5891 };
5892
5893 struct dup_block {
5894         int             num_bad;
5895         struct inode_el *inode_list;
5896 };
5897
5898 /*
5899  * This structure stores information about a particular inode which
5900  * is sharing blocks with other inodes.  This information is collected
5901  * to display to the user, so that the user knows what files he or she
5902  * is dealing with, when trying to decide how to resolve the conflict
5903  * of multiply-claimed blocks.
5904  */
5905 struct dup_inode {
5906         ext2_ino_t              dir;
5907         int                     num_dupblocks;
5908         struct ext2_inode       inode;
5909         struct block_el         *block_list;
5910 };
5911
5912 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
5913                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
5914                                 int ref_offset, void *priv_data);
5915 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5916                         struct dup_inode *dp, char *block_buf);
5917 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5918                       struct dup_inode *dp, char* block_buf);
5919 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
5920
5921 static void pass1b(e2fsck_t ctx, char *block_buf);
5922 static void pass1c(e2fsck_t ctx, char *block_buf);
5923 static void pass1d(e2fsck_t ctx, char *block_buf);
5924
5925 static int dup_inode_count = 0;
5926
5927 static dict_t blk_dict, ino_dict;
5928
5929 static ext2fs_inode_bitmap inode_dup_map;
5930
5931 static int dict_int_cmp(const void *a, const void *b)
5932 {
5933         intptr_t        ia, ib;
5934
5935         ia = (intptr_t)a;
5936         ib = (intptr_t)b;
5937
5938         return (ia-ib);
5939 }
5940
5941 /*
5942  * Add a duplicate block record
5943  */
5944 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
5945                      struct ext2_inode *inode)
5946 {
5947         dnode_t *n;
5948         struct dup_block        *db;
5949         struct dup_inode        *di;
5950         struct block_el         *blk_el;
5951         struct inode_el         *ino_el;
5952
5953         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5954         if (n)
5955                 db = (struct dup_block *) dnode_get(n);
5956         else {
5957                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
5958                          sizeof(struct dup_block), "duplicate block header");
5959                 db->num_bad = 0;
5960                 db->inode_list = 0;
5961                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
5962         }
5963         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
5964                          sizeof(struct inode_el), "inode element");
5965         ino_el->inode = ino;
5966         ino_el->next = db->inode_list;
5967         db->inode_list = ino_el;
5968         db->num_bad++;
5969
5970         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
5971         if (n)
5972                 di = (struct dup_inode *) dnode_get(n);
5973         else {
5974                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
5975                          sizeof(struct dup_inode), "duplicate inode header");
5976                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
5977                 di->num_dupblocks = 0;
5978                 di->block_list = 0;
5979                 di->inode = *inode;
5980                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
5981         }
5982         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
5983                          sizeof(struct block_el), "block element");
5984         blk_el->block = blk;
5985         blk_el->next = di->block_list;
5986         di->block_list = blk_el;
5987         di->num_dupblocks++;
5988 }
5989
5990 /*
5991  * Free a duplicate inode record
5992  */
5993 static void inode_dnode_free(dnode_t *node)
5994 {
5995         struct dup_inode        *di;
5996         struct block_el         *p, *next;
5997
5998         di = (struct dup_inode *) dnode_get(node);
5999         for (p = di->block_list; p; p = next) {
6000                 next = p->next;
6001                 free(p);
6002         }
6003         free(node);
6004 }
6005
6006 /*
6007  * Free a duplicate block record
6008  */
6009 static void block_dnode_free(dnode_t *node)
6010 {
6011         struct dup_block        *db;
6012         struct inode_el         *p, *next;
6013
6014         db = (struct dup_block *) dnode_get(node);
6015         for (p = db->inode_list; p; p = next) {
6016                 next = p->next;
6017                 free(p);
6018         }
6019         free(node);
6020 }
6021
6022
6023 /*
6024  * Main procedure for handling duplicate blocks
6025  */
6026 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6027 {
6028         ext2_filsys             fs = ctx->fs;
6029         struct problem_context  pctx;
6030
6031         clear_problem_context(&pctx);
6032
6033         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6034                       _("multiply claimed inode map"), &inode_dup_map);
6035         if (pctx.errcode) {
6036                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6037                 ctx->flags |= E2F_FLAG_ABORT;
6038                 return;
6039         }
6040
6041         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6042         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6043         dict_set_allocator(&ino_dict, inode_dnode_free);
6044         dict_set_allocator(&blk_dict, block_dnode_free);
6045
6046         pass1b(ctx, block_buf);
6047         pass1c(ctx, block_buf);
6048         pass1d(ctx, block_buf);
6049
6050         /*
6051          * Time to free all of the accumulated data structures that we
6052          * don't need anymore.
6053          */
6054         dict_free_nodes(&ino_dict);
6055         dict_free_nodes(&blk_dict);
6056 }
6057
6058 /*
6059  * Scan the inodes looking for inodes that contain duplicate blocks.
6060  */
6061 struct process_block_struct_1b {
6062         e2fsck_t        ctx;
6063         ext2_ino_t      ino;
6064         int             dup_blocks;
6065         struct ext2_inode *inode;
6066         struct problem_context *pctx;
6067 };
6068
6069 static void pass1b(e2fsck_t ctx, char *block_buf)
6070 {
6071         ext2_filsys fs = ctx->fs;
6072         ext2_ino_t ino;
6073         struct ext2_inode inode;
6074         ext2_inode_scan scan;
6075         struct process_block_struct_1b pb;
6076         struct problem_context pctx;
6077
6078         clear_problem_context(&pctx);
6079
6080         if (!(ctx->options & E2F_OPT_PREEN))
6081                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6082         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6083                                               &scan);
6084         if (pctx.errcode) {
6085                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6086                 ctx->flags |= E2F_FLAG_ABORT;
6087                 return;
6088         }
6089         ctx->stashed_inode = &inode;
6090         pb.ctx = ctx;
6091         pb.pctx = &pctx;
6092         pctx.str = "pass1b";
6093         while (1) {
6094                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6095                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6096                         continue;
6097                 if (pctx.errcode) {
6098                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6099                         ctx->flags |= E2F_FLAG_ABORT;
6100                         return;
6101                 }
6102                 if (!ino)
6103                         break;
6104                 pctx.ino = ctx->stashed_ino = ino;
6105                 if ((ino != EXT2_BAD_INO) &&
6106                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6107                         continue;
6108
6109                 pb.ino = ino;
6110                 pb.dup_blocks = 0;
6111                 pb.inode = &inode;
6112
6113                 if (ext2fs_inode_has_valid_blocks(&inode) ||
6114                     (ino == EXT2_BAD_INO))
6115                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
6116                                      0, block_buf, process_pass1b_block, &pb);
6117                 if (inode.i_file_acl)
6118                         process_pass1b_block(fs, &inode.i_file_acl,
6119                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6120                 if (pb.dup_blocks) {
6121                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
6122                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
6123                             ino == EXT2_ROOT_INO)
6124                                 dup_inode_count++;
6125                 }
6126                 if (pctx.errcode)
6127                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6128         }
6129         ext2fs_close_inode_scan(scan);
6130         e2fsck_use_inode_shortcuts(ctx, 0);
6131 }
6132
6133 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6134                                 blk_t   *block_nr,
6135                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6136                                 blk_t ref_blk FSCK_ATTR((unused)),
6137                                 int ref_offset FSCK_ATTR((unused)),
6138                                 void *priv_data)
6139 {
6140         struct process_block_struct_1b *p;
6141         e2fsck_t ctx;
6142
6143         if (HOLE_BLKADDR(*block_nr))
6144                 return 0;
6145         p = (struct process_block_struct_1b *) priv_data;
6146         ctx = p->ctx;
6147
6148         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6149                 return 0;
6150
6151         /* OK, this is a duplicate block */
6152         if (p->ino != EXT2_BAD_INO) {
6153                 p->pctx->blk = *block_nr;
6154                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6155         }
6156         p->dup_blocks++;
6157         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6158
6159         add_dupe(ctx, p->ino, *block_nr, p->inode);
6160
6161         return 0;
6162 }
6163
6164 /*
6165  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
6166  * is used so that we can print pathnames when prompting the user for
6167  * what to do.
6168  */
6169 struct search_dir_struct {
6170         int             count;
6171         ext2_ino_t      first_inode;
6172         ext2_ino_t      max_inode;
6173 };
6174
6175 static int search_dirent_proc(ext2_ino_t dir, int entry,
6176                               struct ext2_dir_entry *dirent,
6177                               int offset FSCK_ATTR((unused)),
6178                               int blocksize FSCK_ATTR((unused)),
6179                               char *buf FSCK_ATTR((unused)),
6180                               void *priv_data)
6181 {
6182         struct search_dir_struct *sd;
6183         struct dup_inode        *p;
6184         dnode_t                 *n;
6185
6186         sd = (struct search_dir_struct *) priv_data;
6187
6188         if (dirent->inode > sd->max_inode)
6189                 /* Should abort this inode, but not everything */
6190                 return 0;
6191
6192         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6193             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6194                 return 0;
6195
6196         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6197         if (!n)
6198                 return 0;
6199         p = (struct dup_inode *) dnode_get(n);
6200         p->dir = dir;
6201         sd->count--;
6202
6203         return(sd->count ? 0 : DIRENT_ABORT);
6204 }
6205
6206
6207 static void pass1c(e2fsck_t ctx, char *block_buf)
6208 {
6209         ext2_filsys fs = ctx->fs;
6210         struct search_dir_struct sd;
6211         struct problem_context pctx;
6212
6213         clear_problem_context(&pctx);
6214
6215         if (!(ctx->options & E2F_OPT_PREEN))
6216                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6217
6218         /*
6219          * Search through all directories to translate inodes to names
6220          * (by searching for the containing directory for that inode.)
6221          */
6222         sd.count = dup_inode_count;
6223         sd.first_inode = EXT2_FIRST_INODE(fs->super);
6224         sd.max_inode = fs->super->s_inodes_count;
6225         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6226                                   search_dirent_proc, &sd);
6227 }
6228
6229 static void pass1d(e2fsck_t ctx, char *block_buf)
6230 {
6231         ext2_filsys fs = ctx->fs;
6232         struct dup_inode        *p, *t;
6233         struct dup_block        *q;
6234         ext2_ino_t              *shared, ino;
6235         int     shared_len;
6236         int     i;
6237         int     file_ok;
6238         int     meta_data = 0;
6239         struct problem_context pctx;
6240         dnode_t *n, *m;
6241         struct block_el *s;
6242         struct inode_el *r;
6243
6244         clear_problem_context(&pctx);
6245
6246         if (!(ctx->options & E2F_OPT_PREEN))
6247                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6248         e2fsck_read_bitmaps(ctx);
6249
6250         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6251         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6252         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6253                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6254                                 "Shared inode list");
6255         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6256                 p = (struct dup_inode *) dnode_get(n);
6257                 shared_len = 0;
6258                 file_ok = 1;
6259                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6260                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
6261                         continue;
6262
6263                 /*
6264                  * Find all of the inodes which share blocks with this
6265                  * one.  First we find all of the duplicate blocks
6266                  * belonging to this inode, and then search each block
6267                  * get the list of inodes, and merge them together.
6268                  */
6269                 for (s = p->block_list; s; s = s->next) {
6270                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6271                         if (!m)
6272                                 continue; /* Should never happen... */
6273                         q = (struct dup_block *) dnode_get(m);
6274                         if (q->num_bad > 1)
6275                                 file_ok = 0;
6276                         if (check_if_fs_block(ctx, s->block)) {
6277                                 file_ok = 0;
6278                                 meta_data = 1;
6279                         }
6280
6281                         /*
6282                          * Add all inodes used by this block to the
6283                          * shared[] --- which is a unique list, so
6284                          * if an inode is already in shared[], don't
6285                          * add it again.
6286                          */
6287                         for (r = q->inode_list; r; r = r->next) {
6288                                 if (r->inode == ino)
6289                                         continue;
6290                                 for (i = 0; i < shared_len; i++)
6291                                         if (shared[i] == r->inode)
6292                                                 break;
6293                                 if (i == shared_len) {
6294                                         shared[shared_len++] = r->inode;
6295                                 }
6296                         }
6297                 }
6298
6299                 /*
6300                  * Report the inode that we are working on
6301                  */
6302                 pctx.inode = &p->inode;
6303                 pctx.ino = ino;
6304                 pctx.dir = p->dir;
6305                 pctx.blkcount = p->num_dupblocks;
6306                 pctx.num = meta_data ? shared_len+1 : shared_len;
6307                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6308                 pctx.blkcount = 0;
6309                 pctx.num = 0;
6310
6311                 if (meta_data)
6312                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6313
6314                 for (i = 0; i < shared_len; i++) {
6315                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6316                         if (!m)
6317                                 continue; /* should never happen */
6318                         t = (struct dup_inode *) dnode_get(m);
6319                         /*
6320                          * Report the inode that we are sharing with
6321                          */
6322                         pctx.inode = &t->inode;
6323                         pctx.ino = shared[i];
6324                         pctx.dir = t->dir;
6325                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6326                 }
6327                 if (file_ok) {
6328                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6329                         continue;
6330                 }
6331                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6332                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
6333                         if (pctx.errcode)
6334                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6335                         else
6336                                 continue;
6337                 }
6338                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6339                         delete_file(ctx, ino, p, block_buf);
6340                 else
6341                         ext2fs_unmark_valid(fs);
6342         }
6343         ext2fs_free_mem(&shared);
6344 }
6345
6346 /*
6347  * Drop the refcount on the dup_block structure, and clear the entry
6348  * in the block_dup_map if appropriate.
6349  */
6350 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6351 {
6352         p->num_bad--;
6353         if (p->num_bad <= 0 ||
6354             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6355                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6356 }
6357
6358 static int delete_file_block(ext2_filsys fs,
6359                              blk_t      *block_nr,
6360                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6361                              blk_t ref_block FSCK_ATTR((unused)),
6362                              int ref_offset FSCK_ATTR((unused)),
6363                              void *priv_data)
6364 {
6365         struct process_block_struct_1b *pb;
6366         struct dup_block *p;
6367         dnode_t *n;
6368         e2fsck_t ctx;
6369
6370         pb = (struct process_block_struct_1b *) priv_data;
6371         ctx = pb->ctx;
6372
6373         if (HOLE_BLKADDR(*block_nr))
6374                 return 0;
6375
6376         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6377                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6378                 if (n) {
6379                         p = (struct dup_block *) dnode_get(n);
6380                         decrement_badcount(ctx, *block_nr, p);
6381                 } else
6382                         com_err("delete_file_block", 0,
6383                             _("internal error; can't find dup_blk for %d\n"),
6384                                 *block_nr);
6385         } else {
6386                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6387                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6388         }
6389
6390         return 0;
6391 }
6392
6393 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6394                         struct dup_inode *dp, char* block_buf)
6395 {
6396         ext2_filsys fs = ctx->fs;
6397         struct process_block_struct_1b pb;
6398         struct ext2_inode       inode;
6399         struct problem_context  pctx;
6400         unsigned int            count;
6401
6402         clear_problem_context(&pctx);
6403         pctx.ino = pb.ino = ino;
6404         pb.dup_blocks = dp->num_dupblocks;
6405         pb.ctx = ctx;
6406         pctx.str = "delete_file";
6407
6408         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6409         if (ext2fs_inode_has_valid_blocks(&inode))
6410                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6411                                                      delete_file_block, &pb);
6412         if (pctx.errcode)
6413                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6414         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6415         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6416         if (ctx->inode_bad_map)
6417                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6418         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6419
6420         /* Inode may have changed by block_iterate, so reread it */
6421         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6422         inode.i_links_count = 0;
6423         inode.i_dtime = time(0);
6424         if (inode.i_file_acl &&
6425             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6426                 count = 1;
6427                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6428                                                    block_buf, -1, &count);
6429                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6430                         pctx.errcode = 0;
6431                         count = 1;
6432                 }
6433                 if (pctx.errcode) {
6434                         pctx.blk = inode.i_file_acl;
6435                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6436                 }
6437                 /*
6438                  * If the count is zero, then arrange to have the
6439                  * block deleted.  If the block is in the block_dup_map,
6440                  * also call delete_file_block since it will take care
6441                  * of keeping the accounting straight.
6442                  */
6443                 if ((count == 0) ||
6444                     ext2fs_test_block_bitmap(ctx->block_dup_map,
6445                                              inode.i_file_acl))
6446                         delete_file_block(fs, &inode.i_file_acl,
6447                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6448         }
6449         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6450 }
6451
6452 struct clone_struct {
6453         errcode_t       errcode;
6454         ext2_ino_t      dir;
6455         char    *buf;
6456         e2fsck_t ctx;
6457 };
6458
6459 static int clone_file_block(ext2_filsys fs,
6460                             blk_t       *block_nr,
6461                             e2_blkcnt_t blockcnt,
6462                             blk_t ref_block FSCK_ATTR((unused)),
6463                             int ref_offset FSCK_ATTR((unused)),
6464                             void *priv_data)
6465 {
6466         struct dup_block *p;
6467         blk_t   new_block;
6468         errcode_t       retval;
6469         struct clone_struct *cs = (struct clone_struct *) priv_data;
6470         dnode_t *n;
6471         e2fsck_t ctx;
6472
6473         ctx = cs->ctx;
6474
6475         if (HOLE_BLKADDR(*block_nr))
6476                 return 0;
6477
6478         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6479                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6480                 if (n) {
6481                         p = (struct dup_block *) dnode_get(n);
6482                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6483                                                   &new_block);
6484                         if (retval) {
6485                                 cs->errcode = retval;
6486                                 return BLOCK_ABORT;
6487                         }
6488                         if (cs->dir && (blockcnt >= 0)) {
6489                                 retval = ext2fs_set_dir_block(fs->dblist,
6490                                       cs->dir, new_block, blockcnt);
6491                                 if (retval) {
6492                                         cs->errcode = retval;
6493                                         return BLOCK_ABORT;
6494                                 }
6495                         }
6496
6497                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
6498                                                      cs->buf);
6499                         if (retval) {
6500                                 cs->errcode = retval;
6501                                 return BLOCK_ABORT;
6502                         }
6503                         retval = io_channel_write_blk(fs->io, new_block, 1,
6504                                                       cs->buf);
6505                         if (retval) {
6506                                 cs->errcode = retval;
6507                                 return BLOCK_ABORT;
6508                         }
6509                         decrement_badcount(ctx, *block_nr, p);
6510                         *block_nr = new_block;
6511                         ext2fs_mark_block_bitmap(ctx->block_found_map,
6512                                                  new_block);
6513                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
6514                         return BLOCK_CHANGED;
6515                 } else
6516                         com_err("clone_file_block", 0,
6517                             _("internal error; can't find dup_blk for %d\n"),
6518                                 *block_nr);
6519         }
6520         return 0;
6521 }
6522
6523 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6524                       struct dup_inode *dp, char* block_buf)
6525 {
6526         ext2_filsys fs = ctx->fs;
6527         errcode_t       retval;
6528         struct clone_struct cs;
6529         struct problem_context  pctx;
6530         blk_t           blk;
6531         dnode_t         *n;
6532         struct inode_el *ino_el;
6533         struct dup_block        *db;
6534         struct dup_inode        *di;
6535
6536         clear_problem_context(&pctx);
6537         cs.errcode = 0;
6538         cs.dir = 0;
6539         cs.ctx = ctx;
6540         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
6541         if (retval)
6542                 return retval;
6543
6544         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
6545                 cs.dir = ino;
6546
6547         pctx.ino = ino;
6548         pctx.str = "clone_file";
6549         if (ext2fs_inode_has_valid_blocks(&dp->inode))
6550                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6551                                                      clone_file_block, &cs);
6552         ext2fs_mark_bb_dirty(fs);
6553         if (pctx.errcode) {
6554                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6555                 retval = pctx.errcode;
6556                 goto errout;
6557         }
6558         if (cs.errcode) {
6559                 com_err("clone_file", cs.errcode,
6560                         _("returned from clone_file_block"));
6561                 retval = cs.errcode;
6562                 goto errout;
6563         }
6564         /* The inode may have changed on disk, so we have to re-read it */
6565         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
6566         blk = dp->inode.i_file_acl;
6567         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
6568                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
6569                     BLOCK_CHANGED)) {
6570                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
6571                 /*
6572                  * If we cloned the EA block, find all other inodes
6573                  * which refered to that EA block, and modify
6574                  * them to point to the new EA block.
6575                  */
6576                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6577                 db = (struct dup_block *) dnode_get(n);
6578                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
6579                         if (ino_el->inode == ino)
6580                                 continue;
6581                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
6582                         di = (struct dup_inode *) dnode_get(n);
6583                         if (di->inode.i_file_acl == blk) {
6584                                 di->inode.i_file_acl = dp->inode.i_file_acl;
6585                                 e2fsck_write_inode(ctx, ino_el->inode,
6586                                            &di->inode, "clone file EA");
6587                                 decrement_badcount(ctx, blk, db);
6588                         }
6589                 }
6590         }
6591         retval = 0;
6592 errout:
6593         ext2fs_free_mem(&cs.buf);
6594         return retval;
6595 }
6596
6597 /*
6598  * This routine returns 1 if a block overlaps with one of the superblocks,
6599  * group descriptors, inode bitmaps, or block bitmaps.
6600  */
6601 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
6602 {
6603         ext2_filsys fs = ctx->fs;
6604         blk_t   block;
6605         dgrp_t  i;
6606
6607         block = fs->super->s_first_data_block;
6608         for (i = 0; i < fs->group_desc_count; i++) {
6609
6610                 /* Check superblocks/block group descriptros */
6611                 if (ext2fs_bg_has_super(fs, i)) {
6612                         if (test_block >= block &&
6613                             (test_block <= block + fs->desc_blocks))
6614                                 return 1;
6615                 }
6616
6617                 /* Check the inode table */
6618                 if ((fs->group_desc[i].bg_inode_table) &&
6619                     (test_block >= fs->group_desc[i].bg_inode_table) &&
6620                     (test_block < (fs->group_desc[i].bg_inode_table +
6621                                    fs->inode_blocks_per_group)))
6622                         return 1;
6623
6624                 /* Check the bitmap blocks */
6625                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
6626                     (test_block == fs->group_desc[i].bg_inode_bitmap))
6627                         return 1;
6628
6629                 block += fs->super->s_blocks_per_group;
6630         }
6631         return 0;
6632 }
6633 /*
6634  * pass2.c --- check directory structure
6635  *
6636  * Pass 2 of e2fsck iterates through all active directory inodes, and
6637  * applies to following tests to each directory entry in the directory
6638  * blocks in the inodes:
6639  *
6640  *      - The length of the directory entry (rec_len) should be at
6641  *              least 8 bytes, and no more than the remaining space
6642  *              left in the directory block.
6643  *      - The length of the name in the directory entry (name_len)
6644  *              should be less than (rec_len - 8).
6645  *      - The inode number in the directory entry should be within
6646  *              legal bounds.
6647  *      - The inode number should refer to a in-use inode.
6648  *      - The first entry should be '.', and its inode should be
6649  *              the inode of the directory.
6650  *      - The second entry should be '..'.
6651  *
6652  * To minimize disk seek time, the directory blocks are processed in
6653  * sorted order of block numbers.
6654  *
6655  * Pass 2 also collects the following information:
6656  *      - The inode numbers of the subdirectories for each directory.
6657  *
6658  * Pass 2 relies on the following information from previous passes:
6659  *      - The directory information collected in pass 1.
6660  *      - The inode_used_map bitmap
6661  *      - The inode_bad_map bitmap
6662  *      - The inode_dir_map bitmap
6663  *
6664  * Pass 2 frees the following data structures
6665  *      - The inode_bad_map bitmap
6666  *      - The inode_reg_map bitmap
6667  */
6668
6669 /*
6670  * Keeps track of how many times an inode is referenced.
6671  */
6672 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
6673 static int check_dir_block(ext2_filsys fs,
6674                            struct ext2_db_entry *dir_blocks_info,
6675                            void *priv_data);
6676 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
6677                               struct problem_context *pctx);
6678 static int update_dir_block(ext2_filsys fs,
6679                             blk_t       *block_nr,
6680                             e2_blkcnt_t blockcnt,
6681                             blk_t       ref_block,
6682                             int         ref_offset,
6683                             void        *priv_data);
6684 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
6685 static int htree_depth(struct dx_dir_info *dx_dir,
6686                        struct dx_dirblock_info *dx_db);
6687 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
6688
6689 struct check_dir_struct {
6690         char *buf;
6691         struct problem_context  pctx;
6692         int     count, max;
6693         e2fsck_t ctx;
6694 };
6695
6696 static void e2fsck_pass2(e2fsck_t ctx)
6697 {
6698         struct ext2_super_block *sb = ctx->fs->super;
6699         struct problem_context  pctx;
6700         ext2_filsys             fs = ctx->fs;
6701         char                    *buf;
6702         struct dir_info         *dir;
6703         struct check_dir_struct cd;
6704         struct dx_dir_info      *dx_dir;
6705         struct dx_dirblock_info *dx_db, *dx_parent;
6706         int                     b;
6707         int                     i, depth;
6708         problem_t               code;
6709         int                     bad_dir;
6710
6711         clear_problem_context(&cd.pctx);
6712
6713         /* Pass 2 */
6714
6715         if (!(ctx->options & E2F_OPT_PREEN))
6716                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
6717
6718         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
6719                                                 0, ctx->inode_link_info,
6720                                                 &ctx->inode_count);
6721         if (cd.pctx.errcode) {
6722                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
6723                 ctx->flags |= E2F_FLAG_ABORT;
6724                 return;
6725         }
6726         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
6727                                               "directory scan buffer");
6728
6729         /*
6730          * Set up the parent pointer for the root directory, if
6731          * present.  (If the root directory is not present, we will
6732          * create it in pass 3.)
6733          */
6734         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
6735         if (dir)
6736                 dir->parent = EXT2_ROOT_INO;
6737
6738         cd.buf = buf;
6739         cd.ctx = ctx;
6740         cd.count = 1;
6741         cd.max = ext2fs_dblist_count(fs->dblist);
6742
6743         if (ctx->progress)
6744                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
6745
6746         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
6747                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
6748
6749         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
6750                                                 &cd);
6751         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6752                 return;
6753         if (cd.pctx.errcode) {
6754                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
6755                 ctx->flags |= E2F_FLAG_ABORT;
6756                 return;
6757         }
6758
6759 #ifdef ENABLE_HTREE
6760         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
6761                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6762                         return;
6763                 if (dx_dir->numblocks == 0)
6764                         continue;
6765                 clear_problem_context(&pctx);
6766                 bad_dir = 0;
6767                 pctx.dir = dx_dir->ino;
6768                 dx_db = dx_dir->dx_block;
6769                 if (dx_db->flags & DX_FLAG_REFERENCED)
6770                         dx_db->flags |= DX_FLAG_DUP_REF;
6771                 else
6772                         dx_db->flags |= DX_FLAG_REFERENCED;
6773                 /*
6774                  * Find all of the first and last leaf blocks, and
6775                  * update their parent's min and max hash values
6776                  */
6777                 for (b=0, dx_db = dx_dir->dx_block;
6778                      b < dx_dir->numblocks;
6779                      b++, dx_db++) {
6780                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
6781                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
6782                                 continue;
6783                         dx_parent = &dx_dir->dx_block[dx_db->parent];
6784                         /*
6785                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
6786                          */
6787                         if (dx_db->flags & DX_FLAG_FIRST)
6788                                 dx_parent->min_hash = dx_db->min_hash;
6789                         /*
6790                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
6791                          */
6792                         if (dx_db->flags & DX_FLAG_LAST)
6793                                 dx_parent->max_hash = dx_db->max_hash;
6794                 }
6795
6796                 for (b=0, dx_db = dx_dir->dx_block;
6797                      b < dx_dir->numblocks;
6798                      b++, dx_db++) {
6799                         pctx.blkcount = b;
6800                         pctx.group = dx_db->parent;
6801                         code = 0;
6802                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
6803                             (dx_db->min_hash < dx_db->node_min_hash)) {
6804                                 pctx.blk = dx_db->min_hash;
6805                                 pctx.blk2 = dx_db->node_min_hash;
6806                                 code = PR_2_HTREE_MIN_HASH;
6807                                 fix_problem(ctx, code, &pctx);
6808                                 bad_dir++;
6809                         }
6810                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
6811                                 depth = htree_depth(dx_dir, dx_db);
6812                                 if (depth != dx_dir->depth) {
6813                                         code = PR_2_HTREE_BAD_DEPTH;
6814                                         fix_problem(ctx, code, &pctx);
6815                                         bad_dir++;
6816                                 }
6817                         }
6818                         /*
6819                          * This test doesn't apply for the root block
6820                          * at block #0
6821                          */
6822                         if (b &&
6823                             (dx_db->max_hash > dx_db->node_max_hash)) {
6824                                 pctx.blk = dx_db->max_hash;
6825                                 pctx.blk2 = dx_db->node_max_hash;
6826                                 code = PR_2_HTREE_MAX_HASH;
6827                                 fix_problem(ctx, code, &pctx);
6828                                 bad_dir++;
6829                         }
6830                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
6831                                 code = PR_2_HTREE_NOTREF;
6832                                 fix_problem(ctx, code, &pctx);
6833                                 bad_dir++;
6834                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
6835                                 code = PR_2_HTREE_DUPREF;
6836                                 fix_problem(ctx, code, &pctx);
6837                                 bad_dir++;
6838                         }
6839                         if (code == 0)
6840                                 continue;
6841                 }
6842                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
6843                         clear_htree(ctx, dx_dir->ino);
6844                         dx_dir->numblocks = 0;
6845                 }
6846         }
6847 #endif
6848         ext2fs_free_mem(&buf);
6849         ext2fs_free_dblist(fs->dblist);
6850
6851         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
6852         ctx->inode_bad_map = 0;
6853         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
6854         ctx->inode_reg_map = 0;
6855
6856         clear_problem_context(&pctx);
6857         if (ctx->large_files) {
6858                 if (!(sb->s_feature_ro_compat &
6859                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
6860                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
6861                         sb->s_feature_ro_compat |=
6862                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
6863                         ext2fs_mark_super_dirty(fs);
6864                 }
6865                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
6866                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
6867                         ext2fs_update_dynamic_rev(fs);
6868                         ext2fs_mark_super_dirty(fs);
6869                 }
6870         } else if (!ctx->large_files &&
6871             (sb->s_feature_ro_compat &
6872               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
6873                 if (fs->flags & EXT2_FLAG_RW) {
6874                         sb->s_feature_ro_compat &=
6875                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
6876                         ext2fs_mark_super_dirty(fs);
6877                 }
6878         }
6879
6880 }
6881
6882 #define MAX_DEPTH 32000
6883 static int htree_depth(struct dx_dir_info *dx_dir,
6884                        struct dx_dirblock_info *dx_db)
6885 {
6886         int     depth = 0;
6887
6888         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
6889                 dx_db = &dx_dir->dx_block[dx_db->parent];
6890                 depth++;
6891         }
6892         return depth;
6893 }
6894
6895 static int dict_de_cmp(const void *a, const void *b)
6896 {
6897         const struct ext2_dir_entry *de_a, *de_b;
6898         int     a_len, b_len;
6899
6900         de_a = (const struct ext2_dir_entry *) a;
6901         a_len = de_a->name_len & 0xFF;
6902         de_b = (const struct ext2_dir_entry *) b;
6903         b_len = de_b->name_len & 0xFF;
6904
6905         if (a_len != b_len)
6906                 return (a_len - b_len);
6907
6908         return strncmp(de_a->name, de_b->name, a_len);
6909 }
6910
6911 /*
6912  * This is special sort function that makes sure that directory blocks
6913  * with a dirblock of zero are sorted to the beginning of the list.
6914  * This guarantees that the root node of the htree directories are
6915  * processed first, so we know what hash version to use.
6916  */
6917 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
6918 {
6919         const struct ext2_db_entry *db_a =
6920                 (const struct ext2_db_entry *) a;
6921         const struct ext2_db_entry *db_b =
6922                 (const struct ext2_db_entry *) b;
6923
6924         if (db_a->blockcnt && !db_b->blockcnt)
6925                 return 1;
6926
6927         if (!db_a->blockcnt && db_b->blockcnt)
6928                 return -1;
6929
6930         if (db_a->blk != db_b->blk)
6931                 return (int) (db_a->blk - db_b->blk);
6932
6933         if (db_a->ino != db_b->ino)
6934                 return (int) (db_a->ino - db_b->ino);
6935
6936         return (int) (db_a->blockcnt - db_b->blockcnt);
6937 }
6938
6939
6940 /*
6941  * Make sure the first entry in the directory is '.', and that the
6942  * directory entry is sane.
6943  */
6944 static int check_dot(e2fsck_t ctx,
6945                      struct ext2_dir_entry *dirent,
6946                      ext2_ino_t ino, struct problem_context *pctx)
6947 {
6948         struct ext2_dir_entry *nextdir;
6949         int     status = 0;
6950         int     created = 0;
6951         int     new_len;
6952         int     problem = 0;
6953
6954         if (!dirent->inode)
6955                 problem = PR_2_MISSING_DOT;
6956         else if (((dirent->name_len & 0xFF) != 1) ||
6957                  (dirent->name[0] != '.'))
6958                 problem = PR_2_1ST_NOT_DOT;
6959         else if (dirent->name[1] != '\0')
6960                 problem = PR_2_DOT_NULL_TERM;
6961
6962         if (problem) {
6963                 if (fix_problem(ctx, problem, pctx)) {
6964                         if (dirent->rec_len < 12)
6965                                 dirent->rec_len = 12;
6966                         dirent->inode = ino;
6967                         dirent->name_len = 1;
6968                         dirent->name[0] = '.';
6969                         dirent->name[1] = '\0';
6970                         status = 1;
6971                         created = 1;
6972                 }
6973         }
6974         if (dirent->inode != ino) {
6975                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
6976                         dirent->inode = ino;
6977                         status = 1;
6978                 }
6979         }
6980         if (dirent->rec_len > 12) {
6981                 new_len = dirent->rec_len - 12;
6982                 if (new_len > 12) {
6983                         if (created ||
6984                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
6985                                 nextdir = (struct ext2_dir_entry *)
6986                                         ((char *) dirent + 12);
6987                                 dirent->rec_len = 12;
6988                                 nextdir->rec_len = new_len;
6989                                 nextdir->inode = 0;
6990                                 nextdir->name_len = 0;
6991                                 status = 1;
6992                         }
6993                 }
6994         }
6995         return status;
6996 }
6997
6998 /*
6999  * Make sure the second entry in the directory is '..', and that the
7000  * directory entry is sane.  We do not check the inode number of '..'
7001  * here; this gets done in pass 3.
7002  */
7003 static int check_dotdot(e2fsck_t ctx,
7004                         struct ext2_dir_entry *dirent,
7005                         struct dir_info *dir, struct problem_context *pctx)
7006 {
7007         int             problem = 0;
7008
7009         if (!dirent->inode)
7010                 problem = PR_2_MISSING_DOT_DOT;
7011         else if (((dirent->name_len & 0xFF) != 2) ||
7012                  (dirent->name[0] != '.') ||
7013                  (dirent->name[1] != '.'))
7014                 problem = PR_2_2ND_NOT_DOT_DOT;
7015         else if (dirent->name[2] != '\0')
7016                 problem = PR_2_DOT_DOT_NULL_TERM;
7017
7018         if (problem) {
7019                 if (fix_problem(ctx, problem, pctx)) {
7020                         if (dirent->rec_len < 12)
7021                                 dirent->rec_len = 12;
7022                         /*
7023                          * Note: we don't have the parent inode just
7024                          * yet, so we will fill it in with the root
7025                          * inode.  This will get fixed in pass 3.
7026                          */
7027                         dirent->inode = EXT2_ROOT_INO;
7028                         dirent->name_len = 2;
7029                         dirent->name[0] = '.';
7030                         dirent->name[1] = '.';
7031                         dirent->name[2] = '\0';
7032                         return 1;
7033                 }
7034                 return 0;
7035         }
7036         dir->dotdot = dirent->inode;
7037         return 0;
7038 }
7039
7040 /*
7041  * Check to make sure a directory entry doesn't contain any illegal
7042  * characters.
7043  */
7044 static int check_name(e2fsck_t ctx,
7045                       struct ext2_dir_entry *dirent,
7046                       struct problem_context *pctx)
7047 {
7048         int     i;
7049         int     fixup = -1;
7050         int     ret = 0;
7051
7052         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7053                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7054                         if (fixup < 0) {
7055                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7056                         }
7057                         if (fixup) {
7058                                 dirent->name[i] = '.';
7059                                 ret = 1;
7060                         }
7061                 }
7062         }
7063         return ret;
7064 }
7065
7066 /*
7067  * Check the directory filetype (if present)
7068  */
7069
7070 /*
7071  * Given a mode, return the ext2 file type
7072  */
7073 static int ext2_file_type(unsigned int mode)
7074 {
7075         if (LINUX_S_ISREG(mode))
7076                 return EXT2_FT_REG_FILE;
7077
7078         if (LINUX_S_ISDIR(mode))
7079                 return EXT2_FT_DIR;
7080
7081         if (LINUX_S_ISCHR(mode))
7082                 return EXT2_FT_CHRDEV;
7083
7084         if (LINUX_S_ISBLK(mode))
7085                 return EXT2_FT_BLKDEV;
7086
7087         if (LINUX_S_ISLNK(mode))
7088                 return EXT2_FT_SYMLINK;
7089
7090         if (LINUX_S_ISFIFO(mode))
7091                 return EXT2_FT_FIFO;
7092
7093         if (LINUX_S_ISSOCK(mode))
7094                 return EXT2_FT_SOCK;
7095
7096         return 0;
7097 }
7098
7099 static _INLINE_ int check_filetype(e2fsck_t ctx,
7100                                    struct ext2_dir_entry *dirent,
7101                                    struct problem_context *pctx)
7102 {
7103         int     filetype = dirent->name_len >> 8;
7104         int     should_be = EXT2_FT_UNKNOWN;
7105         struct ext2_inode       inode;
7106
7107         if (!(ctx->fs->super->s_feature_incompat &
7108               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7109                 if (filetype == 0 ||
7110                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7111                         return 0;
7112                 dirent->name_len = dirent->name_len & 0xFF;
7113                 return 1;
7114         }
7115
7116         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7117                 should_be = EXT2_FT_DIR;
7118         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7119                                             dirent->inode)) {
7120                 should_be = EXT2_FT_REG_FILE;
7121         } else if (ctx->inode_bad_map &&
7122                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7123                                             dirent->inode))
7124                 should_be = 0;
7125         else {
7126                 e2fsck_read_inode(ctx, dirent->inode, &inode,
7127                                   "check_filetype");
7128                 should_be = ext2_file_type(inode.i_mode);
7129         }
7130         if (filetype == should_be)
7131                 return 0;
7132         pctx->num = should_be;
7133
7134         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7135                         pctx) == 0)
7136                 return 0;
7137
7138         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7139         return 1;
7140 }
7141
7142 #ifdef ENABLE_HTREE
7143 static void parse_int_node(ext2_filsys fs,
7144                            struct ext2_db_entry *db,
7145                            struct check_dir_struct *cd,
7146                            struct dx_dir_info   *dx_dir,
7147                            char *block_buf)
7148 {
7149         struct          ext2_dx_root_info  *root;
7150         struct          ext2_dx_entry *ent;
7151         struct          ext2_dx_countlimit *limit;
7152         struct dx_dirblock_info *dx_db;
7153         int             i, expect_limit, count;
7154         blk_t           blk;
7155         ext2_dirhash_t  min_hash = 0xffffffff;
7156         ext2_dirhash_t  max_hash = 0;
7157         ext2_dirhash_t  hash = 0, prev_hash;
7158
7159         if (db->blockcnt == 0) {
7160                 root = (struct ext2_dx_root_info *) (block_buf + 24);
7161                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7162         } else {
7163                 ent = (struct ext2_dx_entry *) (block_buf+8);
7164         }
7165         limit = (struct ext2_dx_countlimit *) ent;
7166
7167         count = ext2fs_le16_to_cpu(limit->count);
7168         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7169                 sizeof(struct ext2_dx_entry);
7170         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7171                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7172                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7173                         goto clear_and_exit;
7174         }
7175         if (count > expect_limit) {
7176                 cd->pctx.num = count;
7177                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7178                         goto clear_and_exit;
7179                 count = expect_limit;
7180         }
7181
7182         for (i=0; i < count; i++) {
7183                 prev_hash = hash;
7184                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7185                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7186                 /* Check to make sure the block is valid */
7187                 if (blk > (blk_t) dx_dir->numblocks) {
7188                         cd->pctx.blk = blk;
7189                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7190                                         &cd->pctx))
7191                                 goto clear_and_exit;
7192                 }
7193                 if (hash < prev_hash &&
7194                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7195                         goto clear_and_exit;
7196                 dx_db = &dx_dir->dx_block[blk];
7197                 if (dx_db->flags & DX_FLAG_REFERENCED) {
7198                         dx_db->flags |= DX_FLAG_DUP_REF;
7199                 } else {
7200                         dx_db->flags |= DX_FLAG_REFERENCED;
7201                         dx_db->parent = db->blockcnt;
7202                 }
7203                 if (hash < min_hash)
7204                         min_hash = hash;
7205                 if (hash > max_hash)
7206                         max_hash = hash;
7207                 dx_db->node_min_hash = hash;
7208                 if ((i+1) < count)
7209                         dx_db->node_max_hash =
7210                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7211                 else {
7212                         dx_db->node_max_hash = 0xfffffffe;
7213                         dx_db->flags |= DX_FLAG_LAST;
7214                 }
7215                 if (i == 0)
7216                         dx_db->flags |= DX_FLAG_FIRST;
7217         }
7218         dx_db = &dx_dir->dx_block[db->blockcnt];
7219         dx_db->min_hash = min_hash;
7220         dx_db->max_hash = max_hash;
7221         return;
7222
7223 clear_and_exit:
7224         clear_htree(cd->ctx, cd->pctx.ino);
7225         dx_dir->numblocks = 0;
7226 }
7227 #endif /* ENABLE_HTREE */
7228
7229 /*
7230  * Given a busted directory, try to salvage it somehow.
7231  *
7232  */
7233 static void salvage_directory(ext2_filsys fs,
7234                               struct ext2_dir_entry *dirent,
7235                               struct ext2_dir_entry *prev,
7236                               unsigned int *offset)
7237 {
7238         char    *cp = (char *) dirent;
7239         int left = fs->blocksize - *offset - dirent->rec_len;
7240         int name_len = dirent->name_len & 0xFF;
7241
7242         /*
7243          * Special case of directory entry of size 8: copy what's left
7244          * of the directory block up to cover up the invalid hole.
7245          */
7246         if ((left >= 12) && (dirent->rec_len == 8)) {
7247                 memmove(cp, cp+8, left);
7248                 memset(cp + left, 0, 8);
7249                 return;
7250         }
7251         /*
7252          * If the directory entry overruns the end of the directory
7253          * block, and the name is small enough to fit, then adjust the
7254          * record length.
7255          */
7256         if ((left < 0) &&
7257             (name_len + 8 <= dirent->rec_len + left) &&
7258             dirent->inode <= fs->super->s_inodes_count &&
7259             strnlen(dirent->name, name_len) == name_len) {
7260                 dirent->rec_len += left;
7261                 return;
7262         }
7263         /*
7264          * If the directory entry is a multiple of four, so it is
7265          * valid, let the previous directory entry absorb the invalid
7266          * one.
7267          */
7268         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7269                 prev->rec_len += dirent->rec_len;
7270                 *offset += dirent->rec_len;
7271                 return;
7272         }
7273         /*
7274          * Default salvage method --- kill all of the directory
7275          * entries for the rest of the block.  We will either try to
7276          * absorb it into the previous directory entry, or create a
7277          * new empty directory entry the rest of the directory block.
7278          */
7279         if (prev) {
7280                 prev->rec_len += fs->blocksize - *offset;
7281                 *offset = fs->blocksize;
7282         } else {
7283                 dirent->rec_len = fs->blocksize - *offset;
7284                 dirent->name_len = 0;
7285                 dirent->inode = 0;
7286         }
7287 }
7288
7289 static int check_dir_block(ext2_filsys fs,
7290                            struct ext2_db_entry *db,
7291                            void *priv_data)
7292 {
7293         struct dir_info         *subdir, *dir;
7294         struct dx_dir_info      *dx_dir;
7295 #ifdef ENABLE_HTREE
7296         struct dx_dirblock_info *dx_db = 0;
7297 #endif /* ENABLE_HTREE */
7298         struct ext2_dir_entry   *dirent, *prev;
7299         ext2_dirhash_t          hash;
7300         unsigned int            offset = 0;
7301         int                     dir_modified = 0;
7302         int                     dot_state;
7303         blk_t                   block_nr = db->blk;
7304         ext2_ino_t              ino = db->ino;
7305         __u16                   links;
7306         struct check_dir_struct *cd;
7307         char                    *buf;
7308         e2fsck_t                ctx;
7309         int                     problem;
7310         struct ext2_dx_root_info *root;
7311         struct ext2_dx_countlimit *limit;
7312         static dict_t de_dict;
7313         struct problem_context  pctx;
7314         int     dups_found = 0;
7315
7316         cd = (struct check_dir_struct *) priv_data;
7317         buf = cd->buf;
7318         ctx = cd->ctx;
7319
7320         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7321                 return DIRENT_ABORT;
7322
7323         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7324                 return DIRENT_ABORT;
7325
7326         /*
7327          * Make sure the inode is still in use (could have been
7328          * deleted in the duplicate/bad blocks pass.
7329          */
7330         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7331                 return 0;
7332
7333         cd->pctx.ino = ino;
7334         cd->pctx.blk = block_nr;
7335         cd->pctx.blkcount = db->blockcnt;
7336         cd->pctx.ino2 = 0;
7337         cd->pctx.dirent = 0;
7338         cd->pctx.num = 0;
7339
7340         if (db->blk == 0) {
7341                 if (allocate_dir_block(ctx, db, &cd->pctx))
7342                         return 0;
7343                 block_nr = db->blk;
7344         }
7345
7346         if (db->blockcnt)
7347                 dot_state = 2;
7348         else
7349                 dot_state = 0;
7350
7351         if (ctx->dirs_to_hash &&
7352             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7353                 dups_found++;
7354
7355         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7356         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7357                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7358         if (cd->pctx.errcode) {
7359                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7360                         ctx->flags |= E2F_FLAG_ABORT;
7361                         return DIRENT_ABORT;
7362                 }
7363                 memset(buf, 0, fs->blocksize);
7364         }
7365 #ifdef ENABLE_HTREE
7366         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7367         if (dx_dir && dx_dir->numblocks) {
7368                 if (db->blockcnt >= dx_dir->numblocks) {
7369                         printf("XXX should never happen!!!\n");
7370                         abort();
7371                 }
7372                 dx_db = &dx_dir->dx_block[db->blockcnt];
7373                 dx_db->type = DX_DIRBLOCK_LEAF;
7374                 dx_db->phys = block_nr;
7375                 dx_db->min_hash = ~0;
7376                 dx_db->max_hash = 0;
7377
7378                 dirent = (struct ext2_dir_entry *) buf;
7379                 limit = (struct ext2_dx_countlimit *) (buf+8);
7380                 if (db->blockcnt == 0) {
7381                         root = (struct ext2_dx_root_info *) (buf + 24);
7382                         dx_db->type = DX_DIRBLOCK_ROOT;
7383                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7384                         if ((root->reserved_zero ||
7385                              root->info_length < 8 ||
7386                              root->indirect_levels > 1) &&
7387                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7388                                 clear_htree(ctx, ino);
7389                                 dx_dir->numblocks = 0;
7390                                 dx_db = 0;
7391                         }
7392                         dx_dir->hashversion = root->hash_version;
7393                         dx_dir->depth = root->indirect_levels + 1;
7394                 } else if ((dirent->inode == 0) &&
7395                            (dirent->rec_len == fs->blocksize) &&
7396                            (dirent->name_len == 0) &&
7397                            (ext2fs_le16_to_cpu(limit->limit) ==
7398                             ((fs->blocksize-8) /
7399                              sizeof(struct ext2_dx_entry))))
7400                         dx_db->type = DX_DIRBLOCK_NODE;
7401         }
7402 #endif /* ENABLE_HTREE */
7403
7404         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7405         prev = 0;
7406         do {
7407                 problem = 0;
7408                 dirent = (struct ext2_dir_entry *) (buf + offset);
7409                 cd->pctx.dirent = dirent;
7410                 cd->pctx.num = offset;
7411                 if (((offset + dirent->rec_len) > fs->blocksize) ||
7412                     (dirent->rec_len < 12) ||
7413                     ((dirent->rec_len % 4) != 0) ||
7414                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7415                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7416                                 salvage_directory(fs, dirent, prev, &offset);
7417                                 dir_modified++;
7418                                 continue;
7419                         } else
7420                                 goto abort_free_dict;
7421                 }
7422                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7423                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7424                                 dirent->name_len = EXT2_NAME_LEN;
7425                                 dir_modified++;
7426                         }
7427                 }
7428
7429                 if (dot_state == 0) {
7430                         if (check_dot(ctx, dirent, ino, &cd->pctx))
7431                                 dir_modified++;
7432                 } else if (dot_state == 1) {
7433                         dir = e2fsck_get_dir_info(ctx, ino);
7434                         if (!dir) {
7435                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7436                                 goto abort_free_dict;
7437                         }
7438                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7439                                 dir_modified++;
7440                 } else if (dirent->inode == ino) {
7441                         problem = PR_2_LINK_DOT;
7442                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7443                                 dirent->inode = 0;
7444                                 dir_modified++;
7445                                 goto next;
7446                         }
7447                 }
7448                 if (!dirent->inode)
7449                         goto next;
7450
7451                 /*
7452                  * Make sure the inode listed is a legal one.
7453                  */
7454                 if (((dirent->inode != EXT2_ROOT_INO) &&
7455                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
7456                     (dirent->inode > fs->super->s_inodes_count)) {
7457                         problem = PR_2_BAD_INO;
7458                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
7459                                                dirent->inode))) {
7460                         /*
7461                          * If the inode is unused, offer to clear it.
7462                          */
7463                         problem = PR_2_UNUSED_INODE;
7464                 } else if (ctx->inode_bb_map &&
7465                            (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
7466                                                      dirent->inode))) {
7467                         /*
7468                          * If the inode is in a bad block, offer to
7469                          * clear it.
7470                          */
7471                         problem = PR_2_BB_INODE;
7472                 } else if ((dot_state > 1) &&
7473                            ((dirent->name_len & 0xFF) == 1) &&
7474                            (dirent->name[0] == '.')) {
7475                         /*
7476                          * If there's a '.' entry in anything other
7477                          * than the first directory entry, it's a
7478                          * duplicate entry that should be removed.
7479                          */
7480                         problem = PR_2_DUP_DOT;
7481                 } else if ((dot_state > 1) &&
7482                            ((dirent->name_len & 0xFF) == 2) &&
7483                            (dirent->name[0] == '.') &&
7484                            (dirent->name[1] == '.')) {
7485                         /*
7486                          * If there's a '..' entry in anything other
7487                          * than the second directory entry, it's a
7488                          * duplicate entry that should be removed.
7489                          */
7490                         problem = PR_2_DUP_DOT_DOT;
7491                 } else if ((dot_state > 1) &&
7492                            (dirent->inode == EXT2_ROOT_INO)) {
7493                         /*
7494                          * Don't allow links to the root directory.
7495                          * We check this specially to make sure we
7496                          * catch this error case even if the root
7497                          * directory hasn't been created yet.
7498                          */
7499                         problem = PR_2_LINK_ROOT;
7500                 } else if ((dot_state > 1) &&
7501                            (dirent->name_len & 0xFF) == 0) {
7502                         /*
7503                          * Don't allow zero-length directory names.
7504                          */
7505                         problem = PR_2_NULL_NAME;
7506                 }
7507
7508                 if (problem) {
7509                         if (fix_problem(ctx, problem, &cd->pctx)) {
7510                                 dirent->inode = 0;
7511                                 dir_modified++;
7512                                 goto next;
7513                         } else {
7514                                 ext2fs_unmark_valid(fs);
7515                                 if (problem == PR_2_BAD_INO)
7516                                         goto next;
7517                         }
7518                 }
7519
7520                 /*
7521                  * If the inode was marked as having bad fields in
7522                  * pass1, process it and offer to fix/clear it.
7523                  * (We wait until now so that we can display the
7524                  * pathname to the user.)
7525                  */
7526                 if (ctx->inode_bad_map &&
7527                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7528                                              dirent->inode)) {
7529                         if (e2fsck_process_bad_inode(ctx, ino,
7530                                                      dirent->inode,
7531                                                      buf + fs->blocksize)) {
7532                                 dirent->inode = 0;
7533                                 dir_modified++;
7534                                 goto next;
7535                         }
7536                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7537                                 return DIRENT_ABORT;
7538                 }
7539
7540                 if (check_name(ctx, dirent, &cd->pctx))
7541                         dir_modified++;
7542
7543                 if (check_filetype(ctx, dirent, &cd->pctx))
7544                         dir_modified++;
7545
7546 #ifdef ENABLE_HTREE
7547                 if (dx_db) {
7548                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
7549                                        (dirent->name_len & 0xFF),
7550                                        fs->super->s_hash_seed, &hash, 0);
7551                         if (hash < dx_db->min_hash)
7552                                 dx_db->min_hash = hash;
7553                         if (hash > dx_db->max_hash)
7554                                 dx_db->max_hash = hash;
7555                 }
7556 #endif
7557
7558                 /*
7559                  * If this is a directory, then mark its parent in its
7560                  * dir_info structure.  If the parent field is already
7561                  * filled in, then this directory has more than one
7562                  * hard link.  We assume the first link is correct,
7563                  * and ask the user if he/she wants to clear this one.
7564                  */
7565                 if ((dot_state > 1) &&
7566                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
7567                                               dirent->inode))) {
7568                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
7569                         if (!subdir) {
7570                                 cd->pctx.ino = dirent->inode;
7571                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7572                                 goto abort_free_dict;
7573                         }
7574                         if (subdir->parent) {
7575                                 cd->pctx.ino2 = subdir->parent;
7576                                 if (fix_problem(ctx, PR_2_LINK_DIR,
7577                                                 &cd->pctx)) {
7578                                         dirent->inode = 0;
7579                                         dir_modified++;
7580                                         goto next;
7581                                 }
7582                                 cd->pctx.ino2 = 0;
7583                         } else
7584                                 subdir->parent = ino;
7585                 }
7586
7587                 if (dups_found) {
7588                         ;
7589                 } else if (dict_lookup(&de_dict, dirent)) {
7590                         clear_problem_context(&pctx);
7591                         pctx.ino = ino;
7592                         pctx.dirent = dirent;
7593                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
7594                         if (!ctx->dirs_to_hash)
7595                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
7596                         if (ctx->dirs_to_hash)
7597                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
7598                         dups_found++;
7599                 } else
7600                         dict_alloc_insert(&de_dict, dirent, dirent);
7601
7602                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
7603                                         &links);
7604                 if (links > 1)
7605                         ctx->fs_links_count++;
7606                 ctx->fs_total_count++;
7607         next:
7608                 prev = dirent;
7609                 offset += dirent->rec_len;
7610                 dot_state++;
7611         } while (offset < fs->blocksize);
7612 #ifdef ENABLE_HTREE
7613         if (dx_db) {
7614                 cd->pctx.dir = cd->pctx.ino;
7615                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
7616                     (dx_db->type == DX_DIRBLOCK_NODE))
7617                         parse_int_node(fs, db, cd, dx_dir, buf);
7618         }
7619 #endif /* ENABLE_HTREE */
7620         if (offset != fs->blocksize) {
7621                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
7622                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
7623                         dirent->rec_len = cd->pctx.num;
7624                         dir_modified++;
7625                 }
7626         }
7627         if (dir_modified) {
7628                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
7629                 if (cd->pctx.errcode) {
7630                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
7631                                          &cd->pctx))
7632                                 goto abort_free_dict;
7633                 }
7634                 ext2fs_mark_changed(fs);
7635         }
7636         dict_free_nodes(&de_dict);
7637         return 0;
7638 abort_free_dict:
7639         dict_free_nodes(&de_dict);
7640         ctx->flags |= E2F_FLAG_ABORT;
7641         return DIRENT_ABORT;
7642 }
7643
7644 /*
7645  * This function is called to deallocate a block, and is an interator
7646  * functioned called by deallocate inode via ext2fs_iterate_block().
7647  */
7648 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
7649                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
7650                                   blk_t ref_block FSCK_ATTR((unused)),
7651                                   int ref_offset FSCK_ATTR((unused)),
7652                                   void *priv_data)
7653 {
7654         e2fsck_t        ctx = (e2fsck_t) priv_data;
7655
7656         if (HOLE_BLKADDR(*block_nr))
7657                 return 0;
7658         if ((*block_nr < fs->super->s_first_data_block) ||
7659             (*block_nr >= fs->super->s_blocks_count))
7660                 return 0;
7661         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
7662         ext2fs_block_alloc_stats(fs, *block_nr, -1);
7663         return 0;
7664 }
7665
7666 /*
7667  * This fuction deallocates an inode
7668  */
7669 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
7670 {
7671         ext2_filsys fs = ctx->fs;
7672         struct ext2_inode       inode;
7673         struct problem_context  pctx;
7674         __u32                   count;
7675
7676         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
7677         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
7678         inode.i_links_count = 0;
7679         inode.i_dtime = time(0);
7680         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
7681         clear_problem_context(&pctx);
7682         pctx.ino = ino;
7683
7684         /*
7685          * Fix up the bitmaps...
7686          */
7687         e2fsck_read_bitmaps(ctx);
7688         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
7689         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
7690         if (ctx->inode_bad_map)
7691                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
7692         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
7693
7694         if (inode.i_file_acl &&
7695             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
7696                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
7697                                                    block_buf, -1, &count);
7698                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
7699                         pctx.errcode = 0;
7700                         count = 1;
7701                 }
7702                 if (pctx.errcode) {
7703                         pctx.blk = inode.i_file_acl;
7704                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
7705                         ctx->flags |= E2F_FLAG_ABORT;
7706                         return;
7707                 }
7708                 if (count == 0) {
7709                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
7710                                                    inode.i_file_acl);
7711                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
7712                 }
7713                 inode.i_file_acl = 0;
7714         }
7715
7716         if (!ext2fs_inode_has_valid_blocks(&inode))
7717                 return;
7718
7719         if (LINUX_S_ISREG(inode.i_mode) &&
7720             (inode.i_size_high || inode.i_size & 0x80000000UL))
7721                 ctx->large_files--;
7722
7723         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7724                                             deallocate_inode_block, ctx);
7725         if (pctx.errcode) {
7726                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
7727                 ctx->flags |= E2F_FLAG_ABORT;
7728                 return;
7729         }
7730 }
7731
7732 /*
7733  * This fuction clears the htree flag on an inode
7734  */
7735 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
7736 {
7737         struct ext2_inode       inode;
7738
7739         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
7740         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
7741         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
7742         if (ctx->dirs_to_hash)
7743                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
7744 }
7745
7746
7747 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
7748                                     ext2_ino_t ino, char *buf)
7749 {
7750         ext2_filsys fs = ctx->fs;
7751         struct ext2_inode       inode;
7752         int                     inode_modified = 0;
7753         int                     not_fixed = 0;
7754         unsigned char           *frag, *fsize;
7755         struct problem_context  pctx;
7756         int     problem = 0;
7757
7758         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
7759
7760         clear_problem_context(&pctx);
7761         pctx.ino = ino;
7762         pctx.dir = dir;
7763         pctx.inode = &inode;
7764
7765         if (inode.i_file_acl &&
7766             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
7767             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
7768                 inode.i_file_acl = 0;
7769 #ifdef EXT2FS_ENABLE_SWAPFS
7770                 /*
7771                  * This is a special kludge to deal with long symlinks
7772                  * on big endian systems.  i_blocks had already been
7773                  * decremented earlier in pass 1, but since i_file_acl
7774                  * hadn't yet been cleared, ext2fs_read_inode()
7775                  * assumed that the file was short symlink and would
7776                  * not have byte swapped i_block[0].  Hence, we have
7777                  * to byte-swap it here.
7778                  */
7779                 if (LINUX_S_ISLNK(inode.i_mode) &&
7780                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
7781                     (inode.i_blocks == fs->blocksize >> 9))
7782                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
7783 #endif
7784                 inode_modified++;
7785         } else
7786                 not_fixed++;
7787
7788         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
7789             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
7790             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
7791             !(LINUX_S_ISSOCK(inode.i_mode)))
7792                 problem = PR_2_BAD_MODE;
7793         else if (LINUX_S_ISCHR(inode.i_mode)
7794                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7795                 problem = PR_2_BAD_CHAR_DEV;
7796         else if (LINUX_S_ISBLK(inode.i_mode)
7797                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7798                 problem = PR_2_BAD_BLOCK_DEV;
7799         else if (LINUX_S_ISFIFO(inode.i_mode)
7800                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7801                 problem = PR_2_BAD_FIFO;
7802         else if (LINUX_S_ISSOCK(inode.i_mode)
7803                  && !e2fsck_pass1_check_device_inode(fs, &inode))
7804                 problem = PR_2_BAD_SOCKET;
7805         else if (LINUX_S_ISLNK(inode.i_mode)
7806                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
7807                 problem = PR_2_INVALID_SYMLINK;
7808         }
7809
7810         if (problem) {
7811                 if (fix_problem(ctx, problem, &pctx)) {
7812                         deallocate_inode(ctx, ino, 0);
7813                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7814                                 return 0;
7815                         return 1;
7816                 } else
7817                         not_fixed++;
7818                 problem = 0;
7819         }
7820
7821         if (inode.i_faddr) {
7822                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
7823                         inode.i_faddr = 0;
7824                         inode_modified++;
7825                 } else
7826                         not_fixed++;
7827         }
7828
7829         switch (fs->super->s_creator_os) {
7830             case EXT2_OS_LINUX:
7831                 frag = &inode.osd2.linux2.l_i_frag;
7832                 fsize = &inode.osd2.linux2.l_i_fsize;
7833                 break;
7834             case EXT2_OS_HURD:
7835                 frag = &inode.osd2.hurd2.h_i_frag;
7836                 fsize = &inode.osd2.hurd2.h_i_fsize;
7837                 break;
7838             case EXT2_OS_MASIX:
7839                 frag = &inode.osd2.masix2.m_i_frag;
7840                 fsize = &inode.osd2.masix2.m_i_fsize;
7841                 break;
7842             default:
7843                 frag = fsize = 0;
7844         }
7845         if (frag && *frag) {
7846                 pctx.num = *frag;
7847                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
7848                         *frag = 0;
7849                         inode_modified++;
7850                 } else
7851                         not_fixed++;
7852                 pctx.num = 0;
7853         }
7854         if (fsize && *fsize) {
7855                 pctx.num = *fsize;
7856                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
7857                         *fsize = 0;
7858                         inode_modified++;
7859                 } else
7860                         not_fixed++;
7861                 pctx.num = 0;
7862         }
7863
7864         if (inode.i_file_acl &&
7865             ((inode.i_file_acl < fs->super->s_first_data_block) ||
7866              (inode.i_file_acl >= fs->super->s_blocks_count))) {
7867                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
7868                         inode.i_file_acl = 0;
7869                         inode_modified++;
7870                 } else
7871                         not_fixed++;
7872         }
7873         if (inode.i_dir_acl &&
7874             LINUX_S_ISDIR(inode.i_mode)) {
7875                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
7876                         inode.i_dir_acl = 0;
7877                         inode_modified++;
7878                 } else
7879                         not_fixed++;
7880         }
7881
7882         if (inode_modified)
7883                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
7884         if (!not_fixed)
7885                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
7886         return 0;
7887 }
7888
7889
7890 /*
7891  * allocate_dir_block --- this function allocates a new directory
7892  *      block for a particular inode; this is done if a directory has
7893  *      a "hole" in it, or if a directory has a illegal block number
7894  *      that was zeroed out and now needs to be replaced.
7895  */
7896 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
7897                               struct problem_context *pctx)
7898 {
7899         ext2_filsys fs = ctx->fs;
7900         blk_t                   blk;
7901         char                    *block;
7902         struct ext2_inode       inode;
7903
7904         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
7905                 return 1;
7906
7907         /*
7908          * Read the inode and block bitmaps in; we'll be messing with
7909          * them.
7910          */
7911         e2fsck_read_bitmaps(ctx);
7912
7913         /*
7914          * First, find a free block
7915          */
7916         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7917         if (pctx->errcode) {
7918                 pctx->str = "ext2fs_new_block";
7919                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
7920                 return 1;
7921         }
7922         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7923         ext2fs_mark_block_bitmap(fs->block_map, blk);
7924         ext2fs_mark_bb_dirty(fs);
7925
7926         /*
7927          * Now let's create the actual data block for the inode
7928          */
7929         if (db->blockcnt)
7930                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
7931         else
7932                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
7933                                                      EXT2_ROOT_INO, &block);
7934
7935         if (pctx->errcode) {
7936                 pctx->str = "ext2fs_new_dir_block";
7937                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
7938                 return 1;
7939         }
7940
7941         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
7942         ext2fs_free_mem(&block);
7943         if (pctx->errcode) {
7944                 pctx->str = "ext2fs_write_dir_block";
7945                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
7946                 return 1;
7947         }
7948
7949         /*
7950          * Update the inode block count
7951          */
7952         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
7953         inode.i_blocks += fs->blocksize / 512;
7954         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
7955                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
7956         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
7957
7958         /*
7959          * Finally, update the block pointers for the inode
7960          */
7961         db->blk = blk;
7962         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
7963                                       0, update_dir_block, db);
7964         if (pctx->errcode) {
7965                 pctx->str = "ext2fs_block_iterate";
7966                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
7967                 return 1;
7968         }
7969
7970         return 0;
7971 }
7972
7973 /*
7974  * This is a helper function for allocate_dir_block().
7975  */
7976 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
7977                             blk_t       *block_nr,
7978                             e2_blkcnt_t blockcnt,
7979                             blk_t ref_block FSCK_ATTR((unused)),
7980                             int ref_offset FSCK_ATTR((unused)),
7981                             void *priv_data)
7982 {
7983         struct ext2_db_entry *db;
7984
7985         db = (struct ext2_db_entry *) priv_data;
7986         if (db->blockcnt == (int) blockcnt) {
7987                 *block_nr = db->blk;
7988                 return BLOCK_CHANGED;
7989         }
7990         return 0;
7991 }
7992
7993 /*
7994  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
7995  *
7996  * Pass #3 assures that all directories are connected to the
7997  * filesystem tree, using the following algorithm:
7998  *
7999  * First, the root directory is checked to make sure it exists; if
8000  * not, e2fsck will offer to create a new one.  It is then marked as
8001  * "done".
8002  *
8003  * Then, pass3 interates over all directory inodes; for each directory
8004  * it attempts to trace up the filesystem tree, using dirinfo.parent
8005  * until it reaches a directory which has been marked "done".  If it
8006  * can not do so, then the directory must be disconnected, and e2fsck
8007  * will offer to reconnect it to /lost+found.  While it is chasing
8008  * parent pointers up the filesystem tree, if pass3 sees a directory
8009  * twice, then it has detected a filesystem loop, and it will again
8010  * offer to reconnect the directory to /lost+found in to break the
8011  * filesystem loop.
8012  *
8013  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8014  * reconnect inodes to /lost+found; this subroutine is also used by
8015  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
8016  * is responsible for creating /lost+found if it does not exist.
8017  *
8018  * Pass 3 frees the following data structures:
8019  *      - The dirinfo directory information cache.
8020  */
8021
8022 static void check_root(e2fsck_t ctx);
8023 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8024                            struct problem_context *pctx);
8025 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8026
8027 static ext2fs_inode_bitmap inode_loop_detect;
8028 static ext2fs_inode_bitmap inode_done_map;
8029
8030 static void e2fsck_pass3(e2fsck_t ctx)
8031 {
8032         ext2_filsys fs = ctx->fs;
8033         int             i;
8034         struct problem_context  pctx;
8035         struct dir_info *dir;
8036         unsigned long maxdirs, count;
8037
8038         clear_problem_context(&pctx);
8039
8040         /* Pass 3 */
8041
8042         if (!(ctx->options & E2F_OPT_PREEN))
8043                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8044
8045         /*
8046          * Allocate some bitmaps to do loop detection.
8047          */
8048         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8049                                                     &inode_done_map);
8050         if (pctx.errcode) {
8051                 pctx.num = 2;
8052                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8053                 ctx->flags |= E2F_FLAG_ABORT;
8054                 goto abort_exit;
8055         }
8056         check_root(ctx);
8057         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8058                 goto abort_exit;
8059
8060         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8061
8062         maxdirs = e2fsck_get_num_dirinfo(ctx);
8063         count = 1;
8064
8065         if (ctx->progress)
8066                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8067                         goto abort_exit;
8068
8069         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8070                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8071                         goto abort_exit;
8072                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8073                         goto abort_exit;
8074                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8075                         if (check_directory(ctx, dir, &pctx))
8076                                 goto abort_exit;
8077         }
8078
8079         /*
8080          * Force the creation of /lost+found if not present
8081          */
8082         if ((ctx->flags & E2F_OPT_READONLY) == 0)
8083                 e2fsck_get_lost_and_found(ctx, 1);
8084
8085         /*
8086          * If there are any directories that need to be indexed or
8087          * optimized, do it here.
8088          */
8089         e2fsck_rehash_directories(ctx);
8090
8091 abort_exit:
8092         e2fsck_free_dir_info(ctx);
8093         ext2fs_free_inode_bitmap(inode_loop_detect);
8094         inode_loop_detect = 0;
8095         ext2fs_free_inode_bitmap(inode_done_map);
8096         inode_done_map = 0;
8097 }
8098
8099 /*
8100  * This makes sure the root inode is present; if not, we ask if the
8101  * user wants us to create it.  Not creating it is a fatal error.
8102  */
8103 static void check_root(e2fsck_t ctx)
8104 {
8105         ext2_filsys fs = ctx->fs;
8106         blk_t                   blk;
8107         struct ext2_inode       inode;
8108         char *                  block;
8109         struct problem_context  pctx;
8110
8111         clear_problem_context(&pctx);
8112
8113         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8114                 /*
8115                  * If the root inode is not a directory, die here.  The
8116                  * user must have answered 'no' in pass1 when we
8117                  * offered to clear it.
8118                  */
8119                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8120                                                EXT2_ROOT_INO))) {
8121                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8122                         ctx->flags |= E2F_FLAG_ABORT;
8123                 }
8124                 return;
8125         }
8126
8127         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8128                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8129                 ctx->flags |= E2F_FLAG_ABORT;
8130                 return;
8131         }
8132
8133         e2fsck_read_bitmaps(ctx);
8134
8135         /*
8136          * First, find a free block
8137          */
8138         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8139         if (pctx.errcode) {
8140                 pctx.str = "ext2fs_new_block";
8141                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8142                 ctx->flags |= E2F_FLAG_ABORT;
8143                 return;
8144         }
8145         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8146         ext2fs_mark_block_bitmap(fs->block_map, blk);
8147         ext2fs_mark_bb_dirty(fs);
8148
8149         /*
8150          * Now let's create the actual data block for the inode
8151          */
8152         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8153                                             &block);
8154         if (pctx.errcode) {
8155                 pctx.str = "ext2fs_new_dir_block";
8156                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8157                 ctx->flags |= E2F_FLAG_ABORT;
8158                 return;
8159         }
8160
8161         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8162         if (pctx.errcode) {
8163                 pctx.str = "ext2fs_write_dir_block";
8164                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8165                 ctx->flags |= E2F_FLAG_ABORT;
8166                 return;
8167         }
8168         ext2fs_free_mem(&block);
8169
8170         /*
8171          * Set up the inode structure
8172          */
8173         memset(&inode, 0, sizeof(inode));
8174         inode.i_mode = 040755;
8175         inode.i_size = fs->blocksize;
8176         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8177         inode.i_links_count = 2;
8178         inode.i_blocks = fs->blocksize / 512;
8179         inode.i_block[0] = blk;
8180
8181         /*
8182          * Write out the inode.
8183          */
8184         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8185         if (pctx.errcode) {
8186                 pctx.str = "ext2fs_write_inode";
8187                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8188                 ctx->flags |= E2F_FLAG_ABORT;
8189                 return;
8190         }
8191
8192         /*
8193          * Miscellaneous bookkeeping...
8194          */
8195         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8196         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8197         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8198
8199         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8200         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8201         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8202         ext2fs_mark_ib_dirty(fs);
8203 }
8204
8205 /*
8206  * This subroutine is responsible for making sure that a particular
8207  * directory is connected to the root; if it isn't we trace it up as
8208  * far as we can go, and then offer to connect the resulting parent to
8209  * the lost+found.  We have to do loop detection; if we ever discover
8210  * a loop, we treat that as a disconnected directory and offer to
8211  * reparent it to lost+found.
8212  *
8213  * However, loop detection is expensive, because for very large
8214  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8215  * is non-trivial.  Loops in filesystems are also a rare error case,
8216  * and we shouldn't optimize for error cases.  So we try two passes of
8217  * the algorithm.  The first time, we ignore loop detection and merely
8218  * increment a counter; if the counter exceeds some extreme threshold,
8219  * then we try again with the loop detection bitmap enabled.
8220  */
8221 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8222                            struct problem_context *pctx)
8223 {
8224         ext2_filsys     fs = ctx->fs;
8225         struct dir_info *p = dir;
8226         int             loop_pass = 0, parent_count = 0;
8227
8228         if (!p)
8229                 return 0;
8230
8231         while (1) {
8232                 /*
8233                  * Mark this inode as being "done"; by the time we
8234                  * return from this function, the inode we either be
8235                  * verified as being connected to the directory tree,
8236                  * or we will have offered to reconnect this to
8237                  * lost+found.
8238                  *
8239                  * If it was marked done already, then we've reached a
8240                  * parent we've already checked.
8241                  */
8242                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8243                         break;
8244
8245                 /*
8246                  * If this directory doesn't have a parent, or we've
8247                  * seen the parent once already, then offer to
8248                  * reparent it to lost+found
8249                  */
8250                 if (!p->parent ||
8251                     (loop_pass &&
8252                      (ext2fs_test_inode_bitmap(inode_loop_detect,
8253                                               p->parent)))) {
8254                         pctx->ino = p->ino;
8255                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8256                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
8257                                         ext2fs_unmark_valid(fs);
8258                                 else {
8259                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
8260                                         p->parent = ctx->lost_and_found;
8261                                         fix_dotdot(ctx, p, ctx->lost_and_found);
8262                                 }
8263                         }
8264                         break;
8265                 }
8266                 p = e2fsck_get_dir_info(ctx, p->parent);
8267                 if (!p) {
8268                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8269                         return 0;
8270                 }
8271                 if (loop_pass) {
8272                         ext2fs_mark_inode_bitmap(inode_loop_detect,
8273                                                  p->ino);
8274                 } else if (parent_count++ > 2048) {
8275                         /*
8276                          * If we've run into a path depth that's
8277                          * greater than 2048, try again with the inode
8278                          * loop bitmap turned on and start from the
8279                          * top.
8280                          */
8281                         loop_pass = 1;
8282                         if (inode_loop_detect)
8283                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
8284                         else {
8285                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8286                                 if (pctx->errcode) {
8287                                         pctx->num = 1;
8288                                         fix_problem(ctx,
8289                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8290                                         ctx->flags |= E2F_FLAG_ABORT;
8291                                         return -1;
8292                                 }
8293                         }
8294                         p = dir;
8295                 }
8296         }
8297
8298         /*
8299          * Make sure that .. and the parent directory are the same;
8300          * offer to fix it if not.
8301          */
8302         if (dir->parent != dir->dotdot) {
8303                 pctx->ino = dir->ino;
8304                 pctx->ino2 = dir->dotdot;
8305                 pctx->dir = dir->parent;
8306                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8307                         fix_dotdot(ctx, dir, dir->parent);
8308         }
8309         return 0;
8310 }
8311
8312 /*
8313  * This routine gets the lost_and_found inode, making it a directory
8314  * if necessary
8315  */
8316 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8317 {
8318         ext2_filsys fs = ctx->fs;
8319         ext2_ino_t                      ino;
8320         blk_t                   blk;
8321         errcode_t               retval;
8322         struct ext2_inode       inode;
8323         char *                  block;
8324         static const char       name[] = "lost+found";
8325         struct  problem_context pctx;
8326         struct dir_info         *dirinfo;
8327
8328         if (ctx->lost_and_found)
8329                 return ctx->lost_and_found;
8330
8331         clear_problem_context(&pctx);
8332
8333         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8334                                sizeof(name)-1, 0, &ino);
8335         if (retval && !fix)
8336                 return 0;
8337         if (!retval) {
8338                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8339                         ctx->lost_and_found = ino;
8340                         return ino;
8341                 }
8342
8343                 /* Lost+found isn't a directory! */
8344                 if (!fix)
8345                         return 0;
8346                 pctx.ino = ino;
8347                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8348                         return 0;
8349
8350                 /* OK, unlink the old /lost+found file. */
8351                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8352                 if (pctx.errcode) {
8353                         pctx.str = "ext2fs_unlink";
8354                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8355                         return 0;
8356                 }
8357                 dirinfo = e2fsck_get_dir_info(ctx, ino);
8358                 if (dirinfo)
8359                         dirinfo->parent = 0;
8360                 e2fsck_adjust_inode_count(ctx, ino, -1);
8361         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8362                 pctx.errcode = retval;
8363                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8364         }
8365         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8366                 return 0;
8367
8368         /*
8369          * Read the inode and block bitmaps in; we'll be messing with
8370          * them.
8371          */
8372         e2fsck_read_bitmaps(ctx);
8373
8374         /*
8375          * First, find a free block
8376          */
8377         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8378         if (retval) {
8379                 pctx.errcode = retval;
8380                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8381                 return 0;
8382         }
8383         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8384         ext2fs_block_alloc_stats(fs, blk, +1);
8385
8386         /*
8387          * Next find a free inode.
8388          */
8389         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8390                                   ctx->inode_used_map, &ino);
8391         if (retval) {
8392                 pctx.errcode = retval;
8393                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8394                 return 0;
8395         }
8396         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8397         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8398         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8399
8400         /*
8401          * Now let's create the actual data block for the inode
8402          */
8403         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8404         if (retval) {
8405                 pctx.errcode = retval;
8406                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8407                 return 0;
8408         }
8409
8410         retval = ext2fs_write_dir_block(fs, blk, block);
8411         ext2fs_free_mem(&block);
8412         if (retval) {
8413                 pctx.errcode = retval;
8414                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
8415                 return 0;
8416         }
8417
8418         /*
8419          * Set up the inode structure
8420          */
8421         memset(&inode, 0, sizeof(inode));
8422         inode.i_mode = 040700;
8423         inode.i_size = fs->blocksize;
8424         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8425         inode.i_links_count = 2;
8426         inode.i_blocks = fs->blocksize / 512;
8427         inode.i_block[0] = blk;
8428
8429         /*
8430          * Next, write out the inode.
8431          */
8432         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
8433         if (pctx.errcode) {
8434                 pctx.str = "ext2fs_write_inode";
8435                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8436                 return 0;
8437         }
8438         /*
8439          * Finally, create the directory link
8440          */
8441         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
8442         if (pctx.errcode) {
8443                 pctx.str = "ext2fs_link";
8444                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8445                 return 0;
8446         }
8447
8448         /*
8449          * Miscellaneous bookkeeping that needs to be kept straight.
8450          */
8451         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
8452         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
8453         ext2fs_icount_store(ctx->inode_count, ino, 2);
8454         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
8455         ctx->lost_and_found = ino;
8456         return ino;
8457 }
8458
8459 /*
8460  * This routine will connect a file to lost+found
8461  */
8462 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
8463 {
8464         ext2_filsys fs = ctx->fs;
8465         errcode_t       retval;
8466         char            name[80];
8467         struct problem_context  pctx;
8468         struct ext2_inode       inode;
8469         int             file_type = 0;
8470
8471         clear_problem_context(&pctx);
8472         pctx.ino = ino;
8473
8474         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
8475                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
8476                         ctx->bad_lost_and_found++;
8477         }
8478         if (ctx->bad_lost_and_found) {
8479                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
8480                 return 1;
8481         }
8482
8483         sprintf(name, "#%u", ino);
8484         if (ext2fs_read_inode(fs, ino, &inode) == 0)
8485                 file_type = ext2_file_type(inode.i_mode);
8486         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
8487         if (retval == EXT2_ET_DIR_NO_SPACE) {
8488                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
8489                         return 1;
8490                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
8491                                                  1, 0);
8492                 if (retval) {
8493                         pctx.errcode = retval;
8494                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
8495                         return 1;
8496                 }
8497                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
8498                                      ino, file_type);
8499         }
8500         if (retval) {
8501                 pctx.errcode = retval;
8502                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
8503                 return 1;
8504         }
8505         e2fsck_adjust_inode_count(ctx, ino, 1);
8506
8507         return 0;
8508 }
8509
8510 /*
8511  * Utility routine to adjust the inode counts on an inode.
8512  */
8513 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
8514 {
8515         ext2_filsys fs = ctx->fs;
8516         errcode_t               retval;
8517         struct ext2_inode       inode;
8518
8519         if (!ino)
8520                 return 0;
8521
8522         retval = ext2fs_read_inode(fs, ino, &inode);
8523         if (retval)
8524                 return retval;
8525
8526         if (adj == 1) {
8527                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
8528                 if (inode.i_links_count == (__u16) ~0)
8529                         return 0;
8530                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
8531                 inode.i_links_count++;
8532         } else if (adj == -1) {
8533                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
8534                 if (inode.i_links_count == 0)
8535                         return 0;
8536                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
8537                 inode.i_links_count--;
8538         }
8539
8540         retval = ext2fs_write_inode(fs, ino, &inode);
8541         if (retval)
8542                 return retval;
8543
8544         return 0;
8545 }
8546
8547 /*
8548  * Fix parent --- this routine fixes up the parent of a directory.
8549  */
8550 struct fix_dotdot_struct {
8551         ext2_filsys     fs;
8552         ext2_ino_t      parent;
8553         int             done;
8554         e2fsck_t        ctx;
8555 };
8556
8557 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
8558                            int  offset FSCK_ATTR((unused)),
8559                            int  blocksize FSCK_ATTR((unused)),
8560                            char *buf FSCK_ATTR((unused)),
8561                            void *priv_data)
8562 {
8563         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
8564         errcode_t       retval;
8565         struct problem_context pctx;
8566
8567         if ((dirent->name_len & 0xFF) != 2)
8568                 return 0;
8569         if (strncmp(dirent->name, "..", 2))
8570                 return 0;
8571
8572         clear_problem_context(&pctx);
8573
8574         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
8575         if (retval) {
8576                 pctx.errcode = retval;
8577                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
8578         }
8579         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
8580         if (retval) {
8581                 pctx.errcode = retval;
8582                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
8583         }
8584         dirent->inode = fp->parent;
8585
8586         fp->done++;
8587         return DIRENT_ABORT | DIRENT_CHANGED;
8588 }
8589
8590 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
8591 {
8592         ext2_filsys fs = ctx->fs;
8593         errcode_t       retval;
8594         struct fix_dotdot_struct fp;
8595         struct problem_context pctx;
8596
8597         fp.fs = fs;
8598         fp.parent = parent;
8599         fp.done = 0;
8600         fp.ctx = ctx;
8601
8602         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
8603                                     0, fix_dotdot_proc, &fp);
8604         if (retval || !fp.done) {
8605                 clear_problem_context(&pctx);
8606                 pctx.ino = dir->ino;
8607                 pctx.errcode = retval;
8608                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
8609                             PR_3_FIX_PARENT_NOFIND, &pctx);
8610                 ext2fs_unmark_valid(fs);
8611         }
8612         dir->dotdot = parent;
8613
8614         return;
8615 }
8616
8617 /*
8618  * These routines are responsible for expanding a /lost+found if it is
8619  * too small.
8620  */
8621
8622 struct expand_dir_struct {
8623         int                     num;
8624         int                     guaranteed_size;
8625         int                     newblocks;
8626         int                     last_block;
8627         errcode_t               err;
8628         e2fsck_t                ctx;
8629 };
8630
8631 static int expand_dir_proc(ext2_filsys fs,
8632                            blk_t        *blocknr,
8633                            e2_blkcnt_t  blockcnt,
8634                            blk_t ref_block FSCK_ATTR((unused)),
8635                            int ref_offset FSCK_ATTR((unused)),
8636                            void *priv_data)
8637 {
8638         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
8639         blk_t   new_blk;
8640         static blk_t    last_blk = 0;
8641         char            *block;
8642         errcode_t       retval;
8643         e2fsck_t        ctx;
8644
8645         ctx = es->ctx;
8646
8647         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
8648                 return BLOCK_ABORT;
8649
8650         if (blockcnt > 0)
8651                 es->last_block = blockcnt;
8652         if (*blocknr) {
8653                 last_blk = *blocknr;
8654                 return 0;
8655         }
8656         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
8657                                   &new_blk);
8658         if (retval) {
8659                 es->err = retval;
8660                 return BLOCK_ABORT;
8661         }
8662         if (blockcnt > 0) {
8663                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
8664                 if (retval) {
8665                         es->err = retval;
8666                         return BLOCK_ABORT;
8667                 }
8668                 es->num--;
8669                 retval = ext2fs_write_dir_block(fs, new_blk, block);
8670         } else {
8671                 retval = ext2fs_get_mem(fs->blocksize, &block);
8672                 if (retval) {
8673                         es->err = retval;
8674                         return BLOCK_ABORT;
8675                 }
8676                 memset(block, 0, fs->blocksize);
8677                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
8678         }
8679         if (retval) {
8680                 es->err = retval;
8681                 return BLOCK_ABORT;
8682         }
8683         ext2fs_free_mem(&block);
8684         *blocknr = new_blk;
8685         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
8686         ext2fs_block_alloc_stats(fs, new_blk, +1);
8687         es->newblocks++;
8688
8689         if (es->num == 0)
8690                 return (BLOCK_CHANGED | BLOCK_ABORT);
8691         else
8692                 return BLOCK_CHANGED;
8693 }
8694
8695 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
8696                                   int num, int guaranteed_size)
8697 {
8698         ext2_filsys fs = ctx->fs;
8699         errcode_t       retval;
8700         struct expand_dir_struct es;
8701         struct ext2_inode       inode;
8702
8703         if (!(fs->flags & EXT2_FLAG_RW))
8704                 return EXT2_ET_RO_FILSYS;
8705
8706         /*
8707          * Read the inode and block bitmaps in; we'll be messing with
8708          * them.
8709          */
8710         e2fsck_read_bitmaps(ctx);
8711
8712         retval = ext2fs_check_directory(fs, dir);
8713         if (retval)
8714                 return retval;
8715
8716         es.num = num;
8717         es.guaranteed_size = guaranteed_size;
8718         es.last_block = 0;
8719         es.err = 0;
8720         es.newblocks = 0;
8721         es.ctx = ctx;
8722
8723         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
8724                                        0, expand_dir_proc, &es);
8725
8726         if (es.err)
8727                 return es.err;
8728
8729         /*
8730          * Update the size and block count fields in the inode.
8731          */
8732         retval = ext2fs_read_inode(fs, dir, &inode);
8733         if (retval)
8734                 return retval;
8735
8736         inode.i_size = (es.last_block + 1) * fs->blocksize;
8737         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
8738
8739         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
8740
8741         return 0;
8742 }
8743
8744 /*
8745  * pass4.c -- pass #4 of e2fsck: Check reference counts
8746  *
8747  * Pass 4 frees the following data structures:
8748  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
8749  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
8750  */
8751
8752 /*
8753  * This routine is called when an inode is not connected to the
8754  * directory tree.
8755  *
8756  * This subroutine returns 1 then the caller shouldn't bother with the
8757  * rest of the pass 4 tests.
8758  */
8759 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
8760 {
8761         ext2_filsys fs = ctx->fs;
8762         struct ext2_inode       inode;
8763         struct problem_context  pctx;
8764
8765         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
8766         clear_problem_context(&pctx);
8767         pctx.ino = i;
8768         pctx.inode = &inode;
8769
8770         /*
8771          * Offer to delete any zero-length files that does not have
8772          * blocks.  If there is an EA block, it might have useful
8773          * information, so we won't prompt to delete it, but let it be
8774          * reconnected to lost+found.
8775          */
8776         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
8777                                 LINUX_S_ISDIR(inode.i_mode))) {
8778                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
8779                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
8780                         inode.i_links_count = 0;
8781                         inode.i_dtime = time(0);
8782                         e2fsck_write_inode(ctx, i, &inode,
8783                                            "disconnect_inode");
8784                         /*
8785                          * Fix up the bitmaps...
8786                          */
8787                         e2fsck_read_bitmaps(ctx);
8788                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
8789                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
8790                         ext2fs_inode_alloc_stats2(fs, i, -1,
8791                                                   LINUX_S_ISDIR(inode.i_mode));
8792                         return 0;
8793                 }
8794         }
8795
8796         /*
8797          * Prompt to reconnect.
8798          */
8799         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
8800                 if (e2fsck_reconnect_file(ctx, i))
8801                         ext2fs_unmark_valid(fs);
8802         } else {
8803                 /*
8804                  * If we don't attach the inode, then skip the
8805                  * i_links_test since there's no point in trying to
8806                  * force i_links_count to zero.
8807                  */
8808                 ext2fs_unmark_valid(fs);
8809                 return 1;
8810         }
8811         return 0;
8812 }
8813
8814
8815 static void e2fsck_pass4(e2fsck_t ctx)
8816 {
8817         ext2_filsys fs = ctx->fs;
8818         ext2_ino_t      i;
8819         struct ext2_inode       inode;
8820         struct problem_context  pctx;
8821         __u16   link_count, link_counted;
8822         char    *buf = 0;
8823         int     group, maxgroup;
8824
8825         /* Pass 4 */
8826
8827         clear_problem_context(&pctx);
8828
8829         if (!(ctx->options & E2F_OPT_PREEN))
8830                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
8831
8832         group = 0;
8833         maxgroup = fs->group_desc_count;
8834         if (ctx->progress)
8835                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
8836                         return;
8837
8838         for (i=1; i <= fs->super->s_inodes_count; i++) {
8839                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8840                         return;
8841                 if ((i % fs->super->s_inodes_per_group) == 0) {
8842                         group++;
8843                         if (ctx->progress)
8844                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
8845                                         return;
8846                 }
8847                 if (i == EXT2_BAD_INO ||
8848                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
8849                         continue;
8850                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
8851                     (ctx->inode_imagic_map &&
8852                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
8853                     (ctx->inode_bb_map &&
8854                      ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
8855                         continue;
8856                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
8857                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
8858                 if (link_counted == 0) {
8859                         if (!buf)
8860                                 buf = e2fsck_allocate_memory(ctx,
8861                                      fs->blocksize, "bad_inode buffer");
8862                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
8863                                 continue;
8864                         if (disconnect_inode(ctx, i))
8865                                 continue;
8866                         ext2fs_icount_fetch(ctx->inode_link_info, i,
8867                                             &link_count);
8868                         ext2fs_icount_fetch(ctx->inode_count, i,
8869                                             &link_counted);
8870                 }
8871                 if (link_counted != link_count) {
8872                         e2fsck_read_inode(ctx, i, &inode, "pass4");
8873                         pctx.ino = i;
8874                         pctx.inode = &inode;
8875                         if (link_count != inode.i_links_count) {
8876                                 pctx.num = link_count;
8877                                 fix_problem(ctx,
8878                                             PR_4_INCONSISTENT_COUNT, &pctx);
8879                         }
8880                         pctx.num = link_counted;
8881                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
8882                                 inode.i_links_count = link_counted;
8883                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
8884                         }
8885                 }
8886         }
8887         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
8888         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
8889         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
8890         ctx->inode_bb_map = 0;
8891         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
8892         ctx->inode_imagic_map = 0;
8893         ext2fs_free_mem(&buf);
8894 }
8895
8896 /*
8897  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
8898  */
8899
8900 #define NO_BLK ((blk_t) -1)
8901
8902 static void print_bitmap_problem(e2fsck_t ctx, int problem,
8903                             struct problem_context *pctx)
8904 {
8905         switch (problem) {
8906         case PR_5_BLOCK_UNUSED:
8907                 if (pctx->blk == pctx->blk2)
8908                         pctx->blk2 = 0;
8909                 else
8910                         problem = PR_5_BLOCK_RANGE_UNUSED;
8911                 break;
8912         case PR_5_BLOCK_USED:
8913                 if (pctx->blk == pctx->blk2)
8914                         pctx->blk2 = 0;
8915                 else
8916                         problem = PR_5_BLOCK_RANGE_USED;
8917                 break;
8918         case PR_5_INODE_UNUSED:
8919                 if (pctx->ino == pctx->ino2)
8920                         pctx->ino2 = 0;
8921                 else
8922                         problem = PR_5_INODE_RANGE_UNUSED;
8923                 break;
8924         case PR_5_INODE_USED:
8925                 if (pctx->ino == pctx->ino2)
8926                         pctx->ino2 = 0;
8927                 else
8928                         problem = PR_5_INODE_RANGE_USED;
8929                 break;
8930         }
8931         fix_problem(ctx, problem, pctx);
8932         pctx->blk = pctx->blk2 = NO_BLK;
8933         pctx->ino = pctx->ino2 = 0;
8934 }
8935
8936 static void check_block_bitmaps(e2fsck_t ctx)
8937 {
8938         ext2_filsys fs = ctx->fs;
8939         blk_t   i;
8940         int     *free_array;
8941         int     group = 0;
8942         unsigned int    blocks = 0;
8943         unsigned int    free_blocks = 0;
8944         int     group_free = 0;
8945         int     actual, bitmap;
8946         struct problem_context  pctx;
8947         int     problem, save_problem, fixit, had_problem;
8948         errcode_t       retval;
8949
8950         clear_problem_context(&pctx);
8951         free_array = (int *) e2fsck_allocate_memory(ctx,
8952             fs->group_desc_count * sizeof(int), "free block count array");
8953
8954         if ((fs->super->s_first_data_block <
8955              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
8956             (fs->super->s_blocks_count-1 >
8957              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
8958                 pctx.num = 1;
8959                 pctx.blk = fs->super->s_first_data_block;
8960                 pctx.blk2 = fs->super->s_blocks_count -1;
8961                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
8962                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
8963                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
8964
8965                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8966                 return;
8967         }
8968
8969         if ((fs->super->s_first_data_block <
8970              ext2fs_get_block_bitmap_start(fs->block_map)) ||
8971             (fs->super->s_blocks_count-1 >
8972              ext2fs_get_block_bitmap_end(fs->block_map))) {
8973                 pctx.num = 2;
8974                 pctx.blk = fs->super->s_first_data_block;
8975                 pctx.blk2 = fs->super->s_blocks_count -1;
8976                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
8977                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
8978                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
8979
8980                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8981                 return;
8982         }
8983
8984 redo_counts:
8985         had_problem = 0;
8986         save_problem = 0;
8987         pctx.blk = pctx.blk2 = NO_BLK;
8988         for (i = fs->super->s_first_data_block;
8989              i < fs->super->s_blocks_count;
8990              i++) {
8991                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
8992                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
8993
8994                 if (actual == bitmap)
8995                         goto do_counts;
8996
8997                 if (!actual && bitmap) {
8998                         /*
8999                          * Block not used, but marked in use in the bitmap.
9000                          */
9001                         problem = PR_5_BLOCK_UNUSED;
9002                 } else {
9003                         /*
9004                          * Block used, but not marked in use in the bitmap.
9005                          */
9006                         problem = PR_5_BLOCK_USED;
9007                 }
9008                 if (pctx.blk == NO_BLK) {
9009                         pctx.blk = pctx.blk2 = i;
9010                         save_problem = problem;
9011                 } else {
9012                         if ((problem == save_problem) &&
9013                             (pctx.blk2 == i-1))
9014                                 pctx.blk2++;
9015                         else {
9016                                 print_bitmap_problem(ctx, save_problem, &pctx);
9017                                 pctx.blk = pctx.blk2 = i;
9018                                 save_problem = problem;
9019                         }
9020                 }
9021                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9022                 had_problem++;
9023
9024         do_counts:
9025                 if (!bitmap) {
9026                         group_free++;
9027                         free_blocks++;
9028                 }
9029                 blocks ++;
9030                 if ((blocks == fs->super->s_blocks_per_group) ||
9031                     (i == fs->super->s_blocks_count-1)) {
9032                         free_array[group] = group_free;
9033                         group ++;
9034                         blocks = 0;
9035                         group_free = 0;
9036                         if (ctx->progress)
9037                                 if ((ctx->progress)(ctx, 5, group,
9038                                                     fs->group_desc_count*2))
9039                                         return;
9040                 }
9041         }
9042         if (pctx.blk != NO_BLK)
9043                 print_bitmap_problem(ctx, save_problem, &pctx);
9044         if (had_problem)
9045                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9046         else
9047                 fixit = -1;
9048         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9049
9050         if (fixit == 1) {
9051                 ext2fs_free_block_bitmap(fs->block_map);
9052                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9053                                                   &fs->block_map);
9054                 if (retval) {
9055                         clear_problem_context(&pctx);
9056                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9057                         ctx->flags |= E2F_FLAG_ABORT;
9058                         return;
9059                 }
9060                 ext2fs_set_bitmap_padding(fs->block_map);
9061                 ext2fs_mark_bb_dirty(fs);
9062
9063                 /* Redo the counts */
9064                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9065                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9066                 goto redo_counts;
9067         } else if (fixit == 0)
9068                 ext2fs_unmark_valid(fs);
9069
9070         for (i = 0; i < fs->group_desc_count; i++) {
9071                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9072                         pctx.group = i;
9073                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9074                         pctx.blk2 = free_array[i];
9075
9076                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9077                                         &pctx)) {
9078                                 fs->group_desc[i].bg_free_blocks_count =
9079                                         free_array[i];
9080                                 ext2fs_mark_super_dirty(fs);
9081                         } else
9082                                 ext2fs_unmark_valid(fs);
9083                 }
9084         }
9085         if (free_blocks != fs->super->s_free_blocks_count) {
9086                 pctx.group = 0;
9087                 pctx.blk = fs->super->s_free_blocks_count;
9088                 pctx.blk2 = free_blocks;
9089
9090                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9091                         fs->super->s_free_blocks_count = free_blocks;
9092                         ext2fs_mark_super_dirty(fs);
9093                 } else
9094                         ext2fs_unmark_valid(fs);
9095         }
9096         ext2fs_free_mem(&free_array);
9097 }
9098
9099 static void check_inode_bitmaps(e2fsck_t ctx)
9100 {
9101         ext2_filsys fs = ctx->fs;
9102         ext2_ino_t      i;
9103         unsigned int    free_inodes = 0;
9104         int             group_free = 0;
9105         int             dirs_count = 0;
9106         int             group = 0;
9107         unsigned int    inodes = 0;
9108         int             *free_array;
9109         int             *dir_array;
9110         int             actual, bitmap;
9111         errcode_t       retval;
9112         struct problem_context  pctx;
9113         int             problem, save_problem, fixit, had_problem;
9114
9115         clear_problem_context(&pctx);
9116         free_array = (int *) e2fsck_allocate_memory(ctx,
9117             fs->group_desc_count * sizeof(int), "free inode count array");
9118
9119         dir_array = (int *) e2fsck_allocate_memory(ctx,
9120            fs->group_desc_count * sizeof(int), "directory count array");
9121
9122         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9123             (fs->super->s_inodes_count >
9124              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9125                 pctx.num = 3;
9126                 pctx.blk = 1;
9127                 pctx.blk2 = fs->super->s_inodes_count;
9128                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9129                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9130                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9131
9132                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9133                 return;
9134         }
9135         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9136             (fs->super->s_inodes_count >
9137              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9138                 pctx.num = 4;
9139                 pctx.blk = 1;
9140                 pctx.blk2 = fs->super->s_inodes_count;
9141                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9142                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9143                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9144
9145                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9146                 return;
9147         }
9148
9149 redo_counts:
9150         had_problem = 0;
9151         save_problem = 0;
9152         pctx.ino = pctx.ino2 = 0;
9153         for (i = 1; i <= fs->super->s_inodes_count; i++) {
9154                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9155                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9156
9157                 if (actual == bitmap)
9158                         goto do_counts;
9159
9160                 if (!actual && bitmap) {
9161                         /*
9162                          * Inode wasn't used, but marked in bitmap
9163                          */
9164                         problem = PR_5_INODE_UNUSED;
9165                 } else /* if (actual && !bitmap) */ {
9166                         /*
9167                          * Inode used, but not in bitmap
9168                          */
9169                         problem = PR_5_INODE_USED;
9170                 }
9171                 if (pctx.ino == 0) {
9172                         pctx.ino = pctx.ino2 = i;
9173                         save_problem = problem;
9174                 } else {
9175                         if ((problem == save_problem) &&
9176                             (pctx.ino2 == i-1))
9177                                 pctx.ino2++;
9178                         else {
9179                                 print_bitmap_problem(ctx, save_problem, &pctx);
9180                                 pctx.ino = pctx.ino2 = i;
9181                                 save_problem = problem;
9182                         }
9183                 }
9184                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9185                 had_problem++;
9186
9187 do_counts:
9188                 if (!bitmap) {
9189                         group_free++;
9190                         free_inodes++;
9191                 } else {
9192                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9193                                 dirs_count++;
9194                 }
9195                 inodes++;
9196                 if ((inodes == fs->super->s_inodes_per_group) ||
9197                     (i == fs->super->s_inodes_count)) {
9198                         free_array[group] = group_free;
9199                         dir_array[group] = dirs_count;
9200                         group ++;
9201                         inodes = 0;
9202                         group_free = 0;
9203                         dirs_count = 0;
9204                         if (ctx->progress)
9205                                 if ((ctx->progress)(ctx, 5,
9206                                             group + fs->group_desc_count,
9207                                             fs->group_desc_count*2))
9208                                         return;
9209                 }
9210         }
9211         if (pctx.ino)
9212                 print_bitmap_problem(ctx, save_problem, &pctx);
9213
9214         if (had_problem)
9215                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9216         else
9217                 fixit = -1;
9218         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9219
9220         if (fixit == 1) {
9221                 ext2fs_free_inode_bitmap(fs->inode_map);
9222                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9223                                                   &fs->inode_map);
9224                 if (retval) {
9225                         clear_problem_context(&pctx);
9226                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9227                         ctx->flags |= E2F_FLAG_ABORT;
9228                         return;
9229                 }
9230                 ext2fs_set_bitmap_padding(fs->inode_map);
9231                 ext2fs_mark_ib_dirty(fs);
9232
9233                 /* redo counts */
9234                 inodes = 0; free_inodes = 0; group_free = 0;
9235                 dirs_count = 0; group = 0;
9236                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9237                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9238                 goto redo_counts;
9239         } else if (fixit == 0)
9240                 ext2fs_unmark_valid(fs);
9241
9242         for (i = 0; i < fs->group_desc_count; i++) {
9243                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9244                         pctx.group = i;
9245                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9246                         pctx.ino2 = free_array[i];
9247                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9248                                         &pctx)) {
9249                                 fs->group_desc[i].bg_free_inodes_count =
9250                                         free_array[i];
9251                                 ext2fs_mark_super_dirty(fs);
9252                         } else
9253                                 ext2fs_unmark_valid(fs);
9254                 }
9255                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9256                         pctx.group = i;
9257                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9258                         pctx.ino2 = dir_array[i];
9259
9260                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9261                                         &pctx)) {
9262                                 fs->group_desc[i].bg_used_dirs_count =
9263                                         dir_array[i];
9264                                 ext2fs_mark_super_dirty(fs);
9265                         } else
9266                                 ext2fs_unmark_valid(fs);
9267                 }
9268         }
9269         if (free_inodes != fs->super->s_free_inodes_count) {
9270                 pctx.group = -1;
9271                 pctx.ino = fs->super->s_free_inodes_count;
9272                 pctx.ino2 = free_inodes;
9273
9274                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9275                         fs->super->s_free_inodes_count = free_inodes;
9276                         ext2fs_mark_super_dirty(fs);
9277                 } else
9278                         ext2fs_unmark_valid(fs);
9279         }
9280         ext2fs_free_mem(&free_array);
9281         ext2fs_free_mem(&dir_array);
9282 }
9283
9284 static void check_inode_end(e2fsck_t ctx)
9285 {
9286         ext2_filsys fs = ctx->fs;
9287         ext2_ino_t      end, save_inodes_count, i;
9288         struct problem_context  pctx;
9289
9290         clear_problem_context(&pctx);
9291
9292         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9293         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9294                                                      &save_inodes_count);
9295         if (pctx.errcode) {
9296                 pctx.num = 1;
9297                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9298                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9299                 return;
9300         }
9301         if (save_inodes_count == end)
9302                 return;
9303
9304         for (i = save_inodes_count + 1; i <= end; i++) {
9305                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9306                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9307                                 for (i = save_inodes_count + 1; i <= end; i++)
9308                                         ext2fs_mark_inode_bitmap(fs->inode_map,
9309                                                                  i);
9310                                 ext2fs_mark_ib_dirty(fs);
9311                         } else
9312                                 ext2fs_unmark_valid(fs);
9313                         break;
9314                 }
9315         }
9316
9317         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9318                                                      save_inodes_count, 0);
9319         if (pctx.errcode) {
9320                 pctx.num = 2;
9321                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9322                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9323                 return;
9324         }
9325 }
9326
9327 static void check_block_end(e2fsck_t ctx)
9328 {
9329         ext2_filsys fs = ctx->fs;
9330         blk_t   end, save_blocks_count, i;
9331         struct problem_context  pctx;
9332
9333         clear_problem_context(&pctx);
9334
9335         end = fs->block_map->start +
9336                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9337         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9338                                                      &save_blocks_count);
9339         if (pctx.errcode) {
9340                 pctx.num = 3;
9341                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9342                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9343                 return;
9344         }
9345         if (save_blocks_count == end)
9346                 return;
9347
9348         for (i = save_blocks_count + 1; i <= end; i++) {
9349                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9350                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9351                                 for (i = save_blocks_count + 1; i <= end; i++)
9352                                         ext2fs_mark_block_bitmap(fs->block_map,
9353                                                                  i);
9354                                 ext2fs_mark_bb_dirty(fs);
9355                         } else
9356                                 ext2fs_unmark_valid(fs);
9357                         break;
9358                 }
9359         }
9360
9361         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9362                                                      save_blocks_count, 0);
9363         if (pctx.errcode) {
9364                 pctx.num = 4;
9365                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9366                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9367                 return;
9368         }
9369 }
9370
9371 static void e2fsck_pass5(e2fsck_t ctx)
9372 {
9373         struct problem_context  pctx;
9374
9375         /* Pass 5 */
9376
9377         clear_problem_context(&pctx);
9378
9379         if (!(ctx->options & E2F_OPT_PREEN))
9380                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9381
9382         if (ctx->progress)
9383                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9384                         return;
9385
9386         e2fsck_read_bitmaps(ctx);
9387
9388         check_block_bitmaps(ctx);
9389         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9390                 return;
9391         check_inode_bitmaps(ctx);
9392         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9393                 return;
9394         check_inode_end(ctx);
9395         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9396                 return;
9397         check_block_end(ctx);
9398         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9399                 return;
9400
9401         ext2fs_free_inode_bitmap(ctx->inode_used_map);
9402         ctx->inode_used_map = 0;
9403         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9404         ctx->inode_dir_map = 0;
9405         ext2fs_free_block_bitmap(ctx->block_found_map);
9406         ctx->block_found_map = 0;
9407 }
9408
9409 /*
9410  * problem.c --- report filesystem problems to the user
9411  */
9412
9413 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
9414 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
9415 #define PR_NO_DEFAULT   0x000004 /* Default to no */
9416 #define PR_MSG_ONLY     0x000008 /* Print message only */
9417
9418 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
9419
9420 #define PR_FATAL        0x001000 /* Fatal error */
9421 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
9422                                  /* ask another */
9423 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
9424 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
9425 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
9426 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
9427 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
9428
9429
9430 #define PROMPT_NONE     0
9431 #define PROMPT_FIX      1
9432 #define PROMPT_CLEAR    2
9433 #define PROMPT_RELOCATE 3
9434 #define PROMPT_ALLOCATE 4
9435 #define PROMPT_EXPAND   5
9436 #define PROMPT_CONNECT  6
9437 #define PROMPT_CREATE   7
9438 #define PROMPT_SALVAGE  8
9439 #define PROMPT_TRUNCATE 9
9440 #define PROMPT_CLEAR_INODE 10
9441 #define PROMPT_ABORT    11
9442 #define PROMPT_SPLIT    12
9443 #define PROMPT_CONTINUE 13
9444 #define PROMPT_CLONE    14
9445 #define PROMPT_DELETE   15
9446 #define PROMPT_SUPPRESS 16
9447 #define PROMPT_UNLINK   17
9448 #define PROMPT_CLEAR_HTREE 18
9449 #define PROMPT_RECREATE 19
9450 #define PROMPT_NULL     20
9451
9452 struct e2fsck_problem {
9453         problem_t       e2p_code;
9454         const char *    e2p_description;
9455         char            prompt;
9456         int             flags;
9457         problem_t       second_code;
9458 };
9459
9460 struct latch_descr {
9461         int             latch_code;
9462         problem_t       question;
9463         problem_t       end_message;
9464         int             flags;
9465 };
9466
9467 /*
9468  * These are the prompts which are used to ask the user if they want
9469  * to fix a problem.
9470  */
9471 static const char * const prompt[] = {
9472         N_("(no prompt)"),      /* 0 */
9473         N_("Fix"),              /* 1 */
9474         N_("Clear"),            /* 2 */
9475         N_("Relocate"),         /* 3 */
9476         N_("Allocate"),         /* 4 */
9477         N_("Expand"),           /* 5 */
9478         N_("Connect to /lost+found"), /* 6 */
9479         N_("Create"),           /* 7 */
9480         N_("Salvage"),          /* 8 */
9481         N_("Truncate"),         /* 9 */
9482         N_("Clear inode"),      /* 10 */
9483         N_("Abort"),            /* 11 */
9484         N_("Split"),            /* 12 */
9485         N_("Continue"),         /* 13 */
9486         N_("Clone multiply-claimed blocks"), /* 14 */
9487         N_("Delete file"),      /* 15 */
9488         N_("Suppress messages"),/* 16 */
9489         N_("Unlink"),           /* 17 */
9490         N_("Clear HTree index"),/* 18 */
9491         N_("Recreate"),         /* 19 */
9492         "",                     /* 20 */
9493 };
9494
9495 /*
9496  * These messages are printed when we are preen mode and we will be
9497  * automatically fixing the problem.
9498  */
9499 static const char * const preen_msg[] = {
9500         N_("(NONE)"),           /* 0 */
9501         N_("FIXED"),            /* 1 */
9502         N_("CLEARED"),          /* 2 */
9503         N_("RELOCATED"),        /* 3 */
9504         N_("ALLOCATED"),        /* 4 */
9505         N_("EXPANDED"),         /* 5 */
9506         N_("RECONNECTED"),      /* 6 */
9507         N_("CREATED"),          /* 7 */
9508         N_("SALVAGED"),         /* 8 */
9509         N_("TRUNCATED"),        /* 9 */
9510         N_("INODE CLEARED"),    /* 10 */
9511         N_("ABORTED"),          /* 11 */
9512         N_("SPLIT"),            /* 12 */
9513         N_("CONTINUING"),       /* 13 */
9514         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
9515         N_("FILE DELETED"),     /* 15 */
9516         N_("SUPPRESSED"),       /* 16 */
9517         N_("UNLINKED"),         /* 17 */
9518         N_("HTREE INDEX CLEARED"),/* 18 */
9519         N_("WILL RECREATE"),    /* 19 */
9520         "",                     /* 20 */
9521 };
9522
9523 static const struct e2fsck_problem problem_table[] = {
9524
9525         /* Pre-Pass 1 errors */
9526
9527         /* Block bitmap not in group */
9528         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
9529           PROMPT_RELOCATE, PR_LATCH_RELOC },
9530
9531         /* Inode bitmap not in group */
9532         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
9533           PROMPT_RELOCATE, PR_LATCH_RELOC },
9534
9535         /* Inode table not in group */
9536         { PR_0_ITABLE_NOT_GROUP,
9537           N_("@i table for @g %g is not in @g.  (@b %b)\n"
9538           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
9539           PROMPT_RELOCATE, PR_LATCH_RELOC },
9540
9541         /* Superblock corrupt */
9542         { PR_0_SB_CORRUPT,
9543           N_("\nThe @S could not be read or does not describe a correct ext2\n"
9544           "@f.  If the @v is valid and it really contains an ext2\n"
9545           "@f (and not swap or ufs or something else), then the @S\n"
9546           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
9547           "    e2fsck -b %S <@v>\n\n"),
9548           PROMPT_NONE, PR_FATAL },
9549
9550         /* Filesystem size is wrong */
9551         { PR_0_FS_SIZE_WRONG,
9552           N_("The @f size (according to the @S) is %b @bs\n"
9553           "The physical size of the @v is %c @bs\n"
9554           "Either the @S or the partition table is likely to be corrupt!\n"),
9555           PROMPT_ABORT, 0 },
9556
9557         /* Fragments not supported */
9558         { PR_0_NO_FRAGMENTS,
9559           N_("@S @b_size = %b, fragsize = %c.\n"
9560           "This version of e2fsck does not support fragment sizes different\n"
9561           "from the @b size.\n"),
9562           PROMPT_NONE, PR_FATAL },
9563
9564           /* Bad blocks_per_group */
9565         { PR_0_BLOCKS_PER_GROUP,
9566           N_("@S @bs_per_group = %b, should have been %c\n"),
9567           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
9568
9569         /* Bad first_data_block */
9570         { PR_0_FIRST_DATA_BLOCK,
9571           N_("@S first_data_@b = %b, should have been %c\n"),
9572           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
9573
9574         /* Adding UUID to filesystem */
9575         { PR_0_ADD_UUID,
9576           N_("@f did not have a UUID; generating one.\n\n"),
9577           PROMPT_NONE, 0 },
9578
9579         /* Relocate hint */
9580         { PR_0_RELOCATE_HINT,
9581           N_("Note: if several inode or block bitmap blocks or part\n"
9582           "of the inode table require relocation, you may wish to try\n"
9583           "running e2fsck with the '-b %S' option first.  The problem\n"
9584           "may lie only with the primary block group descriptors, and\n"
9585           "the backup block group descriptors may be OK.\n\n"),
9586           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
9587
9588         /* Miscellaneous superblock corruption */
9589         { PR_0_MISC_CORRUPT_SUPER,
9590           N_("Corruption found in @S.  (%s = %N).\n"),
9591           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
9592
9593         /* Error determing physical device size of filesystem */
9594         { PR_0_GETSIZE_ERROR,
9595           N_("Error determining size of the physical @v: %m\n"),
9596           PROMPT_NONE, PR_FATAL },
9597
9598         /* Inode count in superblock is incorrect */
9599         { PR_0_INODE_COUNT_WRONG,
9600           N_("@i count in @S is %i, @s %j.\n"),
9601           PROMPT_FIX, 0 },
9602
9603         { PR_0_HURD_CLEAR_FILETYPE,
9604           N_("The Hurd does not support the filetype feature.\n"),
9605           PROMPT_CLEAR, 0 },
9606
9607         /* Journal inode is invalid */
9608         { PR_0_JOURNAL_BAD_INODE,
9609           N_("@S has an @n ext3 @j (@i %i).\n"),
9610           PROMPT_CLEAR, PR_PREEN_OK },
9611
9612         /* The external journal has (unsupported) multiple filesystems */
9613         { PR_0_JOURNAL_UNSUPP_MULTIFS,
9614           N_("External @j has multiple @f users (unsupported).\n"),
9615           PROMPT_NONE, PR_FATAL },
9616
9617         /* Can't find external journal */
9618         { PR_0_CANT_FIND_JOURNAL,
9619           N_("Can't find external @j\n"),
9620           PROMPT_NONE, PR_FATAL },
9621
9622         /* External journal has bad superblock */
9623         { PR_0_EXT_JOURNAL_BAD_SUPER,
9624           N_("External @j has bad @S\n"),
9625           PROMPT_NONE, PR_FATAL },
9626
9627         /* Superblock has a bad journal UUID */
9628         { PR_0_JOURNAL_BAD_UUID,
9629           N_("External @j does not support this @f\n"),
9630           PROMPT_NONE, PR_FATAL },
9631
9632         /* Journal has an unknown superblock type */
9633         { PR_0_JOURNAL_UNSUPP_SUPER,
9634           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
9635              "It is likely that your copy of e2fsck is old and/or doesn't "
9636              "support this @j format.\n"
9637              "It is also possible the @j @S is corrupt.\n"),
9638           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
9639
9640         /* Journal superblock is corrupt */
9641         { PR_0_JOURNAL_BAD_SUPER,
9642           N_("Ext3 @j @S is corrupt.\n"),
9643           PROMPT_FIX, PR_PREEN_OK },
9644
9645         /* Superblock flag should be cleared */
9646         { PR_0_JOURNAL_HAS_JOURNAL,
9647           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
9648           PROMPT_CLEAR, PR_PREEN_OK },
9649
9650         /* Superblock flag is incorrect */
9651         { PR_0_JOURNAL_RECOVER_SET,
9652           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
9653           PROMPT_CLEAR, PR_PREEN_OK },
9654
9655         /* Journal has data, but recovery flag is clear */
9656         { PR_0_JOURNAL_RECOVERY_CLEAR,
9657           N_("ext3 recovery flag is clear, but @j has data.\n"),
9658           PROMPT_NONE, 0 },
9659
9660         /* Ask if we should clear the journal */
9661         { PR_0_JOURNAL_RESET_JOURNAL,
9662           N_("Clear @j"),
9663           PROMPT_NULL, PR_PREEN_NOMSG },
9664
9665         /* Ask if we should run the journal anyway */
9666         { PR_0_JOURNAL_RUN,
9667           N_("Run @j anyway"),
9668           PROMPT_NULL, 0 },
9669
9670         /* Run the journal by default */
9671         { PR_0_JOURNAL_RUN_DEFAULT,
9672           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
9673           PROMPT_NONE, 0 },
9674
9675         /* Clearing orphan inode */
9676         { PR_0_ORPHAN_CLEAR_INODE,
9677           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
9678           PROMPT_NONE, 0 },
9679
9680         /* Illegal block found in orphaned inode */
9681         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
9682            N_("@I @b #%B (%b) found in @o @i %i.\n"),
9683           PROMPT_NONE, 0 },
9684
9685         /* Already cleared block found in orphaned inode */
9686         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
9687            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
9688           PROMPT_NONE, 0 },
9689
9690         /* Illegal orphan inode in superblock */
9691         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
9692           N_("@I @o @i %i in @S.\n"),
9693           PROMPT_NONE, 0 },
9694
9695         /* Illegal inode in orphaned inode list */
9696         { PR_0_ORPHAN_ILLEGAL_INODE,
9697           N_("@I @i %i in @o @i list.\n"),
9698           PROMPT_NONE, 0 },
9699
9700         /* Filesystem revision is 0, but feature flags are set */
9701         { PR_0_FS_REV_LEVEL,
9702           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
9703           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
9704
9705         /* Journal superblock has an unknown read-only feature flag set */
9706         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
9707           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
9708           PROMPT_ABORT, 0 },
9709
9710         /* Journal superblock has an unknown incompatible feature flag set */
9711         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
9712           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
9713           PROMPT_ABORT, 0 },
9714
9715         /* Journal has unsupported version number */
9716         { PR_0_JOURNAL_UNSUPP_VERSION,
9717           N_("@j version not supported by this e2fsck.\n"),
9718           PROMPT_ABORT, 0 },
9719
9720         /* Moving journal to hidden file */
9721         { PR_0_MOVE_JOURNAL,
9722           N_("Moving @j from /%s to hidden @i.\n\n"),
9723           PROMPT_NONE, 0 },
9724
9725         /* Error moving journal to hidden file */
9726         { PR_0_ERR_MOVE_JOURNAL,
9727           N_("Error moving @j: %m\n\n"),
9728           PROMPT_NONE, 0 },
9729
9730         /* Clearing V2 journal superblock */
9731         { PR_0_CLEAR_V2_JOURNAL,
9732           N_("Found @n V2 @j @S fields (from V1 @j).\n"
9733              "Clearing fields beyond the V1 @j @S...\n\n"),
9734           PROMPT_NONE, 0 },
9735
9736         /* Backup journal inode blocks */
9737         { PR_0_BACKUP_JNL,
9738           N_("Backing up @j @i @b information.\n\n"),
9739           PROMPT_NONE, 0 },
9740
9741         /* Reserved blocks w/o resize_inode */
9742         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
9743           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
9744              "is %N; @s zero.  "),
9745           PROMPT_FIX, 0 },
9746
9747         /* Resize_inode not enabled, but resize inode is non-zero */
9748         { PR_0_CLEAR_RESIZE_INODE,
9749           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
9750           PROMPT_CLEAR, 0 },
9751
9752         /* Resize inode invalid */
9753         { PR_0_RESIZE_INODE_INVALID,
9754           N_("Resize @i not valid.  "),
9755           PROMPT_RECREATE, 0 },
9756
9757         /* Pass 1 errors */
9758
9759         /* Pass 1: Checking inodes, blocks, and sizes */
9760         { PR_1_PASS_HEADER,
9761           N_("Pass 1: Checking @is, @bs, and sizes\n"),
9762           PROMPT_NONE, 0 },
9763
9764         /* Root directory is not an inode */
9765         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
9766           PROMPT_CLEAR, 0 },
9767
9768         /* Root directory has dtime set */
9769         { PR_1_ROOT_DTIME,
9770           N_("@r has dtime set (probably due to old mke2fs).  "),
9771           PROMPT_FIX, PR_PREEN_OK },
9772
9773         /* Reserved inode has bad mode */
9774         { PR_1_RESERVED_BAD_MODE,
9775           N_("Reserved @i %i (%Q) has @n mode.  "),
9776           PROMPT_CLEAR, PR_PREEN_OK },
9777
9778         /* Deleted inode has zero dtime */
9779         { PR_1_ZERO_DTIME,
9780           N_("@D @i %i has zero dtime.  "),
9781           PROMPT_FIX, PR_PREEN_OK },
9782
9783         /* Inode in use, but dtime set */
9784         { PR_1_SET_DTIME,
9785           N_("@i %i is in use, but has dtime set.  "),
9786           PROMPT_FIX, PR_PREEN_OK },
9787
9788         /* Zero-length directory */
9789         { PR_1_ZERO_LENGTH_DIR,
9790           N_("@i %i is a @z @d.  "),
9791           PROMPT_CLEAR, PR_PREEN_OK },
9792
9793         /* Block bitmap conflicts with some other fs block */
9794         { PR_1_BB_CONFLICT,
9795           N_("@g %g's @b @B at %b @C.\n"),
9796           PROMPT_RELOCATE, 0 },
9797
9798         /* Inode bitmap conflicts with some other fs block */
9799         { PR_1_IB_CONFLICT,
9800           N_("@g %g's @i @B at %b @C.\n"),
9801           PROMPT_RELOCATE, 0 },
9802
9803         /* Inode table conflicts with some other fs block */
9804         { PR_1_ITABLE_CONFLICT,
9805           N_("@g %g's @i table at %b @C.\n"),
9806           PROMPT_RELOCATE, 0 },
9807
9808         /* Block bitmap is on a bad block */
9809         { PR_1_BB_BAD_BLOCK,
9810           N_("@g %g's @b @B (%b) is bad.  "),
9811           PROMPT_RELOCATE, 0 },
9812
9813         /* Inode bitmap is on a bad block */
9814         { PR_1_IB_BAD_BLOCK,
9815           N_("@g %g's @i @B (%b) is bad.  "),
9816           PROMPT_RELOCATE, 0 },
9817
9818         /* Inode has incorrect i_size */
9819         { PR_1_BAD_I_SIZE,
9820           N_("@i %i, i_size is %Is, @s %N.  "),
9821           PROMPT_FIX, PR_PREEN_OK },
9822
9823         /* Inode has incorrect i_blocks */
9824         { PR_1_BAD_I_BLOCKS,
9825           N_("@i %i, i_@bs is %Ib, @s %N.  "),
9826           PROMPT_FIX, PR_PREEN_OK },
9827
9828         /* Illegal blocknumber in inode */
9829         { PR_1_ILLEGAL_BLOCK_NUM,
9830           N_("@I @b #%B (%b) in @i %i.  "),
9831           PROMPT_CLEAR, PR_LATCH_BLOCK },
9832
9833         /* Block number overlaps fs metadata */
9834         { PR_1_BLOCK_OVERLAPS_METADATA,
9835           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
9836           PROMPT_CLEAR, PR_LATCH_BLOCK },
9837
9838         /* Inode has illegal blocks (latch question) */
9839         { PR_1_INODE_BLOCK_LATCH,
9840           N_("@i %i has illegal @b(s).  "),
9841           PROMPT_CLEAR, 0 },
9842
9843         /* Too many bad blocks in inode */
9844         { PR_1_TOO_MANY_BAD_BLOCKS,
9845           N_("Too many illegal @bs in @i %i.\n"),
9846           PROMPT_CLEAR_INODE, PR_NO_OK },
9847
9848         /* Illegal block number in bad block inode */
9849         { PR_1_BB_ILLEGAL_BLOCK_NUM,
9850           N_("@I @b #%B (%b) in bad @b @i.  "),
9851           PROMPT_CLEAR, PR_LATCH_BBLOCK },
9852
9853         /* Bad block inode has illegal blocks (latch question) */
9854         { PR_1_INODE_BBLOCK_LATCH,
9855           N_("Bad @b @i has illegal @b(s).  "),
9856           PROMPT_CLEAR, 0 },
9857
9858         /* Duplicate or bad blocks in use! */
9859         { PR_1_DUP_BLOCKS_PREENSTOP,
9860           N_("Duplicate or bad @b in use!\n"),
9861           PROMPT_NONE, 0 },
9862
9863         /* Bad block used as bad block indirect block */
9864         { PR_1_BBINODE_BAD_METABLOCK,
9865           N_("Bad @b %b used as bad @b @i indirect @b.  "),
9866           PROMPT_CLEAR, PR_LATCH_BBLOCK },
9867
9868         /* Inconsistency can't be fixed prompt */
9869         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
9870           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
9871              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
9872              "in the @f.\n"),
9873           PROMPT_CONTINUE, PR_PREEN_NOMSG },
9874
9875         /* Bad primary block */
9876         { PR_1_BAD_PRIMARY_BLOCK,
9877           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
9878           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
9879
9880         /* Bad primary block prompt */
9881         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
9882           N_("You can remove this @b from the bad @b list and hope\n"
9883              "that the @b is really OK.  But there are no guarantees.\n\n"),
9884           PROMPT_CLEAR, PR_PREEN_NOMSG },
9885
9886         /* Bad primary superblock */
9887         { PR_1_BAD_PRIMARY_SUPERBLOCK,
9888           N_("The primary @S (%b) is on the bad @b list.\n"),
9889           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
9890
9891         /* Bad primary block group descriptors */
9892         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
9893           N_("Block %b in the primary @g descriptors "
9894           "is on the bad @b list\n"),
9895           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
9896
9897         /* Bad superblock in group */
9898         { PR_1_BAD_SUPERBLOCK,
9899           N_("Warning: Group %g's @S (%b) is bad.\n"),
9900           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9901
9902         /* Bad block group descriptors in group */
9903         { PR_1_BAD_GROUP_DESCRIPTORS,
9904           N_("Warning: Group %g's copy of the @g descriptors has a bad "
9905           "@b (%b).\n"),
9906           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9907
9908         /* Block claimed for no reason */
9909         { PR_1_PROGERR_CLAIMED_BLOCK,
9910           N_("Programming error?  @b #%b claimed for no reason in "
9911           "process_bad_@b.\n"),
9912           PROMPT_NONE, PR_PREEN_OK },
9913
9914         /* Error allocating blocks for relocating metadata */
9915         { PR_1_RELOC_BLOCK_ALLOCATE,
9916           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
9917           PROMPT_NONE, PR_PREEN_OK },
9918
9919         /* Error allocating block buffer during relocation process */
9920         { PR_1_RELOC_MEMORY_ALLOCATE,
9921           N_("@A @b buffer for relocating %s\n"),
9922           PROMPT_NONE, PR_PREEN_OK },
9923
9924         /* Relocating metadata group information from X to Y */
9925         { PR_1_RELOC_FROM_TO,
9926           N_("Relocating @g %g's %s from %b to %c...\n"),
9927           PROMPT_NONE, PR_PREEN_OK },
9928
9929         /* Relocating metatdata group information to X */
9930         { PR_1_RELOC_TO,
9931           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
9932           PROMPT_NONE, PR_PREEN_OK },
9933
9934         /* Block read error during relocation process */
9935         { PR_1_RELOC_READ_ERR,
9936           N_("Warning: could not read @b %b of %s: %m\n"),
9937           PROMPT_NONE, PR_PREEN_OK },
9938
9939         /* Block write error during relocation process */
9940         { PR_1_RELOC_WRITE_ERR,
9941           N_("Warning: could not write @b %b for %s: %m\n"),
9942           PROMPT_NONE, PR_PREEN_OK },
9943
9944         /* Error allocating inode bitmap */
9945         { PR_1_ALLOCATE_IBITMAP_ERROR,
9946           N_("@A @i @B (%N): %m\n"),
9947           PROMPT_NONE, PR_FATAL },
9948
9949         /* Error allocating block bitmap */
9950         { PR_1_ALLOCATE_BBITMAP_ERROR,
9951           N_("@A @b @B (%N): %m\n"),
9952           PROMPT_NONE, PR_FATAL },
9953
9954         /* Error allocating icount structure */
9955         { PR_1_ALLOCATE_ICOUNT,
9956           N_("@A icount link information: %m\n"),
9957           PROMPT_NONE, PR_FATAL },
9958
9959         /* Error allocating dbcount */
9960         { PR_1_ALLOCATE_DBCOUNT,
9961           N_("@A @d @b array: %m\n"),
9962           PROMPT_NONE, PR_FATAL },
9963
9964         /* Error while scanning inodes */
9965         { PR_1_ISCAN_ERROR,
9966           N_("Error while scanning @is (%i): %m\n"),
9967           PROMPT_NONE, PR_FATAL },
9968
9969         /* Error while iterating over blocks */
9970         { PR_1_BLOCK_ITERATE,
9971           N_("Error while iterating over @bs in @i %i: %m\n"),
9972           PROMPT_NONE, PR_FATAL },
9973
9974         /* Error while storing inode count information */
9975         { PR_1_ICOUNT_STORE,
9976           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
9977           PROMPT_NONE, PR_FATAL },
9978
9979         /* Error while storing directory block information */
9980         { PR_1_ADD_DBLOCK,
9981           N_("Error storing @d @b information "
9982           "(@i=%i, @b=%b, num=%N): %m\n"),
9983           PROMPT_NONE, PR_FATAL },
9984
9985         /* Error while reading inode (for clearing) */
9986         { PR_1_READ_INODE,
9987           N_("Error reading @i %i: %m\n"),
9988           PROMPT_NONE, PR_FATAL },
9989
9990         /* Suppress messages prompt */
9991         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
9992
9993         /* Imagic flag set on an inode when filesystem doesn't support it */
9994         { PR_1_SET_IMAGIC,
9995           N_("@i %i has imagic flag set.  "),
9996           PROMPT_CLEAR, 0 },
9997
9998         /* Immutable flag set on a device or socket inode */
9999         { PR_1_SET_IMMUTABLE,
10000           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10001              "or append-only flag set.  "),
10002           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10003
10004         /* Compression flag set on an inode when filesystem doesn't support it */
10005         { PR_1_COMPR_SET,
10006           N_("@i %i has @cion flag set on @f without @cion support.  "),
10007           PROMPT_CLEAR, 0 },
10008
10009         /* Non-zero size for device, fifo or socket inode */
10010         { PR_1_SET_NONZSIZE,
10011           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
10012           PROMPT_FIX, PR_PREEN_OK },
10013
10014         /* Filesystem revision is 0, but feature flags are set */
10015         { PR_1_FS_REV_LEVEL,
10016           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
10017           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10018
10019         /* Journal inode is not in use, but contains data */
10020         { PR_1_JOURNAL_INODE_NOT_CLEAR,
10021           N_("@j @i is not in use, but contains data.  "),
10022           PROMPT_CLEAR, PR_PREEN_OK },
10023
10024         /* Journal has bad mode */
10025         { PR_1_JOURNAL_BAD_MODE,
10026           N_("@j is not regular file.  "),
10027           PROMPT_FIX, PR_PREEN_OK },
10028
10029         /* Deal with inodes that were part of orphan linked list */
10030         { PR_1_LOW_DTIME,
10031           N_("@i %i was part of the @o @i list.  "),
10032           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10033
10034         /* Deal with inodes that were part of corrupted orphan linked
10035            list (latch question) */
10036         { PR_1_ORPHAN_LIST_REFUGEES,
10037           N_("@is that were part of a corrupted orphan linked list found.  "),
10038           PROMPT_FIX, 0 },
10039
10040         /* Error allocating refcount structure */
10041         { PR_1_ALLOCATE_REFCOUNT,
10042           N_("@A refcount structure (%N): %m\n"),
10043           PROMPT_NONE, PR_FATAL },
10044
10045         /* Error reading extended attribute block */
10046         { PR_1_READ_EA_BLOCK,
10047           N_("Error reading @a @b %b for @i %i.  "),
10048           PROMPT_CLEAR, 0 },
10049
10050         /* Invalid extended attribute block */
10051         { PR_1_BAD_EA_BLOCK,
10052           N_("@i %i has a bad @a @b %b.  "),
10053           PROMPT_CLEAR, 0 },
10054
10055         /* Error reading Extended Attribute block while fixing refcount */
10056         { PR_1_EXTATTR_READ_ABORT,
10057           N_("Error reading @a @b %b (%m).  "),
10058           PROMPT_ABORT, 0 },
10059
10060         /* Extended attribute reference count incorrect */
10061         { PR_1_EXTATTR_REFCOUNT,
10062           N_("@a @b %b has reference count %B, @s %N.  "),
10063           PROMPT_FIX, 0 },
10064
10065         /* Error writing Extended Attribute block while fixing refcount */
10066         { PR_1_EXTATTR_WRITE,
10067           N_("Error writing @a @b %b (%m).  "),
10068           PROMPT_ABORT, 0 },
10069
10070         /* Multiple EA blocks not supported */
10071         { PR_1_EA_MULTI_BLOCK,
10072           N_("@a @b %b has h_@bs > 1.  "),
10073           PROMPT_CLEAR, 0},
10074
10075         /* Error allocating EA region allocation structure */
10076         { PR_1_EA_ALLOC_REGION,
10077           N_("@A @a @b %b.  "),
10078           PROMPT_ABORT, 0},
10079
10080         /* Error EA allocation collision */
10081         { PR_1_EA_ALLOC_COLLISION,
10082           N_("@a @b %b is corrupt (allocation collision).  "),
10083           PROMPT_CLEAR, 0},
10084
10085         /* Bad extended attribute name */
10086         { PR_1_EA_BAD_NAME,
10087           N_("@a @b %b is corrupt (@n name).  "),
10088           PROMPT_CLEAR, 0},
10089
10090         /* Bad extended attribute value */
10091         { PR_1_EA_BAD_VALUE,
10092           N_("@a @b %b is corrupt (@n value).  "),
10093           PROMPT_CLEAR, 0},
10094
10095         /* Inode too big (latch question) */
10096         { PR_1_INODE_TOOBIG,
10097           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
10098
10099         /* Directory too big */
10100         { PR_1_TOOBIG_DIR,
10101           N_("@b #%B (%b) causes @d to be too big.  "),
10102           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10103
10104         /* Regular file too big */
10105         { PR_1_TOOBIG_REG,
10106           N_("@b #%B (%b) causes file to be too big.  "),
10107           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10108
10109         /* Symlink too big */
10110         { PR_1_TOOBIG_SYMLINK,
10111           N_("@b #%B (%b) causes symlink to be too big.  "),
10112           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10113
10114         /* INDEX_FL flag set on a non-HTREE filesystem */
10115         { PR_1_HTREE_SET,
10116           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10117           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10118
10119         /* INDEX_FL flag set on a non-directory */
10120         { PR_1_HTREE_NODIR,
10121           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10122           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10123
10124         /* Invalid root node in HTREE directory */
10125         { PR_1_HTREE_BADROOT,
10126           N_("@h %i has an @n root node.\n"),
10127           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10128
10129         /* Unsupported hash version in HTREE directory */
10130         { PR_1_HTREE_HASHV,
10131           N_("@h %i has an unsupported hash version (%N)\n"),
10132           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10133
10134         /* Incompatible flag in HTREE root node */
10135         { PR_1_HTREE_INCOMPAT,
10136           N_("@h %i uses an incompatible htree root node flag.\n"),
10137           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10138
10139         /* HTREE too deep */
10140         { PR_1_HTREE_DEPTH,
10141           N_("@h %i has a tree depth (%N) which is too big\n"),
10142           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10143
10144         /* Bad block has indirect block that conflicts with filesystem block */
10145         { PR_1_BB_FS_BLOCK,
10146           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10147              "@f metadata.  "),
10148           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10149
10150         /* Resize inode failed */
10151         { PR_1_RESIZE_INODE_CREATE,
10152           N_("Resize @i (re)creation failed: %m."),
10153           PROMPT_ABORT, 0 },
10154
10155         /* invalid inode->i_extra_isize */
10156         { PR_1_EXTRA_ISIZE,
10157           N_("@i %i has a extra size (%IS) which is @n\n"),
10158           PROMPT_FIX, PR_PREEN_OK },
10159
10160         /* invalid ea entry->e_name_len */
10161         { PR_1_ATTR_NAME_LEN,
10162           N_("@a in @i %i has a namelen (%N) which is @n\n"),
10163           PROMPT_CLEAR, PR_PREEN_OK },
10164
10165         /* invalid ea entry->e_value_size */
10166         { PR_1_ATTR_VALUE_SIZE,
10167           N_("@a in @i %i has a value size (%N) which is @n\n"),
10168           PROMPT_CLEAR, PR_PREEN_OK },
10169
10170         /* invalid ea entry->e_value_offs */
10171         { PR_1_ATTR_VALUE_OFFSET,
10172           N_("@a in @i %i has a value offset (%N) which is @n\n"),
10173           PROMPT_CLEAR, PR_PREEN_OK },
10174
10175         /* invalid ea entry->e_value_block */
10176         { PR_1_ATTR_VALUE_BLOCK,
10177           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
10178           PROMPT_CLEAR, PR_PREEN_OK },
10179
10180         /* invalid ea entry->e_hash */
10181         { PR_1_ATTR_HASH,
10182           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
10183           PROMPT_CLEAR, PR_PREEN_OK },
10184
10185         /* Pass 1b errors */
10186
10187         /* Pass 1B: Rescan for duplicate/bad blocks */
10188         { PR_1B_PASS_HEADER,
10189           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
10190           "Pass 1B: Rescanning for @m @bs\n"),
10191           PROMPT_NONE, 0 },
10192
10193         /* Duplicate/bad block(s) header */
10194         { PR_1B_DUP_BLOCK_HEADER,
10195           N_("@m @b(s) in @i %i:"),
10196           PROMPT_NONE, 0 },
10197
10198         /* Duplicate/bad block(s) in inode */
10199         { PR_1B_DUP_BLOCK,
10200           " %b",
10201           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10202
10203         /* Duplicate/bad block(s) end */
10204         { PR_1B_DUP_BLOCK_END,
10205           "\n",
10206           PROMPT_NONE, PR_PREEN_NOHDR },
10207
10208         /* Error while scanning inodes */
10209         { PR_1B_ISCAN_ERROR,
10210           N_("Error while scanning inodes (%i): %m\n"),
10211           PROMPT_NONE, PR_FATAL },
10212
10213         /* Error allocating inode bitmap */
10214         { PR_1B_ALLOCATE_IBITMAP_ERROR,
10215           N_("@A @i @B (@i_dup_map): %m\n"),
10216           PROMPT_NONE, PR_FATAL },
10217
10218         /* Error while iterating over blocks */
10219         { PR_1B_BLOCK_ITERATE,
10220           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10221           PROMPT_NONE, 0 },
10222
10223         /* Error adjusting EA refcount */
10224         { PR_1B_ADJ_EA_REFCOUNT,
10225           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
10226           PROMPT_NONE, 0 },
10227
10228
10229         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
10230         { PR_1C_PASS_HEADER,
10231           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
10232           PROMPT_NONE, 0 },
10233
10234
10235         /* Pass 1D: Reconciling multiply-claimed blocks */
10236         { PR_1D_PASS_HEADER,
10237           N_("Pass 1D: Reconciling @m @bs\n"),
10238           PROMPT_NONE, 0 },
10239
10240         /* File has duplicate blocks */
10241         { PR_1D_DUP_FILE,
10242           N_("File %Q (@i #%i, mod time %IM) \n"
10243           "  has %B @m @b(s), shared with %N file(s):\n"),
10244           PROMPT_NONE, 0 },
10245
10246         /* List of files sharing duplicate blocks */
10247         { PR_1D_DUP_FILE_LIST,
10248           N_("\t%Q (@i #%i, mod time %IM)\n"),
10249           PROMPT_NONE, 0 },
10250
10251         /* File sharing blocks with filesystem metadata  */
10252         { PR_1D_SHARE_METADATA,
10253           N_("\t<@f metadata>\n"),
10254           PROMPT_NONE, 0 },
10255
10256         /* Report of how many duplicate/bad inodes */
10257         { PR_1D_NUM_DUP_INODES,
10258           N_("(There are %N @is containing @m @bs.)\n\n"),
10259           PROMPT_NONE, 0 },
10260
10261         /* Duplicated blocks already reassigned or cloned. */
10262         { PR_1D_DUP_BLOCKS_DEALT,
10263           N_("@m @bs already reassigned or cloned.\n\n"),
10264           PROMPT_NONE, 0 },
10265
10266         /* Clone duplicate/bad blocks? */
10267         { PR_1D_CLONE_QUESTION,
10268           "", PROMPT_CLONE, PR_NO_OK },
10269
10270         /* Delete file? */
10271         { PR_1D_DELETE_QUESTION,
10272           "", PROMPT_DELETE, 0 },
10273
10274         /* Couldn't clone file (error) */
10275         { PR_1D_CLONE_ERROR,
10276           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10277
10278         /* Pass 2 errors */
10279
10280         /* Pass 2: Checking directory structure */
10281         { PR_2_PASS_HEADER,
10282           N_("Pass 2: Checking @d structure\n"),
10283           PROMPT_NONE, 0 },
10284
10285         /* Bad inode number for '.' */
10286         { PR_2_BAD_INODE_DOT,
10287           N_("@n @i number for '.' in @d @i %i.\n"),
10288           PROMPT_FIX, 0 },
10289
10290         /* Directory entry has bad inode number */
10291         { PR_2_BAD_INO,
10292           N_("@E has @n @i #: %Di.\n"),
10293           PROMPT_CLEAR, 0 },
10294
10295         /* Directory entry has deleted or unused inode */
10296         { PR_2_UNUSED_INODE,
10297           N_("@E has @D/unused @i %Di.  "),
10298           PROMPT_CLEAR, PR_PREEN_OK },
10299
10300         /* Directry entry is link to '.' */
10301         { PR_2_LINK_DOT,
10302           N_("@E @L to '.'  "),
10303           PROMPT_CLEAR, 0 },
10304
10305         /* Directory entry points to inode now located in a bad block */
10306         { PR_2_BB_INODE,
10307           N_("@E points to @i (%Di) located in a bad @b.\n"),
10308           PROMPT_CLEAR, 0 },
10309
10310         /* Directory entry contains a link to a directory */
10311         { PR_2_LINK_DIR,
10312           N_("@E @L to @d %P (%Di).\n"),
10313           PROMPT_CLEAR, 0 },
10314
10315         /* Directory entry contains a link to the root directry */
10316         { PR_2_LINK_ROOT,
10317           N_("@E @L to the @r.\n"),
10318           PROMPT_CLEAR, 0 },
10319
10320         /* Directory entry has illegal characters in its name */
10321         { PR_2_BAD_NAME,
10322           N_("@E has illegal characters in its name.\n"),
10323           PROMPT_FIX, 0 },
10324
10325         /* Missing '.' in directory inode */
10326         { PR_2_MISSING_DOT,
10327           N_("Missing '.' in @d @i %i.\n"),
10328           PROMPT_FIX, 0 },
10329
10330         /* Missing '..' in directory inode */
10331         { PR_2_MISSING_DOT_DOT,
10332           N_("Missing '..' in @d @i %i.\n"),
10333           PROMPT_FIX, 0 },
10334
10335         /* First entry in directory inode doesn't contain '.' */
10336         { PR_2_1ST_NOT_DOT,
10337           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
10338           PROMPT_FIX, 0 },
10339
10340         /* Second entry in directory inode doesn't contain '..' */
10341         { PR_2_2ND_NOT_DOT_DOT,
10342           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
10343           PROMPT_FIX, 0 },
10344
10345         /* i_faddr should be zero */
10346         { PR_2_FADDR_ZERO,
10347           N_("i_faddr @F %IF, @s zero.\n"),
10348           PROMPT_CLEAR, 0 },
10349
10350         /* i_file_acl should be zero */
10351         { PR_2_FILE_ACL_ZERO,
10352           N_("i_file_acl @F %If, @s zero.\n"),
10353           PROMPT_CLEAR, 0 },
10354
10355         /* i_dir_acl should be zero */
10356         { PR_2_DIR_ACL_ZERO,
10357           N_("i_dir_acl @F %Id, @s zero.\n"),
10358           PROMPT_CLEAR, 0 },
10359
10360         /* i_frag should be zero */
10361         { PR_2_FRAG_ZERO,
10362           N_("i_frag @F %N, @s zero.\n"),
10363           PROMPT_CLEAR, 0 },
10364
10365         /* i_fsize should be zero */
10366         { PR_2_FSIZE_ZERO,
10367           N_("i_fsize @F %N, @s zero.\n"),
10368           PROMPT_CLEAR, 0 },
10369
10370         /* inode has bad mode */
10371         { PR_2_BAD_MODE,
10372           N_("@i %i (%Q) has @n mode (%Im).\n"),
10373           PROMPT_CLEAR, 0 },
10374
10375         /* directory corrupted */
10376         { PR_2_DIR_CORRUPTED,
10377           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
10378           PROMPT_SALVAGE, 0 },
10379
10380         /* filename too long */
10381         { PR_2_FILENAME_LONG,
10382           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
10383           PROMPT_TRUNCATE, 0 },
10384
10385         /* Directory inode has a missing block (hole) */
10386         { PR_2_DIRECTORY_HOLE,
10387           N_("@d @i %i has an unallocated @b #%B.  "),
10388           PROMPT_ALLOCATE, 0 },
10389
10390         /* '.' is not NULL terminated */
10391         { PR_2_DOT_NULL_TERM,
10392           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
10393           PROMPT_FIX, 0 },
10394
10395         /* '..' is not NULL terminated */
10396         { PR_2_DOT_DOT_NULL_TERM,
10397           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
10398           PROMPT_FIX, 0 },
10399
10400         /* Illegal character device inode */
10401         { PR_2_BAD_CHAR_DEV,
10402           N_("@i %i (%Q) is an @I character @v.\n"),
10403           PROMPT_CLEAR, 0 },
10404
10405         /* Illegal block device inode */
10406         { PR_2_BAD_BLOCK_DEV,
10407           N_("@i %i (%Q) is an @I @b @v.\n"),
10408           PROMPT_CLEAR, 0 },
10409
10410         /* Duplicate '.' entry */
10411         { PR_2_DUP_DOT,
10412           N_("@E is duplicate '.' @e.\n"),
10413           PROMPT_FIX, 0 },
10414
10415         /* Duplicate '..' entry */
10416         { PR_2_DUP_DOT_DOT,
10417           N_("@E is duplicate '..' @e.\n"),
10418           PROMPT_FIX, 0 },
10419
10420         /* Internal error: couldn't find dir_info */
10421         { PR_2_NO_DIRINFO,
10422           N_("Internal error: couldn't find dir_info for %i.\n"),
10423           PROMPT_NONE, PR_FATAL },
10424
10425         /* Final rec_len is wrong */
10426         { PR_2_FINAL_RECLEN,
10427           N_("@E has rec_len of %Dr, @s %N.\n"),
10428           PROMPT_FIX, 0 },
10429
10430         /* Error allocating icount structure */
10431         { PR_2_ALLOCATE_ICOUNT,
10432           N_("@A icount structure: %m\n"),
10433           PROMPT_NONE, PR_FATAL },
10434
10435         /* Error iterating over directory blocks */
10436         { PR_2_DBLIST_ITERATE,
10437           N_("Error iterating over @d @bs: %m\n"),
10438           PROMPT_NONE, PR_FATAL },
10439
10440         /* Error reading directory block */
10441         { PR_2_READ_DIRBLOCK,
10442           N_("Error reading @d @b %b (@i %i): %m\n"),
10443           PROMPT_CONTINUE, 0 },
10444
10445         /* Error writing directory block */
10446         { PR_2_WRITE_DIRBLOCK,
10447           N_("Error writing @d @b %b (@i %i): %m\n"),
10448           PROMPT_CONTINUE, 0 },
10449
10450         /* Error allocating new directory block */
10451         { PR_2_ALLOC_DIRBOCK,
10452           N_("@A new @d @b for @i %i (%s): %m\n"),
10453           PROMPT_NONE, 0 },
10454
10455         /* Error deallocating inode */
10456         { PR_2_DEALLOC_INODE,
10457           N_("Error deallocating @i %i: %m\n"),
10458           PROMPT_NONE, PR_FATAL },
10459
10460         /* Directory entry for '.' is big.  Split? */
10461         { PR_2_SPLIT_DOT,
10462           N_("@d @e for '.' is big.  "),
10463           PROMPT_SPLIT, PR_NO_OK },
10464
10465         /* Illegal FIFO inode */
10466         { PR_2_BAD_FIFO,
10467           N_("@i %i (%Q) is an @I FIFO.\n"),
10468           PROMPT_CLEAR, 0 },
10469
10470         /* Illegal socket inode */
10471         { PR_2_BAD_SOCKET,
10472           N_("@i %i (%Q) is an @I socket.\n"),
10473           PROMPT_CLEAR, 0 },
10474
10475         /* Directory filetype not set */
10476         { PR_2_SET_FILETYPE,
10477           N_("Setting filetype for @E to %N.\n"),
10478           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
10479
10480         /* Directory filetype incorrect */
10481         { PR_2_BAD_FILETYPE,
10482           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
10483           PROMPT_FIX, 0 },
10484
10485         /* Directory filetype set on filesystem */
10486         { PR_2_CLEAR_FILETYPE,
10487           N_("@E has filetype set.\n"),
10488           PROMPT_CLEAR, PR_PREEN_OK },
10489
10490         /* Directory filename is null */
10491         { PR_2_NULL_NAME,
10492           N_("@E has a @z name.\n"),
10493           PROMPT_CLEAR, 0 },
10494
10495         /* Invalid symlink */
10496         { PR_2_INVALID_SYMLINK,
10497           N_("Symlink %Q (@i #%i) is @n.\n"),
10498           PROMPT_CLEAR, 0 },
10499
10500         /* i_file_acl (extended attribute block) is bad */
10501         { PR_2_FILE_ACL_BAD,
10502           N_("@a @b @F @n (%If).\n"),
10503           PROMPT_CLEAR, 0 },
10504
10505         /* Filesystem contains large files, but has no such flag in sb */
10506         { PR_2_FEATURE_LARGE_FILES,
10507           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
10508           PROMPT_FIX, 0 },
10509
10510         /* Node in HTREE directory not referenced */
10511         { PR_2_HTREE_NOTREF,
10512           N_("@p @h %d: node (%B) not referenced\n"),
10513           PROMPT_NONE, 0 },
10514
10515         /* Node in HTREE directory referenced twice */
10516         { PR_2_HTREE_DUPREF,
10517           N_("@p @h %d: node (%B) referenced twice\n"),
10518           PROMPT_NONE, 0 },
10519
10520         /* Node in HTREE directory has bad min hash */
10521         { PR_2_HTREE_MIN_HASH,
10522           N_("@p @h %d: node (%B) has bad min hash\n"),
10523           PROMPT_NONE, 0 },
10524
10525         /* Node in HTREE directory has bad max hash */
10526         { PR_2_HTREE_MAX_HASH,
10527           N_("@p @h %d: node (%B) has bad max hash\n"),
10528           PROMPT_NONE, 0 },
10529
10530         /* Clear invalid HTREE directory */
10531         { PR_2_HTREE_CLEAR,
10532           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
10533
10534         /* Bad block in htree interior node */
10535         { PR_2_HTREE_BADBLK,
10536           N_("@p @h %d (%q): bad @b number %b.\n"),
10537           PROMPT_CLEAR_HTREE, 0 },
10538
10539         /* Error adjusting EA refcount */
10540         { PR_2_ADJ_EA_REFCOUNT,
10541           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
10542           PROMPT_NONE, PR_FATAL },
10543
10544         /* Invalid HTREE root node */
10545         { PR_2_HTREE_BAD_ROOT,
10546           N_("@p @h %d: root node is @n\n"),
10547           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10548
10549         /* Invalid HTREE limit */
10550         { PR_2_HTREE_BAD_LIMIT,
10551           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
10552           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10553
10554         /* Invalid HTREE count */
10555         { PR_2_HTREE_BAD_COUNT,
10556           N_("@p @h %d: node (%B) has @n count (%N)\n"),
10557           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10558
10559         /* HTREE interior node has out-of-order hashes in table */
10560         { PR_2_HTREE_HASH_ORDER,
10561           N_("@p @h %d: node (%B) has an unordered hash table\n"),
10562           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10563
10564         /* Node in HTREE directory has invalid depth */
10565         { PR_2_HTREE_BAD_DEPTH,
10566           N_("@p @h %d: node (%B) has @n depth\n"),
10567           PROMPT_NONE, 0 },
10568
10569         /* Duplicate directory entry found */
10570         { PR_2_DUPLICATE_DIRENT,
10571           N_("Duplicate @E found.  "),
10572           PROMPT_CLEAR, 0 },
10573
10574         /* Non-unique filename found */
10575         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
10576           N_("@E has a non-unique filename.\nRename to %s"),
10577           PROMPT_NULL, 0 },
10578
10579         /* Duplicate directory entry found */
10580         { PR_2_REPORT_DUP_DIRENT,
10581           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
10582           PROMPT_NONE, 0 },
10583
10584         /* Pass 3 errors */
10585
10586         /* Pass 3: Checking directory connectivity */
10587         { PR_3_PASS_HEADER,
10588           N_("Pass 3: Checking @d connectivity\n"),
10589           PROMPT_NONE, 0 },
10590
10591         /* Root inode not allocated */
10592         { PR_3_NO_ROOT_INODE,
10593           N_("@r not allocated.  "),
10594           PROMPT_ALLOCATE, 0 },
10595
10596         /* No room in lost+found */
10597         { PR_3_EXPAND_LF_DIR,
10598           N_("No room in @l @d.  "),
10599           PROMPT_EXPAND, 0 },
10600
10601         /* Unconnected directory inode */
10602         { PR_3_UNCONNECTED_DIR,
10603           N_("Unconnected @d @i %i (%p)\n"),
10604           PROMPT_CONNECT, 0 },
10605
10606         /* /lost+found not found */
10607         { PR_3_NO_LF_DIR,
10608           N_("/@l not found.  "),
10609           PROMPT_CREATE, PR_PREEN_OK },
10610
10611         /* .. entry is incorrect */
10612         { PR_3_BAD_DOT_DOT,
10613           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
10614           PROMPT_FIX, 0 },
10615
10616         /* Bad or non-existent /lost+found.  Cannot reconnect */
10617         { PR_3_NO_LPF,
10618           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
10619           PROMPT_NONE, 0 },
10620
10621         /* Could not expand /lost+found */
10622         { PR_3_CANT_EXPAND_LPF,
10623           N_("Could not expand /@l: %m\n"),
10624           PROMPT_NONE, 0 },
10625
10626         /* Could not reconnect inode */
10627         { PR_3_CANT_RECONNECT,
10628           N_("Could not reconnect %i: %m\n"),
10629           PROMPT_NONE, 0 },
10630
10631         /* Error while trying to find /lost+found */
10632         { PR_3_ERR_FIND_LPF,
10633           N_("Error while trying to find /@l: %m\n"),
10634           PROMPT_NONE, 0 },
10635
10636         /* Error in ext2fs_new_block while creating /lost+found */
10637         { PR_3_ERR_LPF_NEW_BLOCK,
10638           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
10639           PROMPT_NONE, 0 },
10640
10641         /* Error in ext2fs_new_inode while creating /lost+found */
10642         { PR_3_ERR_LPF_NEW_INODE,
10643           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
10644           PROMPT_NONE, 0 },
10645
10646         /* Error in ext2fs_new_dir_block while creating /lost+found */
10647         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
10648           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
10649           PROMPT_NONE, 0 },
10650
10651         /* Error while writing directory block for /lost+found */
10652         { PR_3_ERR_LPF_WRITE_BLOCK,
10653           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
10654           PROMPT_NONE, 0 },
10655
10656         /* Error while adjusting inode count */
10657         { PR_3_ADJUST_INODE,
10658           N_("Error while adjusting @i count on @i %i\n"),
10659           PROMPT_NONE, 0 },
10660
10661         /* Couldn't fix parent directory -- error */
10662         { PR_3_FIX_PARENT_ERR,
10663           N_("Couldn't fix parent of @i %i: %m\n\n"),
10664           PROMPT_NONE, 0 },
10665
10666         /* Couldn't fix parent directory -- couldn't find it */
10667         { PR_3_FIX_PARENT_NOFIND,
10668           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
10669           PROMPT_NONE, 0 },
10670
10671         /* Error allocating inode bitmap */
10672         { PR_3_ALLOCATE_IBITMAP_ERROR,
10673           N_("@A @i @B (%N): %m\n"),
10674           PROMPT_NONE, PR_FATAL },
10675
10676         /* Error creating root directory */
10677         { PR_3_CREATE_ROOT_ERROR,
10678           N_("Error creating root @d (%s): %m\n"),
10679           PROMPT_NONE, PR_FATAL },
10680
10681         /* Error creating lost and found directory */
10682         { PR_3_CREATE_LPF_ERROR,
10683           N_("Error creating /@l @d (%s): %m\n"),
10684           PROMPT_NONE, PR_FATAL },
10685
10686         /* Root inode is not directory; aborting */
10687         { PR_3_ROOT_NOT_DIR_ABORT,
10688           N_("@r is not a @d; aborting.\n"),
10689           PROMPT_NONE, PR_FATAL },
10690
10691         /* Cannot proceed without a root inode. */
10692         { PR_3_NO_ROOT_INODE_ABORT,
10693           N_("Cannot proceed without a @r.\n"),
10694           PROMPT_NONE, PR_FATAL },
10695
10696         /* Internal error: couldn't find dir_info */
10697         { PR_3_NO_DIRINFO,
10698           N_("Internal error: couldn't find dir_info for %i.\n"),
10699           PROMPT_NONE, PR_FATAL },
10700
10701         /* Lost+found not a directory */
10702         { PR_3_LPF_NOTDIR,
10703           N_("/@l is not a @d (ino=%i)\n"),
10704           PROMPT_UNLINK, 0 },
10705
10706         /* Pass 3A Directory Optimization       */
10707
10708         /* Pass 3A: Optimizing directories */
10709         { PR_3A_PASS_HEADER,
10710           N_("Pass 3A: Optimizing directories\n"),
10711           PROMPT_NONE, PR_PREEN_NOMSG },
10712
10713         /* Error iterating over directories */
10714         { PR_3A_OPTIMIZE_ITER,
10715           N_("Failed to create dirs_to_hash iterator: %m"),
10716           PROMPT_NONE, 0 },
10717
10718         /* Error rehash directory */
10719         { PR_3A_OPTIMIZE_DIR_ERR,
10720           N_("Failed to optimize directory %q (%d): %m"),
10721           PROMPT_NONE, 0 },
10722
10723         /* Rehashing dir header */
10724         { PR_3A_OPTIMIZE_DIR_HEADER,
10725           N_("Optimizing directories: "),
10726           PROMPT_NONE, PR_MSG_ONLY },
10727
10728         /* Rehashing directory %d */
10729         { PR_3A_OPTIMIZE_DIR,
10730           " %d",
10731           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
10732
10733         /* Rehashing dir end */
10734         { PR_3A_OPTIMIZE_DIR_END,
10735           "\n",
10736           PROMPT_NONE, PR_PREEN_NOHDR },
10737
10738         /* Pass 4 errors */
10739
10740         /* Pass 4: Checking reference counts */
10741         { PR_4_PASS_HEADER,
10742           N_("Pass 4: Checking reference counts\n"),
10743           PROMPT_NONE, 0 },
10744
10745         /* Unattached zero-length inode */
10746         { PR_4_ZERO_LEN_INODE,
10747           N_("@u @z @i %i.  "),
10748           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
10749
10750         /* Unattached inode */
10751         { PR_4_UNATTACHED_INODE,
10752           N_("@u @i %i\n"),
10753           PROMPT_CONNECT, 0 },
10754
10755         /* Inode ref count wrong */
10756         { PR_4_BAD_REF_COUNT,
10757           N_("@i %i ref count is %Il, @s %N.  "),
10758           PROMPT_FIX, PR_PREEN_OK },
10759
10760         { PR_4_INCONSISTENT_COUNT,
10761           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
10762           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
10763           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
10764           "They @s the same!\n"),
10765           PROMPT_NONE, 0 },
10766
10767         /* Pass 5 errors */
10768
10769         /* Pass 5: Checking group summary information */
10770         { PR_5_PASS_HEADER,
10771           N_("Pass 5: Checking @g summary information\n"),
10772           PROMPT_NONE, 0 },
10773
10774         /* Padding at end of inode bitmap is not set. */
10775         { PR_5_INODE_BMAP_PADDING,
10776           N_("Padding at end of @i @B is not set. "),
10777           PROMPT_FIX, PR_PREEN_OK },
10778
10779         /* Padding at end of block bitmap is not set. */
10780         { PR_5_BLOCK_BMAP_PADDING,
10781           N_("Padding at end of @b @B is not set. "),
10782           PROMPT_FIX, PR_PREEN_OK },
10783
10784         /* Block bitmap differences header */
10785         { PR_5_BLOCK_BITMAP_HEADER,
10786           N_("@b @B differences: "),
10787           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
10788
10789         /* Block not used, but marked in bitmap */
10790         { PR_5_BLOCK_UNUSED,
10791           " -%b",
10792           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10793
10794         /* Block used, but not marked used in bitmap */
10795         { PR_5_BLOCK_USED,
10796           " +%b",
10797           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10798
10799         /* Block bitmap differences end */
10800         { PR_5_BLOCK_BITMAP_END,
10801           "\n",
10802           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10803
10804         /* Inode bitmap differences header */
10805         { PR_5_INODE_BITMAP_HEADER,
10806           N_("@i @B differences: "),
10807           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10808
10809         /* Inode not used, but marked in bitmap */
10810         { PR_5_INODE_UNUSED,
10811           " -%i",
10812           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10813
10814         /* Inode used, but not marked used in bitmap */
10815         { PR_5_INODE_USED,
10816           " +%i",
10817           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10818
10819         /* Inode bitmap differences end */
10820         { PR_5_INODE_BITMAP_END,
10821           "\n",
10822           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10823
10824         /* Free inodes count for group wrong */
10825         { PR_5_FREE_INODE_COUNT_GROUP,
10826           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
10827           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10828
10829         /* Directories count for group wrong */
10830         { PR_5_FREE_DIR_COUNT_GROUP,
10831           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
10832           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10833
10834         /* Free inodes count wrong */
10835         { PR_5_FREE_INODE_COUNT,
10836           N_("Free @is count wrong (%i, counted=%j).\n"),
10837           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10838
10839         /* Free blocks count for group wrong */
10840         { PR_5_FREE_BLOCK_COUNT_GROUP,
10841           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
10842           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10843
10844         /* Free blocks count wrong */
10845         { PR_5_FREE_BLOCK_COUNT,
10846           N_("Free @bs count wrong (%b, counted=%c).\n"),
10847           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
10848
10849         /* Programming error: bitmap endpoints don't match */
10850         { PR_5_BMAP_ENDPOINTS,
10851           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
10852           "match calculated @B endpoints (%i, %j)\n"),
10853           PROMPT_NONE, PR_FATAL },
10854
10855         /* Internal error: fudging end of bitmap */
10856         { PR_5_FUDGE_BITMAP_ERROR,
10857           N_("Internal error: fudging end of bitmap (%N)\n"),
10858           PROMPT_NONE, PR_FATAL },
10859
10860         /* Error copying in replacement inode bitmap */
10861         { PR_5_COPY_IBITMAP_ERROR,
10862           N_("Error copying in replacement @i @B: %m\n"),
10863           PROMPT_NONE, PR_FATAL },
10864
10865         /* Error copying in replacement block bitmap */
10866         { PR_5_COPY_BBITMAP_ERROR,
10867           N_("Error copying in replacement @b @B: %m\n"),
10868           PROMPT_NONE, PR_FATAL },
10869
10870         /* Block range not used, but marked in bitmap */
10871         { PR_5_BLOCK_RANGE_UNUSED,
10872           " -(%b--%c)",
10873           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10874
10875         /* Block range used, but not marked used in bitmap */
10876         { PR_5_BLOCK_RANGE_USED,
10877           " +(%b--%c)",
10878           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10879
10880         /* Inode range not used, but marked in bitmap */
10881         { PR_5_INODE_RANGE_UNUSED,
10882           " -(%i--%j)",
10883           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10884
10885         /* Inode range used, but not marked used in bitmap */
10886         { PR_5_INODE_RANGE_USED,
10887           " +(%i--%j)",
10888           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
10889
10890         { 0 }
10891 };
10892
10893 /*
10894  * This is the latch flags register.  It allows several problems to be
10895  * "latched" together.  This means that the user has to answer but one
10896  * question for the set of problems, and all of the associated
10897  * problems will be either fixed or not fixed.
10898  */
10899 static struct latch_descr pr_latch_info[] = {
10900         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
10901         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
10902         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
10903         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
10904         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
10905         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
10906         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
10907         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
10908         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
10909         { -1, 0, 0 },
10910 };
10911
10912 static const struct e2fsck_problem *find_problem(problem_t code)
10913 {
10914         int     i;
10915
10916         for (i=0; problem_table[i].e2p_code; i++) {
10917                 if (problem_table[i].e2p_code == code)
10918                         return &problem_table[i];
10919         }
10920         return 0;
10921 }
10922
10923 static struct latch_descr *find_latch(int code)
10924 {
10925         int     i;
10926
10927         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
10928                 if (pr_latch_info[i].latch_code == code)
10929                         return &pr_latch_info[i];
10930         }
10931         return 0;
10932 }
10933
10934 int end_problem_latch(e2fsck_t ctx, int mask)
10935 {
10936         struct latch_descr *ldesc;
10937         struct problem_context pctx;
10938         int answer = -1;
10939
10940         ldesc = find_latch(mask);
10941         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
10942                 clear_problem_context(&pctx);
10943                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
10944         }
10945         ldesc->flags &= ~(PRL_VARIABLE);
10946         return answer;
10947 }
10948
10949 int set_latch_flags(int mask, int setflags, int clearflags)
10950 {
10951         struct latch_descr *ldesc;
10952
10953         ldesc = find_latch(mask);
10954         if (!ldesc)
10955                 return -1;
10956         ldesc->flags |= setflags;
10957         ldesc->flags &= ~clearflags;
10958         return 0;
10959 }
10960
10961 void clear_problem_context(struct problem_context *ctx)
10962 {
10963         memset(ctx, 0, sizeof(struct problem_context));
10964         ctx->blkcount = -1;
10965         ctx->group = -1;
10966 }
10967
10968 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
10969 {
10970         ext2_filsys fs = ctx->fs;
10971         const struct e2fsck_problem *ptr;
10972         struct latch_descr *ldesc = 0;
10973         const char *message;
10974         int             def_yn, answer, ans;
10975         int             print_answer = 0;
10976         int             suppress = 0;
10977
10978         ptr = find_problem(code);
10979         if (!ptr) {
10980                 printf(_("Unhandled error code (0x%x)!\n"), code);
10981                 return 0;
10982         }
10983         def_yn = 1;
10984         if ((ptr->flags & PR_NO_DEFAULT) ||
10985             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
10986             (ctx->options & E2F_OPT_NO))
10987                 def_yn= 0;
10988
10989         /*
10990          * Do special latch processing.  This is where we ask the
10991          * latch question, if it exists
10992          */
10993         if (ptr->flags & PR_LATCH_MASK) {
10994                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
10995                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
10996                         ans = fix_problem(ctx, ldesc->question, pctx);
10997                         if (ans == 1)
10998                                 ldesc->flags |= PRL_YES;
10999                         if (ans == 0)
11000                                 ldesc->flags |= PRL_NO;
11001                         ldesc->flags |= PRL_LATCHED;
11002                 }
11003                 if (ldesc->flags & PRL_SUPPRESS)
11004                         suppress++;
11005         }
11006         if ((ptr->flags & PR_PREEN_NOMSG) &&
11007             (ctx->options & E2F_OPT_PREEN))
11008                 suppress++;
11009         if ((ptr->flags & PR_NO_NOMSG) &&
11010             (ctx->options & E2F_OPT_NO))
11011                 suppress++;
11012         if (!suppress) {
11013                 message = ptr->e2p_description;
11014                 if ((ctx->options & E2F_OPT_PREEN) &&
11015                     !(ptr->flags & PR_PREEN_NOHDR)) {
11016                         printf("%s: ", ctx->device_name ?
11017                                ctx->device_name : ctx->filesystem_name);
11018                 }
11019                 if (*message)
11020                         print_e2fsck_message(ctx, _(message), pctx, 1);
11021         }
11022         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11023                 preenhalt(ctx);
11024
11025         if (ptr->flags & PR_FATAL)
11026                 fatal_error(ctx, 0);
11027
11028         if (ptr->prompt == PROMPT_NONE) {
11029                 if (ptr->flags & PR_NOCOLLATE)
11030                         answer = -1;
11031                 else
11032                         answer = def_yn;
11033         } else {
11034                 if (ctx->options & E2F_OPT_PREEN) {
11035                         answer = def_yn;
11036                         if (!(ptr->flags & PR_PREEN_NOMSG))
11037                                 print_answer = 1;
11038                 } else if ((ptr->flags & PR_LATCH_MASK) &&
11039                            (ldesc->flags & (PRL_YES | PRL_NO))) {
11040                         if (!suppress)
11041                                 print_answer = 1;
11042                         if (ldesc->flags & PRL_YES)
11043                                 answer = 1;
11044                         else
11045                                 answer = 0;
11046                 } else
11047                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11048                 if (!answer && !(ptr->flags & PR_NO_OK))
11049                         ext2fs_unmark_valid(fs);
11050
11051                 if (print_answer)
11052                         printf("%s.\n", answer ?
11053                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11054
11055         }
11056
11057         if ((ptr->prompt == PROMPT_ABORT) && answer)
11058                 fatal_error(ctx, 0);
11059
11060         if (ptr->flags & PR_AFTER_CODE)
11061                 answer = fix_problem(ctx, ptr->second_code, pctx);
11062
11063         return answer;
11064 }
11065
11066 /*
11067  * linux/fs/recovery.c
11068  *
11069  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11070  */
11071
11072 /*
11073  * Maintain information about the progress of the recovery job, so that
11074  * the different passes can carry information between them.
11075  */
11076 struct recovery_info
11077 {
11078         tid_t           start_transaction;
11079         tid_t           end_transaction;
11080
11081         int             nr_replays;
11082         int             nr_revokes;
11083         int             nr_revoke_hits;
11084 };
11085
11086 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11087 static int do_one_pass(journal_t *journal,
11088                                 struct recovery_info *info, enum passtype pass);
11089 static int scan_revoke_records(journal_t *, struct buffer_head *,
11090                                 tid_t, struct recovery_info *);
11091
11092 /*
11093  * Read a block from the journal
11094  */
11095
11096 static int jread(struct buffer_head **bhp, journal_t *journal,
11097                  unsigned int offset)
11098 {
11099         int err;
11100         unsigned long blocknr;
11101         struct buffer_head *bh;
11102
11103         *bhp = NULL;
11104
11105         err = journal_bmap(journal, offset, &blocknr);
11106
11107         if (err) {
11108                 printf ("JBD: bad block at offset %u\n", offset);
11109                 return err;
11110         }
11111
11112         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11113         if (!bh)
11114                 return -ENOMEM;
11115
11116         if (!buffer_uptodate(bh)) {
11117                 /* If this is a brand new buffer, start readahead.
11118                    Otherwise, we assume we are already reading it.  */
11119                 if (!buffer_req(bh))
11120                         do_readahead(journal, offset);
11121                 wait_on_buffer(bh);
11122         }
11123
11124         if (!buffer_uptodate(bh)) {
11125                 printf ("JBD: Failed to read block at offset %u\n", offset);
11126                 brelse(bh);
11127                 return -EIO;
11128         }
11129
11130         *bhp = bh;
11131         return 0;
11132 }
11133
11134
11135 /*
11136  * Count the number of in-use tags in a journal descriptor block.
11137  */
11138
11139 static int count_tags(struct buffer_head *bh, int size)
11140 {
11141         char *                  tagp;
11142         journal_block_tag_t *   tag;
11143         int                     nr = 0;
11144
11145         tagp = &bh->b_data[sizeof(journal_header_t)];
11146
11147         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11148                 tag = (journal_block_tag_t *) tagp;
11149
11150                 nr++;
11151                 tagp += sizeof(journal_block_tag_t);
11152                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11153                         tagp += 16;
11154
11155                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11156                         break;
11157         }
11158
11159         return nr;
11160 }
11161
11162
11163 /* Make sure we wrap around the log correctly! */
11164 #define wrap(journal, var)                                            \
11165 do {                                                                \
11166         if (var >= (journal)->j_last)                                   \
11167                 var -= ((journal)->j_last - (journal)->j_first);        \
11168 } while (0)
11169
11170 /**
11171  * int journal_recover(journal_t *journal) - recovers a on-disk journal
11172  * @journal: the journal to recover
11173  *
11174  * The primary function for recovering the log contents when mounting a
11175  * journaled device.
11176  *
11177  * Recovery is done in three passes.  In the first pass, we look for the
11178  * end of the log.  In the second, we assemble the list of revoke
11179  * blocks.  In the third and final pass, we replay any un-revoked blocks
11180  * in the log.
11181  */
11182 int journal_recover(journal_t *journal)
11183 {
11184         int                     err;
11185         journal_superblock_t *  sb;
11186
11187         struct recovery_info    info;
11188
11189         memset(&info, 0, sizeof(info));
11190         sb = journal->j_superblock;
11191
11192         /*
11193          * The journal superblock's s_start field (the current log head)
11194          * is always zero if, and only if, the journal was cleanly
11195          * unmounted.
11196          */
11197
11198         if (!sb->s_start) {
11199                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11200                 return 0;
11201         }
11202
11203         err = do_one_pass(journal, &info, PASS_SCAN);
11204         if (!err)
11205                 err = do_one_pass(journal, &info, PASS_REVOKE);
11206         if (!err)
11207                 err = do_one_pass(journal, &info, PASS_REPLAY);
11208
11209         /* Restart the log at the next transaction ID, thus invalidating
11210          * any existing commit records in the log. */
11211         journal->j_transaction_sequence = ++info.end_transaction;
11212
11213         journal_clear_revoke(journal);
11214         sync_blockdev(journal->j_fs_dev);
11215         return err;
11216 }
11217
11218 static int do_one_pass(journal_t *journal,
11219                         struct recovery_info *info, enum passtype pass)
11220 {
11221         unsigned int            first_commit_ID, next_commit_ID;
11222         unsigned long           next_log_block;
11223         int                     err, success = 0;
11224         journal_superblock_t *  sb;
11225         journal_header_t *      tmp;
11226         struct buffer_head *    bh;
11227         unsigned int            sequence;
11228         int                     blocktype;
11229
11230         /* Precompute the maximum metadata descriptors in a descriptor block */
11231         int                     MAX_BLOCKS_PER_DESC;
11232         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11233                                / sizeof(journal_block_tag_t));
11234
11235         /*
11236          * First thing is to establish what we expect to find in the log
11237          * (in terms of transaction IDs), and where (in terms of log
11238          * block offsets): query the superblock.
11239          */
11240
11241         sb = journal->j_superblock;
11242         next_commit_ID = ntohl(sb->s_sequence);
11243         next_log_block = ntohl(sb->s_start);
11244
11245         first_commit_ID = next_commit_ID;
11246         if (pass == PASS_SCAN)
11247                 info->start_transaction = first_commit_ID;
11248
11249         /*
11250          * Now we walk through the log, transaction by transaction,
11251          * making sure that each transaction has a commit block in the
11252          * expected place.  Each complete transaction gets replayed back
11253          * into the main filesystem.
11254          */
11255
11256         while (1) {
11257                 int                     flags;
11258                 char *                  tagp;
11259                 journal_block_tag_t *   tag;
11260                 struct buffer_head *    obh;
11261                 struct buffer_head *    nbh;
11262
11263                 /* If we already know where to stop the log traversal,
11264                  * check right now that we haven't gone past the end of
11265                  * the log. */
11266
11267                 if (pass != PASS_SCAN)
11268                         if (tid_geq(next_commit_ID, info->end_transaction))
11269                                 break;
11270
11271                 /* Skip over each chunk of the transaction looking
11272                  * either the next descriptor block or the final commit
11273                  * record. */
11274
11275                 err = jread(&bh, journal, next_log_block);
11276                 if (err)
11277                         goto failed;
11278
11279                 next_log_block++;
11280                 wrap(journal, next_log_block);
11281
11282                 /* What kind of buffer is it?
11283                  *
11284                  * If it is a descriptor block, check that it has the
11285                  * expected sequence number.  Otherwise, we're all done
11286                  * here. */
11287
11288                 tmp = (journal_header_t *)bh->b_data;
11289
11290                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11291                         brelse(bh);
11292                         break;
11293                 }
11294
11295                 blocktype = ntohl(tmp->h_blocktype);
11296                 sequence = ntohl(tmp->h_sequence);
11297
11298                 if (sequence != next_commit_ID) {
11299                         brelse(bh);
11300                         break;
11301                 }
11302
11303                 /* OK, we have a valid descriptor block which matches
11304                  * all of the sequence number checks.  What are we going
11305                  * to do with it?  That depends on the pass... */
11306
11307                 switch(blocktype) {
11308                 case JFS_DESCRIPTOR_BLOCK:
11309                         /* If it is a valid descriptor block, replay it
11310                          * in pass REPLAY; otherwise, just skip over the
11311                          * blocks it describes. */
11312                         if (pass != PASS_REPLAY) {
11313                                 next_log_block +=
11314                                         count_tags(bh, journal->j_blocksize);
11315                                 wrap(journal, next_log_block);
11316                                 brelse(bh);
11317                                 continue;
11318                         }
11319
11320                         /* A descriptor block: we can now write all of
11321                          * the data blocks.  Yay, useful work is finally
11322                          * getting done here! */
11323
11324                         tagp = &bh->b_data[sizeof(journal_header_t)];
11325                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11326                                <= journal->j_blocksize) {
11327                                 unsigned long io_block;
11328
11329                                 tag = (journal_block_tag_t *) tagp;
11330                                 flags = ntohl(tag->t_flags);
11331
11332                                 io_block = next_log_block++;
11333                                 wrap(journal, next_log_block);
11334                                 err = jread(&obh, journal, io_block);
11335                                 if (err) {
11336                                         /* Recover what we can, but
11337                                          * report failure at the end. */
11338                                         success = err;
11339                                         printf ("JBD: IO error %d recovering "
11340                                                 "block %ld in log\n",
11341                                                 err, io_block);
11342                                 } else {
11343                                         unsigned long blocknr;
11344
11345                                         blocknr = ntohl(tag->t_blocknr);
11346
11347                                         /* If the block has been
11348                                          * revoked, then we're all done
11349                                          * here. */
11350                                         if (journal_test_revoke
11351                                             (journal, blocknr,
11352                                              next_commit_ID)) {
11353                                                 brelse(obh);
11354                                                 ++info->nr_revoke_hits;
11355                                                 goto skip_write;
11356                                         }
11357
11358                                         /* Find a buffer for the new
11359                                          * data being restored */
11360                                         nbh = getblk(journal->j_fs_dev,
11361                                                        blocknr,
11362                                                      journal->j_blocksize);
11363                                         if (nbh == NULL) {
11364                                                 printf ("JBD: Out of memory "
11365                                                        "during recovery.\n");
11366                                                 err = -ENOMEM;
11367                                                 brelse(bh);
11368                                                 brelse(obh);
11369                                                 goto failed;
11370                                         }
11371
11372                                         lock_buffer(nbh);
11373                                         memcpy(nbh->b_data, obh->b_data,
11374                                                         journal->j_blocksize);
11375                                         if (flags & JFS_FLAG_ESCAPE) {
11376                                                 *((unsigned int *)bh->b_data) =
11377                                                         htonl(JFS_MAGIC_NUMBER);
11378                                         }
11379
11380                                         mark_buffer_uptodate(nbh, 1);
11381                                         mark_buffer_dirty(nbh);
11382                                         ++info->nr_replays;
11383                                         /* ll_rw_block(WRITE, 1, &nbh); */
11384                                         unlock_buffer(nbh);
11385                                         brelse(obh);
11386                                         brelse(nbh);
11387                                 }
11388
11389                         skip_write:
11390                                 tagp += sizeof(journal_block_tag_t);
11391                                 if (!(flags & JFS_FLAG_SAME_UUID))
11392                                         tagp += 16;
11393
11394                                 if (flags & JFS_FLAG_LAST_TAG)
11395                                         break;
11396                         }
11397
11398                         brelse(bh);
11399                         continue;
11400
11401                 case JFS_COMMIT_BLOCK:
11402                         /* Found an expected commit block: not much to
11403                          * do other than move on to the next sequence
11404                          * number. */
11405                         brelse(bh);
11406                         next_commit_ID++;
11407                         continue;
11408
11409                 case JFS_REVOKE_BLOCK:
11410                         /* If we aren't in the REVOKE pass, then we can
11411                          * just skip over this block. */
11412                         if (pass != PASS_REVOKE) {
11413                                 brelse(bh);
11414                                 continue;
11415                         }
11416
11417                         err = scan_revoke_records(journal, bh,
11418                                                   next_commit_ID, info);
11419                         brelse(bh);
11420                         if (err)
11421                                 goto failed;
11422                         continue;
11423
11424                 default:
11425                         goto done;
11426                 }
11427         }
11428
11429  done:
11430         /*
11431          * We broke out of the log scan loop: either we came to the
11432          * known end of the log or we found an unexpected block in the
11433          * log.  If the latter happened, then we know that the "current"
11434          * transaction marks the end of the valid log.
11435          */
11436
11437         if (pass == PASS_SCAN)
11438                 info->end_transaction = next_commit_ID;
11439         else {
11440                 /* It's really bad news if different passes end up at
11441                  * different places (but possible due to IO errors). */
11442                 if (info->end_transaction != next_commit_ID) {
11443                         printf ("JBD: recovery pass %d ended at "
11444                                 "transaction %u, expected %u\n",
11445                                 pass, next_commit_ID, info->end_transaction);
11446                         if (!success)
11447                                 success = -EIO;
11448                 }
11449         }
11450
11451         return success;
11452
11453  failed:
11454         return err;
11455 }
11456
11457
11458 /* Scan a revoke record, marking all blocks mentioned as revoked. */
11459
11460 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
11461                                tid_t sequence, struct recovery_info *info)
11462 {
11463         journal_revoke_header_t *header;
11464         int offset, max;
11465
11466         header = (journal_revoke_header_t *) bh->b_data;
11467         offset = sizeof(journal_revoke_header_t);
11468         max = ntohl(header->r_count);
11469
11470         while (offset < max) {
11471                 unsigned long blocknr;
11472                 int err;
11473
11474                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
11475                 offset += 4;
11476                 err = journal_set_revoke(journal, blocknr, sequence);
11477                 if (err)
11478                         return err;
11479                 ++info->nr_revokes;
11480         }
11481         return 0;
11482 }
11483
11484
11485 /*
11486  * rehash.c --- rebuild hash tree directories
11487  *
11488  * This algorithm is designed for simplicity of implementation and to
11489  * pack the directory as much as possible.  It however requires twice
11490  * as much memory as the size of the directory.  The maximum size
11491  * directory supported using a 4k blocksize is roughly a gigabyte, and
11492  * so there may very well be problems with machines that don't have
11493  * virtual memory, and obscenely large directories.
11494  *
11495  * An alternate algorithm which is much more disk intensive could be
11496  * written, and probably will need to be written in the future.  The
11497  * design goals of such an algorithm are: (a) use (roughly) constant
11498  * amounts of memory, no matter how large the directory, (b) the
11499  * directory must be safe at all times, even if e2fsck is interrupted
11500  * in the middle, (c) we must use minimal amounts of extra disk
11501  * blocks.  This pretty much requires an incremental approach, where
11502  * we are reading from one part of the directory, and inserting into
11503  * the front half.  So the algorithm will have to keep track of a
11504  * moving block boundary between the new tree and the old tree, and
11505  * files will need to be moved from the old directory and inserted
11506  * into the new tree.  If the new directory requires space which isn't
11507  * yet available, blocks from the beginning part of the old directory
11508  * may need to be moved to the end of the directory to make room for
11509  * the new tree:
11510  *
11511  *    --------------------------------------------------------
11512  *    |  new tree   |        | old tree                      |
11513  *    --------------------------------------------------------
11514  *                  ^ ptr    ^ptr
11515  *                tail new   head old
11516  *
11517  * This is going to be a pain in the tuckus to implement, and will
11518  * require a lot more disk accesses.  So I'm going to skip it for now;
11519  * it's only really going to be an issue for really, really big
11520  * filesystems (when we reach the level of tens of millions of files
11521  * in a single directory).  It will probably be easier to simply
11522  * require that e2fsck use VM first.
11523  */
11524
11525 struct fill_dir_struct {
11526         char *buf;
11527         struct ext2_inode *inode;
11528         int err;
11529         e2fsck_t ctx;
11530         struct hash_entry *harray;
11531         int max_array, num_array;
11532         int dir_size;
11533         int compress;
11534         ino_t parent;
11535 };
11536
11537 struct hash_entry {
11538         ext2_dirhash_t  hash;
11539         ext2_dirhash_t  minor_hash;
11540         struct ext2_dir_entry   *dir;
11541 };
11542
11543 struct out_dir {
11544         int             num;
11545         int             max;
11546         char            *buf;
11547         ext2_dirhash_t  *hashes;
11548 };
11549
11550 static int fill_dir_block(ext2_filsys fs,
11551                           blk_t *block_nr,
11552                           e2_blkcnt_t blockcnt,
11553                           blk_t ref_block FSCK_ATTR((unused)),
11554                           int ref_offset FSCK_ATTR((unused)),
11555                           void *priv_data)
11556 {
11557         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
11558         struct hash_entry       *new_array, *ent;
11559         struct ext2_dir_entry   *dirent;
11560         char                    *dir;
11561         unsigned int            offset, dir_offset;
11562
11563         if (blockcnt < 0)
11564                 return 0;
11565
11566         offset = blockcnt * fs->blocksize;
11567         if (offset + fs->blocksize > fd->inode->i_size) {
11568                 fd->err = EXT2_ET_DIR_CORRUPTED;
11569                 return BLOCK_ABORT;
11570         }
11571         dir = (fd->buf+offset);
11572         if (HOLE_BLKADDR(*block_nr)) {
11573                 memset(dir, 0, fs->blocksize);
11574                 dirent = (struct ext2_dir_entry *) dir;
11575                 dirent->rec_len = fs->blocksize;
11576         } else {
11577                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
11578                 if (fd->err)
11579                         return BLOCK_ABORT;
11580         }
11581         /* While the directory block is "hot", index it. */
11582         dir_offset = 0;
11583         while (dir_offset < fs->blocksize) {
11584                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
11585                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
11586                     (dirent->rec_len < 8) ||
11587                     ((dirent->rec_len % 4) != 0) ||
11588                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
11589                         fd->err = EXT2_ET_DIR_CORRUPTED;
11590                         return BLOCK_ABORT;
11591                 }
11592                 dir_offset += dirent->rec_len;
11593                 if (dirent->inode == 0)
11594                         continue;
11595                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
11596                     (dirent->name[0] == '.'))
11597                         continue;
11598                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
11599                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
11600                         fd->parent = dirent->inode;
11601                         continue;
11602                 }
11603                 if (fd->num_array >= fd->max_array) {
11604                         new_array = realloc(fd->harray,
11605                             sizeof(struct hash_entry) * (fd->max_array+500));
11606                         if (!new_array) {
11607                                 fd->err = ENOMEM;
11608                                 return BLOCK_ABORT;
11609                         }
11610                         fd->harray = new_array;
11611                         fd->max_array += 500;
11612                 }
11613                 ent = fd->harray + fd->num_array++;
11614                 ent->dir = dirent;
11615                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
11616                 if (fd->compress)
11617                         ent->hash = ent->minor_hash = 0;
11618                 else {
11619                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
11620                                                  dirent->name,
11621                                                  dirent->name_len & 0xFF,
11622                                                  fs->super->s_hash_seed,
11623                                                  &ent->hash, &ent->minor_hash);
11624                         if (fd->err)
11625                                 return BLOCK_ABORT;
11626                 }
11627         }
11628
11629         return 0;
11630 }
11631
11632 /* Used for sorting the hash entry */
11633 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
11634 {
11635         const struct hash_entry *he_a = (const struct hash_entry *) a;
11636         const struct hash_entry *he_b = (const struct hash_entry *) b;
11637         int     ret;
11638         int     min_len;
11639
11640         min_len = he_a->dir->name_len;
11641         if (min_len > he_b->dir->name_len)
11642                 min_len = he_b->dir->name_len;
11643
11644         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
11645         if (ret == 0) {
11646                 if (he_a->dir->name_len > he_b->dir->name_len)
11647                         ret = 1;
11648                 else if (he_a->dir->name_len < he_b->dir->name_len)
11649                         ret = -1;
11650                 else
11651                         ret = he_b->dir->inode - he_a->dir->inode;
11652         }
11653         return ret;
11654 }
11655
11656 /* Used for sorting the hash entry */
11657 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
11658 {
11659         const struct hash_entry *he_a = (const struct hash_entry *) a;
11660         const struct hash_entry *he_b = (const struct hash_entry *) b;
11661         int     ret;
11662
11663         if (he_a->hash > he_b->hash)
11664                 ret = 1;
11665         else if (he_a->hash < he_b->hash)
11666                 ret = -1;
11667         else {
11668                 if (he_a->minor_hash > he_b->minor_hash)
11669                         ret = 1;
11670                 else if (he_a->minor_hash < he_b->minor_hash)
11671                         ret = -1;
11672                 else
11673                         ret = name_cmp(a, b);
11674         }
11675         return ret;
11676 }
11677
11678 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
11679                                 int blocks)
11680 {
11681         void                    *new_mem;
11682
11683         if (outdir->max) {
11684                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
11685                 if (!new_mem)
11686                         return ENOMEM;
11687                 outdir->buf = new_mem;
11688                 new_mem = realloc(outdir->hashes,
11689                                   blocks * sizeof(ext2_dirhash_t));
11690                 if (!new_mem)
11691                         return ENOMEM;
11692                 outdir->hashes = new_mem;
11693         } else {
11694                 outdir->buf = malloc(blocks * fs->blocksize);
11695                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
11696                 outdir->num = 0;
11697         }
11698         outdir->max = blocks;
11699         return 0;
11700 }
11701
11702 static void free_out_dir(struct out_dir *outdir)
11703 {
11704         free(outdir->buf);
11705         free(outdir->hashes);
11706         outdir->max = 0;
11707         outdir->num =0;
11708 }
11709
11710 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
11711                          char ** ret)
11712 {
11713         errcode_t       retval;
11714
11715         if (outdir->num >= outdir->max) {
11716                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
11717                 if (retval)
11718                         return retval;
11719         }
11720         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
11721         memset(*ret, 0, fs->blocksize);
11722         return 0;
11723 }
11724
11725 /*
11726  * This function is used to make a unique filename.  We do this by
11727  * appending ~0, and then incrementing the number.  However, we cannot
11728  * expand the length of the filename beyond the padding available in
11729  * the directory entry.
11730  */
11731 static void mutate_name(char *str, __u16 *len)
11732 {
11733         int     i;
11734         __u16   l = *len & 0xFF, h = *len & 0xff00;
11735
11736         /*
11737          * First check to see if it looks the name has been mutated
11738          * already
11739          */
11740         for (i = l-1; i > 0; i--) {
11741                 if (!isdigit(str[i]))
11742                         break;
11743         }
11744         if ((i == l-1) || (str[i] != '~')) {
11745                 if (((l-1) & 3) < 2)
11746                         l += 2;
11747                 else
11748                         l = (l+3) & ~3;
11749                 str[l-2] = '~';
11750                 str[l-1] = '0';
11751                 *len = l | h;
11752                 return;
11753         }
11754         for (i = l-1; i >= 0; i--) {
11755                 if (isdigit(str[i])) {
11756                         if (str[i] == '9')
11757                                 str[i] = '0';
11758                         else {
11759                                 str[i]++;
11760                                 return;
11761                         }
11762                         continue;
11763                 }
11764                 if (i == 1) {
11765                         if (str[0] == 'z')
11766                                 str[0] = 'A';
11767                         else if (str[0] == 'Z') {
11768                                 str[0] = '~';
11769                                 str[1] = '0';
11770                         } else
11771                                 str[0]++;
11772                 } else if (i > 0) {
11773                         str[i] = '1';
11774                         str[i-1] = '~';
11775                 } else {
11776                         if (str[0] == '~')
11777                                 str[0] = 'a';
11778                         else
11779                                 str[0]++;
11780                 }
11781                 break;
11782         }
11783 }
11784
11785 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
11786                                     ext2_ino_t ino,
11787                                     struct fill_dir_struct *fd)
11788 {
11789         struct problem_context  pctx;
11790         struct hash_entry       *ent, *prev;
11791         int                     i, j;
11792         int                     fixed = 0;
11793         char                    new_name[256];
11794         __u16                   new_len;
11795
11796         clear_problem_context(&pctx);
11797         pctx.ino = ino;
11798
11799         for (i=1; i < fd->num_array; i++) {
11800                 ent = fd->harray + i;
11801                 prev = ent - 1;
11802                 if (!ent->dir->inode ||
11803                     ((ent->dir->name_len & 0xFF) !=
11804                      (prev->dir->name_len & 0xFF)) ||
11805                     (strncmp(ent->dir->name, prev->dir->name,
11806                              ent->dir->name_len & 0xFF)))
11807                         continue;
11808                 pctx.dirent = ent->dir;
11809                 if ((ent->dir->inode == prev->dir->inode) &&
11810                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
11811                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
11812                         ent->dir->inode = 0;
11813                         fixed++;
11814                         continue;
11815                 }
11816                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
11817                 new_len = ent->dir->name_len;
11818                 mutate_name(new_name, &new_len);
11819                 for (j=0; j < fd->num_array; j++) {
11820                         if ((i==j) ||
11821                             ((ent->dir->name_len & 0xFF) !=
11822                              (fd->harray[j].dir->name_len & 0xFF)) ||
11823                             (strncmp(new_name, fd->harray[j].dir->name,
11824                                      new_len & 0xFF)))
11825                                 continue;
11826                         mutate_name(new_name, &new_len);
11827
11828                         j = -1;
11829                 }
11830                 new_name[new_len & 0xFF] = 0;
11831                 pctx.str = new_name;
11832                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
11833                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
11834                         ent->dir->name_len = new_len;
11835                         ext2fs_dirhash(fs->super->s_def_hash_version,
11836                                        ent->dir->name,
11837                                        ent->dir->name_len & 0xFF,
11838                                        fs->super->s_hash_seed,
11839                                        &ent->hash, &ent->minor_hash);
11840                         fixed++;
11841                 }
11842         }
11843         return fixed;
11844 }
11845
11846
11847 static errcode_t copy_dir_entries(ext2_filsys fs,
11848                                   struct fill_dir_struct *fd,
11849                                   struct out_dir *outdir)
11850 {
11851         errcode_t               retval;
11852         char                    *block_start;
11853         struct hash_entry       *ent;
11854         struct ext2_dir_entry   *dirent;
11855         int                     i, rec_len, left;
11856         ext2_dirhash_t          prev_hash;
11857         int                     offset;
11858
11859         outdir->max = 0;
11860         retval = alloc_size_dir(fs, outdir,
11861                                 (fd->dir_size / fs->blocksize) + 2);
11862         if (retval)
11863                 return retval;
11864         outdir->num = fd->compress ? 0 : 1;
11865         offset = 0;
11866         outdir->hashes[0] = 0;
11867         prev_hash = 1;
11868         if ((retval = get_next_block(fs, outdir, &block_start)))
11869                 return retval;
11870         dirent = (struct ext2_dir_entry *) block_start;
11871         left = fs->blocksize;
11872         for (i=0; i < fd->num_array; i++) {
11873                 ent = fd->harray + i;
11874                 if (ent->dir->inode == 0)
11875                         continue;
11876                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
11877                 if (rec_len > left) {
11878                         if (left)
11879                                 dirent->rec_len += left;
11880                         if ((retval = get_next_block(fs, outdir,
11881                                                       &block_start)))
11882                                 return retval;
11883                         offset = 0;
11884                 }
11885                 left = fs->blocksize - offset;
11886                 dirent = (struct ext2_dir_entry *) (block_start + offset);
11887                 if (offset == 0) {
11888                         if (ent->hash == prev_hash)
11889                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
11890                         else
11891                                 outdir->hashes[outdir->num-1] = ent->hash;
11892                 }
11893                 dirent->inode = ent->dir->inode;
11894                 dirent->name_len = ent->dir->name_len;
11895                 dirent->rec_len = rec_len;
11896                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
11897                 offset += rec_len;
11898                 left -= rec_len;
11899                 if (left < 12) {
11900                         dirent->rec_len += left;
11901                         offset += left;
11902                         left = 0;
11903                 }
11904                 prev_hash = ent->hash;
11905         }
11906         if (left)
11907                 dirent->rec_len += left;
11908
11909         return 0;
11910 }
11911
11912
11913 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
11914                                     ext2_ino_t ino, ext2_ino_t parent)
11915 {
11916         struct ext2_dir_entry           *dir;
11917         struct ext2_dx_root_info        *root;
11918         struct ext2_dx_countlimit       *limits;
11919         int                             filetype = 0;
11920
11921         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
11922                 filetype = EXT2_FT_DIR << 8;
11923
11924         memset(buf, 0, fs->blocksize);
11925         dir = (struct ext2_dir_entry *) buf;
11926         dir->inode = ino;
11927         dir->name[0] = '.';
11928         dir->name_len = 1 | filetype;
11929         dir->rec_len = 12;
11930         dir = (struct ext2_dir_entry *) (buf + 12);
11931         dir->inode = parent;
11932         dir->name[0] = '.';
11933         dir->name[1] = '.';
11934         dir->name_len = 2 | filetype;
11935         dir->rec_len = fs->blocksize - 12;
11936
11937         root = (struct ext2_dx_root_info *) (buf+24);
11938         root->reserved_zero = 0;
11939         root->hash_version = fs->super->s_def_hash_version;
11940         root->info_length = 8;
11941         root->indirect_levels = 0;
11942         root->unused_flags = 0;
11943
11944         limits = (struct ext2_dx_countlimit *) (buf+32);
11945         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
11946         limits->count = 0;
11947
11948         return root;
11949 }
11950
11951
11952 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
11953 {
11954         struct ext2_dir_entry           *dir;
11955         struct ext2_dx_countlimit       *limits;
11956
11957         memset(buf, 0, fs->blocksize);
11958         dir = (struct ext2_dir_entry *) buf;
11959         dir->inode = 0;
11960         dir->rec_len = fs->blocksize;
11961
11962         limits = (struct ext2_dx_countlimit *) (buf+8);
11963         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
11964         limits->count = 0;
11965
11966         return (struct ext2_dx_entry *) limits;
11967 }
11968
11969 /*
11970  * This function takes the leaf nodes which have been written in
11971  * outdir, and populates the root node and any necessary interior nodes.
11972  */
11973 static errcode_t calculate_tree(ext2_filsys fs,
11974                                 struct out_dir *outdir,
11975                                 ext2_ino_t ino,
11976                                 ext2_ino_t parent)
11977 {
11978         struct ext2_dx_root_info        *root_info;
11979         struct ext2_dx_entry            *root, *dx_ent = 0;
11980         struct ext2_dx_countlimit       *root_limit, *limit;
11981         errcode_t                       retval;
11982         char                            * block_start;
11983         int                             i, c1, c2, nblks;
11984         int                             limit_offset, root_offset;
11985
11986         root_info = set_root_node(fs, outdir->buf, ino, parent);
11987         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
11988                 root_info->info_length;
11989         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
11990         c1 = root_limit->limit;
11991         nblks = outdir->num;
11992
11993         /* Write out the pointer blocks */
11994         if (nblks-1 <= c1) {
11995                 /* Just write out the root block, and we're done */
11996                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
11997                 for (i=1; i < nblks; i++) {
11998                         root->block = ext2fs_cpu_to_le32(i);
11999                         if (i != 1)
12000                                 root->hash =
12001                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12002                         root++;
12003                         c1--;
12004                 }
12005         } else {
12006                 c2 = 0;
12007                 limit = 0;
12008                 root_info->indirect_levels = 1;
12009                 for (i=1; i < nblks; i++) {
12010                         if (c1 == 0)
12011                                 return ENOSPC;
12012                         if (c2 == 0) {
12013                                 if (limit)
12014                                         limit->limit = limit->count =
12015                 ext2fs_cpu_to_le16(limit->limit);
12016                                 root = (struct ext2_dx_entry *)
12017                                         (outdir->buf + root_offset);
12018                                 root->block = ext2fs_cpu_to_le32(outdir->num);
12019                                 if (i != 1)
12020                                         root->hash =
12021                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12022                                 if ((retval =  get_next_block(fs, outdir,
12023                                                               &block_start)))
12024                                         return retval;
12025                                 dx_ent = set_int_node(fs, block_start);
12026                                 limit = (struct ext2_dx_countlimit *) dx_ent;
12027                                 c2 = limit->limit;
12028                                 root_offset += sizeof(struct ext2_dx_entry);
12029                                 c1--;
12030                         }
12031                         dx_ent->block = ext2fs_cpu_to_le32(i);
12032                         if (c2 != limit->limit)
12033                                 dx_ent->hash =
12034                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12035                         dx_ent++;
12036                         c2--;
12037                 }
12038                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12039                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12040         }
12041         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12042         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12043         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12044
12045         return 0;
12046 }
12047
12048 struct write_dir_struct {
12049         struct out_dir *outdir;
12050         errcode_t       err;
12051         e2fsck_t        ctx;
12052         int             cleared;
12053 };
12054
12055 /*
12056  * Helper function which writes out a directory block.
12057  */
12058 static int write_dir_block(ext2_filsys fs,
12059                            blk_t        *block_nr,
12060                            e2_blkcnt_t blockcnt,
12061                            blk_t ref_block FSCK_ATTR((unused)),
12062                            int ref_offset FSCK_ATTR((unused)),
12063                            void *priv_data)
12064 {
12065         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12066         blk_t   blk;
12067         char    *dir;
12068
12069         if (*block_nr == 0)
12070                 return 0;
12071         if (blockcnt >= wd->outdir->num) {
12072                 e2fsck_read_bitmaps(wd->ctx);
12073                 blk = *block_nr;
12074                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12075                 ext2fs_block_alloc_stats(fs, blk, -1);
12076                 *block_nr = 0;
12077                 wd->cleared++;
12078                 return BLOCK_CHANGED;
12079         }
12080         if (blockcnt < 0)
12081                 return 0;
12082
12083         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12084         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12085         if (wd->err)
12086                 return BLOCK_ABORT;
12087         return 0;
12088 }
12089
12090 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12091                                  struct out_dir *outdir,
12092                                  ext2_ino_t ino, int compress)
12093 {
12094         struct write_dir_struct wd;
12095         errcode_t       retval;
12096         struct ext2_inode       inode;
12097
12098         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12099         if (retval)
12100                 return retval;
12101
12102         wd.outdir = outdir;
12103         wd.err = 0;
12104         wd.ctx = ctx;
12105         wd.cleared = 0;
12106
12107         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12108                                        write_dir_block, &wd);
12109         if (retval)
12110                 return retval;
12111         if (wd.err)
12112                 return wd.err;
12113
12114         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12115         if (compress)
12116                 inode.i_flags &= ~EXT2_INDEX_FL;
12117         else
12118                 inode.i_flags |= EXT2_INDEX_FL;
12119         inode.i_size = outdir->num * fs->blocksize;
12120         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12121         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12122
12123         return 0;
12124 }
12125
12126 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12127 {
12128         ext2_filsys             fs = ctx->fs;
12129         errcode_t               retval;
12130         struct ext2_inode       inode;
12131         char                    *dir_buf = 0;
12132         struct fill_dir_struct  fd;
12133         struct out_dir          outdir;
12134
12135         outdir.max = outdir.num = 0;
12136         outdir.buf = 0;
12137         outdir.hashes = 0;
12138         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12139
12140         retval = ENOMEM;
12141         fd.harray = 0;
12142         dir_buf = malloc(inode.i_size);
12143         if (!dir_buf)
12144                 goto errout;
12145
12146         fd.max_array = inode.i_size / 32;
12147         fd.num_array = 0;
12148         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12149         if (!fd.harray)
12150                 goto errout;
12151
12152         fd.ctx = ctx;
12153         fd.buf = dir_buf;
12154         fd.inode = &inode;
12155         fd.err = 0;
12156         fd.dir_size = 0;
12157         fd.compress = 0;
12158         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12159             (inode.i_size / fs->blocksize) < 2)
12160                 fd.compress = 1;
12161         fd.parent = 0;
12162
12163         /* Read in the entire directory into memory */
12164         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12165                                        fill_dir_block, &fd);
12166         if (fd.err) {
12167                 retval = fd.err;
12168                 goto errout;
12169         }
12170
12171         /* Sort the list */
12172 resort:
12173         if (fd.compress)
12174                 qsort(fd.harray+2, fd.num_array-2,
12175                       sizeof(struct hash_entry), name_cmp);
12176         else
12177                 qsort(fd.harray, fd.num_array,
12178                       sizeof(struct hash_entry), hash_cmp);
12179
12180         /*
12181          * Look for duplicates
12182          */
12183         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12184                 goto resort;
12185
12186         if (ctx->options & E2F_OPT_NO) {
12187                 retval = 0;
12188                 goto errout;
12189         }
12190
12191         /*
12192          * Copy the directory entries.  In a htree directory these
12193          * will become the leaf nodes.
12194          */
12195         retval = copy_dir_entries(fs, &fd, &outdir);
12196         if (retval)
12197                 goto errout;
12198
12199         free(dir_buf); dir_buf = 0;
12200
12201         if (!fd.compress) {
12202                 /* Calculate the interior nodes */
12203                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12204                 if (retval)
12205                         goto errout;
12206         }
12207
12208         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12209
12210 errout:
12211         free(dir_buf);
12212         free(fd.harray);
12213
12214         free_out_dir(&outdir);
12215         return retval;
12216 }
12217
12218 void e2fsck_rehash_directories(e2fsck_t ctx)
12219 {
12220         struct problem_context  pctx;
12221         struct dir_info         *dir;
12222         ext2_u32_iterate        iter;
12223         ext2_ino_t              ino;
12224         errcode_t               retval;
12225         int                     i, cur, max, all_dirs, dir_index, first = 1;
12226
12227         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12228
12229         if (!ctx->dirs_to_hash && !all_dirs)
12230                 return;
12231
12232         e2fsck_get_lost_and_found(ctx, 0);
12233
12234         clear_problem_context(&pctx);
12235
12236         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12237         cur = 0;
12238         if (all_dirs) {
12239                 i = 0;
12240                 max = e2fsck_get_num_dirinfo(ctx);
12241         } else {
12242                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12243                                                        &iter);
12244                 if (retval) {
12245                         pctx.errcode = retval;
12246                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12247                         return;
12248                 }
12249                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12250         }
12251         while (1) {
12252                 if (all_dirs) {
12253                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12254                                 break;
12255                         ino = dir->ino;
12256                 } else {
12257                         if (!ext2fs_u32_list_iterate(iter, &ino))
12258                                 break;
12259                 }
12260                 if (ino == ctx->lost_and_found)
12261                         continue;
12262                 pctx.dir = ino;
12263                 if (first) {
12264                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12265                         first = 0;
12266                 }
12267                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12268                 if (pctx.errcode) {
12269                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12270                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12271                 }
12272                 if (ctx->progress && !ctx->progress_fd)
12273                         e2fsck_simple_progress(ctx, "Rebuilding directory",
12274                                100.0 * (float) (++cur) / (float) max, ino);
12275         }
12276         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12277         if (!all_dirs)
12278                 ext2fs_u32_list_iterate_end(iter);
12279
12280         ext2fs_u32_list_free(ctx->dirs_to_hash);
12281         ctx->dirs_to_hash = 0;
12282 }
12283
12284 /*
12285  * linux/fs/revoke.c
12286  *
12287  * Journal revoke routines for the generic filesystem journaling code;
12288  * part of the ext2fs journaling system.
12289  *
12290  * Revoke is the mechanism used to prevent old log records for deleted
12291  * metadata from being replayed on top of newer data using the same
12292  * blocks.  The revoke mechanism is used in two separate places:
12293  *
12294  * + Commit: during commit we write the entire list of the current
12295  *   transaction's revoked blocks to the journal
12296  *
12297  * + Recovery: during recovery we record the transaction ID of all
12298  *   revoked blocks.  If there are multiple revoke records in the log
12299  *   for a single block, only the last one counts, and if there is a log
12300  *   entry for a block beyond the last revoke, then that log entry still
12301  *   gets replayed.
12302  *
12303  * We can get interactions between revokes and new log data within a
12304  * single transaction:
12305  *
12306  * Block is revoked and then journaled:
12307  *   The desired end result is the journaling of the new block, so we
12308  *   cancel the revoke before the transaction commits.
12309  *
12310  * Block is journaled and then revoked:
12311  *   The revoke must take precedence over the write of the block, so we
12312  *   need either to cancel the journal entry or to write the revoke
12313  *   later in the log than the log block.  In this case, we choose the
12314  *   latter: journaling a block cancels any revoke record for that block
12315  *   in the current transaction, so any revoke for that block in the
12316  *   transaction must have happened after the block was journaled and so
12317  *   the revoke must take precedence.
12318  *
12319  * Block is revoked and then written as data:
12320  *   The data write is allowed to succeed, but the revoke is _not_
12321  *   cancelled.  We still need to prevent old log records from
12322  *   overwriting the new data.  We don't even need to clear the revoke
12323  *   bit here.
12324  *
12325  * Revoke information on buffers is a tri-state value:
12326  *
12327  * RevokeValid clear:   no cached revoke status, need to look it up
12328  * RevokeValid set, Revoked clear:
12329  *                      buffer has not been revoked, and cancel_revoke
12330  *                      need do nothing.
12331  * RevokeValid set, Revoked set:
12332  *                      buffer has been revoked.
12333  */
12334
12335 static kmem_cache_t *revoke_record_cache;
12336 static kmem_cache_t *revoke_table_cache;
12337
12338 /* Each revoke record represents one single revoked block.  During
12339    journal replay, this involves recording the transaction ID of the
12340    last transaction to revoke this block. */
12341
12342 struct jbd_revoke_record_s
12343 {
12344         struct list_head  hash;
12345         tid_t             sequence;     /* Used for recovery only */
12346         unsigned long     blocknr;
12347 };
12348
12349
12350 /* The revoke table is just a simple hash table of revoke records. */
12351 struct jbd_revoke_table_s
12352 {
12353         /* It is conceivable that we might want a larger hash table
12354          * for recovery.  Must be a power of two. */
12355         int               hash_size;
12356         int               hash_shift;
12357         struct list_head *hash_table;
12358 };
12359
12360
12361 /* Utility functions to maintain the revoke table */
12362
12363 /* Borrowed from buffer.c: this is a tried and tested block hash function */
12364 static inline int hash(journal_t *journal, unsigned long block)
12365 {
12366         struct jbd_revoke_table_s *table = journal->j_revoke;
12367         int hash_shift = table->hash_shift;
12368
12369         return ((block << (hash_shift - 6)) ^
12370                 (block >> 13) ^
12371                 (block << (hash_shift - 12))) & (table->hash_size - 1);
12372 }
12373
12374 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
12375                               tid_t seq)
12376 {
12377         struct list_head *hash_list;
12378         struct jbd_revoke_record_s *record;
12379
12380         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
12381         if (!record)
12382                 goto oom;
12383
12384         record->sequence = seq;
12385         record->blocknr = blocknr;
12386         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
12387         list_add(&record->hash, hash_list);
12388         return 0;
12389
12390 oom:
12391         return -ENOMEM;
12392 }
12393
12394 /* Find a revoke record in the journal's hash table. */
12395
12396 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
12397                                                       unsigned long blocknr)
12398 {
12399         struct list_head *hash_list;
12400         struct jbd_revoke_record_s *record;
12401
12402         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
12403
12404         record = (struct jbd_revoke_record_s *) hash_list->next;
12405         while (&(record->hash) != hash_list) {
12406                 if (record->blocknr == blocknr)
12407                         return record;
12408                 record = (struct jbd_revoke_record_s *) record->hash.next;
12409         }
12410         return NULL;
12411 }
12412
12413 int journal_init_revoke_caches(void)
12414 {
12415         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
12416         if (revoke_record_cache == 0)
12417                 return -ENOMEM;
12418
12419         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
12420         if (revoke_table_cache == 0) {
12421                 do_cache_destroy(revoke_record_cache);
12422                 revoke_record_cache = NULL;
12423                 return -ENOMEM;
12424         }
12425         return 0;
12426 }
12427
12428 void journal_destroy_revoke_caches(void)
12429 {
12430         do_cache_destroy(revoke_record_cache);
12431         revoke_record_cache = 0;
12432         do_cache_destroy(revoke_table_cache);
12433         revoke_table_cache = 0;
12434 }
12435
12436 /* Initialise the revoke table for a given journal to a given size. */
12437
12438 int journal_init_revoke(journal_t *journal, int hash_size)
12439 {
12440         int shift, tmp;
12441
12442         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
12443         if (!journal->j_revoke)
12444                 return -ENOMEM;
12445
12446         /* Check that the hash_size is a power of two */
12447         journal->j_revoke->hash_size = hash_size;
12448
12449         shift = 0;
12450         tmp = hash_size;
12451         while((tmp >>= 1UL) != 0UL)
12452                 shift++;
12453         journal->j_revoke->hash_shift = shift;
12454
12455         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
12456         if (!journal->j_revoke->hash_table) {
12457                 free(journal->j_revoke);
12458                 journal->j_revoke = NULL;
12459                 return -ENOMEM;
12460         }
12461
12462         for (tmp = 0; tmp < hash_size; tmp++)
12463                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
12464
12465         return 0;
12466 }
12467
12468 /* Destoy a journal's revoke table.  The table must already be empty! */
12469
12470 void journal_destroy_revoke(journal_t *journal)
12471 {
12472         struct jbd_revoke_table_s *table;
12473         struct list_head *hash_list;
12474         int i;
12475
12476         table = journal->j_revoke;
12477         if (!table)
12478                 return;
12479
12480         for (i=0; i<table->hash_size; i++) {
12481                 hash_list = &table->hash_table[i];
12482         }
12483
12484         free(table->hash_table);
12485         free(table);
12486         journal->j_revoke = NULL;
12487 }
12488
12489 /*
12490  * Revoke support for recovery.
12491  *
12492  * Recovery needs to be able to:
12493  *
12494  *  record all revoke records, including the tid of the latest instance
12495  *  of each revoke in the journal
12496  *
12497  *  check whether a given block in a given transaction should be replayed
12498  *  (ie. has not been revoked by a revoke record in that or a subsequent
12499  *  transaction)
12500  *
12501  *  empty the revoke table after recovery.
12502  */
12503
12504 /*
12505  * First, setting revoke records.  We create a new revoke record for
12506  * every block ever revoked in the log as we scan it for recovery, and
12507  * we update the existing records if we find multiple revokes for a
12508  * single block.
12509  */
12510
12511 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
12512                        tid_t sequence)
12513 {
12514         struct jbd_revoke_record_s *record;
12515
12516         record = find_revoke_record(journal, blocknr);
12517         if (record) {
12518                 /* If we have multiple occurences, only record the
12519                  * latest sequence number in the hashed record */
12520                 if (tid_gt(sequence, record->sequence))
12521                         record->sequence = sequence;
12522                 return 0;
12523         }
12524         return insert_revoke_hash(journal, blocknr, sequence);
12525 }
12526
12527 /*
12528  * Test revoke records.  For a given block referenced in the log, has
12529  * that block been revoked?  A revoke record with a given transaction
12530  * sequence number revokes all blocks in that transaction and earlier
12531  * ones, but later transactions still need replayed.
12532  */
12533
12534 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
12535                         tid_t sequence)
12536 {
12537         struct jbd_revoke_record_s *record;
12538
12539         record = find_revoke_record(journal, blocknr);
12540         if (!record)
12541                 return 0;
12542         if (tid_gt(sequence, record->sequence))
12543                 return 0;
12544         return 1;
12545 }
12546
12547 /*
12548  * Finally, once recovery is over, we need to clear the revoke table so
12549  * that it can be reused by the running filesystem.
12550  */
12551
12552 void journal_clear_revoke(journal_t *journal)
12553 {
12554         int i;
12555         struct list_head *hash_list;
12556         struct jbd_revoke_record_s *record;
12557         struct jbd_revoke_table_s *revoke_var;
12558
12559         revoke_var = journal->j_revoke;
12560
12561         for (i = 0; i < revoke_var->hash_size; i++) {
12562                 hash_list = &revoke_var->hash_table[i];
12563                 while (!list_empty(hash_list)) {
12564                         record = (struct jbd_revoke_record_s*) hash_list->next;
12565                         list_del(&record->hash);
12566                         free(record);
12567                 }
12568         }
12569 }
12570
12571 /*
12572  * e2fsck.c - superblock checks
12573  */
12574
12575 #define MIN_CHECK 1
12576 #define MAX_CHECK 2
12577
12578 static void check_super_value(e2fsck_t ctx, const char *descr,
12579                               unsigned long value, int flags,
12580                               unsigned long min_val, unsigned long max_val)
12581 {
12582         struct          problem_context pctx;
12583
12584         if (((flags & MIN_CHECK) && (value < min_val)) ||
12585             ((flags & MAX_CHECK) && (value > max_val))) {
12586                 clear_problem_context(&pctx);
12587                 pctx.num = value;
12588                 pctx.str = descr;
12589                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
12590                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
12591         }
12592 }
12593
12594 /*
12595  * This routine may get stubbed out in special compilations of the
12596  * e2fsck code..
12597  */
12598 #ifndef EXT2_SPECIAL_DEVICE_SIZE
12599 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
12600 {
12601         return (ext2fs_get_device_size(ctx->filesystem_name,
12602                                        EXT2_BLOCK_SIZE(ctx->fs->super),
12603                                        &ctx->num_blocks));
12604 }
12605 #endif
12606
12607 /*
12608  * helper function to release an inode
12609  */
12610 struct process_block_struct {
12611         e2fsck_t        ctx;
12612         char            *buf;
12613         struct problem_context *pctx;
12614         int             truncating;
12615         int             truncate_offset;
12616         e2_blkcnt_t     truncate_block;
12617         int             truncated_blocks;
12618         int             abort;
12619         errcode_t       errcode;
12620 };
12621
12622 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
12623                                e2_blkcnt_t blockcnt,
12624                                blk_t    ref_blk FSCK_ATTR((unused)),
12625                                int      ref_offset FSCK_ATTR((unused)),
12626                                void *priv_data)
12627 {
12628         struct process_block_struct *pb;
12629         e2fsck_t                ctx;
12630         struct problem_context  *pctx;
12631         blk_t                   blk = *block_nr;
12632         int                     retval = 0;
12633
12634         pb = (struct process_block_struct *) priv_data;
12635         ctx = pb->ctx;
12636         pctx = pb->pctx;
12637
12638         pctx->blk = blk;
12639         pctx->blkcount = blockcnt;
12640
12641         if (HOLE_BLKADDR(blk))
12642                 return 0;
12643
12644         if ((blk < fs->super->s_first_data_block) ||
12645             (blk >= fs->super->s_blocks_count)) {
12646                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
12647         return_abort:
12648                 pb->abort = 1;
12649                 return BLOCK_ABORT;
12650         }
12651
12652         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
12653                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
12654                 goto return_abort;
12655         }
12656
12657         /*
12658          * If we are deleting an orphan, then we leave the fields alone.
12659          * If we are truncating an orphan, then update the inode fields
12660          * and clean up any partial block data.
12661          */
12662         if (pb->truncating) {
12663                 /*
12664                  * We only remove indirect blocks if they are
12665                  * completely empty.
12666                  */
12667                 if (blockcnt < 0) {
12668                         int     i, limit;
12669                         blk_t   *bp;
12670
12671                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
12672                                                         pb->buf);
12673                         if (pb->errcode)
12674                                 goto return_abort;
12675
12676                         limit = fs->blocksize >> 2;
12677                         for (i = 0, bp = (blk_t *) pb->buf;
12678                              i < limit;  i++, bp++)
12679                                 if (*bp)
12680                                         return 0;
12681                 }
12682                 /*
12683                  * We don't remove direct blocks until we've reached
12684                  * the truncation block.
12685                  */
12686                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
12687                         return 0;
12688                 /*
12689                  * If part of the last block needs truncating, we do
12690                  * it here.
12691                  */
12692                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
12693                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
12694                                                         pb->buf);
12695                         if (pb->errcode)
12696                                 goto return_abort;
12697                         memset(pb->buf + pb->truncate_offset, 0,
12698                                fs->blocksize - pb->truncate_offset);
12699                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
12700                                                          pb->buf);
12701                         if (pb->errcode)
12702                                 goto return_abort;
12703                 }
12704                 pb->truncated_blocks++;
12705                 *block_nr = 0;
12706                 retval |= BLOCK_CHANGED;
12707         }
12708
12709         ext2fs_block_alloc_stats(fs, blk, -1);
12710         return retval;
12711 }
12712
12713 /*
12714  * This function releases an inode.  Returns 1 if an inconsistency was
12715  * found.  If the inode has a link count, then it is being truncated and
12716  * not deleted.
12717  */
12718 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
12719                                 struct ext2_inode *inode, char *block_buf,
12720                                 struct problem_context *pctx)
12721 {
12722         struct process_block_struct     pb;
12723         ext2_filsys                     fs = ctx->fs;
12724         errcode_t                       retval;
12725         __u32                           count;
12726
12727         if (!ext2fs_inode_has_valid_blocks(inode))
12728                 return 0;
12729
12730         pb.buf = block_buf + 3 * ctx->fs->blocksize;
12731         pb.ctx = ctx;
12732         pb.abort = 0;
12733         pb.errcode = 0;
12734         pb.pctx = pctx;
12735         if (inode->i_links_count) {
12736                 pb.truncating = 1;
12737                 pb.truncate_block = (e2_blkcnt_t)
12738                         ((((long long)inode->i_size_high << 32) +
12739                           inode->i_size + fs->blocksize - 1) /
12740                          fs->blocksize);
12741                 pb.truncate_offset = inode->i_size % fs->blocksize;
12742         } else {
12743                 pb.truncating = 0;
12744                 pb.truncate_block = 0;
12745                 pb.truncate_offset = 0;
12746         }
12747         pb.truncated_blocks = 0;
12748         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
12749                                       block_buf, release_inode_block, &pb);
12750         if (retval) {
12751                 com_err("release_inode_blocks", retval,
12752                         _("while calling ext2fs_block_iterate for inode %d"),
12753                         ino);
12754                 return 1;
12755         }
12756         if (pb.abort)
12757                 return 1;
12758
12759         /* Refresh the inode since ext2fs_block_iterate may have changed it */
12760         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
12761
12762         if (pb.truncated_blocks)
12763                 inode->i_blocks -= pb.truncated_blocks *
12764                         (fs->blocksize / 512);
12765
12766         if (inode->i_file_acl) {
12767                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
12768                                                    block_buf, -1, &count);
12769                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
12770                         retval = 0;
12771                         count = 1;
12772                 }
12773                 if (retval) {
12774                         com_err("release_inode_blocks", retval,
12775                 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
12776                                 ino);
12777                         return 1;
12778                 }
12779                 if (count == 0)
12780                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
12781                 inode->i_file_acl = 0;
12782         }
12783         return 0;
12784 }
12785
12786 /*
12787  * This function releases all of the orphan inodes.  It returns 1 if
12788  * it hit some error, and 0 on success.
12789  */
12790 static int release_orphan_inodes(e2fsck_t ctx)
12791 {
12792         ext2_filsys fs = ctx->fs;
12793         ext2_ino_t      ino, next_ino;
12794         struct ext2_inode inode;
12795         struct problem_context pctx;
12796         char *block_buf;
12797
12798         if ((ino = fs->super->s_last_orphan) == 0)
12799                 return 0;
12800
12801         /*
12802          * Win or lose, we won't be using the head of the orphan inode
12803          * list again.
12804          */
12805         fs->super->s_last_orphan = 0;
12806         ext2fs_mark_super_dirty(fs);
12807
12808         /*
12809          * If the filesystem contains errors, don't run the orphan
12810          * list, since the orphan list can't be trusted; and we're
12811          * going to be running a full e2fsck run anyway...
12812          */
12813         if (fs->super->s_state & EXT2_ERROR_FS)
12814                 return 0;
12815
12816         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
12817             (ino > fs->super->s_inodes_count)) {
12818                 clear_problem_context(&pctx);
12819                 pctx.ino = ino;
12820                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
12821                 return 1;
12822         }
12823
12824         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12825                                                     "block iterate buffer");
12826         e2fsck_read_bitmaps(ctx);
12827
12828         while (ino) {
12829                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
12830                 clear_problem_context(&pctx);
12831                 pctx.ino = ino;
12832                 pctx.inode = &inode;
12833                 pctx.str = inode.i_links_count ? _("Truncating") :
12834                         _("Clearing");
12835
12836                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
12837
12838                 next_ino = inode.i_dtime;
12839                 if (next_ino &&
12840                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
12841                      (next_ino > fs->super->s_inodes_count))) {
12842                         pctx.ino = next_ino;
12843                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
12844                         goto return_abort;
12845                 }
12846
12847                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
12848                         goto return_abort;
12849
12850                 if (!inode.i_links_count) {
12851                         ext2fs_inode_alloc_stats2(fs, ino, -1,
12852                                                   LINUX_S_ISDIR(inode.i_mode));
12853                         inode.i_dtime = time(0);
12854                 } else {
12855                         inode.i_dtime = 0;
12856                 }
12857                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
12858                 ino = next_ino;
12859         }
12860         ext2fs_free_mem(&block_buf);
12861         return 0;
12862 return_abort:
12863         ext2fs_free_mem(&block_buf);
12864         return 1;
12865 }
12866
12867 /*
12868  * Check the resize inode to make sure it is sane.  We check both for
12869  * the case where on-line resizing is not enabled (in which case the
12870  * resize inode should be cleared) as well as the case where on-line
12871  * resizing is enabled.
12872  */
12873 static void check_resize_inode(e2fsck_t ctx)
12874 {
12875         ext2_filsys fs = ctx->fs;
12876         struct ext2_inode inode;
12877         struct problem_context  pctx;
12878         int             i, j, gdt_off, ind_off;
12879         blk_t           blk, pblk, expect;
12880         __u32           *dind_buf = 0, *ind_buf;
12881         errcode_t       retval;
12882
12883         clear_problem_context(&pctx);
12884
12885         /*
12886          * If the resize inode feature isn't set, then
12887          * s_reserved_gdt_blocks must be zero.
12888          */
12889         if (!(fs->super->s_feature_compat &
12890               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
12891                 if (fs->super->s_reserved_gdt_blocks) {
12892                         pctx.num = fs->super->s_reserved_gdt_blocks;
12893                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
12894                                         &pctx)) {
12895                                 fs->super->s_reserved_gdt_blocks = 0;
12896                                 ext2fs_mark_super_dirty(fs);
12897                         }
12898                 }
12899         }
12900
12901         /* Read the resize inode */
12902         pctx.ino = EXT2_RESIZE_INO;
12903         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
12904         if (retval) {
12905                 if (fs->super->s_feature_compat &
12906                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
12907                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
12908                 return;
12909         }
12910
12911         /*
12912          * If the resize inode feature isn't set, check to make sure
12913          * the resize inode is cleared; then we're done.
12914          */
12915         if (!(fs->super->s_feature_compat &
12916               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
12917                 for (i=0; i < EXT2_N_BLOCKS; i++) {
12918                         if (inode.i_block[i])
12919                                 break;
12920                 }
12921                 if ((i < EXT2_N_BLOCKS) &&
12922                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
12923                         memset(&inode, 0, sizeof(inode));
12924                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
12925                                            "clear_resize");
12926                 }
12927                 return;
12928         }
12929
12930         /*
12931          * The resize inode feature is enabled; check to make sure the
12932          * only block in use is the double indirect block
12933          */
12934         blk = inode.i_block[EXT2_DIND_BLOCK];
12935         for (i=0; i < EXT2_N_BLOCKS; i++) {
12936                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
12937                         break;
12938         }
12939         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
12940             !(inode.i_mode & LINUX_S_IFREG) ||
12941             (blk < fs->super->s_first_data_block ||
12942              blk >= fs->super->s_blocks_count)) {
12943         resize_inode_invalid:
12944                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
12945                         memset(&inode, 0, sizeof(inode));
12946                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
12947                                            "clear_resize");
12948                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
12949                 }
12950                 if (!(ctx->options & E2F_OPT_READONLY)) {
12951                         fs->super->s_state &= ~EXT2_VALID_FS;
12952                         ext2fs_mark_super_dirty(fs);
12953                 }
12954                 goto cleanup;
12955         }
12956         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
12957                                                     "resize dind buffer");
12958         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
12959
12960         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
12961         if (retval)
12962                 goto resize_inode_invalid;
12963
12964         gdt_off = fs->desc_blocks;
12965         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
12966         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
12967              i++, gdt_off++, pblk++) {
12968                 gdt_off %= fs->blocksize/4;
12969                 if (dind_buf[gdt_off] != pblk)
12970                         goto resize_inode_invalid;
12971                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
12972                 if (retval)
12973                         goto resize_inode_invalid;
12974                 ind_off = 0;
12975                 for (j = 1; j < fs->group_desc_count; j++) {
12976                         if (!ext2fs_bg_has_super(fs, j))
12977                                 continue;
12978                         expect = pblk + (j * fs->super->s_blocks_per_group);
12979                         if (ind_buf[ind_off] != expect)
12980                                 goto resize_inode_invalid;
12981                         ind_off++;
12982                 }
12983         }
12984
12985 cleanup:
12986         ext2fs_free_mem(&dind_buf);
12987
12988  }
12989
12990 static void check_super_block(e2fsck_t ctx)
12991 {
12992         ext2_filsys fs = ctx->fs;
12993         blk_t   first_block, last_block;
12994         struct ext2_super_block *sb = fs->super;
12995         struct ext2_group_desc *gd;
12996         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
12997         blk_t   bpg_max;
12998         int     inodes_per_block;
12999         int     ipg_max;
13000         int     inode_size;
13001         dgrp_t  i;
13002         blk_t   should_be;
13003         struct problem_context  pctx;
13004         __u32   free_blocks = 0, free_inodes = 0;
13005
13006         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13007         ipg_max = inodes_per_block * (blocks_per_group - 4);
13008         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13009                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13010         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13011         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13012                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13013
13014         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13015                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13016         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13017                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13018         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13019                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13020
13021         clear_problem_context(&pctx);
13022
13023         /*
13024          * Verify the super block constants...
13025          */
13026         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13027                           MIN_CHECK, 1, 0);
13028         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13029                           MIN_CHECK, 1, 0);
13030         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13031                           MAX_CHECK, 0, sb->s_blocks_count);
13032         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13033                           MIN_CHECK | MAX_CHECK, 0,
13034                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13035         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13036                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13037         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13038                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13039                           bpg_max);
13040         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13041                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
13042         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13043                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13044         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13045                           MAX_CHECK, 0, sb->s_blocks_count / 2);
13046         check_super_value(ctx, "reserved_gdt_blocks",
13047                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13048                           fs->blocksize/4);
13049         inode_size = EXT2_INODE_SIZE(sb);
13050         check_super_value(ctx, "inode_size",
13051                           inode_size, MIN_CHECK | MAX_CHECK,
13052                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13053         if (inode_size & (inode_size - 1)) {
13054                 pctx.num = inode_size;
13055                 pctx.str = "inode_size";
13056                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13057                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13058                 return;
13059         }
13060
13061         if (!ctx->num_blocks) {
13062                 pctx.errcode = e2fsck_get_device_size(ctx);
13063                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13064                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13065                         ctx->flags |= E2F_FLAG_ABORT;
13066                         return;
13067                 }
13068                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13069                     (ctx->num_blocks < sb->s_blocks_count)) {
13070                         pctx.blk = sb->s_blocks_count;
13071                         pctx.blk2 = ctx->num_blocks;
13072                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13073                                 ctx->flags |= E2F_FLAG_ABORT;
13074                                 return;
13075                         }
13076                 }
13077         }
13078
13079         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13080                 pctx.blk = EXT2_BLOCK_SIZE(sb);
13081                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13082                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13083                 ctx->flags |= E2F_FLAG_ABORT;
13084                 return;
13085         }
13086
13087         should_be = sb->s_frags_per_group >>
13088                 (sb->s_log_block_size - sb->s_log_frag_size);
13089         if (sb->s_blocks_per_group != should_be) {
13090                 pctx.blk = sb->s_blocks_per_group;
13091                 pctx.blk2 = should_be;
13092                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13093                 ctx->flags |= E2F_FLAG_ABORT;
13094                 return;
13095         }
13096
13097         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13098         if (sb->s_first_data_block != should_be) {
13099                 pctx.blk = sb->s_first_data_block;
13100                 pctx.blk2 = should_be;
13101                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13102                 ctx->flags |= E2F_FLAG_ABORT;
13103                 return;
13104         }
13105
13106         should_be = sb->s_inodes_per_group * fs->group_desc_count;
13107         if (sb->s_inodes_count != should_be) {
13108                 pctx.ino = sb->s_inodes_count;
13109                 pctx.ino2 = should_be;
13110                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13111                         sb->s_inodes_count = should_be;
13112                         ext2fs_mark_super_dirty(fs);
13113                 }
13114         }
13115
13116         /*
13117          * Verify the group descriptors....
13118          */
13119         first_block =  sb->s_first_data_block;
13120         last_block = first_block + blocks_per_group;
13121
13122         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13123                 pctx.group = i;
13124
13125                 if (i == fs->group_desc_count - 1)
13126                         last_block = sb->s_blocks_count;
13127                 if ((gd->bg_block_bitmap < first_block) ||
13128                     (gd->bg_block_bitmap >= last_block)) {
13129                         pctx.blk = gd->bg_block_bitmap;
13130                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13131                                 gd->bg_block_bitmap = 0;
13132                 }
13133                 if (gd->bg_block_bitmap == 0) {
13134                         ctx->invalid_block_bitmap_flag[i]++;
13135                         ctx->invalid_bitmaps++;
13136                 }
13137                 if ((gd->bg_inode_bitmap < first_block) ||
13138                     (gd->bg_inode_bitmap >= last_block)) {
13139                         pctx.blk = gd->bg_inode_bitmap;
13140                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13141                                 gd->bg_inode_bitmap = 0;
13142                 }
13143                 if (gd->bg_inode_bitmap == 0) {
13144                         ctx->invalid_inode_bitmap_flag[i]++;
13145                         ctx->invalid_bitmaps++;
13146                 }
13147                 if ((gd->bg_inode_table < first_block) ||
13148                     ((gd->bg_inode_table +
13149                       fs->inode_blocks_per_group - 1) >= last_block)) {
13150                         pctx.blk = gd->bg_inode_table;
13151                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13152                                 gd->bg_inode_table = 0;
13153                 }
13154                 if (gd->bg_inode_table == 0) {
13155                         ctx->invalid_inode_table_flag[i]++;
13156                         ctx->invalid_bitmaps++;
13157                 }
13158                 free_blocks += gd->bg_free_blocks_count;
13159                 free_inodes += gd->bg_free_inodes_count;
13160                 first_block += sb->s_blocks_per_group;
13161                 last_block += sb->s_blocks_per_group;
13162
13163                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13164                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13165                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13166                         ext2fs_unmark_valid(fs);
13167
13168         }
13169
13170         /*
13171          * Update the global counts from the block group counts.  This
13172          * is needed for an experimental patch which eliminates
13173          * locking the entire filesystem when allocating blocks or
13174          * inodes; if the filesystem is not unmounted cleanly, the
13175          * global counts may not be accurate.
13176          */
13177         if ((free_blocks != sb->s_free_blocks_count) ||
13178             (free_inodes != sb->s_free_inodes_count)) {
13179                 if (ctx->options & E2F_OPT_READONLY)
13180                         ext2fs_unmark_valid(fs);
13181                 else {
13182                         sb->s_free_blocks_count = free_blocks;
13183                         sb->s_free_inodes_count = free_inodes;
13184                         ext2fs_mark_super_dirty(fs);
13185                 }
13186         }
13187
13188         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13189             (sb->s_free_inodes_count > sb->s_inodes_count))
13190                 ext2fs_unmark_valid(fs);
13191
13192
13193         /*
13194          * If we have invalid bitmaps, set the error state of the
13195          * filesystem.
13196          */
13197         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13198                 sb->s_state &= ~EXT2_VALID_FS;
13199                 ext2fs_mark_super_dirty(fs);
13200         }
13201
13202         clear_problem_context(&pctx);
13203
13204         /*
13205          * If the UUID field isn't assigned, assign it.
13206          */
13207         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13208                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13209                         uuid_generate(sb->s_uuid);
13210                         ext2fs_mark_super_dirty(fs);
13211                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13212                 }
13213         }
13214
13215         /* FIXME - HURD support?
13216          * For the Hurd, check to see if the filetype option is set,
13217          * since it doesn't support it.
13218          */
13219         if (!(ctx->options & E2F_OPT_READONLY) &&
13220             fs->super->s_creator_os == EXT2_OS_HURD &&
13221             (fs->super->s_feature_incompat &
13222              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13223                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13224                         fs->super->s_feature_incompat &=
13225                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13226                         ext2fs_mark_super_dirty(fs);
13227
13228                 }
13229         }
13230
13231         /*
13232          * If we have any of the compatibility flags set, we need to have a
13233          * revision 1 filesystem.  Most kernels will not check the flags on
13234          * a rev 0 filesystem and we may have corruption issues because of
13235          * the incompatible changes to the filesystem.
13236          */
13237         if (!(ctx->options & E2F_OPT_READONLY) &&
13238             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13239             (fs->super->s_feature_compat ||
13240              fs->super->s_feature_ro_compat ||
13241              fs->super->s_feature_incompat) &&
13242             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13243                 ext2fs_update_dynamic_rev(fs);
13244                 ext2fs_mark_super_dirty(fs);
13245         }
13246
13247         check_resize_inode(ctx);
13248
13249         /*
13250          * Clean up any orphan inodes, if present.
13251          */
13252         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13253                 fs->super->s_state &= ~EXT2_VALID_FS;
13254                 ext2fs_mark_super_dirty(fs);
13255         }
13256
13257         /*
13258          * Move the ext3 journal file, if necessary.
13259          */
13260         e2fsck_move_ext3_journal(ctx);
13261         return;
13262 }
13263
13264 /*
13265  * swapfs.c --- byte-swap an ext2 filesystem
13266  */
13267
13268 #ifdef ENABLE_SWAPFS
13269
13270 struct swap_block_struct {
13271         ext2_ino_t      ino;
13272         int             isdir;
13273         errcode_t       errcode;
13274         char            *dir_buf;
13275         struct ext2_inode *inode;
13276 };
13277
13278 /*
13279  * This is a helper function for block_iterate.  We mark all of the
13280  * indirect and direct blocks as changed, so that block_iterate will
13281  * write them out.
13282  */
13283 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13284                       void *priv_data)
13285 {
13286         errcode_t       retval;
13287
13288         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13289
13290         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13291                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13292                 if (retval) {
13293                         sb->errcode = retval;
13294                         return BLOCK_ABORT;
13295                 }
13296                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13297                 if (retval) {
13298                         sb->errcode = retval;
13299                         return BLOCK_ABORT;
13300                 }
13301         }
13302         if (blockcnt >= 0) {
13303                 if (blockcnt < EXT2_NDIR_BLOCKS)
13304                         return 0;
13305                 return BLOCK_CHANGED;
13306         }
13307         if (blockcnt == BLOCK_COUNT_IND) {
13308                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
13309                         return 0;
13310                 return BLOCK_CHANGED;
13311         }
13312         if (blockcnt == BLOCK_COUNT_DIND) {
13313                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
13314                         return 0;
13315                 return BLOCK_CHANGED;
13316         }
13317         if (blockcnt == BLOCK_COUNT_TIND) {
13318                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
13319                         return 0;
13320                 return BLOCK_CHANGED;
13321         }
13322         return BLOCK_CHANGED;
13323 }
13324
13325 /*
13326  * This function is responsible for byte-swapping all of the indirect,
13327  * block pointers.  It is also responsible for byte-swapping directories.
13328  */
13329 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
13330                               struct ext2_inode *inode)
13331 {
13332         errcode_t                       retval;
13333         struct swap_block_struct        sb;
13334
13335         sb.ino = ino;
13336         sb.inode = inode;
13337         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
13338         sb.errcode = 0;
13339         sb.isdir = 0;
13340         if (LINUX_S_ISDIR(inode->i_mode))
13341                 sb.isdir = 1;
13342
13343         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
13344                                       swap_block, &sb);
13345         if (retval) {
13346                 com_err("swap_inode_blocks", retval,
13347                         _("while calling ext2fs_block_iterate"));
13348                 ctx->flags |= E2F_FLAG_ABORT;
13349                 return;
13350         }
13351         if (sb.errcode) {
13352                 com_err("swap_inode_blocks", sb.errcode,
13353                         _("while calling iterator function"));
13354                 ctx->flags |= E2F_FLAG_ABORT;
13355                 return;
13356         }
13357 }
13358
13359 static void swap_inodes(e2fsck_t ctx)
13360 {
13361         ext2_filsys fs = ctx->fs;
13362         dgrp_t                  group;
13363         unsigned int            i;
13364         ext2_ino_t              ino = 1;
13365         char                    *buf, *block_buf;
13366         errcode_t               retval;
13367         struct ext2_inode *     inode;
13368
13369         e2fsck_use_inode_shortcuts(ctx, 1);
13370
13371         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
13372                                 &buf);
13373         if (retval) {
13374                 com_err("swap_inodes", retval,
13375                         _("while allocating inode buffer"));
13376                 ctx->flags |= E2F_FLAG_ABORT;
13377                 return;
13378         }
13379         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13380                                                     "block interate buffer");
13381         for (group = 0; group < fs->group_desc_count; group++) {
13382                 retval = io_channel_read_blk(fs->io,
13383                       fs->group_desc[group].bg_inode_table,
13384                       fs->inode_blocks_per_group, buf);
13385                 if (retval) {
13386                         com_err("swap_inodes", retval,
13387                                 _("while reading inode table (group %d)"),
13388                                 group);
13389                         ctx->flags |= E2F_FLAG_ABORT;
13390                         return;
13391                 }
13392                 inode = (struct ext2_inode *) buf;
13393                 for (i=0; i < fs->super->s_inodes_per_group;
13394                      i++, ino++, inode++) {
13395                         ctx->stashed_ino = ino;
13396                         ctx->stashed_inode = inode;
13397
13398                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
13399                                 ext2fs_swap_inode(fs, inode, inode, 0);
13400
13401                         /*
13402                          * Skip deleted files.
13403                          */
13404                         if (inode->i_links_count == 0)
13405                                 continue;
13406
13407                         if (LINUX_S_ISDIR(inode->i_mode) ||
13408                             ((inode->i_block[EXT2_IND_BLOCK] ||
13409                               inode->i_block[EXT2_DIND_BLOCK] ||
13410                               inode->i_block[EXT2_TIND_BLOCK]) &&
13411                              ext2fs_inode_has_valid_blocks(inode)))
13412                                 swap_inode_blocks(ctx, ino, block_buf, inode);
13413
13414                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13415                                 return;
13416
13417                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
13418                                 ext2fs_swap_inode(fs, inode, inode, 1);
13419                 }
13420                 retval = io_channel_write_blk(fs->io,
13421                       fs->group_desc[group].bg_inode_table,
13422                       fs->inode_blocks_per_group, buf);
13423                 if (retval) {
13424                         com_err("swap_inodes", retval,
13425                                 _("while writing inode table (group %d)"),
13426                                 group);
13427                         ctx->flags |= E2F_FLAG_ABORT;
13428                         return;
13429                 }
13430         }
13431         ext2fs_free_mem(&buf);
13432         ext2fs_free_mem(&block_buf);
13433         e2fsck_use_inode_shortcuts(ctx, 0);
13434         ext2fs_flush_icache(fs);
13435 }
13436
13437 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
13438 /*
13439  * On the PowerPC, the big-endian variant of the ext2 filesystem
13440  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
13441  * of each word.  Thus a bitmap with only bit 0 set would be, as
13442  * a string of bytes, 00 00 00 01 00 ...
13443  * To cope with this, we byte-reverse each word of a bitmap if
13444  * we have a big-endian filesystem, that is, if we are *not*
13445  * byte-swapping other word-sized numbers.
13446  */
13447 #define EXT2_BIG_ENDIAN_BITMAPS
13448 #endif
13449
13450 #ifdef EXT2_BIG_ENDIAN_BITMAPS
13451 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
13452 {
13453         __u32 *p = (__u32 *) bmap->bitmap;
13454         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
13455
13456         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
13457                 *p = ext2fs_swab32(*p);
13458 }
13459 #endif
13460
13461
13462 #ifdef ENABLE_SWAPFS
13463 static void swap_filesys(e2fsck_t ctx)
13464 {
13465         ext2_filsys fs = ctx->fs;
13466         if (!(ctx->options & E2F_OPT_PREEN))
13467                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
13468
13469         /* Byte swap */
13470
13471         if (fs->super->s_mnt_count) {
13472                 fprintf(stderr, _("%s: the filesystem must be freshly "
13473                         "checked using fsck\n"
13474                         "and not mounted before trying to "
13475                         "byte-swap it.\n"), ctx->device_name);
13476                 ctx->flags |= E2F_FLAG_ABORT;
13477                 return;
13478         }
13479         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
13480                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
13481                                EXT2_FLAG_SWAP_BYTES_WRITE);
13482                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
13483         } else {
13484                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
13485                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
13486         }
13487         swap_inodes(ctx);
13488         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13489                 return;
13490         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
13491                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
13492         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
13493                        EXT2_FLAG_SWAP_BYTES_WRITE);
13494
13495 #ifdef EXT2_BIG_ENDIAN_BITMAPS
13496         e2fsck_read_bitmaps(ctx);
13497         ext2fs_swap_bitmap(fs->inode_map);
13498         ext2fs_swap_bitmap(fs->block_map);
13499         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
13500 #endif
13501         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13502         ext2fs_flush(fs);
13503         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13504 }
13505 #endif  /* ENABLE_SWAPFS */
13506
13507 #endif
13508
13509 /*
13510  * util.c --- miscellaneous utilities
13511  */
13512
13513
13514 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
13515                              const char *description)
13516 {
13517         void *ret;
13518         char buf[256];
13519
13520         ret = malloc(size);
13521         if (!ret) {
13522                 sprintf(buf, "Can't allocate %s\n", description);
13523                 fatal_error(ctx, buf);
13524         }
13525         memset(ret, 0, size);
13526         return ret;
13527 }
13528
13529 static char *string_copy(const char *str, int len)
13530 {
13531         char    *ret;
13532
13533         if (!str)
13534                 return NULL;
13535         if (!len)
13536                 len = strlen(str);
13537         ret = malloc(len+1);
13538         if (ret) {
13539                 strncpy(ret, str, len);
13540                 ret[len] = 0;
13541         }
13542         return ret;
13543 }
13544
13545 #ifndef HAVE_CONIO_H
13546 static int read_a_char(void)
13547 {
13548         char    c;
13549         int     r;
13550         int     fail = 0;
13551
13552         while(1) {
13553                 if (e2fsck_global_ctx &&
13554                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
13555                         return 3;
13556                 }
13557                 r = read(0, &c, 1);
13558                 if (r == 1)
13559                         return c;
13560                 if (fail++ > 100)
13561                         break;
13562         }
13563         return EOF;
13564 }
13565 #endif
13566
13567 static int ask_yn(const char * string, int def)
13568 {
13569         int             c;
13570         const char      *defstr;
13571         static const char short_yes[] = "yY";
13572         static const char short_no[] = "nN";
13573
13574 #ifdef HAVE_TERMIOS_H
13575         struct termios  termios, tmp;
13576
13577         tcgetattr (0, &termios);
13578         tmp = termios;
13579         tmp.c_lflag &= ~(ICANON | ECHO);
13580         tmp.c_cc[VMIN] = 1;
13581         tmp.c_cc[VTIME] = 0;
13582         tcsetattr (0, TCSANOW, &tmp);
13583 #endif
13584
13585         if (def == 1)
13586                 defstr = "<y>";
13587         else if (def == 0)
13588                 defstr = "<n>";
13589         else
13590                 defstr = " (y/n)";
13591         printf("%s%s? ", string, defstr);
13592         while (1) {
13593                 fflush (stdout);
13594                 if ((c = read_a_char()) == EOF)
13595                         break;
13596                 if (c == 3) {
13597 #ifdef HAVE_TERMIOS_H
13598                         tcsetattr (0, TCSANOW, &termios);
13599 #endif
13600                         if (e2fsck_global_ctx &&
13601                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
13602                                 puts("\n");
13603                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
13604                         }
13605                         puts(_("cancelled!\n"));
13606                         return 0;
13607                 }
13608                 if (strchr(short_yes, (char) c)) {
13609                         def = 1;
13610                         break;
13611                 }
13612                 else if (strchr(short_no, (char) c)) {
13613                         def = 0;
13614                         break;
13615                 }
13616                 else if ((c == ' ' || c == '\n') && (def != -1))
13617                         break;
13618         }
13619         if (def)
13620                 puts("yes\n");
13621         else
13622                 puts ("no\n");
13623 #ifdef HAVE_TERMIOS_H
13624         tcsetattr (0, TCSANOW, &termios);
13625 #endif
13626         return def;
13627 }
13628
13629 int ask (e2fsck_t ctx, const char * string, int def)
13630 {
13631         if (ctx->options & E2F_OPT_NO) {
13632                 printf (_("%s? no\n\n"), string);
13633                 return 0;
13634         }
13635         if (ctx->options & E2F_OPT_YES) {
13636                 printf (_("%s? yes\n\n"), string);
13637                 return 1;
13638         }
13639         if (ctx->options & E2F_OPT_PREEN) {
13640                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
13641                 return def;
13642         }
13643         return ask_yn(string, def);
13644 }
13645
13646 void e2fsck_read_bitmaps(e2fsck_t ctx)
13647 {
13648         ext2_filsys fs = ctx->fs;
13649         errcode_t       retval;
13650
13651         if (ctx->invalid_bitmaps) {
13652                 com_err(ctx->program_name, 0,
13653                     _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
13654                         ctx->device_name);
13655                 fatal_error(ctx, 0);
13656         }
13657
13658         ehandler_operation(_("reading inode and block bitmaps"));
13659         retval = ext2fs_read_bitmaps(fs);
13660         ehandler_operation(0);
13661         if (retval) {
13662                 com_err(ctx->program_name, retval,
13663                         _("while retrying to read bitmaps for %s"),
13664                         ctx->device_name);
13665                 fatal_error(ctx, 0);
13666         }
13667 }
13668
13669 static void e2fsck_write_bitmaps(e2fsck_t ctx)
13670 {
13671         ext2_filsys fs = ctx->fs;
13672         errcode_t       retval;
13673
13674         if (ext2fs_test_bb_dirty(fs)) {
13675                 ehandler_operation(_("writing block bitmaps"));
13676                 retval = ext2fs_write_block_bitmap(fs);
13677                 ehandler_operation(0);
13678                 if (retval) {
13679                         com_err(ctx->program_name, retval,
13680                             _("while retrying to write block bitmaps for %s"),
13681                                 ctx->device_name);
13682                         fatal_error(ctx, 0);
13683                 }
13684         }
13685
13686         if (ext2fs_test_ib_dirty(fs)) {
13687                 ehandler_operation(_("writing inode bitmaps"));
13688                 retval = ext2fs_write_inode_bitmap(fs);
13689                 ehandler_operation(0);
13690                 if (retval) {
13691                         com_err(ctx->program_name, retval,
13692                             _("while retrying to write inode bitmaps for %s"),
13693                                 ctx->device_name);
13694                         fatal_error(ctx, 0);
13695                 }
13696         }
13697 }
13698
13699 void preenhalt(e2fsck_t ctx)
13700 {
13701         ext2_filsys fs = ctx->fs;
13702
13703         if (!(ctx->options & E2F_OPT_PREEN))
13704                 return;
13705         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
13706                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
13707                ctx->device_name);
13708         if (fs != NULL) {
13709                 fs->super->s_state |= EXT2_ERROR_FS;
13710                 ext2fs_mark_super_dirty(fs);
13711                 ext2fs_close(fs);
13712         }
13713         exit(EXIT_UNCORRECTED);
13714 }
13715
13716 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
13717                               struct ext2_inode * inode, const char *proc)
13718 {
13719         int retval;
13720
13721         retval = ext2fs_read_inode(ctx->fs, ino, inode);
13722         if (retval) {
13723                 com_err("ext2fs_read_inode", retval,
13724                         _("while reading inode %ld in %s"), ino, proc);
13725                 fatal_error(ctx, 0);
13726         }
13727 }
13728
13729 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
13730                                struct ext2_inode * inode, int bufsize,
13731                                const char *proc)
13732 {
13733         int retval;
13734
13735         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
13736         if (retval) {
13737                 com_err("ext2fs_write_inode", retval,
13738                         _("while writing inode %ld in %s"), ino, proc);
13739                 fatal_error(ctx, 0);
13740         }
13741 }
13742
13743 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
13744                                struct ext2_inode * inode, const char *proc)
13745 {
13746         int retval;
13747
13748         retval = ext2fs_write_inode(ctx->fs, ino, inode);
13749         if (retval) {
13750                 com_err("ext2fs_write_inode", retval,
13751                         _("while writing inode %ld in %s"), ino, proc);
13752                 fatal_error(ctx, 0);
13753         }
13754 }
13755
13756 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
13757                    io_manager manager)
13758 {
13759         struct ext2_super_block *sb;
13760         io_channel              io = NULL;
13761         void                    *buf = NULL;
13762         int                     blocksize;
13763         blk_t                   superblock, ret_sb = 8193;
13764
13765         if (fs && fs->super) {
13766                 ret_sb = (fs->super->s_blocks_per_group +
13767                           fs->super->s_first_data_block);
13768                 if (ctx) {
13769                         ctx->superblock = ret_sb;
13770                         ctx->blocksize = fs->blocksize;
13771                 }
13772                 return ret_sb;
13773         }
13774
13775         if (ctx) {
13776                 if (ctx->blocksize) {
13777                         ret_sb = ctx->blocksize * 8;
13778                         if (ctx->blocksize == 1024)
13779                                 ret_sb++;
13780                         ctx->superblock = ret_sb;
13781                         return ret_sb;
13782                 }
13783                 ctx->superblock = ret_sb;
13784                 ctx->blocksize = 1024;
13785         }
13786
13787         if (!name || !manager)
13788                 goto cleanup;
13789
13790         if (manager->open(name, 0, &io) != 0)
13791                 goto cleanup;
13792
13793         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
13794                 goto cleanup;
13795         sb = (struct ext2_super_block *) buf;
13796
13797         for (blocksize = EXT2_MIN_BLOCK_SIZE;
13798              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
13799                 superblock = blocksize*8;
13800                 if (blocksize == 1024)
13801                         superblock++;
13802                 io_channel_set_blksize(io, blocksize);
13803                 if (io_channel_read_blk(io, superblock,
13804                                         -SUPERBLOCK_SIZE, buf))
13805                         continue;
13806 #ifdef EXT2FS_ENABLE_SWAPFS
13807                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
13808                         ext2fs_swap_super(sb);
13809 #endif
13810                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
13811                         ret_sb = superblock;
13812                         if (ctx) {
13813                                 ctx->superblock = superblock;
13814                                 ctx->blocksize = blocksize;
13815                         }
13816                         break;
13817                 }
13818         }
13819
13820 cleanup:
13821         if (io)
13822                 io_channel_close(io);
13823         ext2fs_free_mem(&buf);
13824         return (ret_sb);
13825 }
13826
13827
13828 /*
13829  * This function runs through the e2fsck passes and calls them all,
13830  * returning restart, abort, or cancel as necessary...
13831  */
13832 typedef void (*pass_t)(e2fsck_t ctx);
13833
13834 static const pass_t e2fsck_passes[] = {
13835         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
13836         e2fsck_pass5, 0 };
13837
13838 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
13839
13840 static int e2fsck_run(e2fsck_t ctx)
13841 {
13842         int     i;
13843         pass_t  e2fsck_pass;
13844
13845         if (setjmp(ctx->abort_loc)) {
13846                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
13847                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
13848         }
13849         ctx->flags |= E2F_FLAG_SETJMP_OK;
13850
13851         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
13852                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
13853                         break;
13854                 e2fsck_pass(ctx);
13855                 if (ctx->progress)
13856                         (void) (ctx->progress)(ctx, 0, 0, 0);
13857         }
13858         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
13859
13860         if (ctx->flags & E2F_FLAG_RUN_RETURN)
13861                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
13862         return 0;
13863 }
13864
13865
13866 /*
13867  * unix.c - The unix-specific code for e2fsck
13868  */
13869
13870
13871 /* Command line options */
13872 static int swapfs;
13873 #ifdef ENABLE_SWAPFS
13874 static int normalize_swapfs;
13875 #endif
13876 static int cflag;               /* check disk */
13877 static int show_version_only;
13878 static int verbose;
13879
13880 static int replace_bad_blocks;
13881 static int keep_bad_blocks;
13882 static char *bad_blocks_file;
13883
13884 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
13885
13886 static void show_stats(e2fsck_t ctx)
13887 {
13888         ext2_filsys fs = ctx->fs;
13889         int inodes, inodes_used, blocks, blocks_used;
13890         int dir_links;
13891         int num_files, num_links;
13892         int frag_percent;
13893
13894         dir_links = 2 * ctx->fs_directory_count - 1;
13895         num_files = ctx->fs_total_count - dir_links;
13896         num_links = ctx->fs_links_count - dir_links;
13897         inodes = fs->super->s_inodes_count;
13898         inodes_used = (fs->super->s_inodes_count -
13899                        fs->super->s_free_inodes_count);
13900         blocks = fs->super->s_blocks_count;
13901         blocks_used = (fs->super->s_blocks_count -
13902                        fs->super->s_free_blocks_count);
13903
13904         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
13905         frag_percent = (frag_percent + 5) / 10;
13906
13907         if (!verbose) {
13908                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
13909                        ctx->device_name, inodes_used, inodes,
13910                        frag_percent / 10, frag_percent % 10,
13911                        blocks_used, blocks);
13912                 return;
13913         }
13914         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
13915                 100 * inodes_used / inodes);
13916         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
13917                 P_E2("", "s", ctx->fs_fragmented),
13918                 frag_percent / 10, frag_percent % 10);
13919         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
13920                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
13921         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
13922                 (int) ((long long) 100 * blocks_used / blocks));
13923         printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
13924         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
13925         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
13926         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
13927         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
13928         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
13929         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
13930         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
13931         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
13932         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
13933         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
13934         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
13935 }
13936
13937 static void check_mount(e2fsck_t ctx)
13938 {
13939         errcode_t       retval;
13940         int             cont;
13941
13942         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
13943                                          &ctx->mount_flags);
13944         if (retval) {
13945                 com_err("ext2fs_check_if_mount", retval,
13946                         _("while determining whether %s is mounted."),
13947                         ctx->filesystem_name);
13948                 return;
13949         }
13950
13951         /*
13952          * If the filesystem isn't mounted, or it's the root filesystem
13953          * and it's mounted read-only, then everything's fine.
13954          */
13955         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
13956             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
13957              (ctx->mount_flags & EXT2_MF_READONLY)))
13958                 return;
13959
13960         if (ctx->options & E2F_OPT_READONLY) {
13961                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
13962                 return;
13963         }
13964
13965         printf(_("%s is mounted.  "), ctx->filesystem_name);
13966         if (!ctx->interactive)
13967                 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
13968         printf(_("\n\n\007\007\007\007WARNING!!!  "
13969                "Running e2fsck on a mounted filesystem may cause\n"
13970                "SEVERE filesystem damage.\007\007\007\n\n"));
13971         cont = ask_yn(_("Do you really want to continue"), -1);
13972         if (!cont) {
13973                 printf (_("check aborted.\n"));
13974                 exit (0);
13975         }
13976         return;
13977 }
13978
13979 static int is_on_batt(void)
13980 {
13981         FILE    *f;
13982         DIR     *d;
13983         char    tmp[80], tmp2[80], fname[80];
13984         unsigned int    acflag;
13985         struct dirent*  de;
13986
13987         f = fopen("/proc/apm", "r");
13988         if (f) {
13989                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
13990                         acflag = 1;
13991                 fclose(f);
13992                 return (acflag != 1);
13993         }
13994         d = opendir("/proc/acpi/ac_adapter");
13995         if (d) {
13996                 while ((de=readdir(d)) != NULL) {
13997                         if (!strncmp(".", de->d_name, 1))
13998                                 continue;
13999                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14000                                  de->d_name);
14001                         f = fopen(fname, "r");
14002                         if (!f)
14003                                 continue;
14004                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14005                                 tmp[0] = 0;
14006                         fclose(f);
14007                         if (strncmp(tmp, "off-line", 8) == 0) {
14008                                 closedir(d);
14009                                 return 1;
14010                         }
14011                 }
14012                 closedir(d);
14013         }
14014         return 0;
14015 }
14016
14017 /*
14018  * This routine checks to see if a filesystem can be skipped; if so,
14019  * it will exit with EXIT_OK.  Under some conditions it will print a
14020  * message explaining why a check is being forced.
14021  */
14022 static void check_if_skip(e2fsck_t ctx)
14023 {
14024         ext2_filsys fs = ctx->fs;
14025         const char *reason = NULL;
14026         unsigned int reason_arg = 0;
14027         long next_check;
14028         int batt = is_on_batt();
14029         time_t now = time(0);
14030
14031         if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14032             cflag || swapfs)
14033                 return;
14034
14035         if ((fs->super->s_state & EXT2_ERROR_FS) ||
14036             !ext2fs_test_valid(fs))
14037                 reason = _(" contains a file system with errors");
14038         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14039                 reason = _(" was not cleanly unmounted");
14040         else if ((fs->super->s_max_mnt_count > 0) &&
14041                  (fs->super->s_mnt_count >=
14042                   (unsigned) fs->super->s_max_mnt_count)) {
14043                 reason = _(" has been mounted %u times without being checked");
14044                 reason_arg = fs->super->s_mnt_count;
14045                 if (batt && (fs->super->s_mnt_count <
14046                              (unsigned) fs->super->s_max_mnt_count*2))
14047                         reason = 0;
14048         } else if (fs->super->s_checkinterval &&
14049                    ((now - fs->super->s_lastcheck) >=
14050                     fs->super->s_checkinterval)) {
14051                 reason = _(" has gone %u days without being checked");
14052                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14053                 if (batt && ((now - fs->super->s_lastcheck) <
14054                              fs->super->s_checkinterval*2))
14055                         reason = 0;
14056         }
14057         if (reason) {
14058                 fputs(ctx->device_name, stdout);
14059                 printf(reason, reason_arg);
14060                 fputs(_(", check forced.\n"), stdout);
14061                 return;
14062         }
14063         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14064                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14065                fs->super->s_inodes_count,
14066                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14067                fs->super->s_blocks_count);
14068         next_check = 100000;
14069         if (fs->super->s_max_mnt_count > 0) {
14070                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14071                 if (next_check <= 0)
14072                         next_check = 1;
14073         }
14074         if (fs->super->s_checkinterval &&
14075             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14076                 next_check = 1;
14077         if (next_check <= 5) {
14078                 if (next_check == 1)
14079                         fputs(_(" (check after next mount)"), stdout);
14080                 else
14081                         printf(_(" (check in %ld mounts)"), next_check);
14082         }
14083         fputc('\n', stdout);
14084         ext2fs_close(fs);
14085         ctx->fs = NULL;
14086         e2fsck_free_context(ctx);
14087         exit(EXIT_OK);
14088 }
14089
14090 /*
14091  * For completion notice
14092  */
14093 struct percent_tbl {
14094         int     max_pass;
14095         int     table[32];
14096 };
14097 static const struct percent_tbl e2fsck_tbl = {
14098         5, { 0, 70, 90, 92,  95, 100 }
14099 };
14100
14101 static char bar[128], spaces[128];
14102
14103 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14104                           int max)
14105 {
14106         float   percent;
14107
14108         if (pass <= 0)
14109                 return 0.0;
14110         if (pass > tbl->max_pass || max == 0)
14111                 return 100.0;
14112         percent = ((float) curr) / ((float) max);
14113         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14114                 + tbl->table[pass-1]);
14115 }
14116
14117 void e2fsck_clear_progbar(e2fsck_t ctx)
14118 {
14119         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14120                 return;
14121
14122         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14123                ctx->stop_meta);
14124         fflush(stdout);
14125         ctx->flags &= ~E2F_FLAG_PROG_BAR;
14126 }
14127
14128 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14129                            unsigned int dpynum)
14130 {
14131         static const char spinner[] = "\\|/-";
14132         int     i;
14133         unsigned int    tick;
14134         struct timeval  tv;
14135         int dpywidth;
14136         int fixed_percent;
14137
14138         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14139                 return 0;
14140
14141         /*
14142          * Calculate the new progress position.  If the
14143          * percentage hasn't changed, then we skip out right
14144          * away.
14145          */
14146         fixed_percent = (int) ((10 * percent) + 0.5);
14147         if (ctx->progress_last_percent == fixed_percent)
14148                 return 0;
14149         ctx->progress_last_percent = fixed_percent;
14150
14151         /*
14152          * If we've already updated the spinner once within
14153          * the last 1/8th of a second, no point doing it
14154          * again.
14155          */
14156         gettimeofday(&tv, NULL);
14157         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
14158         if ((tick == ctx->progress_last_time) &&
14159             (fixed_percent != 0) && (fixed_percent != 1000))
14160                 return 0;
14161         ctx->progress_last_time = tick;
14162
14163         /*
14164          * Advance the spinner, and note that the progress bar
14165          * will be on the screen
14166          */
14167         ctx->progress_pos = (ctx->progress_pos+1) & 3;
14168         ctx->flags |= E2F_FLAG_PROG_BAR;
14169
14170         dpywidth = 66 - strlen(label);
14171         dpywidth = 8 * (dpywidth / 8);
14172         if (dpynum)
14173                 dpywidth -= 8;
14174
14175         i = ((percent * dpywidth) + 50) / 100;
14176         printf("%s%s: |%s%s", ctx->start_meta, label,
14177                bar + (sizeof(bar) - (i+1)),
14178                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
14179         if (fixed_percent == 1000)
14180                 fputc('|', stdout);
14181         else
14182                 fputc(spinner[ctx->progress_pos & 3], stdout);
14183         printf(" %4.1f%%  ", percent);
14184         if (dpynum)
14185                 printf("%u\r", dpynum);
14186         else
14187                 fputs(" \r", stdout);
14188         fputs(ctx->stop_meta, stdout);
14189
14190         if (fixed_percent == 1000)
14191                 e2fsck_clear_progbar(ctx);
14192         fflush(stdout);
14193
14194         return 0;
14195 }
14196
14197 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
14198                                   unsigned long cur, unsigned long max)
14199 {
14200         char buf[80];
14201         float percent;
14202
14203         if (pass == 0)
14204                 return 0;
14205
14206         if (ctx->progress_fd) {
14207                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
14208                 write(ctx->progress_fd, buf, strlen(buf));
14209         } else {
14210                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
14211                 e2fsck_simple_progress(ctx, ctx->device_name,
14212                                        percent, 0);
14213         }
14214         return 0;
14215 }
14216
14217 static void reserve_stdio_fds(void)
14218 {
14219         int     fd;
14220
14221         while (1) {
14222                 fd = open(bb_dev_null, O_RDWR);
14223                 if (fd > 2)
14224                         break;
14225                 if (fd < 0) {
14226                         fprintf(stderr, _("ERROR: Couldn't open "
14227                                 "/dev/null (%s)\n"),
14228                                 strerror(errno));
14229                         break;
14230                 }
14231         }
14232         close(fd);
14233 }
14234
14235 static void signal_progress_on(int sig FSCK_ATTR((unused)))
14236 {
14237         e2fsck_t ctx = e2fsck_global_ctx;
14238
14239         if (!ctx)
14240                 return;
14241
14242         ctx->progress = e2fsck_update_progress;
14243         ctx->progress_fd = 0;
14244 }
14245
14246 static void signal_progress_off(int sig FSCK_ATTR((unused)))
14247 {
14248         e2fsck_t ctx = e2fsck_global_ctx;
14249
14250         if (!ctx)
14251                 return;
14252
14253         e2fsck_clear_progbar(ctx);
14254         ctx->progress = 0;
14255 }
14256
14257 static void signal_cancel(int sig FSCK_ATTR((unused)))
14258 {
14259         e2fsck_t ctx = e2fsck_global_ctx;
14260
14261         if (!ctx)
14262                 exit(FSCK_CANCELED);
14263
14264         ctx->flags |= E2F_FLAG_CANCEL;
14265 }
14266
14267 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
14268 {
14269         char    *buf, *token, *next, *p, *arg;
14270         int     ea_ver;
14271         int     extended_usage = 0;
14272
14273         buf = string_copy(opts, 0);
14274         for (token = buf; token && *token; token = next) {
14275                 p = strchr(token, ',');
14276                 next = 0;
14277                 if (p) {
14278                         *p = 0;
14279                         next = p+1;
14280                 }
14281                 arg = strchr(token, '=');
14282                 if (arg) {
14283                         *arg = 0;
14284                         arg++;
14285                 }
14286                 if (strcmp(token, "ea_ver") == 0) {
14287                         if (!arg) {
14288                                 extended_usage++;
14289                                 continue;
14290                         }
14291                         ea_ver = strtoul(arg, &p, 0);
14292                         if (*p ||
14293                             ((ea_ver != 1) && (ea_ver != 2))) {
14294                                 fprintf(stderr,
14295                                         _("Invalid EA version.\n"));
14296                                 extended_usage++;
14297                                 continue;
14298                         }
14299                         ctx->ext_attr_ver = ea_ver;
14300                 } else {
14301                         fprintf(stderr, _("Unknown extended option: %s\n"),
14302                                 token);
14303                         extended_usage++;
14304                 }
14305         }
14306         if (extended_usage) {
14307                 bb_error_msg_and_die(
14308                         "Extended options are separated by commas, "
14309                         "and may take an argument which\n"
14310                         "is set off by an equals ('=') sign.  "
14311                         "Valid extended options are:\n"
14312                         "\tea_ver=<ea_version (1 or 2)>\n\n");
14313         }
14314 }
14315
14316
14317 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
14318 {
14319         int             flush = 0;
14320         int             c, fd;
14321         e2fsck_t        ctx;
14322         errcode_t       retval;
14323         struct sigaction        sa;
14324         char            *extended_opts = 0;
14325
14326         retval = e2fsck_allocate_context(&ctx);
14327         if (retval)
14328                 return retval;
14329
14330         *ret_ctx = ctx;
14331
14332         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
14333         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
14334         if (isatty(0) && isatty(1)) {
14335                 ctx->interactive = 1;
14336         } else {
14337                 ctx->start_meta[0] = '\001';
14338                 ctx->stop_meta[0] = '\002';
14339         }
14340         memset(bar, '=', sizeof(bar)-1);
14341         memset(spaces, ' ', sizeof(spaces)-1);
14342         blkid_get_cache(&ctx->blkid, NULL);
14343
14344         if (argc && *argv)
14345                 ctx->program_name = *argv;
14346         else
14347                 ctx->program_name = "e2fsck";
14348         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
14349                 switch (c) {
14350                 case 'C':
14351                         ctx->progress = e2fsck_update_progress;
14352                         ctx->progress_fd = atoi(optarg);
14353                         if (!ctx->progress_fd)
14354                                 break;
14355                         /* Validate the file descriptor to avoid disasters */
14356                         fd = dup(ctx->progress_fd);
14357                         if (fd < 0) {
14358                                 fprintf(stderr,
14359                                 _("Error validating file descriptor %d: %s\n"),
14360                                         ctx->progress_fd,
14361                                         error_message(errno));
14362                                 fatal_error(ctx,
14363                         _("Invalid completion information file descriptor"));
14364                         } else
14365                                 close(fd);
14366                         break;
14367                 case 'D':
14368                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
14369                         break;
14370                 case 'E':
14371                         extended_opts = optarg;
14372                         break;
14373                 case 'p':
14374                 case 'a':
14375                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
14376                         conflict_opt:
14377                                 fatal_error(ctx,
14378         _("Only one the options -p/-a, -n or -y may be specified."));
14379                         }
14380                         ctx->options |= E2F_OPT_PREEN;
14381                         break;
14382                 case 'n':
14383                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
14384                                 goto conflict_opt;
14385                         ctx->options |= E2F_OPT_NO;
14386                         break;
14387                 case 'y':
14388                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
14389                                 goto conflict_opt;
14390                         ctx->options |= E2F_OPT_YES;
14391                         break;
14392                 case 't':
14393                         /* FIXME - This needs to go away in a future path - will change binary */
14394                         fprintf(stderr, _("The -t option is not "
14395                                 "supported on this version of e2fsck.\n"));
14396                         break;
14397                 case 'c':
14398                         if (cflag++)
14399                                 ctx->options |= E2F_OPT_WRITECHECK;
14400                         ctx->options |= E2F_OPT_CHECKBLOCKS;
14401                         break;
14402                 case 'r':
14403                         /* What we do by default, anyway! */
14404                         break;
14405                 case 'b':
14406                         ctx->use_superblock = atoi(optarg);
14407                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
14408                         break;
14409                 case 'B':
14410                         ctx->blocksize = atoi(optarg);
14411                         break;
14412                 case 'I':
14413                         ctx->inode_buffer_blocks = atoi(optarg);
14414                         break;
14415                 case 'j':
14416                         ctx->journal_name = string_copy(optarg, 0);
14417                         break;
14418                 case 'P':
14419                         ctx->process_inode_size = atoi(optarg);
14420                         break;
14421                 case 'L':
14422                         replace_bad_blocks++;
14423                 case 'l':
14424                         bad_blocks_file = string_copy(optarg, 0);
14425                         break;
14426                 case 'd':
14427                         ctx->options |= E2F_OPT_DEBUG;
14428                         break;
14429                 case 'f':
14430                         ctx->options |= E2F_OPT_FORCE;
14431                         break;
14432                 case 'F':
14433                         flush = 1;
14434                         break;
14435                 case 'v':
14436                         verbose = 1;
14437                         break;
14438                 case 'V':
14439                         show_version_only = 1;
14440                         break;
14441                 case 'N':
14442                         ctx->device_name = optarg;
14443                         break;
14444 #ifdef ENABLE_SWAPFS
14445                 case 's':
14446                         normalize_swapfs = 1;
14447                 case 'S':
14448                         swapfs = 1;
14449                         break;
14450 #else
14451                 case 's':
14452                 case 'S':
14453                         fprintf(stderr, _("Byte-swapping filesystems "
14454                                           "not compiled in this version "
14455                                           "of e2fsck\n"));
14456                         exit(1);
14457 #endif
14458                 case 'k':
14459                         keep_bad_blocks++;
14460                         break;
14461                 default:
14462                         usage();
14463                 }
14464         if (show_version_only)
14465                 return 0;
14466         if (optind != argc - 1)
14467                 usage();
14468         if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
14469             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
14470                 ctx->options |= E2F_OPT_READONLY;
14471         ctx->io_options = strchr(argv[optind], '?');
14472         if (ctx->io_options)
14473                 *ctx->io_options++ = 0;
14474         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
14475         if (!ctx->filesystem_name) {
14476                 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
14477                         argv[optind]);
14478                 fatal_error(ctx, 0);
14479         }
14480         if (extended_opts)
14481                 parse_extended_opts(ctx, extended_opts);
14482
14483         if (flush) {
14484                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
14485                 if (fd < 0) {
14486                         com_err("open", errno,
14487                                 _("while opening %s for flushing"),
14488                                 ctx->filesystem_name);
14489                         fatal_error(ctx, 0);
14490                 }
14491                 if ((retval = ext2fs_sync_device(fd, 1))) {
14492                         com_err("ext2fs_sync_device", retval,
14493                                 _("while trying to flush %s"),
14494                                 ctx->filesystem_name);
14495                         fatal_error(ctx, 0);
14496                 }
14497                 close(fd);
14498         }
14499 #ifdef ENABLE_SWAPFS
14500         if (swapfs) {
14501                 if (cflag || bad_blocks_file) {
14502                         fprintf(stderr, _("Incompatible options not "
14503                                           "allowed when byte-swapping.\n"));
14504                         exit(EXIT_USAGE);
14505                 }
14506         }
14507 #endif
14508         if (cflag && bad_blocks_file) {
14509                 fprintf(stderr, _("The -c and the -l/-L options may "
14510                                   "not be both used at the same time.\n"));
14511                 exit(EXIT_USAGE);
14512         }
14513         /*
14514          * Set up signal action
14515          */
14516         memset(&sa, 0, sizeof(struct sigaction));
14517         sa.sa_handler = signal_cancel;
14518         sigaction(SIGINT, &sa, 0);
14519         sigaction(SIGTERM, &sa, 0);
14520 #ifdef SA_RESTART
14521         sa.sa_flags = SA_RESTART;
14522 #endif
14523         e2fsck_global_ctx = ctx;
14524         sa.sa_handler = signal_progress_on;
14525         sigaction(SIGUSR1, &sa, 0);
14526         sa.sa_handler = signal_progress_off;
14527         sigaction(SIGUSR2, &sa, 0);
14528
14529         /* Update our PATH to include /sbin if we need to run badblocks  */
14530         if (cflag)
14531                 e2fs_set_sbin_path();
14532         return 0;
14533 }
14534
14535 static const char my_ver_string[] = E2FSPROGS_VERSION;
14536 static const char my_ver_date[] = E2FSPROGS_DATE;
14537
14538 int e2fsck_main (int argc, char *argv[])
14539 {
14540         errcode_t       retval;
14541         int             exit_value = EXIT_OK;
14542         ext2_filsys     fs = 0;
14543         io_manager      io_ptr;
14544         struct ext2_super_block *sb;
14545         const char      *lib_ver_date;
14546         int             my_ver, lib_ver;
14547         e2fsck_t        ctx;
14548         struct problem_context pctx;
14549         int flags, run_result;
14550
14551         clear_problem_context(&pctx);
14552
14553         my_ver = ext2fs_parse_version_string(my_ver_string);
14554         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
14555         if (my_ver > lib_ver) {
14556                 fprintf( stderr, _("Error: ext2fs library version "
14557                         "out of date!\n"));
14558                 show_version_only++;
14559         }
14560
14561         retval = PRS(argc, argv, &ctx);
14562         if (retval) {
14563                 com_err("e2fsck", retval,
14564                         _("while trying to initialize program"));
14565                 exit(EXIT_ERROR);
14566         }
14567         reserve_stdio_fds();
14568
14569         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
14570                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
14571                          my_ver_date);
14572
14573         if (show_version_only) {
14574                 fprintf(stderr, _("\tUsing %s, %s\n"),
14575                         error_message(EXT2_ET_BASE), lib_ver_date);
14576                 exit(EXIT_OK);
14577         }
14578
14579         check_mount(ctx);
14580
14581         if (!(ctx->options & E2F_OPT_PREEN) &&
14582             !(ctx->options & E2F_OPT_NO) &&
14583             !(ctx->options & E2F_OPT_YES)) {
14584                 if (!ctx->interactive)
14585                         fatal_error(ctx,
14586                                     _("need terminal for interactive repairs"));
14587         }
14588         ctx->superblock = ctx->use_superblock;
14589 restart:
14590 #ifdef CONFIG_TESTIO_DEBUG
14591         io_ptr = test_io_manager;
14592         test_io_backing_manager = unix_io_manager;
14593 #else
14594         io_ptr = unix_io_manager;
14595 #endif
14596         flags = 0;
14597         if ((ctx->options & E2F_OPT_READONLY) == 0)
14598                 flags |= EXT2_FLAG_RW;
14599
14600         if (ctx->superblock && ctx->blocksize) {
14601                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
14602                                       flags, ctx->superblock, ctx->blocksize,
14603                                       io_ptr, &fs);
14604         } else if (ctx->superblock) {
14605                 int blocksize;
14606                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
14607                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
14608                         retval = ext2fs_open2(ctx->filesystem_name,
14609                                               ctx->io_options, flags,
14610                                               ctx->superblock, blocksize,
14611                                               io_ptr, &fs);
14612                         if (!retval)
14613                                 break;
14614                 }
14615         } else
14616                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
14617                                       flags, 0, 0, io_ptr, &fs);
14618         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
14619             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
14620             ((retval == EXT2_ET_BAD_MAGIC) ||
14621              ((retval == 0) && ext2fs_check_desc(fs)))) {
14622                 if (!fs || (fs->group_desc_count > 1)) {
14623                         printf(_("%s trying backup blocks...\n"),
14624                                retval ? _("Couldn't find ext2 superblock,") :
14625                                _("Group descriptors look bad..."));
14626                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
14627                         if (fs)
14628                                 ext2fs_close(fs);
14629                         goto restart;
14630                 }
14631         }
14632         if (retval) {
14633                 com_err(ctx->program_name, retval, _("while trying to open %s"),
14634                         ctx->filesystem_name);
14635                 if (retval == EXT2_ET_REV_TOO_HIGH) {
14636                         printf(_("The filesystem revision is apparently "
14637                                "too high for this version of e2fsck.\n"
14638                                "(Or the filesystem superblock "
14639                                "is corrupt)\n\n"));
14640                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
14641                 } else if (retval == EXT2_ET_SHORT_READ)
14642                         printf(_("Could this be a zero-length partition?\n"));
14643                 else if ((retval == EPERM) || (retval == EACCES))
14644                         printf(_("You must have %s access to the "
14645                                "filesystem or be root\n"),
14646                                (ctx->options & E2F_OPT_READONLY) ?
14647                                "r/o" : "r/w");
14648                 else if (retval == ENXIO)
14649                         printf(_("Possibly non-existent or swap device?\n"));
14650 #ifdef EROFS
14651                 else if (retval == EROFS)
14652                         printf(_("Disk write-protected; use the -n option "
14653                                "to do a read-only\n"
14654                                "check of the device.\n"));
14655 #endif
14656                 else
14657                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
14658                 fatal_error(ctx, 0);
14659         }
14660         ctx->fs = fs;
14661         fs->priv_data = ctx;
14662         sb = fs->super;
14663         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
14664                 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
14665                         _("while trying to open %s"),
14666                         ctx->filesystem_name);
14667         get_newer:
14668                 fatal_error(ctx, _("Get a newer version of e2fsck!"));
14669         }
14670
14671         /*
14672          * Set the device name, which is used whenever we print error
14673          * or informational messages to the user.
14674          */
14675         if (ctx->device_name == 0 &&
14676             (sb->s_volume_name[0] != 0)) {
14677                 ctx->device_name = string_copy(sb->s_volume_name,
14678                                                sizeof(sb->s_volume_name));
14679         }
14680         if (ctx->device_name == 0)
14681                 ctx->device_name = ctx->filesystem_name;
14682
14683         /*
14684          * Make sure the ext3 superblock fields are consistent.
14685          */
14686         retval = e2fsck_check_ext3_journal(ctx);
14687         if (retval) {
14688                 com_err(ctx->program_name, retval,
14689                         _("while checking ext3 journal for %s"),
14690                         ctx->device_name);
14691                 fatal_error(ctx, 0);
14692         }
14693
14694         /*
14695          * Check to see if we need to do ext3-style recovery.  If so,
14696          * do it, and then restart the fsck.
14697          */
14698         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
14699                 if (ctx->options & E2F_OPT_READONLY) {
14700                         printf(_("Warning: skipping journal recovery "
14701                                  "because doing a read-only filesystem "
14702                                  "check.\n"));
14703                         io_channel_flush(ctx->fs->io);
14704                 } else {
14705                         if (ctx->flags & E2F_FLAG_RESTARTED) {
14706                                 /*
14707                                  * Whoops, we attempted to run the
14708                                  * journal twice.  This should never
14709                                  * happen, unless the hardware or
14710                                  * device driver is being bogus.
14711                                  */
14712                                 com_err(ctx->program_name, 0,
14713                                         _("unable to set superblock flags on %s\n"), ctx->device_name);
14714                                 fatal_error(ctx, 0);
14715                         }
14716                         retval = e2fsck_run_ext3_journal(ctx);
14717                         if (retval) {
14718                                 com_err(ctx->program_name, retval,
14719                                 _("while recovering ext3 journal of %s"),
14720                                         ctx->device_name);
14721                                 fatal_error(ctx, 0);
14722                         }
14723                         ext2fs_close(ctx->fs);
14724                         ctx->fs = 0;
14725                         ctx->flags |= E2F_FLAG_RESTARTED;
14726                         goto restart;
14727                 }
14728         }
14729
14730         /*
14731          * Check for compatibility with the feature sets.  We need to
14732          * be more stringent than ext2fs_open().
14733          */
14734         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
14735             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
14736                 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
14737                         "(%s)", ctx->device_name);
14738                 goto get_newer;
14739         }
14740         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
14741                 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
14742                         "(%s)", ctx->device_name);
14743                 goto get_newer;
14744         }
14745 #ifdef ENABLE_COMPRESSION
14746         /* FIXME - do we support this at all? */
14747         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
14748                 com_err(ctx->program_name, 0,
14749                         _("Warning: compression support is experimental.\n"));
14750 #endif
14751 #ifndef ENABLE_HTREE
14752         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
14753                 com_err(ctx->program_name, 0,
14754                         _("E2fsck not compiled with HTREE support,\n\t"
14755                           "but filesystem %s has HTREE directories.\n"),
14756                         ctx->device_name);
14757                 goto get_newer;
14758         }
14759 #endif
14760
14761         /*
14762          * If the user specified a specific superblock, presumably the
14763          * master superblock has been trashed.  So we mark the
14764          * superblock as dirty, so it can be written out.
14765          */
14766         if (ctx->superblock &&
14767             !(ctx->options & E2F_OPT_READONLY))
14768                 ext2fs_mark_super_dirty(fs);
14769
14770         /*
14771          * We only update the master superblock because (a) paranoia;
14772          * we don't want to corrupt the backup superblocks, and (b) we
14773          * don't need to update the mount count and last checked
14774          * fields in the backup superblock (the kernel doesn't
14775          * update the backup superblocks anyway).
14776          */
14777         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14778
14779         ehandler_init(fs->io);
14780
14781         if (ctx->superblock)
14782                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
14783         ext2fs_mark_valid(fs);
14784         check_super_block(ctx);
14785         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14786                 fatal_error(ctx, 0);
14787         check_if_skip(ctx);
14788         if (bad_blocks_file)
14789                 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
14790         else if (cflag)
14791                 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
14792         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14793                 fatal_error(ctx, 0);
14794 #ifdef ENABLE_SWAPFS
14795
14796 #ifdef WORDS_BIGENDIAN
14797 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
14798 #else
14799 #define NATIVE_FLAG 0
14800 #endif
14801
14802
14803         if (normalize_swapfs) {
14804                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
14805                         fprintf(stderr, _("%s: Filesystem byte order "
14806                                 "already normalized.\n"), ctx->device_name);
14807                         fatal_error(ctx, 0);
14808                 }
14809         }
14810         if (swapfs) {
14811                 swap_filesys(ctx);
14812                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14813                         fatal_error(ctx, 0);
14814         }
14815 #endif
14816
14817         /*
14818          * Mark the system as valid, 'til proven otherwise
14819          */
14820         ext2fs_mark_valid(fs);
14821
14822         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
14823         if (retval) {
14824                 com_err(ctx->program_name, retval,
14825                         _("while reading bad blocks inode"));
14826                 preenhalt(ctx);
14827                 printf(_("This doesn't bode well,"
14828                          " but we'll try to go on...\n"));
14829         }
14830
14831         run_result = e2fsck_run(ctx);
14832         e2fsck_clear_progbar(ctx);
14833         if (run_result == E2F_FLAG_RESTART) {
14834                 printf(_("Restarting e2fsck from the beginning...\n"));
14835                 retval = e2fsck_reset_context(ctx);
14836                 if (retval) {
14837                         com_err(ctx->program_name, retval,
14838                                 _("while resetting context"));
14839                         fatal_error(ctx, 0);
14840                 }
14841                 ext2fs_close(fs);
14842                 goto restart;
14843         }
14844         if (run_result & E2F_FLAG_CANCEL) {
14845                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
14846                        ctx->device_name : ctx->filesystem_name);
14847                 exit_value |= FSCK_CANCELED;
14848         }
14849         if (run_result & E2F_FLAG_ABORT)
14850                 fatal_error(ctx, _("aborted"));
14851
14852         /* Cleanup */
14853         if (ext2fs_test_changed(fs)) {
14854                 exit_value |= EXIT_NONDESTRUCT;
14855                 if (!(ctx->options & E2F_OPT_PREEN))
14856                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
14857                                ctx->device_name);
14858                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
14859                         printf(_("%s: ***** REBOOT LINUX *****\n"),
14860                                ctx->device_name);
14861                         exit_value |= EXIT_DESTRUCT;
14862                 }
14863         }
14864         if (!ext2fs_test_valid(fs)) {
14865                 printf(_("\n%s: ********** WARNING: Filesystem still has "
14866                          "errors **********\n\n"), ctx->device_name);
14867                 exit_value |= EXIT_UNCORRECTED;
14868                 exit_value &= ~EXIT_NONDESTRUCT;
14869         }
14870         if (exit_value & FSCK_CANCELED)
14871                 exit_value &= ~EXIT_NONDESTRUCT;
14872         else {
14873                 show_stats(ctx);
14874                 if (!(ctx->options & E2F_OPT_READONLY)) {
14875                         if (ext2fs_test_valid(fs)) {
14876                                 if (!(sb->s_state & EXT2_VALID_FS))
14877                                         exit_value |= EXIT_NONDESTRUCT;
14878                                 sb->s_state = EXT2_VALID_FS;
14879                         } else
14880                                 sb->s_state &= ~EXT2_VALID_FS;
14881                         sb->s_mnt_count = 0;
14882                         sb->s_lastcheck = time(NULL);
14883                         ext2fs_mark_super_dirty(fs);
14884                 }
14885         }
14886
14887         e2fsck_write_bitmaps(ctx);
14888
14889         ext2fs_close(fs);
14890         ctx->fs = NULL;
14891         free(ctx->filesystem_name);
14892         free(ctx->journal_name);
14893         e2fsck_free_context(ctx);
14894
14895         return exit_value;
14896 }