Cleanup patch from Denis Vlasenko. Mostly variants of removing the if(x)
[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 #include <sys/types.h>
39 #include <inttypes.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <time.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47 #include <setjmp.h>
48 #include <errno.h>
49 #include <getopt.h>
50 #include <limits.h>
51 #include <stddef.h>
52 #include <assert.h>
53 #include <signal.h>
54 #include <sys/time.h>
55 #include <sys/stat.h>
56 #include <sys/resource.h>
57 #include <sys/param.h>
58 #include <sys/mount.h>
59 #include <sys/ioctl.h>
60 #include <malloc.h>
61 #include <termios.h>
62 #include <mntent.h>
63 #include <dirent.h>
64
65 #include "fsck.h"
66
67 #include "ext2fs/ext2_fs.h"
68 #include "ext2fs/ext2fs.h"
69 #include "blkid/blkid.h"
70 #include "ext2fs/ext2_ext_attr.h"
71 #include "uuid/uuid.h"
72
73 #ifdef __GNUC__
74 #define _INLINE_ __inline__
75 #define EXT2FS_ATTR(x) __attribute__(x)
76 #else
77 #define _INLINE_
78 #define EXT2FS_ATTR(x)
79 #endif
80
81 /*
82  * The last ext2fs revision level that this version of e2fsck is able to
83  * support
84  */
85 #define E2FSCK_CURRENT_REV      1
86
87 /*
88  * The directory information structure; stores directory information
89  * collected in earlier passes, to avoid disk i/o in fetching the
90  * directory information.
91  */
92 struct dir_info {
93         ext2_ino_t              ino;    /* Inode number */
94         ext2_ino_t              dotdot; /* Parent according to '..' */
95         ext2_ino_t              parent; /* Parent according to treewalk */
96 };
97
98
99 /*
100  * The indexed directory information structure; stores information for
101  * directories which contain a hash tree index.
102  */
103 struct dx_dir_info {
104         ext2_ino_t              ino;            /* Inode number */
105         int                     numblocks;      /* number of blocks */
106         int                     hashversion;
107         short                   depth;          /* depth of tree */
108         struct dx_dirblock_info *dx_block;      /* Array of size numblocks */
109 };
110
111 #define DX_DIRBLOCK_ROOT        1
112 #define DX_DIRBLOCK_LEAF        2
113 #define DX_DIRBLOCK_NODE        3
114 #define DX_DIRBLOCK_CORRUPT     4
115 #define DX_DIRBLOCK_CLEARED     8
116
117 struct dx_dirblock_info {
118         int             type;
119         blk_t           phys;
120         int             flags;
121         blk_t           parent;
122         ext2_dirhash_t  min_hash;
123         ext2_dirhash_t  max_hash;
124         ext2_dirhash_t  node_min_hash;
125         ext2_dirhash_t  node_max_hash;
126 };
127
128 #define DX_FLAG_REFERENCED      1
129 #define DX_FLAG_DUP_REF         2
130 #define DX_FLAG_FIRST           4
131 #define DX_FLAG_LAST            8
132
133 #ifdef RESOURCE_TRACK
134 /*
135  * This structure is used for keeping track of how much resources have
136  * been used for a particular pass of e2fsck.
137  */
138 struct resource_track {
139         struct timeval time_start;
140         struct timeval user_start;
141         struct timeval system_start;
142         void    *brk_start;
143 };
144 #endif
145
146 /*
147  * E2fsck options
148  */
149 #define E2F_OPT_READONLY        0x0001
150 #define E2F_OPT_PREEN           0x0002
151 #define E2F_OPT_YES             0x0004
152 #define E2F_OPT_NO              0x0008
153 #define E2F_OPT_TIME            0x0010
154 #define E2F_OPT_TIME2           0x0020
155 #define E2F_OPT_CHECKBLOCKS     0x0040
156 #define E2F_OPT_DEBUG           0x0080
157 #define E2F_OPT_FORCE           0x0100
158 #define E2F_OPT_WRITECHECK      0x0200
159 #define E2F_OPT_COMPRESS_DIRS   0x0400
160
161 /*
162  * E2fsck flags
163  */
164 #define E2F_FLAG_ABORT          0x0001 /* Abort signaled */
165 #define E2F_FLAG_CANCEL         0x0002 /* Cancel signaled */
166 #define E2F_FLAG_SIGNAL_MASK    0x0003
167 #define E2F_FLAG_RESTART        0x0004 /* Restart signaled */
168
169 #define E2F_FLAG_SETJMP_OK      0x0010 /* Setjmp valid for abort */
170
171 #define E2F_FLAG_PROG_BAR       0x0020 /* Progress bar on screen */
172 #define E2F_FLAG_PROG_SUPPRESS  0x0040 /* Progress suspended */
173 #define E2F_FLAG_JOURNAL_INODE  0x0080 /* Create a new ext3 journal inode */
174 #define E2F_FLAG_SB_SPECIFIED   0x0100 /* The superblock was explicitly
175                                         * specified by the user */
176 #define E2F_FLAG_RESTARTED      0x0200 /* E2fsck has been restarted */
177 #define E2F_FLAG_RESIZE_INODE   0x0400 /* Request to recreate resize inode */
178
179 /*
180  * Defines for indicating the e2fsck pass number
181  */
182 #define E2F_PASS_1      1
183 #define E2F_PASS_2      2
184 #define E2F_PASS_3      3
185 #define E2F_PASS_4      4
186 #define E2F_PASS_5      5
187 #define E2F_PASS_1B     6
188
189
190 /*
191  * This is the global e2fsck structure.
192  */
193 typedef struct e2fsck_struct *e2fsck_t;
194
195 /*
196  * Define the extended attribute refcount structure
197  */
198 typedef struct ea_refcount *ext2_refcount_t;
199
200 struct e2fsck_struct {
201         ext2_filsys fs;
202         const char *program_name;
203         char *filesystem_name;
204         char *device_name;
205         char *io_options;
206         int     flags;          /* E2fsck internal flags */
207         int     options;
208         blk_t   use_superblock; /* sb requested by user */
209         blk_t   superblock;     /* sb used to open fs */
210         int     blocksize;      /* blocksize */
211         blk_t   num_blocks;     /* Total number of blocks */
212         int     mount_flags;
213         blkid_cache blkid;      /* blkid cache */
214
215         jmp_buf abort_loc;
216
217         unsigned long abort_code;
218
219         int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
220                         unsigned long max);
221
222         ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
223         ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
224         ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
225         ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
226         ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
227         ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
228
229         ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
230         ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
231         ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
232
233         /*
234          * Inode count arrays
235          */
236         ext2_icount_t   inode_count;
237         ext2_icount_t inode_link_info;
238
239         ext2_refcount_t refcount;
240         ext2_refcount_t refcount_extra;
241
242         /*
243          * Array of flags indicating whether an inode bitmap, block
244          * bitmap, or inode table is invalid
245          */
246         int *invalid_inode_bitmap_flag;
247         int *invalid_block_bitmap_flag;
248         int *invalid_inode_table_flag;
249         int invalid_bitmaps;    /* There are invalid bitmaps/itable */
250
251         /*
252          * Block buffer
253          */
254         char *block_buf;
255
256         /*
257          * For pass1_check_directory and pass1_get_blocks
258          */
259         ext2_ino_t stashed_ino;
260         struct ext2_inode *stashed_inode;
261
262         /*
263          * Location of the lost and found directory
264          */
265         ext2_ino_t lost_and_found;
266         int bad_lost_and_found;
267
268         /*
269          * Directory information
270          */
271         int             dir_info_count;
272         int             dir_info_size;
273         struct dir_info *dir_info;
274
275         /*
276          * Indexed directory information
277          */
278         int             dx_dir_info_count;
279         int             dx_dir_info_size;
280         struct dx_dir_info *dx_dir_info;
281
282         /*
283          * Directories to hash
284          */
285         ext2_u32_list   dirs_to_hash;
286
287         /*
288          * Tuning parameters
289          */
290         int process_inode_size;
291         int inode_buffer_blocks;
292
293         /*
294          * ext3 journal support
295          */
296         io_channel      journal_io;
297         char    *journal_name;
298
299 #ifdef RESOURCE_TRACK
300         /*
301          * For timing purposes
302          */
303         struct resource_track   global_rtrack;
304 #endif
305
306         /*
307          * How we display the progress update (for unix)
308          */
309         int progress_fd;
310         int progress_pos;
311         int progress_last_percent;
312         unsigned int progress_last_time;
313         int interactive;        /* Are we connected directly to a tty? */
314         char start_meta[2], stop_meta[2];
315
316         /* File counts */
317         int fs_directory_count;
318         int fs_regular_count;
319         int fs_blockdev_count;
320         int fs_chardev_count;
321         int fs_links_count;
322         int fs_symlinks_count;
323         int fs_fast_symlinks_count;
324         int fs_fifo_count;
325         int fs_total_count;
326         int fs_badblocks_count;
327         int fs_sockets_count;
328         int fs_ind_count;
329         int fs_dind_count;
330         int fs_tind_count;
331         int fs_fragmented;
332         int large_files;
333         int fs_ext_attr_inodes;
334         int fs_ext_attr_blocks;
335
336         int ext_attr_ver;
337
338         /*
339          * For the use of callers of the e2fsck functions; not used by
340          * e2fsck functions themselves.
341          */
342         void *priv_data;
343 };
344
345 /* Used by the region allocation code */
346 typedef __u32 region_addr_t;
347 typedef struct region_struct *region_t;
348
349 /*
350  * Procedure declarations
351  */
352
353 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
354
355 /* pass1.c */
356 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
357
358 /* pass2.c */
359 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
360                                     ext2_ino_t ino, char *buf);
361
362 /* pass3.c */
363 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
364 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
365                                          int num, int gauranteed_size);
366 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
367 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
368                                            int adj);
369
370 /* rehash.c */
371 static void e2fsck_rehash_directories(e2fsck_t ctx);
372
373 /* util.c */
374 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
375                                     const char *description);
376 static int ask(e2fsck_t ctx, const char * string, int def);
377 static void e2fsck_read_bitmaps(e2fsck_t ctx);
378 static void preenhalt(e2fsck_t ctx);
379 #ifdef RESOURCE_TRACK
380 static void print_resource_track(const char *desc,
381                                  struct resource_track *track);
382 static void init_resource_track(struct resource_track *track);
383 #endif
384 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
385                               struct ext2_inode * inode, const char * proc);
386 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
387                                struct ext2_inode * inode, const char * proc);
388 #ifdef MTRACE
389 static void mtrace_print(char *mesg);
390 #endif
391 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
392                            const char *name, io_manager manager);
393
394 /* unix.c */
395 static void e2fsck_clear_progbar(e2fsck_t ctx);
396 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
397                                   float percent, unsigned int dpynum);
398 /*
399  * problem.h --- e2fsck problem error codes
400  */
401
402 typedef __u32 problem_t;
403
404 struct problem_context {
405         errcode_t       errcode;
406         ext2_ino_t ino, ino2, dir;
407         struct ext2_inode *inode;
408         struct ext2_dir_entry *dirent;
409         blk_t   blk, blk2;
410         e2_blkcnt_t     blkcount;
411         int             group;
412         __u64   num;
413         const char *str;
414 };
415
416 /*
417  * We define a set of "latch groups"; these are problems which are
418  * handled as a set.  The user answers once for a particular latch
419  * group.
420  */
421 #define PR_LATCH_MASK         0x0ff0 /* Latch mask */
422 #define PR_LATCH_BLOCK        0x0010 /* Latch for illegal blocks (pass 1) */
423 #define PR_LATCH_BBLOCK       0x0020 /* Latch for bad block inode blocks (pass 1) */
424 #define PR_LATCH_IBITMAP      0x0030 /* Latch for pass 5 inode bitmap proc. */
425 #define PR_LATCH_BBITMAP      0x0040 /* Latch for pass 5 inode bitmap proc. */
426 #define PR_LATCH_RELOC        0x0050 /* Latch for superblock relocate hint */
427 #define PR_LATCH_DBLOCK       0x0060 /* Latch for pass 1b dup block headers */
428 #define PR_LATCH_LOW_DTIME    0x0070 /* Latch for pass1 orphaned list refugees */
429 #define PR_LATCH_TOOBIG       0x0080 /* Latch for file to big errors */
430 #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
431
432 #define PR_LATCH(x)     ((((x) & PR_LATCH_MASK) >> 4) - 1)
433
434 /*
435  * Latch group descriptor flags
436  */
437 #define PRL_YES         0x0001  /* Answer yes */
438 #define PRL_NO          0x0002  /* Answer no */
439 #define PRL_LATCHED     0x0004  /* The latch group is latched */
440 #define PRL_SUPPRESS    0x0008  /* Suppress all latch group questions */
441
442 #define PRL_VARIABLE    0x000f  /* All the flags that need to be reset */
443
444 /*
445  * Pre-Pass 1 errors
446  */
447
448 /* Block bitmap not in group */
449 #define PR_0_BB_NOT_GROUP       0x000001
450
451 /* Inode bitmap not in group */
452 #define PR_0_IB_NOT_GROUP       0x000002
453
454 /* Inode table not in group */
455 #define PR_0_ITABLE_NOT_GROUP   0x000003
456
457 /* Superblock corrupt */
458 #define PR_0_SB_CORRUPT         0x000004
459
460 /* Filesystem size is wrong */
461 #define PR_0_FS_SIZE_WRONG      0x000005
462
463 /* Fragments not supported */
464 #define PR_0_NO_FRAGMENTS       0x000006
465
466 /* Bad blocks_per_group */
467 #define PR_0_BLOCKS_PER_GROUP   0x000007
468
469 /* Bad first_data_block */
470 #define PR_0_FIRST_DATA_BLOCK   0x000008
471
472 /* Adding UUID to filesystem */
473 #define PR_0_ADD_UUID           0x000009
474
475 /* Relocate hint */
476 #define PR_0_RELOCATE_HINT      0x00000A
477
478 /* Miscellaneous superblock corruption */
479 #define PR_0_MISC_CORRUPT_SUPER 0x00000B
480
481 /* Error determing physical device size of filesystem */
482 #define PR_0_GETSIZE_ERROR      0x00000C
483
484 /* Inode count in the superblock incorrect */
485 #define PR_0_INODE_COUNT_WRONG  0x00000D
486
487 /* The Hurd does not support the filetype feature */
488 #define PR_0_HURD_CLEAR_FILETYPE 0x00000E
489
490 /* Journal inode is invalid */
491 #define PR_0_JOURNAL_BAD_INODE  0x00000F
492
493 /* The external journal has multiple filesystems (which we can't handle yet) */
494 #define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010
495
496 /* Can't find external journal */
497 #define PR_0_CANT_FIND_JOURNAL  0x000011
498
499 /* External journal has bad superblock */
500 #define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012
501
502 /* Superblock has a bad journal UUID */
503 #define PR_0_JOURNAL_BAD_UUID   0x000013
504
505 /* Journal has an unknown superblock type */
506 #define PR_0_JOURNAL_UNSUPP_SUPER 0x000014
507
508 /* Journal superblock is corrupt */
509 #define PR_0_JOURNAL_BAD_SUPER  0x000015
510
511 /* Journal superblock is corrupt */
512 #define PR_0_JOURNAL_HAS_JOURNAL 0x000016
513
514 /* Superblock has recovery flag set but no journal */
515 #define PR_0_JOURNAL_RECOVER_SET 0x000017
516
517 /* Journal has data, but recovery flag is clear */
518 #define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018
519
520 /* Ask if we should clear the journal */
521 #define PR_0_JOURNAL_RESET_JOURNAL 0x000019
522
523 /* Filesystem revision is 0, but feature flags are set */
524 #define PR_0_FS_REV_LEVEL       0x00001A
525
526 /* Clearing orphan inode */
527 #define PR_0_ORPHAN_CLEAR_INODE                 0x000020
528
529 /* Illegal block found in orphaned inode */
530 #define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM           0x000021
531
532 /* Already cleared block found in orphaned inode */
533 #define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK       0x000022
534
535 /* Illegal orphan inode in superblock */
536 #define PR_0_ORPHAN_ILLEGAL_HEAD_INODE          0x000023
537
538 /* Illegal inode in orphaned inode list */
539 #define PR_0_ORPHAN_ILLEGAL_INODE               0x000024
540
541 /* Journal has unsupported read-only feature - abort */
542 #define PR_0_JOURNAL_UNSUPP_ROCOMPAT            0x000025
543
544 /* Journal has unsupported incompatible feature - abort */
545 #define PR_0_JOURNAL_UNSUPP_INCOMPAT            0x000026
546
547 /* Journal has unsupported version number */
548 #define PR_0_JOURNAL_UNSUPP_VERSION             0x000027
549
550 /* Moving journal to hidden file */
551 #define PR_0_MOVE_JOURNAL                       0x000028
552
553 /* Error moving journal */
554 #define PR_0_ERR_MOVE_JOURNAL                   0x000029
555
556 /* Clearing V2 journal superblock */
557 #define PR_0_CLEAR_V2_JOURNAL                   0x00002A
558
559 /* Run journal anyway */
560 #define PR_0_JOURNAL_RUN                        0x00002B
561
562 /* Run journal anyway by default */
563 #define PR_0_JOURNAL_RUN_DEFAULT                0x00002C
564
565 /* Backup journal inode blocks */
566 #define PR_0_BACKUP_JNL                         0x00002D
567
568 /* Reserved blocks w/o resize_inode */
569 #define PR_0_NONZERO_RESERVED_GDT_BLOCKS        0x00002E
570
571 /* Resize_inode not enabled, but resize inode is non-zero */
572 #define PR_0_CLEAR_RESIZE_INODE                 0x00002F
573
574 /* Resize inode invalid */
575 #define PR_0_RESIZE_INODE_INVALID               0x000030
576
577 /*
578  * Pass 1 errors
579  */
580
581 /* Pass 1: Checking inodes, blocks, and sizes */
582 #define PR_1_PASS_HEADER                0x010000
583
584 /* Root directory is not an inode */
585 #define PR_1_ROOT_NO_DIR                0x010001
586
587 /* Root directory has dtime set */
588 #define PR_1_ROOT_DTIME                 0x010002
589
590 /* Reserved inode has bad mode */
591 #define PR_1_RESERVED_BAD_MODE          0x010003
592
593 /* Deleted inode has zero dtime */
594 #define PR_1_ZERO_DTIME                 0x010004
595
596 /* Inode in use, but dtime set */
597 #define PR_1_SET_DTIME                  0x010005
598
599 /* Zero-length directory */
600 #define PR_1_ZERO_LENGTH_DIR            0x010006
601
602 /* Block bitmap conflicts with some other fs block */
603 #define PR_1_BB_CONFLICT                0x010007
604
605 /* Inode bitmap conflicts with some other fs block */
606 #define PR_1_IB_CONFLICT                0x010008
607
608 /* Inode table conflicts with some other fs block */
609 #define PR_1_ITABLE_CONFLICT            0x010009
610
611 /* Block bitmap is on a bad block */
612 #define PR_1_BB_BAD_BLOCK               0x01000A
613
614 /* Inode bitmap is on a bad block */
615 #define PR_1_IB_BAD_BLOCK               0x01000B
616
617 /* Inode has incorrect i_size */
618 #define PR_1_BAD_I_SIZE                 0x01000C
619
620 /* Inode has incorrect i_blocks */
621 #define PR_1_BAD_I_BLOCKS               0x01000D
622
623 /* Illegal block number in inode */
624 #define PR_1_ILLEGAL_BLOCK_NUM          0x01000E
625
626 /* Block number overlaps fs metadata */
627 #define PR_1_BLOCK_OVERLAPS_METADATA    0x01000F
628
629 /* Inode has illegal blocks (latch question) */
630 #define PR_1_INODE_BLOCK_LATCH          0x010010
631
632 /* Too many bad blocks in inode */
633 #define PR_1_TOO_MANY_BAD_BLOCKS        0x010011
634
635 /* Illegal block number in bad block inode */
636 #define PR_1_BB_ILLEGAL_BLOCK_NUM       0x010012
637
638 /* Bad block inode has illegal blocks (latch question) */
639 #define PR_1_INODE_BBLOCK_LATCH         0x010013
640
641 /* Duplicate or bad blocks in use! */
642 #define PR_1_DUP_BLOCKS_PREENSTOP       0x010014
643
644 /* Bad block used as bad block indirect block */
645 #define PR_1_BBINODE_BAD_METABLOCK      0x010015
646
647 /* Inconsistency can't be fixed prompt */
648 #define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
649
650 /* Bad primary block */
651 #define PR_1_BAD_PRIMARY_BLOCK          0x010017
652
653 /* Bad primary block prompt */
654 #define PR_1_BAD_PRIMARY_BLOCK_PROMPT   0x010018
655
656 /* Bad primary superblock */
657 #define PR_1_BAD_PRIMARY_SUPERBLOCK     0x010019
658
659 /* Bad primary block group descriptors */
660 #define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A
661
662 /* Bad superblock in group */
663 #define PR_1_BAD_SUPERBLOCK             0x01001B
664
665 /* Bad block group descriptors in group */
666 #define PR_1_BAD_GROUP_DESCRIPTORS      0x01001C
667
668 /* Block claimed for no reason */
669 #define PR_1_PROGERR_CLAIMED_BLOCK      0x01001D
670
671 /* Error allocating blocks for relocating metadata */
672 #define PR_1_RELOC_BLOCK_ALLOCATE       0x01001E
673
674 /* Error allocating block buffer during relocation process */
675 #define PR_1_RELOC_MEMORY_ALLOCATE      0x01001F
676
677 /* Relocating metadata group information from X to Y */
678 #define PR_1_RELOC_FROM_TO              0x010020
679
680 /* Relocating metatdata group information to X */
681 #define PR_1_RELOC_TO                   0x010021
682
683 /* Block read error during relocation process */
684 #define PR_1_RELOC_READ_ERR             0x010022
685
686 /* Block write error during relocation process */
687 #define PR_1_RELOC_WRITE_ERR            0x010023
688
689 /* Error allocating inode bitmap */
690 #define PR_1_ALLOCATE_IBITMAP_ERROR     0x010024
691
692 /* Error allocating block bitmap */
693 #define PR_1_ALLOCATE_BBITMAP_ERROR     0x010025
694
695 /* Error allocating icount structure */
696 #define PR_1_ALLOCATE_ICOUNT            0x010026
697
698 /* Error allocating dbcount */
699 #define PR_1_ALLOCATE_DBCOUNT           0x010027
700
701 /* Error while scanning inodes */
702 #define PR_1_ISCAN_ERROR                0x010028
703
704 /* Error while iterating over blocks */
705 #define PR_1_BLOCK_ITERATE              0x010029
706
707 /* Error while storing inode count information */
708 #define PR_1_ICOUNT_STORE               0x01002A
709
710 /* Error while storing directory block information */
711 #define PR_1_ADD_DBLOCK                 0x01002B
712
713 /* Error while reading inode (for clearing) */
714 #define PR_1_READ_INODE                 0x01002C
715
716 /* Suppress messages prompt */
717 #define PR_1_SUPPRESS_MESSAGES          0x01002D
718
719 /* Imagic flag set on an inode when filesystem doesn't support it */
720 #define PR_1_SET_IMAGIC                 0x01002F
721
722 /* Immutable flag set on a device or socket inode */
723 #define PR_1_SET_IMMUTABLE              0x010030
724
725 /* Compression flag set on a non-compressed filesystem */
726 #define PR_1_COMPR_SET                  0x010031
727
728 /* Non-zero size on on device, fifo or socket inode */
729 #define PR_1_SET_NONZSIZE               0x010032
730
731 /* Filesystem revision is 0, but feature flags are set */
732 #define PR_1_FS_REV_LEVEL               0x010033
733
734 /* Journal inode not in use, needs clearing */
735 #define PR_1_JOURNAL_INODE_NOT_CLEAR    0x010034
736
737 /* Journal inode has wrong mode */
738 #define PR_1_JOURNAL_BAD_MODE           0x010035
739
740 /* Inode that was part of orphan linked list */
741 #define PR_1_LOW_DTIME                  0x010036
742
743 /* Latch question which asks how to deal with low dtime inodes */
744 #define PR_1_ORPHAN_LIST_REFUGEES       0x010037
745
746 /* Error allocating refcount structure */
747 #define PR_1_ALLOCATE_REFCOUNT          0x010038
748
749 /* Error reading Extended Attribute block */
750 #define PR_1_READ_EA_BLOCK              0x010039
751
752 /* Invalid Extended Attribute block */
753 #define PR_1_BAD_EA_BLOCK               0x01003A
754
755 /* Error reading Extended Attribute block while fixing refcount -- abort */
756 #define PR_1_EXTATTR_READ_ABORT         0x01003B
757
758 /* Extended attribute reference count incorrect */
759 #define PR_1_EXTATTR_REFCOUNT           0x01003C
760
761 /* Error writing Extended Attribute block while fixing refcount */
762 #define PR_1_EXTATTR_WRITE              0x01003D
763
764 /* Multiple EA blocks not supported */
765 #define PR_1_EA_MULTI_BLOCK             0x01003E
766
767 /* Error allocating EA region allocation structure */
768 #define PR_1_EA_ALLOC_REGION            0x01003F
769
770 /* Error EA allocation collision */
771 #define PR_1_EA_ALLOC_COLLISION         0x010040
772
773 /* Bad extended attribute name */
774 #define PR_1_EA_BAD_NAME                0x010041
775
776 /* Bad extended attribute value */
777 #define PR_1_EA_BAD_VALUE               0x010042
778
779 /* Inode too big (latch question) */
780 #define PR_1_INODE_TOOBIG               0x010043
781
782 /* Directory too big */
783 #define PR_1_TOOBIG_DIR                 0x010044
784
785 /* Regular file too big */
786 #define PR_1_TOOBIG_REG                 0x010045
787
788 /* Symlink too big */
789 #define PR_1_TOOBIG_SYMLINK             0x010046
790
791 /* INDEX_FL flag set on a non-HTREE filesystem */
792 #define PR_1_HTREE_SET                  0x010047
793
794 /* INDEX_FL flag set on a non-directory */
795 #define PR_1_HTREE_NODIR                0x010048
796
797 /* Invalid root node in HTREE directory */
798 #define PR_1_HTREE_BADROOT              0x010049
799
800 /* Unsupported hash version in HTREE directory */
801 #define PR_1_HTREE_HASHV                0x01004A
802
803 /* Incompatible flag in HTREE root node */
804 #define PR_1_HTREE_INCOMPAT             0x01004B
805
806 /* HTREE too deep */
807 #define PR_1_HTREE_DEPTH                0x01004C
808
809 /* Bad block has indirect block that conflicts with filesystem block */
810 #define PR_1_BB_FS_BLOCK                0x01004D
811
812 /* Resize inode failed */
813 #define PR_1_RESIZE_INODE_CREATE        0x01004E
814
815 /* inode->i_size is too long */
816 #define PR_1_EXTRA_ISIZE                0x01004F
817
818 /* attribute name is too long */
819 #define PR_1_ATTR_NAME_LEN              0x010050
820
821 /* wrong EA value offset */
822 #define PR_1_ATTR_VALUE_OFFSET          0x010051
823
824 /* wrong EA blocknumber */
825 #define PR_1_ATTR_VALUE_BLOCK           0x010052
826
827 /* wrong EA value size */
828 #define PR_1_ATTR_VALUE_SIZE            0x010053
829
830 /* wrong EA hash value */
831 #define PR_1_ATTR_HASH                  0x010054
832
833 /*
834  * Pass 1b errors
835  */
836
837 /* Pass 1B: Rescan for duplicate/bad blocks */
838 #define PR_1B_PASS_HEADER       0x011000
839
840 /* Duplicate/bad block(s) header */
841 #define PR_1B_DUP_BLOCK_HEADER  0x011001
842
843 /* Duplicate/bad block(s) in inode */
844 #define PR_1B_DUP_BLOCK         0x011002
845
846 /* Duplicate/bad block(s) end */
847 #define PR_1B_DUP_BLOCK_END     0x011003
848
849 /* Error while scanning inodes */
850 #define PR_1B_ISCAN_ERROR       0x011004
851
852 /* Error allocating inode bitmap */
853 #define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
854
855 /* Error while iterating over blocks */
856 #define PR_1B_BLOCK_ITERATE     0x0110006
857
858 /* Error adjusting EA refcount */
859 #define PR_1B_ADJ_EA_REFCOUNT   0x0110007
860
861
862 /* Pass 1C: Scan directories for inodes with dup blocks. */
863 #define PR_1C_PASS_HEADER       0x012000
864
865
866 /* Pass 1D: Reconciling duplicate blocks */
867 #define PR_1D_PASS_HEADER       0x013000
868
869 /* File has duplicate blocks */
870 #define PR_1D_DUP_FILE          0x013001
871
872 /* List of files sharing duplicate blocks */
873 #define PR_1D_DUP_FILE_LIST     0x013002
874
875 /* File sharing blocks with filesystem metadata  */
876 #define PR_1D_SHARE_METADATA    0x013003
877
878 /* Report of how many duplicate/bad inodes */
879 #define PR_1D_NUM_DUP_INODES    0x013004
880
881 /* Duplicated blocks already reassigned or cloned. */
882 #define PR_1D_DUP_BLOCKS_DEALT  0x013005
883
884 /* Clone duplicate/bad blocks? */
885 #define PR_1D_CLONE_QUESTION    0x013006
886
887 /* Delete file? */
888 #define PR_1D_DELETE_QUESTION   0x013007
889
890 /* Couldn't clone file (error) */
891 #define PR_1D_CLONE_ERROR       0x013008
892
893 /*
894  * Pass 2 errors
895  */
896
897 /* Pass 2: Checking directory structure */
898 #define PR_2_PASS_HEADER        0x020000
899
900 /* Bad inode number for '.' */
901 #define PR_2_BAD_INODE_DOT      0x020001
902
903 /* Directory entry has bad inode number */
904 #define PR_2_BAD_INO            0x020002
905
906 /* Directory entry has deleted or unused inode */
907 #define PR_2_UNUSED_INODE       0x020003
908
909 /* Directry entry is link to '.' */
910 #define PR_2_LINK_DOT           0x020004
911
912 /* Directory entry points to inode now located in a bad block */
913 #define PR_2_BB_INODE           0x020005
914
915 /* Directory entry contains a link to a directory */
916 #define PR_2_LINK_DIR           0x020006
917
918 /* Directory entry contains a link to the root directry */
919 #define PR_2_LINK_ROOT          0x020007
920
921 /* Directory entry has illegal characters in its name */
922 #define PR_2_BAD_NAME           0x020008
923
924 /* Missing '.' in directory inode */
925 #define PR_2_MISSING_DOT        0x020009
926
927 /* Missing '..' in directory inode */
928 #define PR_2_MISSING_DOT_DOT    0x02000A
929
930 /* First entry in directory inode doesn't contain '.' */
931 #define PR_2_1ST_NOT_DOT        0x02000B
932
933 /* Second entry in directory inode doesn't contain '..' */
934 #define PR_2_2ND_NOT_DOT_DOT    0x02000C
935
936 /* i_faddr should be zero */
937 #define PR_2_FADDR_ZERO         0x02000D
938
939 /* i_file_acl should be zero */
940 #define PR_2_FILE_ACL_ZERO      0x02000E
941
942 /* i_dir_acl should be zero */
943 #define PR_2_DIR_ACL_ZERO       0x02000F
944
945 /* i_frag should be zero */
946 #define PR_2_FRAG_ZERO          0x020010
947
948 /* i_fsize should be zero */
949 #define PR_2_FSIZE_ZERO         0x020011
950
951 /* inode has bad mode */
952 #define PR_2_BAD_MODE           0x020012
953
954 /* directory corrupted */
955 #define PR_2_DIR_CORRUPTED      0x020013
956
957 /* filename too long */
958 #define PR_2_FILENAME_LONG      0x020014
959
960 /* Directory inode has a missing block (hole) */
961 #define PR_2_DIRECTORY_HOLE     0x020015
962
963 /* '.' is not NULL terminated */
964 #define PR_2_DOT_NULL_TERM      0x020016
965
966 /* '..' is not NULL terminated */
967 #define PR_2_DOT_DOT_NULL_TERM  0x020017
968
969 /* Illegal character device in inode */
970 #define PR_2_BAD_CHAR_DEV       0x020018
971
972 /* Illegal block device in inode */
973 #define PR_2_BAD_BLOCK_DEV      0x020019
974
975 /* Duplicate '.' entry */
976 #define PR_2_DUP_DOT            0x02001A
977
978 /* Duplicate '..' entry */
979 #define PR_2_DUP_DOT_DOT        0x02001B
980
981 /* Internal error: couldn't find dir_info */
982 #define PR_2_NO_DIRINFO         0x02001C
983
984 /* Final rec_len is wrong */
985 #define PR_2_FINAL_RECLEN       0x02001D
986
987 /* Error allocating icount structure */
988 #define PR_2_ALLOCATE_ICOUNT    0x02001E
989
990 /* Error iterating over directory blocks */
991 #define PR_2_DBLIST_ITERATE     0x02001F
992
993 /* Error reading directory block */
994 #define PR_2_READ_DIRBLOCK      0x020020
995
996 /* Error writing directory block */
997 #define PR_2_WRITE_DIRBLOCK     0x020021
998
999 /* Error allocating new directory block */
1000 #define PR_2_ALLOC_DIRBOCK      0x020022
1001
1002 /* Error deallocating inode */
1003 #define PR_2_DEALLOC_INODE      0x020023
1004
1005 /* Directory entry for '.' is big.  Split? */
1006 #define PR_2_SPLIT_DOT          0x020024
1007
1008 /* Illegal FIFO */
1009 #define PR_2_BAD_FIFO           0x020025
1010
1011 /* Illegal socket */
1012 #define PR_2_BAD_SOCKET         0x020026
1013
1014 /* Directory filetype not set */
1015 #define PR_2_SET_FILETYPE       0x020027
1016
1017 /* Directory filetype incorrect */
1018 #define PR_2_BAD_FILETYPE       0x020028
1019
1020 /* Directory filetype set when it shouldn't be */
1021 #define PR_2_CLEAR_FILETYPE     0x020029
1022
1023 /* Directory filename can't be zero-length  */
1024 #define PR_2_NULL_NAME          0x020030
1025
1026 /* Invalid symlink */
1027 #define PR_2_INVALID_SYMLINK    0x020031
1028
1029 /* i_file_acl (extended attribute) is bad */
1030 #define PR_2_FILE_ACL_BAD       0x020032
1031
1032 /* Filesystem contains large files, but has no such flag in sb */
1033 #define PR_2_FEATURE_LARGE_FILES 0x020033
1034
1035 /* Node in HTREE directory not referenced */
1036 #define PR_2_HTREE_NOTREF       0x020034
1037
1038 /* Node in HTREE directory referenced twice */
1039 #define PR_2_HTREE_DUPREF       0x020035
1040
1041 /* Node in HTREE directory has bad min hash */
1042 #define PR_2_HTREE_MIN_HASH     0x020036
1043
1044 /* Node in HTREE directory has bad max hash */
1045 #define PR_2_HTREE_MAX_HASH     0x020037
1046
1047 /* Clear invalid HTREE directory */
1048 #define PR_2_HTREE_CLEAR        0x020038
1049
1050 /* Clear the htree flag forcibly */
1051 /* #define PR_2_HTREE_FCLR      0x020039 */
1052
1053 /* Bad block in htree interior node */
1054 #define PR_2_HTREE_BADBLK       0x02003A
1055
1056 /* Error adjusting EA refcount */
1057 #define PR_2_ADJ_EA_REFCOUNT    0x02003B
1058
1059 /* Invalid HTREE root node */
1060 #define PR_2_HTREE_BAD_ROOT     0x02003C
1061
1062 /* Invalid HTREE limit */
1063 #define PR_2_HTREE_BAD_LIMIT    0x02003D
1064
1065 /* Invalid HTREE count */
1066 #define PR_2_HTREE_BAD_COUNT    0x02003E
1067
1068 /* HTREE interior node has out-of-order hashes in table */
1069 #define PR_2_HTREE_HASH_ORDER   0x02003F
1070
1071 /* Node in HTREE directory has bad depth */
1072 #define PR_2_HTREE_BAD_DEPTH    0x020040
1073
1074 /* Duplicate directory entry found */
1075 #define PR_2_DUPLICATE_DIRENT   0x020041
1076
1077 /* Non-unique filename found */
1078 #define PR_2_NON_UNIQUE_FILE    0x020042
1079
1080 /* Duplicate directory entry found */
1081 #define PR_2_REPORT_DUP_DIRENT  0x020043
1082
1083 /*
1084  * Pass 3 errors
1085  */
1086
1087 /* Pass 3: Checking directory connectivity */
1088 #define PR_3_PASS_HEADER                0x030000
1089
1090 /* Root inode not allocated */
1091 #define PR_3_NO_ROOT_INODE              0x030001
1092
1093 /* No room in lost+found */
1094 #define PR_3_EXPAND_LF_DIR              0x030002
1095
1096 /* Unconnected directory inode */
1097 #define PR_3_UNCONNECTED_DIR            0x030003
1098
1099 /* /lost+found not found */
1100 #define PR_3_NO_LF_DIR                  0x030004
1101
1102 /* .. entry is incorrect */
1103 #define PR_3_BAD_DOT_DOT                0x030005
1104
1105 /* Bad or non-existent /lost+found.  Cannot reconnect */
1106 #define PR_3_NO_LPF                     0x030006
1107
1108 /* Could not expand /lost+found */
1109 #define PR_3_CANT_EXPAND_LPF            0x030007
1110
1111 /* Could not reconnect inode */
1112 #define PR_3_CANT_RECONNECT             0x030008
1113
1114 /* Error while trying to find /lost+found */
1115 #define PR_3_ERR_FIND_LPF               0x030009
1116
1117 /* Error in ext2fs_new_block while creating /lost+found */
1118 #define PR_3_ERR_LPF_NEW_BLOCK          0x03000A
1119
1120 /* Error in ext2fs_new_inode while creating /lost+found */
1121 #define PR_3_ERR_LPF_NEW_INODE          0x03000B
1122
1123 /* Error in ext2fs_new_dir_block while creating /lost+found */
1124 #define PR_3_ERR_LPF_NEW_DIR_BLOCK      0x03000C
1125
1126 /* Error while writing directory block for /lost+found */
1127 #define PR_3_ERR_LPF_WRITE_BLOCK        0x03000D
1128
1129 /* Error while adjusting inode count */
1130 #define PR_3_ADJUST_INODE               0x03000E
1131
1132 /* Couldn't fix parent directory -- error */
1133 #define PR_3_FIX_PARENT_ERR             0x03000F
1134
1135 /* Couldn't fix parent directory -- couldn't find it */
1136 #define PR_3_FIX_PARENT_NOFIND          0x030010
1137
1138 /* Error allocating inode bitmap */
1139 #define PR_3_ALLOCATE_IBITMAP_ERROR     0x030011
1140
1141 /* Error creating root directory */
1142 #define PR_3_CREATE_ROOT_ERROR          0x030012
1143
1144 /* Error creating lost and found directory */
1145 #define PR_3_CREATE_LPF_ERROR           0x030013
1146
1147 /* Root inode is not directory; aborting */
1148 #define PR_3_ROOT_NOT_DIR_ABORT         0x030014
1149
1150 /* Cannot proceed without a root inode. */
1151 #define PR_3_NO_ROOT_INODE_ABORT        0x030015
1152
1153 /* Internal error: couldn't find dir_info */
1154 #define PR_3_NO_DIRINFO                 0x030016
1155
1156 /* Lost+found is not a directory */
1157 #define PR_3_LPF_NOTDIR                 0x030017
1158
1159 /*
1160  * Pass 3a --- rehashing diretories
1161  */
1162 /* Pass 3a: Reindexing directories */
1163 #define PR_3A_PASS_HEADER               0x031000
1164
1165 /* Error iterating over directories */
1166 #define PR_3A_OPTIMIZE_ITER             0x031001
1167
1168 /* Error rehash directory */
1169 #define PR_3A_OPTIMIZE_DIR_ERR          0x031002
1170
1171 /* Rehashing dir header */
1172 #define PR_3A_OPTIMIZE_DIR_HEADER               0x031003
1173
1174 /* Rehashing directory %d */
1175 #define PR_3A_OPTIMIZE_DIR              0x031004
1176
1177 /* Rehashing dir end */
1178 #define PR_3A_OPTIMIZE_DIR_END          0x031005
1179
1180 /*
1181  * Pass 4 errors
1182  */
1183
1184 /* Pass 4: Checking reference counts */
1185 #define PR_4_PASS_HEADER        0x040000
1186
1187 /* Unattached zero-length inode */
1188 #define PR_4_ZERO_LEN_INODE     0x040001
1189
1190 /* Unattached inode */
1191 #define PR_4_UNATTACHED_INODE   0x040002
1192
1193 /* Inode ref count wrong */
1194 #define PR_4_BAD_REF_COUNT      0x040003
1195
1196 /* Inconsistent inode count information cached */
1197 #define PR_4_INCONSISTENT_COUNT 0x040004
1198
1199 /*
1200  * Pass 5 errors
1201  */
1202
1203 /* Pass 5: Checking group summary information */
1204 #define PR_5_PASS_HEADER                0x050000
1205
1206 /* Padding at end of inode bitmap is not set. */
1207 #define PR_5_INODE_BMAP_PADDING         0x050001
1208
1209 /* Padding at end of block bitmap is not set. */
1210 #define PR_5_BLOCK_BMAP_PADDING         0x050002
1211
1212 /* Block bitmap differences header */
1213 #define PR_5_BLOCK_BITMAP_HEADER        0x050003
1214
1215 /* Block not used, but marked in bitmap */
1216 #define PR_5_BLOCK_UNUSED               0x050004
1217
1218 /* Block used, but not marked used in bitmap */
1219 #define PR_5_BLOCK_USED                 0x050005
1220
1221 /* Block bitmap differences end */
1222 #define PR_5_BLOCK_BITMAP_END           0x050006
1223
1224 /* Inode bitmap differences header */
1225 #define PR_5_INODE_BITMAP_HEADER        0x050007
1226
1227 /* Inode not used, but marked in bitmap */
1228 #define PR_5_INODE_UNUSED               0x050008
1229
1230 /* Inode used, but not marked used in bitmap */
1231 #define PR_5_INODE_USED                 0x050009
1232
1233 /* Inode bitmap differences end */
1234 #define PR_5_INODE_BITMAP_END           0x05000A
1235
1236 /* Free inodes count for group wrong */
1237 #define PR_5_FREE_INODE_COUNT_GROUP     0x05000B
1238
1239 /* Directories count for group wrong */
1240 #define PR_5_FREE_DIR_COUNT_GROUP       0x05000C
1241
1242 /* Free inodes count wrong */
1243 #define PR_5_FREE_INODE_COUNT   0x05000D
1244
1245 /* Free blocks count for group wrong */
1246 #define PR_5_FREE_BLOCK_COUNT_GROUP     0x05000E
1247
1248 /* Free blocks count wrong */
1249 #define PR_5_FREE_BLOCK_COUNT           0x05000F
1250
1251 /* Programming error: bitmap endpoints don't match */
1252 #define PR_5_BMAP_ENDPOINTS             0x050010
1253
1254 /* Internal error: fudging end of bitmap */
1255 #define PR_5_FUDGE_BITMAP_ERROR         0x050011
1256
1257 /* Error copying in replacement inode bitmap */
1258 #define PR_5_COPY_IBITMAP_ERROR         0x050012
1259
1260 /* Error copying in replacement block bitmap */
1261 #define PR_5_COPY_BBITMAP_ERROR         0x050013
1262
1263 /* Block range not used, but marked in bitmap */
1264 #define PR_5_BLOCK_RANGE_UNUSED         0x050014
1265
1266 /* Block range used, but not marked used in bitmap */
1267 #define PR_5_BLOCK_RANGE_USED           0x050015
1268
1269 /* Inode range not used, but marked in bitmap */
1270 #define PR_5_INODE_RANGE_UNUSED         0x050016
1271
1272 /* Inode rangeused, but not marked used in bitmap */
1273 #define PR_5_INODE_RANGE_USED           0x050017
1274
1275 /*
1276  * Function declarations
1277  */
1278 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
1279 static int end_problem_latch(e2fsck_t ctx, int mask);
1280 static int set_latch_flags(int mask, int setflags, int clearflags);
1281 static void clear_problem_context(struct problem_context *ctx);
1282
1283 /*
1284  * Dictionary Abstract Data Type
1285  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
1286  *
1287  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
1288  * kazlib_1_20
1289  */
1290
1291 #ifndef DICT_H
1292 #define DICT_H
1293
1294 /*
1295  * Blurb for inclusion into C++ translation units
1296  */
1297
1298 typedef unsigned long dictcount_t;
1299 #define DICTCOUNT_T_MAX ULONG_MAX
1300
1301 /*
1302  * The dictionary is implemented as a red-black tree
1303  */
1304
1305 typedef enum { dnode_red, dnode_black } dnode_color_t;
1306
1307 typedef struct dnode_t {
1308     struct dnode_t *dict_left;
1309     struct dnode_t *dict_right;
1310     struct dnode_t *dict_parent;
1311     dnode_color_t dict_color;
1312     const void *dict_key;
1313     void *dict_data;
1314 } dnode_t;
1315
1316 typedef int (*dict_comp_t)(const void *, const void *);
1317 typedef void (*dnode_free_t)(dnode_t *);
1318
1319 typedef struct dict_t {
1320     dnode_t dict_nilnode;
1321     dictcount_t dict_nodecount;
1322     dictcount_t dict_maxcount;
1323     dict_comp_t dict_compare;
1324     dnode_free_t dict_freenode;
1325     int dict_dupes;
1326 } dict_t;
1327
1328 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
1329
1330 typedef struct dict_load_t {
1331     dict_t *dict_dictptr;
1332     dnode_t dict_nilnode;
1333 } dict_load_t;
1334
1335 #define dict_count(D) ((D)->dict_nodecount)
1336 #define dnode_get(N) ((N)->dict_data)
1337 #define dnode_getkey(N) ((N)->dict_key)
1338
1339 #endif
1340
1341 /*
1342  * Compatibility header file for e2fsck which should be included
1343  * instead of linux/jfs.h
1344  *
1345  * Copyright (C) 2000 Stephen C. Tweedie
1346  */
1347
1348 /*
1349  * Pull in the definition of the e2fsck context structure
1350  */
1351
1352
1353 struct buffer_head {
1354         char            b_data[8192];
1355         e2fsck_t        b_ctx;
1356         io_channel      b_io;
1357         int             b_size;
1358         blk_t           b_blocknr;
1359         int             b_dirty;
1360         int             b_uptodate;
1361         int             b_err;
1362 };
1363
1364 struct inode {
1365         e2fsck_t        i_ctx;
1366         ext2_ino_t      i_ino;
1367         struct ext2_inode i_ext2;
1368 };
1369
1370 struct kdev_s {
1371         e2fsck_t        k_ctx;
1372         int             k_dev;
1373 };
1374
1375 #define K_DEV_FS        1
1376 #define K_DEV_JOURNAL   2
1377
1378 typedef struct kdev_s *kdev_t;
1379
1380 #define lock_buffer(bh) do {} while(0)
1381 #define unlock_buffer(bh) do {} while(0)
1382 #define buffer_req(bh) 1
1383 #define do_readahead(journal, start) do {} while(0)
1384
1385 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
1386
1387 typedef struct {
1388         int     object_length;
1389 } kmem_cache_t;
1390
1391 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1392
1393 /*
1394  * We use the standard libext2fs portability tricks for inline
1395  * functions.
1396  */
1397
1398 static _INLINE_ kmem_cache_t * do_cache_create(int len)
1399 {
1400         kmem_cache_t *new_cache;
1401
1402         new_cache = malloc(sizeof(*new_cache));
1403         if (new_cache)
1404                 new_cache->object_length = len;
1405         return new_cache;
1406 }
1407
1408 static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1409 {
1410         free(cache);
1411 }
1412
1413 /*
1414  * Now pull in the real linux/jfs.h definitions.
1415  */
1416 #include "ext2fs/kernel-jbd.h"
1417
1418 /*
1419  * badblocks.c --- replace/append bad blocks to the bad block inode
1420  */
1421
1422 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
1423                                  void *priv_data);
1424
1425
1426 static void invalid_block(ext2_filsys fs FSCK_ATTR((unused)), blk_t blk)
1427 {
1428         printf(_("Bad block %u out of range; ignored.\n"), blk);
1429         return;
1430 }
1431
1432 static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1433                           int replace_bad_blocks)
1434 {
1435         ext2_filsys fs = ctx->fs;
1436         errcode_t       retval;
1437         badblocks_list  bb_list = 0;
1438         FILE            *f;
1439         char            buf[1024];
1440
1441         e2fsck_read_bitmaps(ctx);
1442
1443         /*
1444          * Make sure the bad block inode is sane.  If there are any
1445          * illegal blocks, clear them.
1446          */
1447         retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
1448                                       check_bb_inode_blocks, 0);
1449         if (retval) {
1450                 com_err("ext2fs_block_iterate", retval,
1451                         _("while sanity checking the bad blocks inode"));
1452                 goto fatal;
1453         }
1454
1455         /*
1456          * If we're appending to the bad blocks inode, read in the
1457          * current bad blocks.
1458          */
1459         if (!replace_bad_blocks) {
1460                 retval = ext2fs_read_bb_inode(fs, &bb_list);
1461                 if (retval) {
1462                         com_err("ext2fs_read_bb_inode", retval,
1463                                 _("while reading the bad blocks inode"));
1464                         goto fatal;
1465                 }
1466         }
1467
1468         /*
1469          * Now read in the bad blocks from the file; if
1470          * bad_blocks_file is null, then try to run the badblocks
1471          * command.
1472          */
1473         if (bad_blocks_file) {
1474                 f = fopen(bad_blocks_file, "r");
1475                 if (!f) {
1476                         com_err("read_bad_blocks_file", errno,
1477                                 _("while trying to open %s"), bad_blocks_file);
1478                         goto fatal;
1479                 }
1480         } else {
1481                 sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
1482                         (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
1483                         (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
1484                         fs->device_name, fs->super->s_blocks_count);
1485                 f = popen(buf, "r");
1486                 if (!f) {
1487                         com_err("read_bad_blocks_file", errno,
1488                                 _("while trying popen '%s'"), buf);
1489                         goto fatal;
1490                 }
1491         }
1492         retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
1493         if (bad_blocks_file)
1494                 fclose(f);
1495         else
1496                 pclose(f);
1497         if (retval) {
1498                 com_err("ext2fs_read_bb_FILE", retval,
1499                         _("while reading in list of bad blocks from file"));
1500                 goto fatal;
1501         }
1502
1503         /*
1504          * Finally, update the bad blocks from the bad_block_map
1505          */
1506         retval = ext2fs_update_bb_inode(fs, bb_list);
1507         if (retval) {
1508                 com_err("ext2fs_update_bb_inode", retval,
1509                         _("while updating bad block inode"));
1510                 goto fatal;
1511         }
1512
1513         ext2fs_badblocks_list_free(bb_list);
1514         return;
1515
1516 fatal:
1517         ctx->flags |= E2F_FLAG_ABORT;
1518         return;
1519
1520 }
1521
1522 static int check_bb_inode_blocks(ext2_filsys fs,
1523                                  blk_t *block_nr,
1524                                  int blockcnt FSCK_ATTR((unused)),
1525                                  void *priv_data FSCK_ATTR((unused)))
1526 {
1527         if (!*block_nr)
1528                 return 0;
1529
1530         /*
1531          * If the block number is outrageous, clear it and ignore it.
1532          */
1533         if (*block_nr >= fs->super->s_blocks_count ||
1534             *block_nr < fs->super->s_first_data_block) {
1535                 printf(_("Warning illegal block %u found in bad block inode.  Cleared.\n"), *block_nr);
1536                 *block_nr = 0;
1537                 return BLOCK_CHANGED;
1538         }
1539
1540         return 0;
1541 }
1542
1543 /*
1544  * Dictionary Abstract Data Type
1545  */
1546
1547
1548 /*
1549  * These macros provide short convenient names for structure members,
1550  * which are embellished with dict_ prefixes so that they are
1551  * properly confined to the documented namespace. It's legal for a
1552  * program which uses dict to define, for instance, a macro called ``parent''.
1553  * Such a macro would interfere with the dnode_t struct definition.
1554  * In general, highly portable and reusable C modules which expose their
1555  * structures need to confine structure member names to well-defined spaces.
1556  * The resulting identifiers aren't necessarily convenient to use, nor
1557  * readable, in the implementation, however!
1558  */
1559
1560 #define left dict_left
1561 #define right dict_right
1562 #define parent dict_parent
1563 #define color dict_color
1564 #define key dict_key
1565 #define data dict_data
1566
1567 #define nilnode dict_nilnode
1568 #define maxcount dict_maxcount
1569 #define compare dict_compare
1570 #define dupes dict_dupes
1571
1572 #define dict_root(D) ((D)->nilnode.left)
1573 #define dict_nil(D) (&(D)->nilnode)
1574 #define DICT_DEPTH_MAX 64
1575
1576 static void dnode_free(dnode_t *node);
1577
1578 /*
1579  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
1580  * its right child C are rearranged so that the P instead becomes the left
1581  * child of C.   The left subtree of C is inherited as the new right subtree
1582  * for P.  The ordering of the keys within the tree is thus preserved.
1583  */
1584
1585 static void rotate_left(dnode_t *upper)
1586 {
1587     dnode_t *lower, *lowleft, *upparent;
1588
1589     lower = upper->right;
1590     upper->right = lowleft = lower->left;
1591     lowleft->parent = upper;
1592
1593     lower->parent = upparent = upper->parent;
1594
1595     /* don't need to check for root node here because root->parent is
1596        the sentinel nil node, and root->parent->left points back to root */
1597
1598     if (upper == upparent->left) {
1599         upparent->left = lower;
1600     } else {
1601         assert (upper == upparent->right);
1602         upparent->right = lower;
1603     }
1604
1605     lower->left = upper;
1606     upper->parent = lower;
1607 }
1608
1609 /*
1610  * This operation is the ``mirror'' image of rotate_left. It is
1611  * the same procedure, but with left and right interchanged.
1612  */
1613
1614 static void rotate_right(dnode_t *upper)
1615 {
1616     dnode_t *lower, *lowright, *upparent;
1617
1618     lower = upper->left;
1619     upper->left = lowright = lower->right;
1620     lowright->parent = upper;
1621
1622     lower->parent = upparent = upper->parent;
1623
1624     if (upper == upparent->right) {
1625         upparent->right = lower;
1626     } else {
1627         assert (upper == upparent->left);
1628         upparent->left = lower;
1629     }
1630
1631     lower->right = upper;
1632     upper->parent = lower;
1633 }
1634
1635 /*
1636  * Do a postorder traversal of the tree rooted at the specified
1637  * node and free everything under it.  Used by dict_free().
1638  */
1639
1640 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1641 {
1642     if (node == nil)
1643         return;
1644     free_nodes(dict, node->left, nil);
1645     free_nodes(dict, node->right, nil);
1646     dict->dict_freenode(node);
1647 }
1648
1649 /*
1650  * Verify that the tree contains the given node. This is done by
1651  * traversing all of the nodes and comparing their pointers to the
1652  * given pointer. Returns 1 if the node is found, otherwise
1653  * returns zero. It is intended for debugging purposes.
1654  */
1655
1656 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1657 {
1658     if (root != nil) {
1659         return root == node
1660                 || verify_dict_has_node(nil, root->left, node)
1661                 || verify_dict_has_node(nil, root->right, node);
1662     }
1663     return 0;
1664 }
1665
1666
1667 /*
1668  * Select a different set of node allocator routines.
1669  */
1670
1671 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1672 {
1673     assert (dict_count(dict) == 0);
1674     dict->dict_freenode = fr;
1675 }
1676
1677 /*
1678  * Free all the nodes in the dictionary by using the dictionary's
1679  * installed free routine. The dictionary is emptied.
1680  */
1681
1682 static void dict_free_nodes(dict_t *dict)
1683 {
1684     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1685     free_nodes(dict, root, nil);
1686     dict->dict_nodecount = 0;
1687     dict->nilnode.left = &dict->nilnode;
1688     dict->nilnode.right = &dict->nilnode;
1689 }
1690
1691 /*
1692  * Initialize a user-supplied dictionary object.
1693  */
1694
1695 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1696 {
1697     dict->compare = comp;
1698     dict->dict_freenode = dnode_free;
1699     dict->dict_nodecount = 0;
1700     dict->maxcount = maxcount;
1701     dict->nilnode.left = &dict->nilnode;
1702     dict->nilnode.right = &dict->nilnode;
1703     dict->nilnode.parent = &dict->nilnode;
1704     dict->nilnode.color = dnode_black;
1705     dict->dupes = 0;
1706     return dict;
1707 }
1708
1709 /*
1710  * Locate a node in the dictionary having the given key.
1711  * If the node is not found, a null a pointer is returned (rather than
1712  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
1713  * located node is returned.
1714  */
1715
1716 static dnode_t *dict_lookup(dict_t *dict, const void *key)
1717 {
1718     dnode_t *root = dict_root(dict);
1719     dnode_t *nil = dict_nil(dict);
1720     dnode_t *saved;
1721     int result;
1722
1723     /* simple binary search adapted for trees that contain duplicate keys */
1724
1725     while (root != nil) {
1726         result = dict->compare(key, root->key);
1727         if (result < 0)
1728             root = root->left;
1729         else if (result > 0)
1730             root = root->right;
1731         else {
1732             if (!dict->dupes) { /* no duplicates, return match          */
1733                 return root;
1734             } else {            /* could be dupes, find leftmost one    */
1735                 do {
1736                     saved = root;
1737                     root = root->left;
1738                     while (root != nil && dict->compare(key, root->key))
1739                         root = root->right;
1740                 } while (root != nil);
1741                 return saved;
1742             }
1743         }
1744     }
1745
1746     return NULL;
1747 }
1748
1749 /*
1750  * Insert a node into the dictionary. The node should have been
1751  * initialized with a data field. All other fields are ignored.
1752  * The behavior is undefined if the user attempts to insert into
1753  * a dictionary that is already full (for which the dict_isfull()
1754  * function returns true).
1755  */
1756
1757 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1758 {
1759     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1760     dnode_t *parent = nil, *uncle, *grandpa;
1761     int result = -1;
1762
1763     node->key = key;
1764
1765     /* basic binary tree insert */
1766
1767     while (where != nil) {
1768         parent = where;
1769         result = dict->compare(key, where->key);
1770         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
1771         assert (dict->dupes || result != 0);
1772         if (result < 0)
1773             where = where->left;
1774         else
1775             where = where->right;
1776     }
1777
1778     assert (where == nil);
1779
1780     if (result < 0)
1781         parent->left = node;
1782     else
1783         parent->right = node;
1784
1785     node->parent = parent;
1786     node->left = nil;
1787     node->right = nil;
1788
1789     dict->dict_nodecount++;
1790
1791     /* red black adjustments */
1792
1793     node->color = dnode_red;
1794
1795     while (parent->color == dnode_red) {
1796         grandpa = parent->parent;
1797         if (parent == grandpa->left) {
1798             uncle = grandpa->right;
1799             if (uncle->color == dnode_red) {    /* red parent, red uncle */
1800                 parent->color = dnode_black;
1801                 uncle->color = dnode_black;
1802                 grandpa->color = dnode_red;
1803                 node = grandpa;
1804                 parent = grandpa->parent;
1805             } else {                            /* red parent, black uncle */
1806                 if (node == parent->right) {
1807                     rotate_left(parent);
1808                     parent = node;
1809                     assert (grandpa == parent->parent);
1810                     /* rotation between parent and child preserves grandpa */
1811                 }
1812                 parent->color = dnode_black;
1813                 grandpa->color = dnode_red;
1814                 rotate_right(grandpa);
1815                 break;
1816             }
1817         } else {        /* symmetric cases: parent == parent->parent->right */
1818             uncle = grandpa->left;
1819             if (uncle->color == dnode_red) {
1820                 parent->color = dnode_black;
1821                 uncle->color = dnode_black;
1822                 grandpa->color = dnode_red;
1823                 node = grandpa;
1824                 parent = grandpa->parent;
1825             } else {
1826                 if (node == parent->left) {
1827                     rotate_right(parent);
1828                     parent = node;
1829                     assert (grandpa == parent->parent);
1830                 }
1831                 parent->color = dnode_black;
1832                 grandpa->color = dnode_red;
1833                 rotate_left(grandpa);
1834                 break;
1835             }
1836         }
1837     }
1838
1839     dict_root(dict)->color = dnode_black;
1840
1841 }
1842
1843 /*
1844  * Allocate a node using the dictionary's allocator routine, give it
1845  * the data item.
1846  */
1847
1848 static dnode_t *dnode_init(dnode_t *dnode, void *data)
1849 {
1850     dnode->data = data;
1851     dnode->parent = NULL;
1852     dnode->left = NULL;
1853     dnode->right = NULL;
1854     return dnode;
1855 }
1856
1857 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1858 {
1859     dnode_t *node = malloc(sizeof(dnode_t));
1860
1861     if (node) {
1862         dnode_init(node, data);
1863         dict_insert(dict, node, key);
1864         return 1;
1865     }
1866     return 0;
1867 }
1868
1869 /*
1870  * Return the node with the lowest (leftmost) key. If the dictionary is empty
1871  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
1872  */
1873
1874 static dnode_t *dict_first(dict_t *dict)
1875 {
1876     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
1877
1878     if (root != nil)
1879         while ((left = root->left) != nil)
1880             root = left;
1881
1882     return (root == nil) ? NULL : root;
1883 }
1884
1885 /*
1886  * Return the given node's successor node---the node which has the
1887  * next key in the the left to right ordering. If the node has
1888  * no successor, a null pointer is returned rather than a pointer to
1889  * the nil node.
1890  */
1891
1892 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
1893 {
1894     dnode_t *nil = dict_nil(dict), *parent, *left;
1895
1896     if (curr->right != nil) {
1897         curr = curr->right;
1898         while ((left = curr->left) != nil)
1899             curr = left;
1900         return curr;
1901     }
1902
1903     parent = curr->parent;
1904
1905     while (parent != nil && curr == parent->right) {
1906         curr = parent;
1907         parent = curr->parent;
1908     }
1909
1910     return (parent == nil) ? NULL : parent;
1911 }
1912
1913
1914 static void dnode_free(dnode_t *node)
1915 {
1916     free(node);
1917 }
1918
1919
1920 #undef left
1921 #undef right
1922 #undef parent
1923 #undef color
1924 #undef key
1925 #undef data
1926
1927 #undef nilnode
1928 #undef maxcount
1929 #undef compare
1930 #undef dupes
1931
1932
1933 /*
1934  * dirinfo.c --- maintains the directory information table for e2fsck.
1935  */
1936
1937 /*
1938  * This subroutine is called during pass1 to create a directory info
1939  * entry.  During pass1, the passed-in parent is 0; it will get filled
1940  * in during pass2.
1941  */
1942 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
1943 {
1944         struct dir_info *dir;
1945         int             i, j;
1946         ext2_ino_t      num_dirs;
1947         errcode_t       retval;
1948         unsigned long   old_size;
1949
1950 #if 0
1951         printf("add_dir_info for inode %lu...\n", ino);
1952 #endif
1953         if (!ctx->dir_info) {
1954                 ctx->dir_info_count = 0;
1955                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
1956                 if (retval)
1957                         num_dirs = 1024;        /* Guess */
1958                 ctx->dir_info_size = num_dirs + 10;
1959                 ctx->dir_info  = (struct dir_info *)
1960                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
1961                                                * sizeof (struct dir_info),
1962                                                "directory map");
1963         }
1964
1965         if (ctx->dir_info_count >= ctx->dir_info_size) {
1966                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
1967                 ctx->dir_info_size += 10;
1968                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
1969                                            sizeof(struct dir_info),
1970                                            &ctx->dir_info);
1971                 if (retval) {
1972                         ctx->dir_info_size -= 10;
1973                         return;
1974                 }
1975         }
1976
1977         /*
1978          * Normally, add_dir_info is called with each inode in
1979          * sequential order; but once in a while (like when pass 3
1980          * needs to recreate the root directory or lost+found
1981          * directory) it is called out of order.  In those cases, we
1982          * need to move the dir_info entries down to make room, since
1983          * the dir_info array needs to be sorted by inode number for
1984          * get_dir_info()'s sake.
1985          */
1986         if (ctx->dir_info_count &&
1987             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
1988                 for (i = ctx->dir_info_count-1; i > 0; i--)
1989                         if (ctx->dir_info[i-1].ino < ino)
1990                                 break;
1991                 dir = &ctx->dir_info[i];
1992                 if (dir->ino != ino)
1993                         for (j = ctx->dir_info_count++; j > i; j--)
1994                                 ctx->dir_info[j] = ctx->dir_info[j-1];
1995         } else
1996                 dir = &ctx->dir_info[ctx->dir_info_count++];
1997
1998         dir->ino = ino;
1999         dir->dotdot = parent;
2000         dir->parent = parent;
2001 }
2002
2003 /*
2004  * get_dir_info() --- given an inode number, try to find the directory
2005  * information entry for it.
2006  */
2007 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2008 {
2009         int     low, high, mid;
2010
2011         low = 0;
2012         high = ctx->dir_info_count-1;
2013         if (!ctx->dir_info)
2014                 return 0;
2015         if (ino == ctx->dir_info[low].ino)
2016                 return &ctx->dir_info[low];
2017         if  (ino == ctx->dir_info[high].ino)
2018                 return &ctx->dir_info[high];
2019
2020         while (low < high) {
2021                 mid = (low+high)/2;
2022                 if (mid == low || mid == high)
2023                         break;
2024                 if (ino == ctx->dir_info[mid].ino)
2025                         return &ctx->dir_info[mid];
2026                 if (ino < ctx->dir_info[mid].ino)
2027                         high = mid;
2028                 else
2029                         low = mid;
2030         }
2031         return 0;
2032 }
2033
2034 /*
2035  * Free the dir_info structure when it isn't needed any more.
2036  */
2037 static void e2fsck_free_dir_info(e2fsck_t ctx)
2038 {
2039         ext2fs_free_mem(&ctx->dir_info);
2040         ctx->dir_info_size = 0;
2041         ctx->dir_info_count = 0;
2042 }
2043
2044 /*
2045  * Return the count of number of directories in the dir_info structure
2046  */
2047 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2048 {
2049         return ctx->dir_info_count;
2050 }
2051
2052 /*
2053  * A simple interator function
2054  */
2055 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2056 {
2057         if (*control >= ctx->dir_info_count)
2058                 return 0;
2059
2060         return(ctx->dir_info + (*control)++);
2061 }
2062
2063 /*
2064  * dirinfo.c --- maintains the directory information table for e2fsck.
2065  *
2066  */
2067
2068 #ifdef ENABLE_HTREE
2069
2070 /*
2071  * This subroutine is called during pass1 to create a directory info
2072  * entry.  During pass1, the passed-in parent is 0; it will get filled
2073  * in during pass2.
2074  */
2075 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2076 {
2077         struct dx_dir_info *dir;
2078         int             i, j;
2079         errcode_t       retval;
2080         unsigned long   old_size;
2081
2082 #if 0
2083         printf("add_dx_dir_info for inode %lu...\n", ino);
2084 #endif
2085         if (!ctx->dx_dir_info) {
2086                 ctx->dx_dir_info_count = 0;
2087                 ctx->dx_dir_info_size = 100; /* Guess */
2088                 ctx->dx_dir_info  = (struct dx_dir_info *)
2089                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
2090                                                * sizeof (struct dx_dir_info),
2091                                                "directory map");
2092         }
2093
2094         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
2095                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
2096                 ctx->dx_dir_info_size += 10;
2097                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
2098                                            sizeof(struct dx_dir_info),
2099                                            &ctx->dx_dir_info);
2100                 if (retval) {
2101                         ctx->dx_dir_info_size -= 10;
2102                         return;
2103                 }
2104         }
2105
2106         /*
2107          * Normally, add_dx_dir_info is called with each inode in
2108          * sequential order; but once in a while (like when pass 3
2109          * needs to recreate the root directory or lost+found
2110          * directory) it is called out of order.  In those cases, we
2111          * need to move the dx_dir_info entries down to make room, since
2112          * the dx_dir_info array needs to be sorted by inode number for
2113          * get_dx_dir_info()'s sake.
2114          */
2115         if (ctx->dx_dir_info_count &&
2116             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
2117                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
2118                         if (ctx->dx_dir_info[i-1].ino < ino)
2119                                 break;
2120                 dir = &ctx->dx_dir_info[i];
2121                 if (dir->ino != ino)
2122                         for (j = ctx->dx_dir_info_count++; j > i; j--)
2123                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
2124         } else
2125                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
2126
2127         dir->ino = ino;
2128         dir->numblocks = num_blocks;
2129         dir->hashversion = 0;
2130         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
2131                                        * sizeof (struct dx_dirblock_info),
2132                                        "dx_block info array");
2133
2134 }
2135
2136 /*
2137  * get_dx_dir_info() --- given an inode number, try to find the directory
2138  * information entry for it.
2139  */
2140 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2141 {
2142         int     low, high, mid;
2143
2144         low = 0;
2145         high = ctx->dx_dir_info_count-1;
2146         if (!ctx->dx_dir_info)
2147                 return 0;
2148         if (ino == ctx->dx_dir_info[low].ino)
2149                 return &ctx->dx_dir_info[low];
2150         if  (ino == ctx->dx_dir_info[high].ino)
2151                 return &ctx->dx_dir_info[high];
2152
2153         while (low < high) {
2154                 mid = (low+high)/2;
2155                 if (mid == low || mid == high)
2156                         break;
2157                 if (ino == ctx->dx_dir_info[mid].ino)
2158                         return &ctx->dx_dir_info[mid];
2159                 if (ino < ctx->dx_dir_info[mid].ino)
2160                         high = mid;
2161                 else
2162                         low = mid;
2163         }
2164         return 0;
2165 }
2166
2167 /*
2168  * Free the dx_dir_info structure when it isn't needed any more.
2169  */
2170 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2171 {
2172         int     i;
2173         struct dx_dir_info *dir;
2174
2175         if (ctx->dx_dir_info) {
2176                 dir = ctx->dx_dir_info;
2177                 for (i=0; i < ctx->dx_dir_info_count; i++) {
2178                         ext2fs_free_mem(&dir->dx_block);
2179                 }
2180                 ext2fs_free_mem(&ctx->dx_dir_info);
2181         }
2182         ctx->dx_dir_info_size = 0;
2183         ctx->dx_dir_info_count = 0;
2184 }
2185
2186 /*
2187  * A simple interator function
2188  */
2189 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2190 {
2191         if (*control >= ctx->dx_dir_info_count)
2192                 return 0;
2193
2194         return(ctx->dx_dir_info + (*control)++);
2195 }
2196
2197 #endif /* ENABLE_HTREE */
2198 /*
2199  * e2fsck.c - a consistency checker for the new extended file system.
2200  *
2201  */
2202
2203 /*
2204  * This function allocates an e2fsck context
2205  */
2206 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2207 {
2208         e2fsck_t        context;
2209         errcode_t       retval;
2210
2211         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
2212         if (retval)
2213                 return retval;
2214
2215         memset(context, 0, sizeof(struct e2fsck_struct));
2216
2217         context->process_inode_size = 256;
2218         context->ext_attr_ver = 2;
2219
2220         *ret = context;
2221         return 0;
2222 }
2223
2224 struct ea_refcount_el {
2225         blk_t   ea_blk;
2226         int     ea_count;
2227 };
2228
2229 struct ea_refcount {
2230         blk_t           count;
2231         blk_t           size;
2232         blk_t           cursor;
2233         struct ea_refcount_el   *list;
2234 };
2235
2236 static void ea_refcount_free(ext2_refcount_t refcount)
2237 {
2238         if (!refcount)
2239                 return;
2240
2241         ext2fs_free_mem(&refcount->list);
2242         ext2fs_free_mem(&refcount);
2243 }
2244
2245 /*
2246  * This function resets an e2fsck context; it is called when e2fsck
2247  * needs to be restarted.
2248  */
2249 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
2250 {
2251         ctx->flags = 0;
2252         ctx->lost_and_found = 0;
2253         ctx->bad_lost_and_found = 0;
2254         ext2fs_free_inode_bitmap(ctx->inode_used_map);
2255         ctx->inode_used_map = 0;
2256         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
2257         ctx->inode_dir_map = 0;
2258         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
2259         ctx->inode_reg_map = 0;
2260         ext2fs_free_block_bitmap(ctx->block_found_map);
2261         ctx->block_found_map = 0;
2262         ext2fs_free_icount(ctx->inode_link_info);
2263         ctx->inode_link_info = 0;
2264         if (ctx->journal_io) {
2265                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2266                         io_channel_close(ctx->journal_io);
2267                 ctx->journal_io = 0;
2268         }
2269         if (ctx->fs) {
2270                 ext2fs_free_dblist(ctx->fs->dblist);
2271                 ctx->fs->dblist = 0;
2272         }
2273         e2fsck_free_dir_info(ctx);
2274 #ifdef ENABLE_HTREE
2275         e2fsck_free_dx_dir_info(ctx);
2276 #endif
2277         ea_refcount_free(ctx->refcount);
2278         ctx->refcount = 0;
2279         ea_refcount_free(ctx->refcount_extra);
2280         ctx->refcount_extra = 0;
2281         ext2fs_free_block_bitmap(ctx->block_dup_map);
2282         ctx->block_dup_map = 0;
2283         ext2fs_free_block_bitmap(ctx->block_ea_map);
2284         ctx->block_ea_map = 0;
2285         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
2286         ctx->inode_bb_map = 0;
2287         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2288         ctx->inode_bad_map = 0;
2289         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
2290         ctx->inode_imagic_map = 0;
2291         ext2fs_u32_list_free(ctx->dirs_to_hash);
2292         ctx->dirs_to_hash = 0;
2293
2294         /*
2295          * Clear the array of invalid meta-data flags
2296          */
2297         ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
2298         ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
2299         ext2fs_free_mem(&ctx->invalid_inode_table_flag);
2300
2301         /* Clear statistic counters */
2302         ctx->fs_directory_count = 0;
2303         ctx->fs_regular_count = 0;
2304         ctx->fs_blockdev_count = 0;
2305         ctx->fs_chardev_count = 0;
2306         ctx->fs_links_count = 0;
2307         ctx->fs_symlinks_count = 0;
2308         ctx->fs_fast_symlinks_count = 0;
2309         ctx->fs_fifo_count = 0;
2310         ctx->fs_total_count = 0;
2311         ctx->fs_badblocks_count = 0;
2312         ctx->fs_sockets_count = 0;
2313         ctx->fs_ind_count = 0;
2314         ctx->fs_dind_count = 0;
2315         ctx->fs_tind_count = 0;
2316         ctx->fs_fragmented = 0;
2317         ctx->large_files = 0;
2318
2319         /* Reset the superblock to the user's requested value */
2320         ctx->superblock = ctx->use_superblock;
2321
2322         return 0;
2323 }
2324
2325 static void e2fsck_free_context(e2fsck_t ctx)
2326 {
2327         if (!ctx)
2328                 return;
2329
2330         e2fsck_reset_context(ctx);
2331         if (ctx->blkid)
2332                 blkid_put_cache(ctx->blkid);
2333
2334         ext2fs_free_mem(&ctx);
2335 }
2336
2337 /*
2338  * ea_refcount.c
2339  */
2340
2341 /*
2342  * The strategy we use for keeping track of EA refcounts is as
2343  * follows.  We keep a sorted array of first EA blocks and its
2344  * reference counts.  Once the refcount has dropped to zero, it is
2345  * removed from the array to save memory space.  Once the EA block is
2346  * checked, its bit is set in the block_ea_map bitmap.
2347  */
2348
2349
2350 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2351 {
2352         ext2_refcount_t refcount;
2353         errcode_t       retval;
2354         size_t          bytes;
2355
2356         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2357         if (retval)
2358                 return retval;
2359         memset(refcount, 0, sizeof(struct ea_refcount));
2360
2361         if (!size)
2362                 size = 500;
2363         refcount->size = size;
2364         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2365 #ifdef DEBUG
2366         printf("Refcount allocated %d entries, %d bytes.\n",
2367                refcount->size, bytes);
2368 #endif
2369         retval = ext2fs_get_mem(bytes, &refcount->list);
2370         if (retval)
2371                 goto errout;
2372         memset(refcount->list, 0, bytes);
2373
2374         refcount->count = 0;
2375         refcount->cursor = 0;
2376
2377         *ret = refcount;
2378         return 0;
2379
2380 errout:
2381         ea_refcount_free(refcount);
2382         return(retval);
2383 }
2384
2385 /*
2386  * collapse_refcount() --- go through the refcount array, and get rid
2387  * of any count == zero entries
2388  */
2389 static void refcount_collapse(ext2_refcount_t refcount)
2390 {
2391         unsigned int    i, j;
2392         struct ea_refcount_el   *list;
2393
2394         list = refcount->list;
2395         for (i = 0, j = 0; i < refcount->count; i++) {
2396                 if (list[i].ea_count) {
2397                         if (i != j)
2398                                 list[j] = list[i];
2399                         j++;
2400                 }
2401         }
2402 #if defined(DEBUG) || defined(TEST_PROGRAM)
2403         printf("Refcount_collapse: size was %d, now %d\n",
2404                refcount->count, j);
2405 #endif
2406         refcount->count = j;
2407 }
2408
2409
2410 /*
2411  * insert_refcount_el() --- Insert a new entry into the sorted list at a
2412  *      specified position.
2413  */
2414 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2415                                                  blk_t blk, int pos)
2416 {
2417         struct ea_refcount_el   *el;
2418         errcode_t               retval;
2419         blk_t                   new_size = 0;
2420         int                     num;
2421
2422         if (refcount->count >= refcount->size) {
2423                 new_size = refcount->size + 100;
2424 #ifdef DEBUG
2425                 printf("Reallocating refcount %d entries...\n", new_size);
2426 #endif
2427                 retval = ext2fs_resize_mem((size_t) refcount->size *
2428                                            sizeof(struct ea_refcount_el),
2429                                            (size_t) new_size *
2430                                            sizeof(struct ea_refcount_el),
2431                                            &refcount->list);
2432                 if (retval)
2433                         return 0;
2434                 refcount->size = new_size;
2435         }
2436         num = (int) refcount->count - pos;
2437         if (num < 0)
2438                 return 0;       /* should never happen */
2439         if (num) {
2440                 memmove(&refcount->list[pos+1], &refcount->list[pos],
2441                         sizeof(struct ea_refcount_el) * num);
2442         }
2443         refcount->count++;
2444         el = &refcount->list[pos];
2445         el->ea_count = 0;
2446         el->ea_blk = blk;
2447         return el;
2448 }
2449
2450
2451 /*
2452  * get_refcount_el() --- given an block number, try to find refcount
2453  *      information in the sorted list.  If the create flag is set,
2454  *      and we can't find an entry, create one in the sorted list.
2455  */
2456 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2457                                               blk_t blk, int create)
2458 {
2459         float   range;
2460         int     low, high, mid;
2461         blk_t   lowval, highval;
2462
2463         if (!refcount || !refcount->list)
2464                 return 0;
2465 retry:
2466         low = 0;
2467         high = (int) refcount->count-1;
2468         if (create && ((refcount->count == 0) ||
2469                        (blk > refcount->list[high].ea_blk))) {
2470                 if (refcount->count >= refcount->size)
2471                         refcount_collapse(refcount);
2472
2473                 return insert_refcount_el(refcount, blk,
2474                                           (unsigned) refcount->count);
2475         }
2476         if (refcount->count == 0)
2477                 return 0;
2478
2479         if (refcount->cursor >= refcount->count)
2480                 refcount->cursor = 0;
2481         if (blk == refcount->list[refcount->cursor].ea_blk)
2482                 return &refcount->list[refcount->cursor++];
2483 #ifdef DEBUG
2484         printf("Non-cursor get_refcount_el: %u\n", blk);
2485 #endif
2486         while (low <= high) {
2487 #if 0
2488                 mid = (low+high)/2;
2489 #else
2490                 if (low == high)
2491                         mid = low;
2492                 else {
2493                         /* Interpolate for efficiency */
2494                         lowval = refcount->list[low].ea_blk;
2495                         highval = refcount->list[high].ea_blk;
2496
2497                         if (blk < lowval)
2498                                 range = 0;
2499                         else if (blk > highval)
2500                                 range = 1;
2501                         else
2502                                 range = ((float) (blk - lowval)) /
2503                                         (highval - lowval);
2504                         mid = low + ((int) (range * (high-low)));
2505                 }
2506 #endif
2507                 if (blk == refcount->list[mid].ea_blk) {
2508                         refcount->cursor = mid+1;
2509                         return &refcount->list[mid];
2510                 }
2511                 if (blk < refcount->list[mid].ea_blk)
2512                         high = mid-1;
2513                 else
2514                         low = mid+1;
2515         }
2516         /*
2517          * If we need to create a new entry, it should be right at
2518          * low (where high will be left at low-1).
2519          */
2520         if (create) {
2521                 if (refcount->count >= refcount->size) {
2522                         refcount_collapse(refcount);
2523                         if (refcount->count < refcount->size)
2524                                 goto retry;
2525                 }
2526                 return insert_refcount_el(refcount, blk, low);
2527         }
2528         return 0;
2529 }
2530
2531 static errcode_t
2532 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2533 {
2534         struct ea_refcount_el   *el;
2535
2536         el = get_refcount_el(refcount, blk, 1);
2537         if (!el)
2538                 return EXT2_ET_NO_MEMORY;
2539         el->ea_count++;
2540
2541         if (ret)
2542                 *ret = el->ea_count;
2543         return 0;
2544 }
2545
2546 static errcode_t
2547 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2548 {
2549         struct ea_refcount_el   *el;
2550
2551         el = get_refcount_el(refcount, blk, 0);
2552         if (!el || el->ea_count == 0)
2553                 return EXT2_ET_INVALID_ARGUMENT;
2554
2555         el->ea_count--;
2556
2557         if (ret)
2558                 *ret = el->ea_count;
2559         return 0;
2560 }
2561
2562 static errcode_t
2563 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2564 {
2565         struct ea_refcount_el   *el;
2566
2567         /*
2568          * Get the refcount element
2569          */
2570         el = get_refcount_el(refcount, blk, count ? 1 : 0);
2571         if (!el)
2572                 return count ? EXT2_ET_NO_MEMORY : 0;
2573         el->ea_count = count;
2574         return 0;
2575 }
2576
2577 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2578 {
2579         refcount->cursor = 0;
2580 }
2581
2582
2583 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2584 {
2585         struct ea_refcount_el   *list;
2586
2587         while (1) {
2588                 if (refcount->cursor >= refcount->count)
2589                         return 0;
2590                 list = refcount->list;
2591                 if (list[refcount->cursor].ea_count) {
2592                         if (ret)
2593                                 *ret = list[refcount->cursor].ea_count;
2594                         return list[refcount->cursor++].ea_blk;
2595                 }
2596                 refcount->cursor++;
2597         }
2598 }
2599
2600
2601 /*
2602  * ehandler.c --- handle bad block errors which come up during the
2603  *      course of an e2fsck session.
2604  */
2605
2606
2607 static const char *operation;
2608
2609 static errcode_t
2610 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2611                          void *data, size_t size FSCK_ATTR((unused)),
2612                          int actual FSCK_ATTR((unused)), errcode_t error)
2613 {
2614         int     i;
2615         char    *p;
2616         ext2_filsys fs = (ext2_filsys) channel->app_data;
2617         e2fsck_t ctx;
2618
2619         ctx = (e2fsck_t) fs->priv_data;
2620
2621         /*
2622          * If more than one block was read, try reading each block
2623          * separately.  We could use the actual bytes read to figure
2624          * out where to start, but we don't bother.
2625          */
2626         if (count > 1) {
2627                 p = (char *) data;
2628                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2629                         error = io_channel_read_blk(channel, block,
2630                                                     1, p);
2631                         if (error)
2632                                 return error;
2633                 }
2634                 return 0;
2635         }
2636         if (operation)
2637                 printf(_("Error reading block %lu (%s) while %s.  "), block,
2638                        error_message(error), operation);
2639         else
2640                 printf(_("Error reading block %lu (%s).  "), block,
2641                        error_message(error));
2642         preenhalt(ctx);
2643         if (ask(ctx, _("Ignore error"), 1)) {
2644                 if (ask(ctx, _("Force rewrite"), 1))
2645                         io_channel_write_blk(channel, block, 1, data);
2646                 return 0;
2647         }
2648
2649         return error;
2650 }
2651
2652 static errcode_t
2653 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2654                         const void *data, size_t size FSCK_ATTR((unused)),
2655                         int actual FSCK_ATTR((unused)), errcode_t error)
2656 {
2657         int             i;
2658         const char      *p;
2659         ext2_filsys fs = (ext2_filsys) channel->app_data;
2660         e2fsck_t ctx;
2661
2662         ctx = (e2fsck_t) fs->priv_data;
2663
2664         /*
2665          * If more than one block was written, try writing each block
2666          * separately.  We could use the actual bytes read to figure
2667          * out where to start, but we don't bother.
2668          */
2669         if (count > 1) {
2670                 p = (const char *) data;
2671                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2672                         error = io_channel_write_blk(channel, block,
2673                                                      1, p);
2674                         if (error)
2675                                 return error;
2676                 }
2677                 return 0;
2678         }
2679
2680         if (operation)
2681                 printf(_("Error writing block %lu (%s) while %s.  "), block,
2682                        error_message(error), operation);
2683         else
2684                 printf(_("Error writing block %lu (%s).  "), block,
2685                        error_message(error));
2686         preenhalt(ctx);
2687         if (ask(ctx, _("Ignore error"), 1))
2688                 return 0;
2689
2690         return error;
2691 }
2692
2693 static inline const char *ehandler_operation(const char *op)
2694 {
2695         const char *ret = operation;
2696
2697         operation = op;
2698         return ret;
2699 }
2700
2701 static void ehandler_init(io_channel channel)
2702 {
2703         channel->read_error = e2fsck_handle_read_error;
2704         channel->write_error = e2fsck_handle_write_error;
2705 }
2706
2707 /*
2708  * journal.c --- code for handling the "ext3" journal
2709  *
2710  * Copyright (C) 2000 Andreas Dilger
2711  * Copyright (C) 2000 Theodore Ts'o
2712  *
2713  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2714  * Copyright (C) 1999 Red Hat Software
2715  *
2716  * This file may be redistributed under the terms of the
2717  * GNU General Public License version 2 or at your discretion
2718  * any later version.
2719  */
2720
2721 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2722
2723
2724 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
2725 static int bh_count = 0;
2726 #endif
2727
2728 /*
2729  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2730  * This creates a larger static binary, and a smaller binary using
2731  * shared libraries.  It's also probably slightly less CPU-efficient,
2732  * which is why it's not on by default.  But, it's a good way of
2733  * testing the functions in inode_io.c and fileio.c.
2734  */
2735 #undef USE_INODE_IO
2736
2737 /* Kernel compatibility functions for handling the journal.  These allow us
2738  * to use the recovery.c file virtually unchanged from the kernel, so we
2739  * don't have to do much to keep kernel and user recovery in sync.
2740  */
2741 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2742 {
2743 #ifdef USE_INODE_IO
2744         *phys = block;
2745         return 0;
2746 #else
2747         struct inode    *inode = journal->j_inode;
2748         errcode_t       retval;
2749         blk_t           pblk;
2750
2751         if (!inode) {
2752                 *phys = block;
2753                 return 0;
2754         }
2755
2756         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2757                             &inode->i_ext2, NULL, 0, block, &pblk);
2758         *phys = pblk;
2759         return (retval);
2760 #endif
2761 }
2762
2763 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2764 {
2765         struct buffer_head *bh;
2766
2767         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2768         if (!bh)
2769                 return NULL;
2770
2771         jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
2772                   (unsigned long) blocknr, blocksize, ++bh_count);
2773
2774         bh->b_ctx = kdev->k_ctx;
2775         if (kdev->k_dev == K_DEV_FS)
2776                 bh->b_io = kdev->k_ctx->fs->io;
2777         else
2778                 bh->b_io = kdev->k_ctx->journal_io;
2779         bh->b_size = blocksize;
2780         bh->b_blocknr = blocknr;
2781
2782         return bh;
2783 }
2784
2785 static void sync_blockdev(kdev_t kdev)
2786 {
2787         io_channel      io;
2788
2789         if (kdev->k_dev == K_DEV_FS)
2790                 io = kdev->k_ctx->fs->io;
2791         else
2792                 io = kdev->k_ctx->journal_io;
2793
2794         io_channel_flush(io);
2795 }
2796
2797 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2798 {
2799         int retval;
2800         struct buffer_head *bh;
2801
2802         for (; nr > 0; --nr) {
2803                 bh = *bhp++;
2804                 if (rw == READ && !bh->b_uptodate) {
2805                         jfs_debug(3, "reading block %lu/%p\n",
2806                                   (unsigned long) bh->b_blocknr, (void *) bh);
2807                         retval = io_channel_read_blk(bh->b_io,
2808                                                      bh->b_blocknr,
2809                                                      1, bh->b_data);
2810                         if (retval) {
2811                                 com_err(bh->b_ctx->device_name, retval,
2812                                         "while reading block %lu\n",
2813                                         (unsigned long) bh->b_blocknr);
2814                                 bh->b_err = retval;
2815                                 continue;
2816                         }
2817                         bh->b_uptodate = 1;
2818                 } else if (rw == WRITE && bh->b_dirty) {
2819                         jfs_debug(3, "writing block %lu/%p\n",
2820                                   (unsigned long) bh->b_blocknr, (void *) bh);
2821                         retval = io_channel_write_blk(bh->b_io,
2822                                                       bh->b_blocknr,
2823                                                       1, bh->b_data);
2824                         if (retval) {
2825                                 com_err(bh->b_ctx->device_name, retval,
2826                                         "while writing block %lu\n",
2827                                         (unsigned long) bh->b_blocknr);
2828                                 bh->b_err = retval;
2829                                 continue;
2830                         }
2831                         bh->b_dirty = 0;
2832                         bh->b_uptodate = 1;
2833                 } else {
2834                         jfs_debug(3, "no-op %s for block %lu\n",
2835                                   rw == READ ? "read" : "write",
2836                                   (unsigned long) bh->b_blocknr);
2837                 }
2838         }
2839 }
2840
2841 static inline void mark_buffer_dirty(struct buffer_head *bh)
2842 {
2843         bh->b_dirty = 1;
2844 }
2845
2846 static inline void mark_buffer_clean(struct buffer_head * bh)
2847 {
2848         bh->b_dirty = 0;
2849 }
2850
2851 static void brelse(struct buffer_head *bh)
2852 {
2853         if (bh->b_dirty)
2854                 ll_rw_block(WRITE, 1, &bh);
2855         jfs_debug(3, "freeing block %lu/%p (total %d)\n",
2856                   (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
2857         ext2fs_free_mem(&bh);
2858 }
2859
2860 static inline int buffer_uptodate(struct buffer_head *bh)
2861 {
2862         return bh->b_uptodate;
2863 }
2864
2865 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2866 {
2867         bh->b_uptodate = val;
2868 }
2869
2870 static void wait_on_buffer(struct buffer_head *bh)
2871 {
2872         if (!bh->b_uptodate)
2873                 ll_rw_block(READ, 1, &bh);
2874 }
2875
2876
2877 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2878 {
2879         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2880
2881         /* if we had an error doing journal recovery, we need a full fsck */
2882         if (error)
2883                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2884         ext2fs_mark_super_dirty(ctx->fs);
2885 }
2886
2887 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2888 {
2889         struct ext2_super_block *sb = ctx->fs->super;
2890         struct ext2_super_block jsuper;
2891         struct problem_context  pctx;
2892         struct buffer_head      *bh;
2893         struct inode            *j_inode = NULL;
2894         struct kdev_s           *dev_fs = NULL, *dev_journal;
2895         const char              *journal_name = 0;
2896         journal_t               *journal = NULL;
2897         errcode_t               retval = 0;
2898         io_manager              io_ptr = 0;
2899         unsigned long           start = 0;
2900         blk_t                   blk;
2901         int                     ext_journal = 0;
2902         int                     tried_backup_jnl = 0;
2903         int                     i;
2904
2905         clear_problem_context(&pctx);
2906
2907         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2908         if (!journal) {
2909                 return EXT2_ET_NO_MEMORY;
2910         }
2911
2912         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2913         if (!dev_fs) {
2914                 retval = EXT2_ET_NO_MEMORY;
2915                 goto errout;
2916         }
2917         dev_journal = dev_fs+1;
2918
2919         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2920         dev_fs->k_dev = K_DEV_FS;
2921         dev_journal->k_dev = K_DEV_JOURNAL;
2922
2923         journal->j_dev = dev_journal;
2924         journal->j_fs_dev = dev_fs;
2925         journal->j_inode = NULL;
2926         journal->j_blocksize = ctx->fs->blocksize;
2927
2928         if (uuid_is_null(sb->s_journal_uuid)) {
2929                 if (!sb->s_journal_inum)
2930                         return EXT2_ET_BAD_INODE_NUM;
2931                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2932                                                  "journal inode");
2933                 if (!j_inode) {
2934                         retval = EXT2_ET_NO_MEMORY;
2935                         goto errout;
2936                 }
2937
2938                 j_inode->i_ctx = ctx;
2939                 j_inode->i_ino = sb->s_journal_inum;
2940
2941                 if ((retval = ext2fs_read_inode(ctx->fs,
2942                                                 sb->s_journal_inum,
2943                                                 &j_inode->i_ext2))) {
2944                 try_backup_journal:
2945                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
2946                             tried_backup_jnl)
2947                                 goto errout;
2948                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
2949                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
2950                                EXT2_N_BLOCKS*4);
2951                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
2952                         j_inode->i_ext2.i_links_count = 1;
2953                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
2954                         tried_backup_jnl++;
2955                 }
2956                 if (!j_inode->i_ext2.i_links_count ||
2957                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
2958                         retval = EXT2_ET_NO_JOURNAL;
2959                         goto try_backup_journal;
2960                 }
2961                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
2962                     JFS_MIN_JOURNAL_BLOCKS) {
2963                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
2964                         goto try_backup_journal;
2965                 }
2966                 for (i=0; i < EXT2_N_BLOCKS; i++) {
2967                         blk = j_inode->i_ext2.i_block[i];
2968                         if (!blk) {
2969                                 if (i < EXT2_NDIR_BLOCKS) {
2970                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
2971                                         goto try_backup_journal;
2972                                 }
2973                                 continue;
2974                         }
2975                         if (blk < sb->s_first_data_block ||
2976                             blk >= sb->s_blocks_count) {
2977                                 retval = EXT2_ET_BAD_BLOCK_NUM;
2978                                 goto try_backup_journal;
2979                         }
2980                 }
2981                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
2982
2983 #ifdef USE_INODE_IO
2984                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
2985                                                  &j_inode->i_ext2,
2986                                                  &journal_name);
2987                 if (retval)
2988                         goto errout;
2989
2990                 io_ptr = inode_io_manager;
2991 #else
2992                 journal->j_inode = j_inode;
2993                 ctx->journal_io = ctx->fs->io;
2994                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
2995                         goto errout;
2996 #endif
2997         } else {
2998                 ext_journal = 1;
2999                 if (!ctx->journal_name) {
3000                         char uuid[37];
3001
3002                         uuid_unparse(sb->s_journal_uuid, uuid);
3003                         ctx->journal_name = blkid_get_devname(ctx->blkid,
3004                                                               "UUID", uuid);
3005                         if (!ctx->journal_name)
3006                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
3007                 }
3008                 journal_name = ctx->journal_name;
3009
3010                 if (!journal_name) {
3011                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
3012                         return EXT2_ET_LOAD_EXT_JOURNAL;
3013                 }
3014
3015                 jfs_debug(1, "Using journal file %s\n", journal_name);
3016                 io_ptr = unix_io_manager;
3017         }
3018
3019 #if 0
3020         test_io_backing_manager = io_ptr;
3021         io_ptr = test_io_manager;
3022 #endif
3023 #ifndef USE_INODE_IO
3024         if (ext_journal)
3025 #endif
3026                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
3027                                       &ctx->journal_io);
3028         if (retval)
3029                 goto errout;
3030
3031         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
3032
3033         if (ext_journal) {
3034                 if (ctx->fs->blocksize == 1024)
3035                         start = 1;
3036                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
3037                 if (!bh) {
3038                         retval = EXT2_ET_NO_MEMORY;
3039                         goto errout;
3040                 }
3041                 ll_rw_block(READ, 1, &bh);
3042                 if ((retval = bh->b_err) != 0)
3043                         goto errout;
3044                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
3045                        sizeof(jsuper));
3046                 brelse(bh);
3047 #ifdef EXT2FS_ENABLE_SWAPFS
3048                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
3049                         ext2fs_swap_super(&jsuper);
3050 #endif
3051                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
3052                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
3053                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
3054                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
3055                         goto errout;
3056                 }
3057                 /* Make sure the journal UUID is correct */
3058                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
3059                            sizeof(jsuper.s_uuid))) {
3060                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
3061                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
3062                         goto errout;
3063                 }
3064
3065                 journal->j_maxlen = jsuper.s_blocks_count;
3066                 start++;
3067         }
3068
3069         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
3070                 retval = EXT2_ET_NO_MEMORY;
3071                 goto errout;
3072         }
3073
3074         journal->j_sb_buffer = bh;
3075         journal->j_superblock = (journal_superblock_t *)bh->b_data;
3076
3077 #ifdef USE_INODE_IO
3078         ext2fs_free_mem(&j_inode);
3079 #endif
3080
3081         *ret_journal = journal;
3082         return 0;
3083
3084 errout:
3085         ext2fs_free_mem(&dev_fs);
3086         ext2fs_free_mem(&j_inode);
3087         ext2fs_free_mem(&journal);
3088         return retval;
3089
3090 }
3091
3092 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
3093                                               struct problem_context *pctx)
3094 {
3095         struct ext2_super_block *sb = ctx->fs->super;
3096         int recover = ctx->fs->super->s_feature_incompat &
3097                 EXT3_FEATURE_INCOMPAT_RECOVER;
3098         int has_journal = ctx->fs->super->s_feature_compat &
3099                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3100
3101         if (has_journal || sb->s_journal_inum) {
3102                 /* The journal inode is bogus, remove and force full fsck */
3103                 pctx->ino = sb->s_journal_inum;
3104                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
3105                         if (has_journal && sb->s_journal_inum)
3106                                 printf("*** ext3 journal has been deleted - "
3107                                        "filesystem is now ext2 only ***\n\n");
3108                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3109                         sb->s_journal_inum = 0;
3110                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
3111                         e2fsck_clear_recover(ctx, 1);
3112                         return 0;
3113                 }
3114                 return EXT2_ET_BAD_INODE_NUM;
3115         } else if (recover) {
3116                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
3117                         e2fsck_clear_recover(ctx, 1);
3118                         return 0;
3119                 }
3120                 return EXT2_ET_UNSUPP_FEATURE;
3121         }
3122         return 0;
3123 }
3124
3125 #define V1_SB_SIZE      0x0024
3126 static void clear_v2_journal_fields(journal_t *journal)
3127 {
3128         e2fsck_t ctx = journal->j_dev->k_ctx;
3129         struct problem_context pctx;
3130
3131         clear_problem_context(&pctx);
3132
3133         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
3134                 return;
3135
3136         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
3137                ctx->fs->blocksize-V1_SB_SIZE);
3138         mark_buffer_dirty(journal->j_sb_buffer);
3139 }
3140
3141
3142 static errcode_t e2fsck_journal_load(journal_t *journal)
3143 {
3144         e2fsck_t ctx = journal->j_dev->k_ctx;
3145         journal_superblock_t *jsb;
3146         struct buffer_head *jbh = journal->j_sb_buffer;
3147         struct problem_context pctx;
3148
3149         clear_problem_context(&pctx);
3150
3151         ll_rw_block(READ, 1, &jbh);
3152         if (jbh->b_err) {
3153                 com_err(ctx->device_name, jbh->b_err,
3154                         _("reading journal superblock\n"));
3155                 return jbh->b_err;
3156         }
3157
3158         jsb = journal->j_superblock;
3159         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
3160         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
3161                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3162
3163         switch (ntohl(jsb->s_header.h_blocktype)) {
3164         case JFS_SUPERBLOCK_V1:
3165                 journal->j_format_version = 1;
3166                 if (jsb->s_feature_compat ||
3167                     jsb->s_feature_incompat ||
3168                     jsb->s_feature_ro_compat ||
3169                     jsb->s_nr_users)
3170                         clear_v2_journal_fields(journal);
3171                 break;
3172
3173         case JFS_SUPERBLOCK_V2:
3174                 journal->j_format_version = 2;
3175                 if (ntohl(jsb->s_nr_users) > 1 &&
3176                     uuid_is_null(ctx->fs->super->s_journal_uuid))
3177                         clear_v2_journal_fields(journal);
3178                 if (ntohl(jsb->s_nr_users) > 1) {
3179                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
3180                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3181                 }
3182                 break;
3183
3184         /*
3185          * These should never appear in a journal super block, so if
3186          * they do, the journal is badly corrupted.
3187          */
3188         case JFS_DESCRIPTOR_BLOCK:
3189         case JFS_COMMIT_BLOCK:
3190         case JFS_REVOKE_BLOCK:
3191                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3192
3193         /* If we don't understand the superblock major type, but there
3194          * is a magic number, then it is likely to be a new format we
3195          * just don't understand, so leave it alone. */
3196         default:
3197                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3198         }
3199
3200         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
3201                 return EXT2_ET_UNSUPP_FEATURE;
3202
3203         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
3204                 return EXT2_ET_RO_UNSUPP_FEATURE;
3205
3206         /* We have now checked whether we know enough about the journal
3207          * format to be able to proceed safely, so any other checks that
3208          * fail we should attempt to recover from. */
3209         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
3210                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3211                         _("%s: no valid journal superblock found\n"),
3212                         ctx->device_name);
3213                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3214         }
3215
3216         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
3217                 journal->j_maxlen = ntohl(jsb->s_maxlen);
3218         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
3219                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3220                         _("%s: journal too short\n"),
3221                         ctx->device_name);
3222                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3223         }
3224
3225         journal->j_tail_sequence = ntohl(jsb->s_sequence);
3226         journal->j_transaction_sequence = journal->j_tail_sequence;
3227         journal->j_tail = ntohl(jsb->s_start);
3228         journal->j_first = ntohl(jsb->s_first);
3229         journal->j_last = ntohl(jsb->s_maxlen);
3230
3231         return 0;
3232 }
3233
3234 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
3235                                        journal_t *journal)
3236 {
3237         char *p;
3238         union {
3239                 uuid_t uuid;
3240                 __u32 val[4];
3241         } u;
3242         __u32 new_seq = 0;
3243         int i;
3244
3245         /* Leave a valid existing V1 superblock signature alone.
3246          * Anything unrecognisable we overwrite with a new V2
3247          * signature. */
3248
3249         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
3250             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
3251                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
3252                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
3253         }
3254
3255         /* Zero out everything else beyond the superblock header */
3256
3257         p = ((char *) jsb) + sizeof(journal_header_t);
3258         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
3259
3260         jsb->s_blocksize = htonl(ctx->fs->blocksize);
3261         jsb->s_maxlen = htonl(journal->j_maxlen);
3262         jsb->s_first = htonl(1);
3263
3264         /* Initialize the journal sequence number so that there is "no"
3265          * chance we will find old "valid" transactions in the journal.
3266          * This avoids the need to zero the whole journal (slow to do,
3267          * and risky when we are just recovering the filesystem).
3268          */
3269         uuid_generate(u.uuid);
3270         for (i = 0; i < 4; i ++)
3271                 new_seq ^= u.val[i];
3272         jsb->s_sequence = htonl(new_seq);
3273
3274         mark_buffer_dirty(journal->j_sb_buffer);
3275         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
3276 }
3277
3278 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
3279                                                   journal_t *journal,
3280                                                   struct problem_context *pctx)
3281 {
3282         struct ext2_super_block *sb = ctx->fs->super;
3283         int recover = ctx->fs->super->s_feature_incompat &
3284                 EXT3_FEATURE_INCOMPAT_RECOVER;
3285
3286         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
3287                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
3288                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
3289                                                    journal);
3290                         journal->j_transaction_sequence = 1;
3291                         e2fsck_clear_recover(ctx, recover);
3292                         return 0;
3293                 }
3294                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3295         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
3296                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3297
3298         return 0;
3299 }
3300
3301 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
3302                                    int reset, int drop)
3303 {
3304         journal_superblock_t *jsb;
3305
3306         if (drop)
3307                 mark_buffer_clean(journal->j_sb_buffer);
3308         else if (!(ctx->options & E2F_OPT_READONLY)) {
3309                 jsb = journal->j_superblock;
3310                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
3311                 if (reset)
3312                         jsb->s_start = 0; /* this marks the journal as empty */
3313                 mark_buffer_dirty(journal->j_sb_buffer);
3314         }
3315         brelse(journal->j_sb_buffer);
3316
3317         if (ctx->journal_io) {
3318                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
3319                         io_channel_close(ctx->journal_io);
3320                 ctx->journal_io = 0;
3321         }
3322
3323 #ifndef USE_INODE_IO
3324         ext2fs_free_mem(&journal->j_inode);
3325 #endif
3326         ext2fs_free_mem(&journal->j_fs_dev);
3327         ext2fs_free_mem(&journal);
3328 }
3329
3330 /*
3331  * This function makes sure that the superblock fields regarding the
3332  * journal are consistent.
3333  */
3334 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
3335 {
3336         struct ext2_super_block *sb = ctx->fs->super;
3337         journal_t *journal;
3338         int recover = ctx->fs->super->s_feature_incompat &
3339                 EXT3_FEATURE_INCOMPAT_RECOVER;
3340         struct problem_context pctx;
3341         problem_t problem;
3342         int reset = 0, force_fsck = 0;
3343         int retval;
3344
3345         /* If we don't have any journal features, don't do anything more */
3346         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3347             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
3348             uuid_is_null(sb->s_journal_uuid))
3349                 return 0;
3350
3351         clear_problem_context(&pctx);
3352         pctx.num = sb->s_journal_inum;
3353
3354         retval = e2fsck_get_journal(ctx, &journal);
3355         if (retval) {
3356                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3357                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3358                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3359                     (retval == EXT2_ET_NO_JOURNAL))
3360                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3361                 return retval;
3362         }
3363
3364         retval = e2fsck_journal_load(journal);
3365         if (retval) {
3366                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3367                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3368                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3369                                   &pctx))) ||
3370                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3371                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3372                                   &pctx))) ||
3373                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3374                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3375                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3376                                                                   &pctx);
3377                 e2fsck_journal_release(ctx, journal, 0, 1);
3378                 return retval;
3379         }
3380
3381         /*
3382          * We want to make the flags consistent here.  We will not leave with
3383          * needs_recovery set but has_journal clear.  We can't get in a loop
3384          * with -y, -n, or -p, only if a user isn't making up their mind.
3385          */
3386 no_has_journal:
3387         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3388                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3389                 pctx.str = "inode";
3390                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3391                         if (recover &&
3392                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3393                                 goto no_has_journal;
3394                         /*
3395                          * Need a full fsck if we are releasing a
3396                          * journal stored on a reserved inode.
3397                          */
3398                         force_fsck = recover ||
3399                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3400                         /* Clear all of the journal fields */
3401                         sb->s_journal_inum = 0;
3402                         sb->s_journal_dev = 0;
3403                         memset(sb->s_journal_uuid, 0,
3404                                sizeof(sb->s_journal_uuid));
3405                         e2fsck_clear_recover(ctx, force_fsck);
3406                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3407                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3408                         ext2fs_mark_super_dirty(ctx->fs);
3409                 }
3410         }
3411
3412         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3413             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3414             journal->j_superblock->s_start != 0) {
3415                 /* Print status information */
3416                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3417                 if (ctx->superblock)
3418                         problem = PR_0_JOURNAL_RUN_DEFAULT;
3419                 else
3420                         problem = PR_0_JOURNAL_RUN;
3421                 if (fix_problem(ctx, problem, &pctx)) {
3422                         ctx->options |= E2F_OPT_FORCE;
3423                         sb->s_feature_incompat |=
3424                                 EXT3_FEATURE_INCOMPAT_RECOVER;
3425                         ext2fs_mark_super_dirty(ctx->fs);
3426                 } else if (fix_problem(ctx,
3427                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3428                         reset = 1;
3429                         sb->s_state &= ~EXT2_VALID_FS;
3430                         ext2fs_mark_super_dirty(ctx->fs);
3431                 }
3432                 /*
3433                  * If the user answers no to the above question, we
3434                  * ignore the fact that journal apparently has data;
3435                  * accidentally replaying over valid data would be far
3436                  * worse than skipping a questionable recovery.
3437                  *
3438                  * XXX should we abort with a fatal error here?  What
3439                  * will the ext3 kernel code do if a filesystem with
3440                  * !NEEDS_RECOVERY but with a non-zero
3441                  * journal->j_superblock->s_start is mounted?
3442                  */
3443         }
3444
3445         e2fsck_journal_release(ctx, journal, reset, 0);
3446         return retval;
3447 }
3448
3449 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3450 {
3451         journal_t *journal;
3452         int retval;
3453
3454         journal_init_revoke_caches();
3455         retval = e2fsck_get_journal(ctx, &journal);
3456         if (retval)
3457                 return retval;
3458
3459         retval = e2fsck_journal_load(journal);
3460         if (retval)
3461                 goto errout;
3462
3463         retval = journal_init_revoke(journal, 1024);
3464         if (retval)
3465                 goto errout;
3466
3467         retval = -journal_recover(journal);
3468         if (retval)
3469                 goto errout;
3470
3471         if (journal->j_superblock->s_errno) {
3472                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3473                 ext2fs_mark_super_dirty(ctx->fs);
3474                 journal->j_superblock->s_errno = 0;
3475                 mark_buffer_dirty(journal->j_sb_buffer);
3476         }
3477
3478 errout:
3479         journal_destroy_revoke(journal);
3480         journal_destroy_revoke_caches();
3481         e2fsck_journal_release(ctx, journal, 1, 0);
3482         return retval;
3483 }
3484
3485 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3486 {
3487         io_manager io_ptr = ctx->fs->io->manager;
3488         int blocksize = ctx->fs->blocksize;
3489         errcode_t       retval, recover_retval;
3490
3491         printf(_("%s: recovering journal\n"), ctx->device_name);
3492         if (ctx->options & E2F_OPT_READONLY) {
3493                 printf(_("%s: won't do journal recovery while read-only\n"),
3494                        ctx->device_name);
3495                 return EXT2_ET_FILE_RO;
3496         }
3497
3498         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3499                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
3500
3501         recover_retval = recover_ext3_journal(ctx);
3502
3503         /*
3504          * Reload the filesystem context to get up-to-date data from disk
3505          * because journal recovery will change the filesystem under us.
3506          */
3507         ext2fs_close(ctx->fs);
3508         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3509                              ctx->superblock, blocksize, io_ptr,
3510                              &ctx->fs);
3511
3512         if (retval) {
3513                 com_err(ctx->program_name, retval,
3514                         _("while trying to re-open %s"),
3515                         ctx->device_name);
3516                 fatal_error(ctx, 0);
3517         }
3518         ctx->fs->priv_data = ctx;
3519
3520         /* Set the superblock flags */
3521         e2fsck_clear_recover(ctx, recover_retval);
3522         return recover_retval;
3523 }
3524
3525 /*
3526  * This function will move the journal inode from a visible file in
3527  * the filesystem directory hierarchy to the reserved inode if necessary.
3528  */
3529 static const char * const journal_names[] = {
3530         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3531
3532 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3533 {
3534         struct ext2_super_block *sb = ctx->fs->super;
3535         struct problem_context  pctx;
3536         struct ext2_inode       inode;
3537         ext2_filsys             fs = ctx->fs;
3538         ext2_ino_t              ino;
3539         errcode_t               retval;
3540         const char * const *    cpp;
3541         int                     group, mount_flags;
3542
3543         clear_problem_context(&pctx);
3544
3545         /*
3546          * If the filesystem is opened read-only, or there is no
3547          * journal, then do nothing.
3548          */
3549         if ((ctx->options & E2F_OPT_READONLY) ||
3550             (sb->s_journal_inum == 0) ||
3551             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3552                 return;
3553
3554         /*
3555          * Read in the journal inode
3556          */
3557         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3558                 return;
3559
3560         /*
3561          * If it's necessary to backup the journal inode, do so.
3562          */
3563         if ((sb->s_jnl_backup_type == 0) ||
3564             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3565              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3566                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3567                         memcpy(sb->s_jnl_blocks, inode.i_block,
3568                                EXT2_N_BLOCKS*4);
3569                         sb->s_jnl_blocks[16] = inode.i_size;
3570                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3571                         ext2fs_mark_super_dirty(fs);
3572                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3573                 }
3574         }
3575
3576         /*
3577          * If the journal is already the hidden inode, then do nothing
3578          */
3579         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3580                 return;
3581
3582         /*
3583          * The journal inode had better have only one link and not be readable.
3584          */
3585         if (inode.i_links_count != 1)
3586                 return;
3587
3588         /*
3589          * If the filesystem is mounted, or we can't tell whether
3590          * or not it's mounted, do nothing.
3591          */
3592         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3593         if (retval || (mount_flags & EXT2_MF_MOUNTED))
3594                 return;
3595
3596         /*
3597          * If we can't find the name of the journal inode, then do
3598          * nothing.
3599          */
3600         for (cpp = journal_names; *cpp; cpp++) {
3601                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3602                                        strlen(*cpp), 0, &ino);
3603                 if ((retval == 0) && (ino == sb->s_journal_inum))
3604                         break;
3605         }
3606         if (*cpp == 0)
3607                 return;
3608
3609         /* We need the inode bitmap to be loaded */
3610         retval = ext2fs_read_bitmaps(fs);
3611         if (retval)
3612                 return;
3613
3614         pctx.str = *cpp;
3615         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3616                 return;
3617
3618         /*
3619          * OK, we've done all the checks, let's actually move the
3620          * journal inode.  Errors at this point mean we need to force
3621          * an ext2 filesystem check.
3622          */
3623         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3624                 goto err_out;
3625         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3626                 goto err_out;
3627         sb->s_journal_inum = EXT2_JOURNAL_INO;
3628         ext2fs_mark_super_dirty(fs);
3629         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3630         inode.i_links_count = 0;
3631         inode.i_dtime = time(0);
3632         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3633                 goto err_out;
3634
3635         group = ext2fs_group_of_ino(fs, ino);
3636         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3637         ext2fs_mark_ib_dirty(fs);
3638         fs->group_desc[group].bg_free_inodes_count++;
3639         fs->super->s_free_inodes_count++;
3640         return;
3641
3642 err_out:
3643         pctx.errcode = retval;
3644         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3645         fs->super->s_state &= ~EXT2_VALID_FS;
3646         ext2fs_mark_super_dirty(fs);
3647         return;
3648 }
3649
3650 /*
3651  * message.c --- print e2fsck messages (with compression)
3652  *
3653  * print_e2fsck_message() prints a message to the user, using
3654  * compression techniques and expansions of abbreviations.
3655  *
3656  * The following % expansions are supported:
3657  *
3658  *      %b      <blk>                   block number
3659  *      %B      <blkcount>              integer
3660  *      %c      <blk2>                  block number
3661  *      %Di     <dirent>->ino           inode number
3662  *      %Dn     <dirent>->name          string
3663  *      %Dr     <dirent>->rec_len
3664  *      %Dl     <dirent>->name_len
3665  *      %Dt     <dirent>->filetype
3666  *      %d      <dir>                   inode number
3667  *      %g      <group>                 integer
3668  *      %i      <ino>                   inode number
3669  *      %Is     <inode> -> i_size
3670  *      %IS     <inode> -> i_extra_isize
3671  *      %Ib     <inode> -> i_blocks
3672  *      %Il     <inode> -> i_links_count
3673  *      %Im     <inode> -> i_mode
3674  *      %IM     <inode> -> i_mtime
3675  *      %IF     <inode> -> i_faddr
3676  *      %If     <inode> -> i_file_acl
3677  *      %Id     <inode> -> i_dir_acl
3678  *      %Iu     <inode> -> i_uid
3679  *      %Ig     <inode> -> i_gid
3680  *      %j      <ino2>                  inode number
3681  *      %m      <com_err error message>
3682  *      %N      <num>
3683  *      %p      ext2fs_get_pathname of directory <ino>
3684  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
3685  *                      the containing directory.  (If dirent is NULL
3686  *                      then return the pathname of directory <ino2>)
3687  *      %q      ext2fs_get_pathname of directory <dir>
3688  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
3689  *                      the containing directory.
3690  *      %s      <str>                   miscellaneous string
3691  *      %S      backup superblock
3692  *      %X      <num> hexadecimal format
3693  *
3694  * The following '@' expansions are supported:
3695  *
3696  *      @a      extended attribute
3697  *      @A      error allocating
3698  *      @b      block
3699  *      @B      bitmap
3700  *      @c      compress
3701  *      @C      conflicts with some other fs block
3702  *      @D      deleted
3703  *      @d      directory
3704  *      @e      entry
3705  *      @E      Entry '%Dn' in %p (%i)
3706  *      @f      filesystem
3707  *      @F      for @i %i (%Q) is
3708  *      @g      group
3709  *      @h      HTREE directory inode
3710  *      @i      inode
3711  *      @I      illegal
3712  *      @j      journal
3713  *      @l      lost+found
3714  *      @L      is a link
3715  *      @o      orphaned
3716  *      @p      problem in
3717  *      @r      root inode
3718  *      @s      should be
3719  *      @S      superblock
3720  *      @u      unattached
3721  *      @v      device
3722  *      @z      zero-length
3723  */
3724
3725
3726 /*
3727  * This structure defines the abbreviations used by the text strings
3728  * below.  The first character in the string is the index letter.  An
3729  * abbreviation of the form '@<i>' is expanded by looking up the index
3730  * letter <i> in the table below.
3731  */
3732 static const char * const abbrevs[] = {
3733         N_("aextended attribute"),
3734         N_("Aerror allocating"),
3735         N_("bblock"),
3736         N_("Bbitmap"),
3737         N_("ccompress"),
3738         N_("Cconflicts with some other fs @b"),
3739         N_("iinode"),
3740         N_("Iillegal"),
3741         N_("jjournal"),
3742         N_("Ddeleted"),
3743         N_("ddirectory"),
3744         N_("eentry"),
3745         N_("E@e '%Dn' in %p (%i)"),
3746         N_("ffilesystem"),
3747         N_("Ffor @i %i (%Q) is"),
3748         N_("ggroup"),
3749         N_("hHTREE @d @i"),
3750         N_("llost+found"),
3751         N_("Lis a link"),
3752         N_("oorphaned"),
3753         N_("pproblem in"),
3754         N_("rroot @i"),
3755         N_("sshould be"),
3756         N_("Ssuper@b"),
3757         N_("uunattached"),
3758         N_("vdevice"),
3759         N_("zzero-length"),
3760         "@@",
3761         0
3762         };
3763
3764 /*
3765  * Give more user friendly names to the "special" inodes.
3766  */
3767 #define num_special_inodes      11
3768 static const char * const special_inode_name[] =
3769 {
3770         N_("<The NULL inode>"),                 /* 0 */
3771         N_("<The bad blocks inode>"),           /* 1 */
3772         "/",                                    /* 2 */
3773         N_("<The ACL index inode>"),            /* 3 */
3774         N_("<The ACL data inode>"),             /* 4 */
3775         N_("<The boot loader inode>"),          /* 5 */
3776         N_("<The undelete directory inode>"),   /* 6 */
3777         N_("<The group descriptor inode>"),     /* 7 */
3778         N_("<The journal inode>"),              /* 8 */
3779         N_("<Reserved inode 9>"),               /* 9 */
3780         N_("<Reserved inode 10>"),              /* 10 */
3781 };
3782
3783 /*
3784  * This function does "safe" printing.  It will convert non-printable
3785  * ASCII characters using '^' and M- notation.
3786  */
3787 static void safe_print(const char *cp, int len)
3788 {
3789         unsigned char   ch;
3790
3791         if (len < 0)
3792                 len = strlen(cp);
3793
3794         while (len--) {
3795                 ch = *cp++;
3796                 if (ch > 128) {
3797                         fputs("M-", stdout);
3798                         ch -= 128;
3799                 }
3800                 if ((ch < 32) || (ch == 0x7f)) {
3801                         fputc('^', stdout);
3802                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3803                 }
3804                 fputc(ch, stdout);
3805         }
3806 }
3807
3808
3809 /*
3810  * This function prints a pathname, using the ext2fs_get_pathname
3811  * function
3812  */
3813 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3814 {
3815         errcode_t       retval;
3816         char            *path;
3817
3818         if (!dir && (ino < num_special_inodes)) {
3819                 fputs(_(special_inode_name[ino]), stdout);
3820                 return;
3821         }
3822
3823         retval = ext2fs_get_pathname(fs, dir, ino, &path);
3824         if (retval)
3825                 fputs("???", stdout);
3826         else {
3827                 safe_print(path, -1);
3828                 ext2fs_free_mem(&path);
3829         }
3830 }
3831
3832 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3833                           struct problem_context *pctx, int first);
3834 /*
3835  * This function handles the '@' expansion.  We allow recursive
3836  * expansion; an @ expression can contain further '@' and '%'
3837  * expressions.
3838  */
3839 static void expand_at_expression(e2fsck_t ctx, char ch,
3840                                           struct problem_context *pctx,
3841                                           int *first)
3842 {
3843         const char * const *cpp;
3844         const char *str;
3845
3846         /* Search for the abbreviation */
3847         for (cpp = abbrevs; *cpp; cpp++) {
3848                 if (ch == *cpp[0])
3849                         break;
3850         }
3851         if (*cpp) {
3852                 str = _(*cpp) + 1;
3853                 if (*first && islower(*str)) {
3854                         *first = 0;
3855                         fputc(toupper(*str++), stdout);
3856                 }
3857                 print_e2fsck_message(ctx, str, pctx, *first);
3858         } else
3859                 printf("@%c", ch);
3860 }
3861
3862 /*
3863  * This function expands '%IX' expressions
3864  */
3865 static void expand_inode_expression(char ch,
3866                                              struct problem_context *ctx)
3867 {
3868         struct ext2_inode       *inode;
3869         struct ext2_inode_large *large_inode;
3870         char *                  time_str;
3871         time_t                  t;
3872         int                     do_gmt = -1;
3873
3874         if (!ctx || !ctx->inode)
3875                 goto no_inode;
3876
3877         inode = ctx->inode;
3878         large_inode = (struct ext2_inode_large *) inode;
3879
3880         switch (ch) {
3881         case 's':
3882                 if (LINUX_S_ISDIR(inode->i_mode))
3883                         printf("%u", inode->i_size);
3884                 else {
3885 #ifdef EXT2_NO_64_TYPE
3886                         if (inode->i_size_high)
3887                                 printf("0x%x%08x", inode->i_size_high,
3888                                        inode->i_size);
3889                         else
3890                                 printf("%u", inode->i_size);
3891 #else
3892                         printf("%llu", (inode->i_size |
3893                                         ((__u64) inode->i_size_high << 32)));
3894 #endif
3895                 }
3896                 break;
3897         case 'S':
3898                 printf("%u", large_inode->i_extra_isize);
3899                 break;
3900         case 'b':
3901                 printf("%u", inode->i_blocks);
3902                 break;
3903         case 'l':
3904                 printf("%d", inode->i_links_count);
3905                 break;
3906         case 'm':
3907                 printf("0%o", inode->i_mode);
3908                 break;
3909         case 'M':
3910                 /* The diet libc doesn't respect the TZ environemnt variable */
3911                 if (do_gmt == -1) {
3912                         time_str = getenv("TZ");
3913                         if (!time_str)
3914                                 time_str = "";
3915                         do_gmt = !strcmp(time_str, "GMT");
3916                 }
3917                 t = inode->i_mtime;
3918                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3919                 printf("%.24s", time_str);
3920                 break;
3921         case 'F':
3922                 printf("%u", inode->i_faddr);
3923                 break;
3924         case 'f':
3925                 printf("%u", inode->i_file_acl);
3926                 break;
3927         case 'd':
3928                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3929                               inode->i_dir_acl : 0));
3930                 break;
3931         case 'u':
3932                 printf("%d", (inode->i_uid |
3933                               (inode->osd2.linux2.l_i_uid_high << 16)));
3934                 break;
3935         case 'g':
3936                 printf("%d", (inode->i_gid |
3937                               (inode->osd2.linux2.l_i_gid_high << 16)));
3938                 break;
3939         default:
3940         no_inode:
3941                 printf("%%I%c", ch);
3942                 break;
3943         }
3944 }
3945
3946 /*
3947  * This function expands '%dX' expressions
3948  */
3949 static _INLINE_ void expand_dirent_expression(char ch,
3950                                               struct problem_context *ctx)
3951 {
3952         struct ext2_dir_entry   *dirent;
3953         int     len;
3954
3955         if (!ctx || !ctx->dirent)
3956                 goto no_dirent;
3957
3958         dirent = ctx->dirent;
3959
3960         switch (ch) {
3961         case 'i':
3962                 printf("%u", dirent->inode);
3963                 break;
3964         case 'n':
3965                 len = dirent->name_len & 0xFF;
3966                 if (len > EXT2_NAME_LEN)
3967                         len = EXT2_NAME_LEN;
3968                 if (len > dirent->rec_len)
3969                         len = dirent->rec_len;
3970                 safe_print(dirent->name, len);
3971                 break;
3972         case 'r':
3973                 printf("%u", dirent->rec_len);
3974                 break;
3975         case 'l':
3976                 printf("%u", dirent->name_len & 0xFF);
3977                 break;
3978         case 't':
3979                 printf("%u", dirent->name_len >> 8);
3980                 break;
3981         default:
3982         no_dirent:
3983                 printf("%%D%c", ch);
3984                 break;
3985         }
3986 }
3987
3988 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
3989                                                struct problem_context *ctx)
3990 {
3991         if (!ctx)
3992                 goto no_context;
3993
3994         switch (ch) {
3995         case '%':
3996                 fputc('%', stdout);
3997                 break;
3998         case 'b':
3999                 printf("%u", ctx->blk);
4000                 break;
4001         case 'B':
4002 #ifdef EXT2_NO_64_TYPE
4003                 printf("%d", ctx->blkcount);
4004 #else
4005                 printf("%lld", ctx->blkcount);
4006 #endif
4007                 break;
4008         case 'c':
4009                 printf("%u", ctx->blk2);
4010                 break;
4011         case 'd':
4012                 printf("%u", ctx->dir);
4013                 break;
4014         case 'g':
4015                 printf("%d", ctx->group);
4016                 break;
4017         case 'i':
4018                 printf("%u", ctx->ino);
4019                 break;
4020         case 'j':
4021                 printf("%u", ctx->ino2);
4022                 break;
4023         case 'm':
4024                 printf("%s", error_message(ctx->errcode));
4025                 break;
4026         case 'N':
4027 #ifdef EXT2_NO_64_TYPE
4028                 printf("%u", ctx->num);
4029 #else
4030                 printf("%llu", ctx->num);
4031 #endif
4032                 break;
4033         case 'p':
4034                 print_pathname(fs, ctx->ino, 0);
4035                 break;
4036         case 'P':
4037                 print_pathname(fs, ctx->ino2,
4038                                ctx->dirent ? ctx->dirent->inode : 0);
4039                 break;
4040         case 'q':
4041                 print_pathname(fs, ctx->dir, 0);
4042                 break;
4043         case 'Q':
4044                 print_pathname(fs, ctx->dir, ctx->ino);
4045                 break;
4046         case 'S':
4047                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4048                 break;
4049         case 's':
4050                 printf("%s", ctx->str ? ctx->str : "NULL");
4051                 break;
4052         case 'X':
4053 #ifdef EXT2_NO_64_TYPE
4054                 printf("0x%x", ctx->num);
4055 #else
4056                 printf("0x%llx", ctx->num);
4057 #endif
4058                 break;
4059         default:
4060         no_context:
4061                 printf("%%%c", ch);
4062                 break;
4063         }
4064 }
4065
4066
4067 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4068                           struct problem_context *pctx, int first)
4069 {
4070         ext2_filsys fs = ctx->fs;
4071         const char *    cp;
4072         int             i;
4073
4074         e2fsck_clear_progbar(ctx);
4075         for (cp = msg; *cp; cp++) {
4076                 if (cp[0] == '@') {
4077                         cp++;
4078                         expand_at_expression(ctx, *cp, pctx, &first);
4079                 } else if (cp[0] == '%' && cp[1] == 'I') {
4080                         cp += 2;
4081                         expand_inode_expression(*cp, pctx);
4082                 } else if (cp[0] == '%' && cp[1] == 'D') {
4083                         cp += 2;
4084                         expand_dirent_expression(*cp, pctx);
4085                 } else if ((cp[0] == '%')) {
4086                         cp++;
4087                         expand_percent_expression(fs, *cp, pctx);
4088                 } else {
4089                         for (i=0; cp[i]; i++)
4090                                 if ((cp[i] == '@') || cp[i] == '%')
4091                                         break;
4092                         printf("%.*s", i, cp);
4093                         cp += i-1;
4094                 }
4095                 first = 0;
4096         }
4097 }
4098
4099
4100 /*
4101  * region.c --- code which manages allocations within a region.
4102  */
4103
4104 struct region_el {
4105         region_addr_t   start;
4106         region_addr_t   end;
4107         struct region_el *next;
4108 };
4109
4110 struct region_struct {
4111         region_addr_t   min;
4112         region_addr_t   max;
4113         struct region_el *allocated;
4114 };
4115
4116 static region_t region_create(region_addr_t min, region_addr_t max)
4117 {
4118         region_t        region;
4119
4120         region = malloc(sizeof(struct region_struct));
4121         if (!region)
4122                 return NULL;
4123         memset(region, 0, sizeof(struct region_struct));
4124         region->min = min;
4125         region->max = max;
4126         return region;
4127 }
4128
4129 static void region_free(region_t region)
4130 {
4131         struct region_el        *r, *next;
4132
4133         for (r = region->allocated; r; r = next) {
4134                 next = r->next;
4135                 free(r);
4136         }
4137         memset(region, 0, sizeof(struct region_struct));
4138         free(region);
4139 }
4140
4141 static int region_allocate(region_t region, region_addr_t start, int n)
4142 {
4143         struct region_el        *r, *new_region, *prev, *next;
4144         region_addr_t end;
4145
4146         end = start+n;
4147         if ((start < region->min) || (end > region->max))
4148                 return -1;
4149         if (n == 0)
4150                 return 1;
4151
4152         /*
4153          * Search through the linked list.  If we find that it
4154          * conflicts witih something that's already allocated, return
4155          * 1; if we can find an existing region which we can grow, do
4156          * so.  Otherwise, stop when we find the appropriate place
4157          * insert a new region element into the linked list.
4158          */
4159         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4160                 if (((start >= r->start) && (start < r->end)) ||
4161                     ((end > r->start) && (end <= r->end)) ||
4162                     ((start <= r->start) && (end >= r->end)))
4163                         return 1;
4164                 if (end == r->start) {
4165                         r->start = start;
4166                         return 0;
4167                 }
4168                 if (start == r->end) {
4169                         if ((next = r->next)) {
4170                                 if (end > next->start)
4171                                         return 1;
4172                                 if (end == next->start) {
4173                                         r->end = next->end;
4174                                         r->next = next->next;
4175                                         free(next);
4176                                         return 0;
4177                                 }
4178                         }
4179                         r->end = end;
4180                         return 0;
4181                 }
4182                 if (start < r->start)
4183                         break;
4184         }
4185         /*
4186          * Insert a new region element structure into the linked list
4187          */
4188         new_region = malloc(sizeof(struct region_el));
4189         if (!new_region)
4190                 return -1;
4191         new_region->start = start;
4192         new_region->end = start + n;
4193         new_region->next = r;
4194         if (prev)
4195                 prev->next = new_region;
4196         else
4197                 region->allocated = new_region;
4198         return 0;
4199 }
4200
4201 /*
4202  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4203  *
4204  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4205  * and applies the following tests to each inode:
4206  *
4207  *      - The mode field of the inode must be legal.
4208  *      - The size and block count fields of the inode are correct.
4209  *      - A data block must not be used by another inode
4210  *
4211  * Pass 1 also gathers the collects the following information:
4212  *
4213  *      - A bitmap of which inodes are in use.          (inode_used_map)
4214  *      - A bitmap of which inodes are directories.     (inode_dir_map)
4215  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
4216  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
4217  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
4218  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
4219  *      - A bitmap of which blocks are in use.          (block_found_map)
4220  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
4221  *      - The data blocks of the directory inodes.      (dir_map)
4222  *
4223  * Pass 1 is designed to stash away enough information so that the
4224  * other passes should not need to read in the inode information
4225  * during the normal course of a filesystem check.  (Althogh if an
4226  * inconsistency is detected, other passes may need to read in an
4227  * inode to fix it.)
4228  *
4229  * Note that pass 1B will be invoked if there are any duplicate blocks
4230  * found.
4231  */
4232
4233
4234 static int process_block(ext2_filsys fs, blk_t  *blocknr,
4235                          e2_blkcnt_t blockcnt, blk_t ref_blk,
4236                          int ref_offset, void *priv_data);
4237 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4238                              e2_blkcnt_t blockcnt, blk_t ref_blk,
4239                              int ref_offset, void *priv_data);
4240 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4241                          char *block_buf);
4242 static void mark_table_blocks(e2fsck_t ctx);
4243 static void alloc_bb_map(e2fsck_t ctx);
4244 static void alloc_imagic_map(e2fsck_t ctx);
4245 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4246 static void handle_fs_bad_blocks(e2fsck_t ctx);
4247 static void process_inodes(e2fsck_t ctx, char *block_buf);
4248 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4249 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4250                                   dgrp_t group, void * priv_data);
4251 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4252                                     char *block_buf, int adjust_sign);
4253 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4254
4255 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4256                                struct ext2_inode * inode, int bufsize,
4257                                const char *proc);
4258
4259 struct process_block_struct_1 {
4260         ext2_ino_t      ino;
4261         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
4262                                 fragmented:1, compressed:1, bbcheck:1;
4263         blk_t           num_blocks;
4264         blk_t           max_blocks;
4265         e2_blkcnt_t     last_block;
4266         int             num_illegal_blocks;
4267         blk_t           previous_block;
4268         struct ext2_inode *inode;
4269         struct problem_context *pctx;
4270         ext2fs_block_bitmap fs_meta_blocks;
4271         e2fsck_t        ctx;
4272 };
4273
4274 struct process_inode_block {
4275         ext2_ino_t ino;
4276         struct ext2_inode inode;
4277 };
4278
4279 struct scan_callback_struct {
4280         e2fsck_t        ctx;
4281         char            *block_buf;
4282 };
4283
4284 /*
4285  * For the inodes to process list.
4286  */
4287 static struct process_inode_block *inodes_to_process;
4288 static int process_inode_count;
4289
4290 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4291                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
4292
4293 /*
4294  * Free all memory allocated by pass1 in preparation for restarting
4295  * things.
4296  */
4297 static void unwind_pass1(void)
4298 {
4299         ext2fs_free_mem(&inodes_to_process);
4300 }
4301
4302 /*
4303  * Check to make sure a device inode is real.  Returns 1 if the device
4304  * checks out, 0 if not.
4305  *
4306  * Note: this routine is now also used to check FIFO's and Sockets,
4307  * since they have the same requirement; the i_block fields should be
4308  * zero.
4309  */
4310 static int
4311 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4312 {
4313         int     i;
4314
4315         /*
4316          * If i_blocks is non-zero, or the index flag is set, then
4317          * this is a bogus device/fifo/socket
4318          */
4319         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4320             (inode->i_flags & EXT2_INDEX_FL))
4321                 return 0;
4322
4323         /*
4324          * We should be able to do the test below all the time, but
4325          * because the kernel doesn't forcibly clear the device
4326          * inode's additional i_block fields, there are some rare
4327          * occasions when a legitimate device inode will have non-zero
4328          * additional i_block fields.  So for now, we only complain
4329          * when the immutable flag is set, which should never happen
4330          * for devices.  (And that's when the problem is caused, since
4331          * you can't set or clear immutable flags for devices.)  Once
4332          * the kernel has been fixed we can change this...
4333          */
4334         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4335                 for (i=4; i < EXT2_N_BLOCKS; i++)
4336                         if (inode->i_block[i])
4337                                 return 0;
4338         }
4339         return 1;
4340 }
4341
4342 /*
4343  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
4344  * checks out, 0 if not.
4345  */
4346 static int
4347 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4348 {
4349         unsigned int len;
4350         int i;
4351         blk_t   blocks;
4352
4353         if ((inode->i_size_high || inode->i_size == 0) ||
4354             (inode->i_flags & EXT2_INDEX_FL))
4355                 return 0;
4356
4357         blocks = ext2fs_inode_data_blocks(fs, inode);
4358         if (blocks) {
4359                 if ((inode->i_size >= fs->blocksize) ||
4360                     (blocks != fs->blocksize >> 9) ||
4361                     (inode->i_block[0] < fs->super->s_first_data_block) ||
4362                     (inode->i_block[0] >= fs->super->s_blocks_count))
4363                         return 0;
4364
4365                 for (i = 1; i < EXT2_N_BLOCKS; i++)
4366                         if (inode->i_block[i])
4367                                 return 0;
4368
4369                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4370                         return 0;
4371
4372                 len = strnlen(buf, fs->blocksize);
4373                 if (len == fs->blocksize)
4374                         return 0;
4375         } else {
4376                 if (inode->i_size >= sizeof(inode->i_block))
4377                         return 0;
4378
4379                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4380                 if (len == sizeof(inode->i_block))
4381                         return 0;
4382         }
4383         if (len != inode->i_size)
4384                 return 0;
4385         return 1;
4386 }
4387
4388 /*
4389  * If the immutable (or append-only) flag is set on the inode, offer
4390  * to clear it.
4391  */
4392 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4393 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4394 {
4395         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4396                 return;
4397
4398         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4399                 return;
4400
4401         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4402         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4403 }
4404
4405 /*
4406  * If device, fifo or socket, check size is zero -- if not offer to
4407  * clear it
4408  */
4409 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4410 {
4411         struct ext2_inode *inode = pctx->inode;
4412
4413         if ((inode->i_size == 0) && (inode->i_size_high == 0))
4414                 return;
4415
4416         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4417                 return;
4418
4419         inode->i_size = 0;
4420         inode->i_size_high = 0;
4421         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4422 }
4423
4424 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4425 {
4426         struct ext2_super_block *sb = ctx->fs->super;
4427         struct ext2_inode_large *inode;
4428         struct ext2_ext_attr_entry *entry;
4429         char *start, *end;
4430         int storage_size, remain, offs;
4431         int problem = 0;
4432
4433         inode = (struct ext2_inode_large *) pctx->inode;
4434         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4435                 inode->i_extra_isize;
4436         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4437                 inode->i_extra_isize + sizeof(__u32);
4438         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4439         entry = (struct ext2_ext_attr_entry *) start;
4440
4441         /* scan all entry's headers first */
4442
4443         /* take finish entry 0UL into account */
4444         remain = storage_size - sizeof(__u32);
4445         offs = end - start;
4446
4447         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4448
4449                 /* header eats this space */
4450                 remain -= sizeof(struct ext2_ext_attr_entry);
4451
4452                 /* is attribute name valid? */
4453                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4454                         pctx->num = entry->e_name_len;
4455                         problem = PR_1_ATTR_NAME_LEN;
4456                         goto fix;
4457                 }
4458
4459                 /* attribute len eats this space */
4460                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4461
4462                 /* check value size */
4463                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4464                         pctx->num = entry->e_value_size;
4465                         problem = PR_1_ATTR_VALUE_SIZE;
4466                         goto fix;
4467                 }
4468
4469                 /* check value placement */
4470                 if (entry->e_value_offs +
4471                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4472                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4473                         pctx->num = entry->e_value_offs;
4474                         problem = PR_1_ATTR_VALUE_OFFSET;
4475                         goto fix;
4476                 }
4477
4478                 /* e_value_block must be 0 in inode's ea */
4479                 if (entry->e_value_block != 0) {
4480                         pctx->num = entry->e_value_block;
4481                         problem = PR_1_ATTR_VALUE_BLOCK;
4482                         goto fix;
4483                 }
4484
4485                 /* e_hash must be 0 in inode's ea */
4486                 if (entry->e_hash != 0) {
4487                         pctx->num = entry->e_hash;
4488                         problem = PR_1_ATTR_HASH;
4489                         goto fix;
4490                 }
4491
4492                 remain -= entry->e_value_size;
4493                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4494
4495                 entry = EXT2_EXT_ATTR_NEXT(entry);
4496         }
4497 fix:
4498         /*
4499          * it seems like a corruption. it's very unlikely we could repair
4500          * EA(s) in automatic fashion -bzzz
4501          */
4502 #if 0
4503         problem = PR_1_ATTR_HASH;
4504 #endif
4505         if (problem == 0 || !fix_problem(ctx, problem, pctx))
4506                 return;
4507
4508         /* simple remove all possible EA(s) */
4509         *((__u32 *)start) = 0UL;
4510         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4511                                 EXT2_INODE_SIZE(sb), "pass1");
4512 }
4513
4514 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4515 {
4516         struct ext2_super_block *sb = ctx->fs->super;
4517         struct ext2_inode_large *inode;
4518         __u32 *eamagic;
4519         int min, max;
4520
4521         inode = (struct ext2_inode_large *) pctx->inode;
4522         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4523                 /* this isn't large inode. so, nothing to check */
4524                 return;
4525         }
4526
4527 #if 0
4528         printf("inode #%u, i_extra_size %d\n", pctx->ino,
4529                         inode->i_extra_isize);
4530 #endif
4531         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4532         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4533         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4534         /*
4535          * For now we will allow i_extra_isize to be 0, but really
4536          * implementations should never allow i_extra_isize to be 0
4537          */
4538         if (inode->i_extra_isize &&
4539             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4540                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4541                         return;
4542                 inode->i_extra_isize = min;
4543                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4544                                         EXT2_INODE_SIZE(sb), "pass1");
4545                 return;
4546         }
4547
4548         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4549                         inode->i_extra_isize);
4550         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4551                 /* it seems inode has an extended attribute(s) in body */
4552                 check_ea_in_inode(ctx, pctx);
4553         }
4554 }
4555
4556 static void e2fsck_pass1(e2fsck_t ctx)
4557 {
4558         int     i;
4559         __u64   max_sizes;
4560         ext2_filsys fs = ctx->fs;
4561         ext2_ino_t      ino;
4562         struct ext2_inode *inode;
4563         ext2_inode_scan scan;
4564         char            *block_buf;
4565 #ifdef RESOURCE_TRACK
4566         struct resource_track   rtrack;
4567 #endif
4568         unsigned char   frag, fsize;
4569         struct          problem_context pctx;
4570         struct          scan_callback_struct scan_struct;
4571         struct ext2_super_block *sb = ctx->fs->super;
4572         int             imagic_fs;
4573         int             busted_fs_time = 0;
4574         int             inode_size;
4575
4576 #ifdef RESOURCE_TRACK
4577         init_resource_track(&rtrack);
4578 #endif
4579         clear_problem_context(&pctx);
4580
4581         if (!(ctx->options & E2F_OPT_PREEN))
4582                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4583
4584         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4585             !(ctx->options & E2F_OPT_NO)) {
4586                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4587                         ctx->dirs_to_hash = 0;
4588         }
4589
4590 #ifdef MTRACE
4591         mtrace_print("Pass 1");
4592 #endif
4593
4594 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4595
4596         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4597                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4598                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4599                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4600                 max_sizes = (max_sizes * (1UL << i)) - 1;
4601                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4602         }
4603 #undef EXT2_BPP
4604
4605         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4606
4607         /*
4608          * Allocate bitmaps structures
4609          */
4610         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4611                                               &ctx->inode_used_map);
4612         if (pctx.errcode) {
4613                 pctx.num = 1;
4614                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4615                 ctx->flags |= E2F_FLAG_ABORT;
4616                 return;
4617         }
4618         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4619                                 _("directory inode map"), &ctx->inode_dir_map);
4620         if (pctx.errcode) {
4621                 pctx.num = 2;
4622                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4623                 ctx->flags |= E2F_FLAG_ABORT;
4624                 return;
4625         }
4626         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4627                         _("regular file inode map"), &ctx->inode_reg_map);
4628         if (pctx.errcode) {
4629                 pctx.num = 6;
4630                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4631                 ctx->flags |= E2F_FLAG_ABORT;
4632                 return;
4633         }
4634         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4635                                               &ctx->block_found_map);
4636         if (pctx.errcode) {
4637                 pctx.num = 1;
4638                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4639                 ctx->flags |= E2F_FLAG_ABORT;
4640                 return;
4641         }
4642         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4643                                              &ctx->inode_link_info);
4644         if (pctx.errcode) {
4645                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4646                 ctx->flags |= E2F_FLAG_ABORT;
4647                 return;
4648         }
4649         inode_size = EXT2_INODE_SIZE(fs->super);
4650         inode = (struct ext2_inode *)
4651                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4652
4653         inodes_to_process = (struct process_inode_block *)
4654                 e2fsck_allocate_memory(ctx,
4655                                        (ctx->process_inode_size *
4656                                         sizeof(struct process_inode_block)),
4657                                        "array of inodes to process");
4658         process_inode_count = 0;
4659
4660         pctx.errcode = ext2fs_init_dblist(fs, 0);
4661         if (pctx.errcode) {
4662                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4663                 ctx->flags |= E2F_FLAG_ABORT;
4664                 return;
4665         }
4666
4667         /*
4668          * If the last orphan field is set, clear it, since the pass1
4669          * processing will automatically find and clear the orphans.
4670          * In the future, we may want to try using the last_orphan
4671          * linked list ourselves, but for now, we clear it so that the
4672          * ext3 mount code won't get confused.
4673          */
4674         if (!(ctx->options & E2F_OPT_READONLY)) {
4675                 if (fs->super->s_last_orphan) {
4676                         fs->super->s_last_orphan = 0;
4677                         ext2fs_mark_super_dirty(fs);
4678                 }
4679         }
4680
4681         mark_table_blocks(ctx);
4682         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4683                                                     "block interate buffer");
4684         e2fsck_use_inode_shortcuts(ctx, 1);
4685         ehandler_operation(_("doing inode scan"));
4686         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4687                                               &scan);
4688         if (pctx.errcode) {
4689                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4690                 ctx->flags |= E2F_FLAG_ABORT;
4691                 return;
4692         }
4693         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4694         ctx->stashed_inode = inode;
4695         scan_struct.ctx = ctx;
4696         scan_struct.block_buf = block_buf;
4697         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4698         if (ctx->progress)
4699                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4700                         return;
4701         if (fs->super->s_wtime < fs->super->s_inodes_count)
4702                 busted_fs_time = 1;
4703
4704         while (1) {
4705                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4706                                                           inode, inode_size);
4707                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4708                         return;
4709                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4710                         if (!ctx->inode_bb_map)
4711                                 alloc_bb_map(ctx);
4712                         ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4713                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4714                         continue;
4715                 }
4716                 if (pctx.errcode) {
4717                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4718                         ctx->flags |= E2F_FLAG_ABORT;
4719                         return;
4720                 }
4721                 if (!ino)
4722                         break;
4723                 pctx.ino = ino;
4724                 pctx.inode = inode;
4725                 ctx->stashed_ino = ino;
4726                 if (inode->i_links_count) {
4727                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4728                                            ino, inode->i_links_count);
4729                         if (pctx.errcode) {
4730                                 pctx.num = inode->i_links_count;
4731                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4732                                 ctx->flags |= E2F_FLAG_ABORT;
4733                                 return;
4734                         }
4735                 }
4736                 if (ino == EXT2_BAD_INO) {
4737                         struct process_block_struct_1 pb;
4738
4739                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4740                                                           &pb.fs_meta_blocks);
4741                         if (pctx.errcode) {
4742                                 pctx.num = 4;
4743                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4744                                 ctx->flags |= E2F_FLAG_ABORT;
4745                                 return;
4746                         }
4747                         pb.ino = EXT2_BAD_INO;
4748                         pb.num_blocks = pb.last_block = 0;
4749                         pb.num_illegal_blocks = 0;
4750                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4751                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4752                         pb.inode = inode;
4753                         pb.pctx = &pctx;
4754                         pb.ctx = ctx;
4755                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4756                                      block_buf, process_bad_block, &pb);
4757                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4758                         if (pctx.errcode) {
4759                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4760                                 ctx->flags |= E2F_FLAG_ABORT;
4761                                 return;
4762                         }
4763                         if (pb.bbcheck)
4764                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4765                                 ctx->flags |= E2F_FLAG_ABORT;
4766                                 return;
4767                         }
4768                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4769                         clear_problem_context(&pctx);
4770                         continue;
4771                 } else if (ino == EXT2_ROOT_INO) {
4772                         /*
4773                          * Make sure the root inode is a directory; if
4774                          * not, offer to clear it.  It will be
4775                          * regnerated in pass #3.
4776                          */
4777                         if (!LINUX_S_ISDIR(inode->i_mode)) {
4778                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4779                                         inode->i_dtime = time(0);
4780                                         inode->i_links_count = 0;
4781                                         ext2fs_icount_store(ctx->inode_link_info,
4782                                                             ino, 0);
4783                                         e2fsck_write_inode(ctx, ino, inode,
4784                                                            "pass1");
4785                                 }
4786
4787                         }
4788                         /*
4789                          * If dtime is set, offer to clear it.  mke2fs
4790                          * version 0.2b created filesystems with the
4791                          * dtime field set for the root and lost+found
4792                          * directories.  We won't worry about
4793                          * /lost+found, since that can be regenerated
4794                          * easily.  But we will fix the root directory
4795                          * as a special case.
4796                          */
4797                         if (inode->i_dtime && inode->i_links_count) {
4798                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4799                                         inode->i_dtime = 0;
4800                                         e2fsck_write_inode(ctx, ino, inode,
4801                                                            "pass1");
4802                                 }
4803                         }
4804                 } else if (ino == EXT2_JOURNAL_INO) {
4805                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4806                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4807                                 if (!LINUX_S_ISREG(inode->i_mode) &&
4808                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4809                                                 &pctx)) {
4810                                         inode->i_mode = LINUX_S_IFREG;
4811                                         e2fsck_write_inode(ctx, ino, inode,
4812                                                            "pass1");
4813                                 }
4814                                 check_blocks(ctx, &pctx, block_buf);
4815                                 continue;
4816                         }
4817                         if ((inode->i_links_count || inode->i_blocks ||
4818                              inode->i_blocks || inode->i_block[0]) &&
4819                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4820                                         &pctx)) {
4821                                 memset(inode, 0, inode_size);
4822                                 ext2fs_icount_store(ctx->inode_link_info,
4823                                                     ino, 0);
4824                                 e2fsck_write_inode_full(ctx, ino, inode,
4825                                                         inode_size, "pass1");
4826                         }
4827                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4828                         int     problem = 0;
4829
4830                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4831                         if (ino == EXT2_BOOT_LOADER_INO) {
4832                                 if (LINUX_S_ISDIR(inode->i_mode))
4833                                         problem = PR_1_RESERVED_BAD_MODE;
4834                         } else if (ino == EXT2_RESIZE_INO) {
4835                                 if (inode->i_mode &&
4836                                     !LINUX_S_ISREG(inode->i_mode))
4837                                         problem = PR_1_RESERVED_BAD_MODE;
4838                         } else {
4839                                 if (inode->i_mode != 0)
4840                                         problem = PR_1_RESERVED_BAD_MODE;
4841                         }
4842                         if (problem) {
4843                                 if (fix_problem(ctx, problem, &pctx)) {
4844                                         inode->i_mode = 0;
4845                                         e2fsck_write_inode(ctx, ino, inode,
4846                                                            "pass1");
4847                                 }
4848                         }
4849                         check_blocks(ctx, &pctx, block_buf);
4850                         continue;
4851                 }
4852                 /*
4853                  * Check for inodes who might have been part of the
4854                  * orphaned list linked list.  They should have gotten
4855                  * dealt with by now, unless the list had somehow been
4856                  * corrupted.
4857                  *
4858                  * FIXME: In the future, inodes which are still in use
4859                  * (and which are therefore) pending truncation should
4860                  * be handled specially.  Right now we just clear the
4861                  * dtime field, and the normal e2fsck handling of
4862                  * inodes where i_size and the inode blocks are
4863                  * inconsistent is to fix i_size, instead of releasing
4864                  * the extra blocks.  This won't catch the inodes that
4865                  * was at the end of the orphan list, but it's better
4866                  * than nothing.  The right answer is that there
4867                  * shouldn't be any bugs in the orphan list handling.  :-)
4868                  */
4869                 if (inode->i_dtime && !busted_fs_time &&
4870                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
4871                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4872                                 inode->i_dtime = inode->i_links_count ?
4873                                         0 : time(0);
4874                                 e2fsck_write_inode(ctx, ino, inode,
4875                                                    "pass1");
4876                         }
4877                 }
4878
4879                 /*
4880                  * This code assumes that deleted inodes have
4881                  * i_links_count set to 0.
4882                  */
4883                 if (!inode->i_links_count) {
4884                         if (!inode->i_dtime && inode->i_mode) {
4885                                 if (fix_problem(ctx,
4886                                             PR_1_ZERO_DTIME, &pctx)) {
4887                                         inode->i_dtime = time(0);
4888                                         e2fsck_write_inode(ctx, ino, inode,
4889                                                            "pass1");
4890                                 }
4891                         }
4892                         continue;
4893                 }
4894                 /*
4895                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
4896                  * deleted files.  Oops.
4897                  *
4898                  * Since all new ext2 implementations get this right,
4899                  * we now assume that the case of non-zero
4900                  * i_links_count and non-zero dtime means that we
4901                  * should keep the file, not delete it.
4902                  *
4903                  */
4904                 if (inode->i_dtime) {
4905                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4906                                 inode->i_dtime = 0;
4907                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
4908                         }
4909                 }
4910
4911                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4912                 switch (fs->super->s_creator_os) {
4913                     case EXT2_OS_LINUX:
4914                         frag = inode->osd2.linux2.l_i_frag;
4915                         fsize = inode->osd2.linux2.l_i_fsize;
4916                         break;
4917                     case EXT2_OS_HURD:
4918                         frag = inode->osd2.hurd2.h_i_frag;
4919                         fsize = inode->osd2.hurd2.h_i_fsize;
4920                         break;
4921                     case EXT2_OS_MASIX:
4922                         frag = inode->osd2.masix2.m_i_frag;
4923                         fsize = inode->osd2.masix2.m_i_fsize;
4924                         break;
4925                     default:
4926                         frag = fsize = 0;
4927                 }
4928
4929                 if (inode->i_faddr || frag || fsize ||
4930                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4931                         mark_inode_bad(ctx, ino);
4932                 if (inode->i_flags & EXT2_IMAGIC_FL) {
4933                         if (imagic_fs) {
4934                                 if (!ctx->inode_imagic_map)
4935                                         alloc_imagic_map(ctx);
4936                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4937                                                          ino);
4938                         } else {
4939                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4940                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
4941                                         e2fsck_write_inode(ctx, ino,
4942                                                            inode, "pass1");
4943                                 }
4944                         }
4945                 }
4946
4947                 check_inode_extra_space(ctx, &pctx);
4948
4949                 if (LINUX_S_ISDIR(inode->i_mode)) {
4950                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
4951                         e2fsck_add_dir_info(ctx, ino, 0);
4952                         ctx->fs_directory_count++;
4953                 } else if (LINUX_S_ISREG (inode->i_mode)) {
4954                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
4955                         ctx->fs_regular_count++;
4956                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
4957                            e2fsck_pass1_check_device_inode(fs, inode)) {
4958                         check_immutable(ctx, &pctx);
4959                         check_size(ctx, &pctx);
4960                         ctx->fs_chardev_count++;
4961                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
4962                            e2fsck_pass1_check_device_inode(fs, inode)) {
4963                         check_immutable(ctx, &pctx);
4964                         check_size(ctx, &pctx);
4965                         ctx->fs_blockdev_count++;
4966                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
4967                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
4968                         check_immutable(ctx, &pctx);
4969                         ctx->fs_symlinks_count++;
4970                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
4971                                 ctx->fs_fast_symlinks_count++;
4972                                 check_blocks(ctx, &pctx, block_buf);
4973                                 continue;
4974                         }
4975                 }
4976                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
4977                          e2fsck_pass1_check_device_inode(fs, inode)) {
4978                         check_immutable(ctx, &pctx);
4979                         check_size(ctx, &pctx);
4980                         ctx->fs_fifo_count++;
4981                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
4982                            e2fsck_pass1_check_device_inode(fs, inode)) {
4983                         check_immutable(ctx, &pctx);
4984                         check_size(ctx, &pctx);
4985                         ctx->fs_sockets_count++;
4986                 } else
4987                         mark_inode_bad(ctx, ino);
4988                 if (inode->i_block[EXT2_IND_BLOCK])
4989                         ctx->fs_ind_count++;
4990                 if (inode->i_block[EXT2_DIND_BLOCK])
4991                         ctx->fs_dind_count++;
4992                 if (inode->i_block[EXT2_TIND_BLOCK])
4993                         ctx->fs_tind_count++;
4994                 if (inode->i_block[EXT2_IND_BLOCK] ||
4995                     inode->i_block[EXT2_DIND_BLOCK] ||
4996                     inode->i_block[EXT2_TIND_BLOCK] ||
4997                     inode->i_file_acl) {
4998                         inodes_to_process[process_inode_count].ino = ino;
4999                         inodes_to_process[process_inode_count].inode = *inode;
5000                         process_inode_count++;
5001                 } else
5002                         check_blocks(ctx, &pctx, block_buf);
5003
5004                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5005                         return;
5006
5007                 if (process_inode_count >= ctx->process_inode_size) {
5008                         process_inodes(ctx, block_buf);
5009
5010                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5011                                 return;
5012                 }
5013         }
5014         process_inodes(ctx, block_buf);
5015         ext2fs_close_inode_scan(scan);
5016         ehandler_operation(0);
5017
5018         /*
5019          * If any extended attribute blocks' reference counts need to
5020          * be adjusted, either up (ctx->refcount_extra), or down
5021          * (ctx->refcount), then fix them.
5022          */
5023         if (ctx->refcount) {
5024                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5025                 ea_refcount_free(ctx->refcount);
5026                 ctx->refcount = 0;
5027         }
5028         if (ctx->refcount_extra) {
5029                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5030                                         block_buf, +1);
5031                 ea_refcount_free(ctx->refcount_extra);
5032                 ctx->refcount_extra = 0;
5033         }
5034
5035         if (ctx->invalid_bitmaps)
5036                 handle_fs_bad_blocks(ctx);
5037
5038         /* We don't need the block_ea_map any more */
5039         ext2fs_free_block_bitmap(ctx->block_ea_map);
5040         ctx->block_ea_map = 0;
5041
5042         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5043                 ext2fs_block_bitmap save_bmap;
5044
5045                 save_bmap = fs->block_map;
5046                 fs->block_map = ctx->block_found_map;
5047                 clear_problem_context(&pctx);
5048                 pctx.errcode = ext2fs_create_resize_inode(fs);
5049                 if (pctx.errcode) {
5050                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5051                         /* Should never get here */
5052                         ctx->flags |= E2F_FLAG_ABORT;
5053                         return;
5054                 }
5055                 fs->block_map = save_bmap;
5056                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5057         }
5058
5059         if (ctx->flags & E2F_FLAG_RESTART) {
5060                 /*
5061                  * Only the master copy of the superblock and block
5062                  * group descriptors are going to be written during a
5063                  * restart, so set the superblock to be used to be the
5064                  * master superblock.
5065                  */
5066                 ctx->use_superblock = 0;
5067                 unwind_pass1();
5068                 goto endit;
5069         }
5070
5071         if (ctx->block_dup_map) {
5072                 if (ctx->options & E2F_OPT_PREEN) {
5073                         clear_problem_context(&pctx);
5074                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5075                 }
5076                 e2fsck_pass1_dupblocks(ctx, block_buf);
5077         }
5078         ext2fs_free_mem(&inodes_to_process);
5079 endit:
5080         e2fsck_use_inode_shortcuts(ctx, 0);
5081
5082         ext2fs_free_mem(&block_buf);
5083         ext2fs_free_mem(&inode);
5084
5085 #ifdef RESOURCE_TRACK
5086         if (ctx->options & E2F_OPT_TIME2) {
5087                 e2fsck_clear_progbar(ctx);
5088                 print_resource_track(_("Pass 1"), &rtrack);
5089         }
5090 #endif
5091 }
5092
5093 /*
5094  * When the inode_scan routines call this callback at the end of the
5095  * glock group, call process_inodes.
5096  */
5097 static errcode_t scan_callback(ext2_filsys fs,
5098                                ext2_inode_scan scan FSCK_ATTR((unused)),
5099                                dgrp_t group, void * priv_data)
5100 {
5101         struct scan_callback_struct *scan_struct;
5102         e2fsck_t ctx;
5103
5104         scan_struct = (struct scan_callback_struct *) priv_data;
5105         ctx = scan_struct->ctx;
5106
5107         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5108
5109         if (ctx->progress)
5110                 if ((ctx->progress)(ctx, 1, group+1,
5111                                     ctx->fs->group_desc_count))
5112                         return EXT2_ET_CANCEL_REQUESTED;
5113
5114         return 0;
5115 }
5116
5117 /*
5118  * Process the inodes in the "inodes to process" list.
5119  */
5120 static void process_inodes(e2fsck_t ctx, char *block_buf)
5121 {
5122         int                     i;
5123         struct ext2_inode       *old_stashed_inode;
5124         ext2_ino_t              old_stashed_ino;
5125         const char              *old_operation;
5126         char                    buf[80];
5127         struct problem_context  pctx;
5128
5129 #if 0
5130         printf("begin process_inodes: ");
5131 #endif
5132         if (process_inode_count == 0)
5133                 return;
5134         old_operation = ehandler_operation(0);
5135         old_stashed_inode = ctx->stashed_inode;
5136         old_stashed_ino = ctx->stashed_ino;
5137         qsort(inodes_to_process, process_inode_count,
5138                       sizeof(struct process_inode_block), process_inode_cmp);
5139         clear_problem_context(&pctx);
5140         for (i=0; i < process_inode_count; i++) {
5141                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5142                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5143
5144 #if 0
5145                 printf("%u ", pctx.ino);
5146 #endif
5147                 sprintf(buf, _("reading indirect blocks of inode %u"),
5148                         pctx.ino);
5149                 ehandler_operation(buf);
5150                 check_blocks(ctx, &pctx, block_buf);
5151                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5152                         break;
5153         }
5154         ctx->stashed_inode = old_stashed_inode;
5155         ctx->stashed_ino = old_stashed_ino;
5156         process_inode_count = 0;
5157 #if 0
5158         printf("end process inodes\n");
5159 #endif
5160         ehandler_operation(old_operation);
5161 }
5162
5163 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5164 {
5165         const struct process_inode_block *ib_a =
5166                 (const struct process_inode_block *) a;
5167         const struct process_inode_block *ib_b =
5168                 (const struct process_inode_block *) b;
5169         int     ret;
5170
5171         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5172                ib_b->inode.i_block[EXT2_IND_BLOCK]);
5173         if (ret == 0)
5174                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5175         return ret;
5176 }
5177
5178 /*
5179  * Mark an inode as being bad in some what
5180  */
5181 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5182 {
5183         struct          problem_context pctx;
5184
5185         if (!ctx->inode_bad_map) {
5186                 clear_problem_context(&pctx);
5187
5188                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5189                             _("bad inode map"), &ctx->inode_bad_map);
5190                 if (pctx.errcode) {
5191                         pctx.num = 3;
5192                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5193                         /* Should never get here */
5194                         ctx->flags |= E2F_FLAG_ABORT;
5195                         return;
5196                 }
5197         }
5198         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5199 }
5200
5201
5202 /*
5203  * This procedure will allocate the inode "bb" (badblock) map table
5204  */
5205 static void alloc_bb_map(e2fsck_t ctx)
5206 {
5207         struct          problem_context pctx;
5208
5209         clear_problem_context(&pctx);
5210         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5211                                               _("inode in bad block map"),
5212                                               &ctx->inode_bb_map);
5213         if (pctx.errcode) {
5214                 pctx.num = 4;
5215                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5216                 /* Should never get here */
5217                 ctx->flags |= E2F_FLAG_ABORT;
5218                 return;
5219         }
5220 }
5221
5222 /*
5223  * This procedure will allocate the inode imagic table
5224  */
5225 static void alloc_imagic_map(e2fsck_t ctx)
5226 {
5227         struct          problem_context pctx;
5228
5229         clear_problem_context(&pctx);
5230         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5231                                               _("imagic inode map"),
5232                                               &ctx->inode_imagic_map);
5233         if (pctx.errcode) {
5234                 pctx.num = 5;
5235                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5236                 /* Should never get here */
5237                 ctx->flags |= E2F_FLAG_ABORT;
5238                 return;
5239         }
5240 }
5241
5242 /*
5243  * Marks a block as in use, setting the dup_map if it's been set
5244  * already.  Called by process_block and process_bad_block.
5245  *
5246  * WARNING: Assumes checks have already been done to make sure block
5247  * is valid.  This is true in both process_block and process_bad_block.
5248  */
5249 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5250 {
5251         struct          problem_context pctx;
5252
5253         clear_problem_context(&pctx);
5254
5255         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5256                 if (!ctx->block_dup_map) {
5257                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5258                               _("multiply claimed block map"),
5259                               &ctx->block_dup_map);
5260                         if (pctx.errcode) {
5261                                 pctx.num = 3;
5262                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5263                                             &pctx);
5264                                 /* Should never get here */
5265                                 ctx->flags |= E2F_FLAG_ABORT;
5266                                 return;
5267                         }
5268                 }
5269                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5270         } else {
5271                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5272         }
5273 }
5274
5275 /*
5276  * Adjust the extended attribute block's reference counts at the end
5277  * of pass 1, either by subtracting out references for EA blocks that
5278  * are still referenced in ctx->refcount, or by adding references for
5279  * EA blocks that had extra references as accounted for in
5280  * ctx->refcount_extra.
5281  */
5282 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5283                                     char *block_buf, int adjust_sign)
5284 {
5285         struct ext2_ext_attr_header     *header;
5286         struct problem_context          pctx;
5287         ext2_filsys                     fs = ctx->fs;
5288         blk_t                           blk;
5289         __u32                           should_be;
5290         int                             count;
5291
5292         clear_problem_context(&pctx);
5293
5294         ea_refcount_intr_begin(refcount);
5295         while (1) {
5296                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5297                         break;
5298                 pctx.blk = blk;
5299                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5300                 if (pctx.errcode) {
5301                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5302                         return;
5303                 }
5304                 header = (struct ext2_ext_attr_header *) block_buf;
5305                 pctx.blkcount = header->h_refcount;
5306                 should_be = header->h_refcount + adjust_sign * count;
5307                 pctx.num = should_be;
5308                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5309                         header->h_refcount = should_be;
5310                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5311                                                              block_buf);
5312                         if (pctx.errcode) {
5313                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5314                                 continue;
5315                         }
5316                 }
5317         }
5318 }
5319
5320 /*
5321  * Handle processing the extended attribute blocks
5322  */
5323 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5324                            char *block_buf)
5325 {
5326         ext2_filsys fs = ctx->fs;
5327         ext2_ino_t      ino = pctx->ino;
5328         struct ext2_inode *inode = pctx->inode;
5329         blk_t           blk;
5330         char *          end;
5331         struct ext2_ext_attr_header *header;
5332         struct ext2_ext_attr_entry *entry;
5333         int             count;
5334         region_t        region;
5335
5336         blk = inode->i_file_acl;
5337         if (blk == 0)
5338                 return 0;
5339
5340         /*
5341          * If the Extended attribute flag isn't set, then a non-zero
5342          * file acl means that the inode is corrupted.
5343          *
5344          * Or if the extended attribute block is an invalid block,
5345          * then the inode is also corrupted.
5346          */
5347         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5348             (blk < fs->super->s_first_data_block) ||
5349             (blk >= fs->super->s_blocks_count)) {
5350                 mark_inode_bad(ctx, ino);
5351                 return 0;
5352         }
5353
5354         /* If ea bitmap hasn't been allocated, create it */
5355         if (!ctx->block_ea_map) {
5356                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5357                                                       _("ext attr block map"),
5358                                                       &ctx->block_ea_map);
5359                 if (pctx->errcode) {
5360                         pctx->num = 2;
5361                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5362                         ctx->flags |= E2F_FLAG_ABORT;
5363                         return 0;
5364                 }
5365         }
5366
5367         /* Create the EA refcount structure if necessary */
5368         if (!ctx->refcount) {
5369                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5370                 if (pctx->errcode) {
5371                         pctx->num = 1;
5372                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5373                         ctx->flags |= E2F_FLAG_ABORT;
5374                         return 0;
5375                 }
5376         }
5377
5378 #if 0
5379         /* Debugging text */
5380         printf("Inode %u has EA block %u\n", ino, blk);
5381 #endif
5382
5383         /* Have we seen this EA block before? */
5384         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5385                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5386                         return 1;
5387                 /* Ooops, this EA was referenced more than it stated */
5388                 if (!ctx->refcount_extra) {
5389                         pctx->errcode = ea_refcount_create(0,
5390                                            &ctx->refcount_extra);
5391                         if (pctx->errcode) {
5392                                 pctx->num = 2;
5393                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5394                                 ctx->flags |= E2F_FLAG_ABORT;
5395                                 return 0;
5396                         }
5397                 }
5398                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5399                 return 1;
5400         }
5401
5402         /*
5403          * OK, we haven't seen this EA block yet.  So we need to
5404          * validate it
5405          */
5406         pctx->blk = blk;
5407         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5408         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5409                 goto clear_extattr;
5410         header = (struct ext2_ext_attr_header *) block_buf;
5411         pctx->blk = inode->i_file_acl;
5412         if (((ctx->ext_attr_ver == 1) &&
5413              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5414             ((ctx->ext_attr_ver == 2) &&
5415              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5416                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5417                         goto clear_extattr;
5418         }
5419
5420         if (header->h_blocks != 1) {
5421                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5422                         goto clear_extattr;
5423         }
5424
5425         region = region_create(0, fs->blocksize);
5426         if (!region) {
5427                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5428                 ctx->flags |= E2F_FLAG_ABORT;
5429                 return 0;
5430         }
5431         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5432                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5433                         goto clear_extattr;
5434         }
5435
5436         entry = (struct ext2_ext_attr_entry *)(header+1);
5437         end = block_buf + fs->blocksize;
5438         while ((char *)entry < end && *(__u32 *)entry) {
5439                 if (region_allocate(region, (char *)entry - (char *)header,
5440                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5441                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5442                                 goto clear_extattr;
5443                 }
5444                 if ((ctx->ext_attr_ver == 1 &&
5445                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5446                     (ctx->ext_attr_ver == 2 &&
5447                      entry->e_name_index == 0)) {
5448                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5449                                 goto clear_extattr;
5450                 }
5451                 if (entry->e_value_block != 0) {
5452                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5453                                 goto clear_extattr;
5454                 }
5455                 if (entry->e_value_size &&
5456                     region_allocate(region, entry->e_value_offs,
5457                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5458                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5459                                 goto clear_extattr;
5460                 }
5461                 entry = EXT2_EXT_ATTR_NEXT(entry);
5462         }
5463         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5464                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5465                         goto clear_extattr;
5466         }
5467         region_free(region);
5468
5469         count = header->h_refcount - 1;
5470         if (count)
5471                 ea_refcount_store(ctx->refcount, blk, count);
5472         mark_block_used(ctx, blk);
5473         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5474
5475         return 1;
5476
5477 clear_extattr:
5478         inode->i_file_acl = 0;
5479         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5480         return 0;
5481 }
5482
5483 /* Returns 1 if bad htree, 0 if OK */
5484 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5485                         ext2_ino_t ino FSCK_ATTR((unused)),
5486                         struct ext2_inode *inode,
5487                         char *block_buf)
5488 {
5489         struct ext2_dx_root_info        *root;
5490         ext2_filsys                     fs = ctx->fs;
5491         errcode_t                       retval;
5492         blk_t                           blk;
5493
5494         if ((!LINUX_S_ISDIR(inode->i_mode) &&
5495              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5496             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5497              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5498                 return 1;
5499
5500         blk = inode->i_block[0];
5501         if (((blk == 0) ||
5502              (blk < fs->super->s_first_data_block) ||
5503              (blk >= fs->super->s_blocks_count)) &&
5504             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5505                 return 1;
5506
5507         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5508         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5509                 return 1;
5510
5511         /* XXX should check that beginning matches a directory */
5512         root = (struct ext2_dx_root_info *) (block_buf + 24);
5513
5514         if ((root->reserved_zero || root->info_length < 8) &&
5515             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5516                 return 1;
5517
5518         pctx->num = root->hash_version;
5519         if ((root->hash_version != EXT2_HASH_LEGACY) &&
5520             (root->hash_version != EXT2_HASH_HALF_MD4) &&
5521             (root->hash_version != EXT2_HASH_TEA) &&
5522             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5523                 return 1;
5524
5525         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5526             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5527                 return 1;
5528
5529         pctx->num = root->indirect_levels;
5530         if ((root->indirect_levels > 1) &&
5531             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5532                 return 1;
5533
5534         return 0;
5535 }
5536
5537 /*
5538  * This subroutine is called on each inode to account for all of the
5539  * blocks used by that inode.
5540  */
5541 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5542                          char *block_buf)
5543 {
5544         ext2_filsys fs = ctx->fs;
5545         struct process_block_struct_1 pb;
5546         ext2_ino_t      ino = pctx->ino;
5547         struct ext2_inode *inode = pctx->inode;
5548         int             bad_size = 0;
5549         int             dirty_inode = 0;
5550         __u64           size;
5551
5552         pb.ino = ino;
5553         pb.num_blocks = 0;
5554         pb.last_block = -1;
5555         pb.num_illegal_blocks = 0;
5556         pb.suppress = 0; pb.clear = 0;
5557         pb.fragmented = 0;
5558         pb.compressed = 0;
5559         pb.previous_block = 0;
5560         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5561         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5562         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5563         pb.inode = inode;
5564         pb.pctx = pctx;
5565         pb.ctx = ctx;
5566         pctx->ino = ino;
5567         pctx->errcode = 0;
5568
5569         if (inode->i_flags & EXT2_COMPRBLK_FL) {
5570                 if (fs->super->s_feature_incompat &
5571                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
5572                         pb.compressed = 1;
5573                 else {
5574                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5575                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5576                                 dirty_inode++;
5577                         }
5578                 }
5579         }
5580
5581         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5582                 pb.num_blocks++;
5583
5584         if (ext2fs_inode_has_valid_blocks(inode))
5585                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5586                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5587                                        block_buf, process_block, &pb);
5588         end_problem_latch(ctx, PR_LATCH_BLOCK);
5589         end_problem_latch(ctx, PR_LATCH_TOOBIG);
5590         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5591                 goto out;
5592         if (pctx->errcode)
5593                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5594
5595         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5596                 ctx->fs_fragmented++;
5597
5598         if (pb.clear) {
5599                 inode->i_links_count = 0;
5600                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5601                 inode->i_dtime = time(0);
5602                 dirty_inode++;
5603                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5604                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5605                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5606                 /*
5607                  * The inode was probably partially accounted for
5608                  * before processing was aborted, so we need to
5609                  * restart the pass 1 scan.
5610                  */
5611                 ctx->flags |= E2F_FLAG_RESTART;
5612                 goto out;
5613         }
5614
5615         if (inode->i_flags & EXT2_INDEX_FL) {
5616                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5617                         inode->i_flags &= ~EXT2_INDEX_FL;
5618                         dirty_inode++;
5619                 } else {
5620 #ifdef ENABLE_HTREE
5621                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5622 #endif
5623                 }
5624         }
5625         if (ctx->dirs_to_hash && pb.is_dir &&
5626             !(inode->i_flags & EXT2_INDEX_FL) &&
5627             ((inode->i_size / fs->blocksize) >= 3))
5628                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5629
5630         if (!pb.num_blocks && pb.is_dir) {
5631                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5632                         inode->i_links_count = 0;
5633                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5634                         inode->i_dtime = time(0);
5635                         dirty_inode++;
5636                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5637                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5638                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5639                         ctx->fs_directory_count--;
5640                         goto out;
5641                 }
5642         }
5643
5644         pb.num_blocks *= (fs->blocksize / 512);
5645 #if 0
5646         printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5647                ino, inode->i_size, pb.last_block, inode->i_blocks,
5648                pb.num_blocks);
5649 #endif
5650         if (pb.is_dir) {
5651                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5652                 if (nblock > (pb.last_block + 1))
5653                         bad_size = 1;
5654                 else if (nblock < (pb.last_block + 1)) {
5655                         if (((pb.last_block + 1) - nblock) >
5656                             fs->super->s_prealloc_dir_blocks)
5657                                 bad_size = 2;
5658                 }
5659         } else {
5660                 size = EXT2_I_SIZE(inode);
5661                 if ((pb.last_block >= 0) &&
5662                     (size < (__u64) pb.last_block * fs->blocksize))
5663                         bad_size = 3;
5664                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5665                         bad_size = 4;
5666         }
5667         /* i_size for symlinks is checked elsewhere */
5668         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5669                 pctx->num = (pb.last_block+1) * fs->blocksize;
5670                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5671                         inode->i_size = pctx->num;
5672                         if (!LINUX_S_ISDIR(inode->i_mode))
5673                                 inode->i_size_high = pctx->num >> 32;
5674                         dirty_inode++;
5675                 }
5676                 pctx->num = 0;
5677         }
5678         if (LINUX_S_ISREG(inode->i_mode) &&
5679             (inode->i_size_high || inode->i_size & 0x80000000UL))
5680                 ctx->large_files++;
5681         if (pb.num_blocks != inode->i_blocks) {
5682                 pctx->num = pb.num_blocks;
5683                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5684                         inode->i_blocks = pb.num_blocks;
5685                         dirty_inode++;
5686                 }
5687                 pctx->num = 0;
5688         }
5689 out:
5690         if (dirty_inode)
5691                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5692 }
5693
5694 #if 0
5695 /*
5696  * Helper function called by process block when an illegal block is
5697  * found.  It returns a description about why the block is illegal
5698  */
5699 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5700 {
5701         blk_t   super;
5702         int     i;
5703         static char     problem[80];
5704
5705         super = fs->super->s_first_data_block;
5706         strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5707         if (block < super) {
5708                 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5709                 return(problem);
5710         } else if (block >= fs->super->s_blocks_count) {
5711                 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5712                 return(problem);
5713         }
5714         for (i = 0; i < fs->group_desc_count; i++) {
5715                 if (block == super) {
5716                         sprintf(problem, "is the superblock in group %d", i);
5717                         break;
5718                 }
5719                 if (block > super &&
5720                     block <= (super + fs->desc_blocks)) {
5721                         sprintf(problem, "is in the group descriptors "
5722                                 "of group %d", i);
5723                         break;
5724                 }
5725                 if (block == fs->group_desc[i].bg_block_bitmap) {
5726                         sprintf(problem, "is the block bitmap of group %d", i);
5727                         break;
5728                 }
5729                 if (block == fs->group_desc[i].bg_inode_bitmap) {
5730                         sprintf(problem, "is the inode bitmap of group %d", i);
5731                         break;
5732                 }
5733                 if (block >= fs->group_desc[i].bg_inode_table &&
5734                     (block < fs->group_desc[i].bg_inode_table
5735                      + fs->inode_blocks_per_group)) {
5736                         sprintf(problem, "is in the inode table of group %d",
5737                                 i);
5738                         break;
5739                 }
5740                 super += fs->super->s_blocks_per_group;
5741         }
5742         return(problem);
5743 }
5744 #endif
5745
5746 /*
5747  * This is a helper function for check_blocks().
5748  */
5749 static int process_block(ext2_filsys fs,
5750                   blk_t *block_nr,
5751                   e2_blkcnt_t blockcnt,
5752                   blk_t ref_block FSCK_ATTR((unused)),
5753                   int ref_offset FSCK_ATTR((unused)),
5754                   void *priv_data)
5755 {
5756         struct process_block_struct_1 *p;
5757         struct problem_context *pctx;
5758         blk_t   blk = *block_nr;
5759         int     ret_code = 0;
5760         int     problem = 0;
5761         e2fsck_t        ctx;
5762
5763         p = (struct process_block_struct_1 *) priv_data;
5764         pctx = p->pctx;
5765         ctx = p->ctx;
5766
5767         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5768                 /* todo: Check that the comprblk_fl is high, that the
5769                    blkaddr pattern looks right (all non-holes up to
5770                    first EXT2FS_COMPRESSED_BLKADDR, then all
5771                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5772                    that the feature_incompat bit is high, and that the
5773                    inode is a regular file.  If we're doing a "full
5774                    check" (a concept introduced to e2fsck by e2compr,
5775                    meaning that we look at data blocks as well as
5776                    metadata) then call some library routine that
5777                    checks the compressed data.  I'll have to think
5778                    about this, because one particularly important
5779                    problem to be able to fix is to recalculate the
5780                    cluster size if necessary.  I think that perhaps
5781                    we'd better do most/all e2compr-specific checks
5782                    separately, after the non-e2compr checks.  If not
5783                    doing a full check, it may be useful to test that
5784                    the personality is linux; e.g. if it isn't then
5785                    perhaps this really is just an illegal block. */
5786                 return 0;
5787         }
5788
5789         if (blk == 0) {
5790                 if (p->is_dir == 0) {
5791                         /*
5792                          * Should never happen, since only directories
5793                          * get called with BLOCK_FLAG_HOLE
5794                          */
5795 #if DEBUG_E2FSCK
5796                         printf("process_block() called with blk == 0, "
5797                                "blockcnt=%d, inode %lu???\n",
5798                                blockcnt, p->ino);
5799 #endif
5800                         return 0;
5801                 }
5802                 if (blockcnt < 0)
5803                         return 0;
5804                 if (blockcnt * fs->blocksize < p->inode->i_size) {
5805 #if 0
5806                         printf("Missing block (#%d) in directory inode %lu!\n",
5807                                blockcnt, p->ino);
5808 #endif
5809                         goto mark_dir;
5810                 }
5811                 return 0;
5812         }
5813
5814 #if 0
5815         printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5816                blockcnt);
5817 #endif
5818
5819         /*
5820          * Simplistic fragmentation check.  We merely require that the
5821          * file be contiguous.  (Which can never be true for really
5822          * big files that are greater than a block group.)
5823          */
5824         if (!HOLE_BLKADDR(p->previous_block)) {
5825                 if (p->previous_block+1 != blk)
5826                         p->fragmented = 1;
5827         }
5828         p->previous_block = blk;
5829
5830         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5831                 problem = PR_1_TOOBIG_DIR;
5832         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5833                 problem = PR_1_TOOBIG_REG;
5834         if (!p->is_dir && !p->is_reg && blockcnt > 0)
5835                 problem = PR_1_TOOBIG_SYMLINK;
5836
5837         if (blk < fs->super->s_first_data_block ||
5838             blk >= fs->super->s_blocks_count)
5839                 problem = PR_1_ILLEGAL_BLOCK_NUM;
5840
5841         if (problem) {
5842                 p->num_illegal_blocks++;
5843                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5844                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5845                                 p->clear = 1;
5846                                 return BLOCK_ABORT;
5847                         }
5848                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5849                                 p->suppress = 1;
5850                                 set_latch_flags(PR_LATCH_BLOCK,
5851                                                 PRL_SUPPRESS, 0);
5852                         }
5853                 }
5854                 pctx->blk = blk;
5855                 pctx->blkcount = blockcnt;
5856                 if (fix_problem(ctx, problem, pctx)) {
5857                         blk = *block_nr = 0;
5858                         ret_code = BLOCK_CHANGED;
5859                         goto mark_dir;
5860                 } else
5861                         return 0;
5862         }
5863
5864         if (p->ino == EXT2_RESIZE_INO) {
5865                 /*
5866                  * The resize inode has already be sanity checked
5867                  * during pass #0 (the superblock checks).  All we
5868                  * have to do is mark the double indirect block as
5869                  * being in use; all of the other blocks are handled
5870                  * by mark_table_blocks()).
5871                  */
5872                 if (blockcnt == BLOCK_COUNT_DIND)
5873                         mark_block_used(ctx, blk);
5874         } else
5875                 mark_block_used(ctx, blk);
5876         p->num_blocks++;
5877         if (blockcnt >= 0)
5878                 p->last_block = blockcnt;
5879 mark_dir:
5880         if (p->is_dir && (blockcnt >= 0)) {
5881                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5882                                                     blk, blockcnt);
5883                 if (pctx->errcode) {
5884                         pctx->blk = blk;
5885                         pctx->num = blockcnt;
5886                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5887                         /* Should never get here */
5888                         ctx->flags |= E2F_FLAG_ABORT;
5889                         return BLOCK_ABORT;
5890                 }
5891         }
5892         return ret_code;
5893 }
5894
5895 static int process_bad_block(ext2_filsys fs,
5896                       blk_t *block_nr,
5897                       e2_blkcnt_t blockcnt,
5898                       blk_t ref_block FSCK_ATTR((unused)),
5899                       int ref_offset FSCK_ATTR((unused)),
5900                       void *priv_data)
5901 {
5902         struct process_block_struct_1 *p;
5903         blk_t           blk = *block_nr;
5904         blk_t           first_block;
5905         dgrp_t          i;
5906         struct problem_context *pctx;
5907         e2fsck_t        ctx;
5908
5909         /*
5910          * Note: This function processes blocks for the bad blocks
5911          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
5912          */
5913
5914         if (!blk)
5915                 return 0;
5916
5917         p = (struct process_block_struct_1 *) priv_data;
5918         ctx = p->ctx;
5919         pctx = p->pctx;
5920
5921         pctx->ino = EXT2_BAD_INO;
5922         pctx->blk = blk;
5923         pctx->blkcount = blockcnt;
5924
5925         if ((blk < fs->super->s_first_data_block) ||
5926             (blk >= fs->super->s_blocks_count)) {
5927                 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5928                         *block_nr = 0;
5929                         return BLOCK_CHANGED;
5930                 } else
5931                         return 0;
5932         }
5933
5934         if (blockcnt < 0) {
5935                 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5936                         p->bbcheck = 1;
5937                         if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5938                                 *block_nr = 0;
5939                                 return BLOCK_CHANGED;
5940                         }
5941                 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5942                                                     blk)) {
5943                         p->bbcheck = 1;
5944                         if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5945                                         pctx)) {
5946                                 *block_nr = 0;
5947                                 return BLOCK_CHANGED;
5948                         }
5949                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5950                                 return BLOCK_ABORT;
5951                 } else
5952                         mark_block_used(ctx, blk);
5953                 return 0;
5954         }
5955 #if 0
5956         printf ("DEBUG: Marking %u as bad.\n", blk);
5957 #endif
5958         ctx->fs_badblocks_count++;
5959         /*
5960          * If the block is not used, then mark it as used and return.
5961          * If it is already marked as found, this must mean that
5962          * there's an overlap between the filesystem table blocks
5963          * (bitmaps and inode table) and the bad block list.
5964          */
5965         if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
5966                 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
5967                 return 0;
5968         }
5969         /*
5970          * Try to find the where the filesystem block was used...
5971          */
5972         first_block = fs->super->s_first_data_block;
5973
5974         for (i = 0; i < fs->group_desc_count; i++ ) {
5975                 pctx->group = i;
5976                 pctx->blk = blk;
5977                 if (!ext2fs_bg_has_super(fs, i))
5978                         goto skip_super;
5979                 if (blk == first_block) {
5980                         if (i == 0) {
5981                                 if (fix_problem(ctx,
5982                                                 PR_1_BAD_PRIMARY_SUPERBLOCK,
5983                                                 pctx)) {
5984                                         *block_nr = 0;
5985                                         return BLOCK_CHANGED;
5986                                 }
5987                                 return 0;
5988                         }
5989                         fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
5990                         return 0;
5991                 }
5992                 if ((blk > first_block) &&
5993                     (blk <= first_block + fs->desc_blocks)) {
5994                         if (i == 0) {
5995                                 pctx->blk = *block_nr;
5996                                 if (fix_problem(ctx,
5997                         PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
5998                                         *block_nr = 0;
5999                                         return BLOCK_CHANGED;
6000                                 }
6001                                 return 0;
6002                         }
6003                         fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6004                         return 0;
6005                 }
6006         skip_super:
6007                 if (blk == fs->group_desc[i].bg_block_bitmap) {
6008                         if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6009                                 ctx->invalid_block_bitmap_flag[i]++;
6010                                 ctx->invalid_bitmaps++;
6011                         }
6012                         return 0;
6013                 }
6014                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6015                         if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6016                                 ctx->invalid_inode_bitmap_flag[i]++;
6017                                 ctx->invalid_bitmaps++;
6018                         }
6019                         return 0;
6020                 }
6021                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6022                     (blk < (fs->group_desc[i].bg_inode_table +
6023                             fs->inode_blocks_per_group))) {
6024                         /*
6025                          * If there are bad blocks in the inode table,
6026                          * the inode scan code will try to do
6027                          * something reasonable automatically.
6028                          */
6029                         return 0;
6030                 }
6031                 first_block += fs->super->s_blocks_per_group;
6032         }
6033         /*
6034          * If we've gotten to this point, then the only
6035          * possibility is that the bad block inode meta data
6036          * is using a bad block.
6037          */
6038         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6039             (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6040             (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6041                 p->bbcheck = 1;
6042                 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6043                         *block_nr = 0;
6044                         return BLOCK_CHANGED;
6045                 }
6046                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6047                         return BLOCK_ABORT;
6048                 return 0;
6049         }
6050
6051         pctx->group = -1;
6052
6053         /* Warn user that the block wasn't claimed */
6054         fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6055
6056         return 0;
6057 }
6058
6059 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6060                             const char *name, int num, blk_t *new_block)
6061 {
6062         ext2_filsys fs = ctx->fs;
6063         blk_t           old_block = *new_block;
6064         int             i;
6065         char            *buf;
6066         struct problem_context  pctx;
6067
6068         clear_problem_context(&pctx);
6069
6070         pctx.group = group;
6071         pctx.blk = old_block;
6072         pctx.str = name;
6073
6074         pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6075                         first_block + fs->super->s_blocks_per_group,
6076                                         num, ctx->block_found_map, new_block);
6077         if (pctx.errcode) {
6078                 pctx.num = num;
6079                 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6080                 ext2fs_unmark_valid(fs);
6081                 return;
6082         }
6083         pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6084         if (pctx.errcode) {
6085                 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6086                 ext2fs_unmark_valid(fs);
6087                 return;
6088         }
6089         ext2fs_mark_super_dirty(fs);
6090         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6091         pctx.blk2 = *new_block;
6092         fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6093                           PR_1_RELOC_TO), &pctx);
6094         pctx.blk2 = 0;
6095         for (i = 0; i < num; i++) {
6096                 pctx.blk = i;
6097                 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6098                 if (old_block) {
6099                         pctx.errcode = io_channel_read_blk(fs->io,
6100                                    old_block + i, 1, buf);
6101                         if (pctx.errcode)
6102                                 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6103                 } else
6104                         memset(buf, 0, fs->blocksize);
6105
6106                 pctx.blk = (*new_block) + i;
6107                 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6108                                               1, buf);
6109                 if (pctx.errcode)
6110                         fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6111         }
6112         ext2fs_free_mem(&buf);
6113 }
6114
6115 /*
6116  * This routine gets called at the end of pass 1 if bad blocks are
6117  * detected in the superblock, group descriptors, inode_bitmaps, or
6118  * block bitmaps.  At this point, all of the blocks have been mapped
6119  * out, so we can try to allocate new block(s) to replace the bad
6120  * blocks.
6121  */
6122 static void handle_fs_bad_blocks(e2fsck_t ctx)
6123 {
6124         ext2_filsys fs = ctx->fs;
6125         dgrp_t          i;
6126         int             first_block = fs->super->s_first_data_block;
6127
6128         for (i = 0; i < fs->group_desc_count; i++) {
6129                 if (ctx->invalid_block_bitmap_flag[i]) {
6130                         new_table_block(ctx, first_block, i, _("block bitmap"),
6131                                         1, &fs->group_desc[i].bg_block_bitmap);
6132                 }
6133                 if (ctx->invalid_inode_bitmap_flag[i]) {
6134                         new_table_block(ctx, first_block, i, _("inode bitmap"),
6135                                         1, &fs->group_desc[i].bg_inode_bitmap);
6136                 }
6137                 if (ctx->invalid_inode_table_flag[i]) {
6138                         new_table_block(ctx, first_block, i, _("inode table"),
6139                                         fs->inode_blocks_per_group,
6140                                         &fs->group_desc[i].bg_inode_table);
6141                         ctx->flags |= E2F_FLAG_RESTART;
6142                 }
6143                 first_block += fs->super->s_blocks_per_group;
6144         }
6145         ctx->invalid_bitmaps = 0;
6146 }
6147
6148 /*
6149  * This routine marks all blocks which are used by the superblock,
6150  * group descriptors, inode bitmaps, and block bitmaps.
6151  */
6152 static void mark_table_blocks(e2fsck_t ctx)
6153 {
6154         ext2_filsys fs = ctx->fs;
6155         blk_t   block, b;
6156         dgrp_t  i;
6157         int     j;
6158         struct problem_context pctx;
6159
6160         clear_problem_context(&pctx);
6161
6162         block = fs->super->s_first_data_block;
6163         for (i = 0; i < fs->group_desc_count; i++) {
6164                 pctx.group = i;
6165
6166                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6167
6168                 /*
6169                  * Mark the blocks used for the inode table
6170                  */
6171                 if (fs->group_desc[i].bg_inode_table) {
6172                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
6173                              j < fs->inode_blocks_per_group;
6174                              j++, b++) {
6175                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6176                                                              b)) {
6177                                         pctx.blk = b;
6178                                         if (fix_problem(ctx,
6179                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
6180                                                 ctx->invalid_inode_table_flag[i]++;
6181                                                 ctx->invalid_bitmaps++;
6182                                         }
6183                                 } else {
6184                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
6185                                                              b);
6186                                 }
6187                         }
6188                 }
6189
6190                 /*
6191                  * Mark block used for the block bitmap
6192                  */
6193                 if (fs->group_desc[i].bg_block_bitmap) {
6194                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6195                                      fs->group_desc[i].bg_block_bitmap)) {
6196                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6197                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6198                                         ctx->invalid_block_bitmap_flag[i]++;
6199                                         ctx->invalid_bitmaps++;
6200                                 }
6201                         } else {
6202                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6203                                      fs->group_desc[i].bg_block_bitmap);
6204                     }
6205
6206                 }
6207                 /*
6208                  * Mark block used for the inode bitmap
6209                  */
6210                 if (fs->group_desc[i].bg_inode_bitmap) {
6211                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6212                                      fs->group_desc[i].bg_inode_bitmap)) {
6213                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6214                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6215                                         ctx->invalid_inode_bitmap_flag[i]++;
6216                                         ctx->invalid_bitmaps++;
6217                                 }
6218                         } else {
6219                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6220                                      fs->group_desc[i].bg_inode_bitmap);
6221                         }
6222                 }
6223                 block += fs->super->s_blocks_per_group;
6224         }
6225 }
6226
6227 /*
6228  * Thes subroutines short circuits ext2fs_get_blocks and
6229  * ext2fs_check_directory; we use them since we already have the inode
6230  * structure, so there's no point in letting the ext2fs library read
6231  * the inode again.
6232  */
6233 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6234                                   blk_t *blocks)
6235 {
6236         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6237         int     i;
6238
6239         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6240                 return EXT2_ET_CALLBACK_NOTHANDLED;
6241
6242         for (i=0; i < EXT2_N_BLOCKS; i++)
6243                 blocks[i] = ctx->stashed_inode->i_block[i];
6244         return 0;
6245 }
6246
6247 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6248                                   struct ext2_inode *inode)
6249 {
6250         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6251
6252         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6253                 return EXT2_ET_CALLBACK_NOTHANDLED;
6254         *inode = *ctx->stashed_inode;
6255         return 0;
6256 }
6257
6258 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6259                             struct ext2_inode *inode)
6260 {
6261         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6262
6263         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6264                 *ctx->stashed_inode = *inode;
6265         return EXT2_ET_CALLBACK_NOTHANDLED;
6266 }
6267
6268 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6269 {
6270         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6271
6272         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6273                 return EXT2_ET_CALLBACK_NOTHANDLED;
6274
6275         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6276                 return EXT2_ET_NO_DIRECTORY;
6277         return 0;
6278 }
6279
6280 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6281 {
6282         ext2_filsys fs = ctx->fs;
6283
6284         if (bool) {
6285                 fs->get_blocks = pass1_get_blocks;
6286                 fs->check_directory = pass1_check_directory;
6287                 fs->read_inode = pass1_read_inode;
6288                 fs->write_inode = pass1_write_inode;
6289                 ctx->stashed_ino = 0;
6290         } else {
6291                 fs->get_blocks = 0;
6292                 fs->check_directory = 0;
6293                 fs->read_inode = 0;
6294                 fs->write_inode = 0;
6295         }
6296 }
6297
6298 /*
6299  * pass1b.c --- Pass #1b of e2fsck
6300  *
6301  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
6302  * only invoked if pass 1 discovered blocks which are in use by more
6303  * than one inode.
6304  *
6305  * Pass1B scans the data blocks of all the inodes again, generating a
6306  * complete list of duplicate blocks and which inodes have claimed
6307  * them.
6308  *
6309  * Pass1C does a tree-traversal of the filesystem, to determine the
6310  * parent directories of these inodes.  This step is necessary so that
6311  * e2fsck can print out the pathnames of affected inodes.
6312  *
6313  * Pass1D is a reconciliation pass.  For each inode with duplicate
6314  * blocks, the user is prompted if s/he would like to clone the file
6315  * (so that the file gets a fresh copy of the duplicated blocks) or
6316  * simply to delete the file.
6317  *
6318  */
6319
6320
6321 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6322 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
6323 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
6324
6325 /* Define an extension to the ext2 library's block count information */
6326 #define BLOCK_COUNT_EXTATTR     (-5)
6327
6328 struct block_el {
6329         blk_t   block;
6330         struct block_el *next;
6331 };
6332
6333 struct inode_el {
6334         ext2_ino_t      inode;
6335         struct inode_el *next;
6336 };
6337
6338 struct dup_block {
6339         int             num_bad;
6340         struct inode_el *inode_list;
6341 };
6342
6343 /*
6344  * This structure stores information about a particular inode which
6345  * is sharing blocks with other inodes.  This information is collected
6346  * to display to the user, so that the user knows what files he or she
6347  * is dealing with, when trying to decide how to resolve the conflict
6348  * of multiply-claimed blocks.
6349  */
6350 struct dup_inode {
6351         ext2_ino_t              dir;
6352         int                     num_dupblocks;
6353         struct ext2_inode       inode;
6354         struct block_el         *block_list;
6355 };
6356
6357 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
6358                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
6359                                 int ref_offset, void *priv_data);
6360 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6361                         struct dup_inode *dp, char *block_buf);
6362 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6363                       struct dup_inode *dp, char* block_buf);
6364 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6365
6366 static void pass1b(e2fsck_t ctx, char *block_buf);
6367 static void pass1c(e2fsck_t ctx, char *block_buf);
6368 static void pass1d(e2fsck_t ctx, char *block_buf);
6369
6370 static int dup_inode_count = 0;
6371
6372 static dict_t blk_dict, ino_dict;
6373
6374 static ext2fs_inode_bitmap inode_dup_map;
6375
6376 static int dict_int_cmp(const void *a, const void *b)
6377 {
6378         intptr_t        ia, ib;
6379
6380         ia = (intptr_t)a;
6381         ib = (intptr_t)b;
6382
6383         return (ia-ib);
6384 }
6385
6386 /*
6387  * Add a duplicate block record
6388  */
6389 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6390                      struct ext2_inode *inode)
6391 {
6392         dnode_t *n;
6393         struct dup_block        *db;
6394         struct dup_inode        *di;
6395         struct block_el         *blk_el;
6396         struct inode_el         *ino_el;
6397
6398         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6399         if (n)
6400                 db = (struct dup_block *) dnode_get(n);
6401         else {
6402                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6403                          sizeof(struct dup_block), "duplicate block header");
6404                 db->num_bad = 0;
6405                 db->inode_list = 0;
6406                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6407         }
6408         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6409                          sizeof(struct inode_el), "inode element");
6410         ino_el->inode = ino;
6411         ino_el->next = db->inode_list;
6412         db->inode_list = ino_el;
6413         db->num_bad++;
6414
6415         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6416         if (n)
6417                 di = (struct dup_inode *) dnode_get(n);
6418         else {
6419                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6420                          sizeof(struct dup_inode), "duplicate inode header");
6421                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6422                 di->num_dupblocks = 0;
6423                 di->block_list = 0;
6424                 di->inode = *inode;
6425                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6426         }
6427         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6428                          sizeof(struct block_el), "block element");
6429         blk_el->block = blk;
6430         blk_el->next = di->block_list;
6431         di->block_list = blk_el;
6432         di->num_dupblocks++;
6433 }
6434
6435 /*
6436  * Free a duplicate inode record
6437  */
6438 static void inode_dnode_free(dnode_t *node)
6439 {
6440         struct dup_inode        *di;
6441         struct block_el         *p, *next;
6442
6443         di = (struct dup_inode *) dnode_get(node);
6444         for (p = di->block_list; p; p = next) {
6445                 next = p->next;
6446                 free(p);
6447         }
6448         free(node);
6449 }
6450
6451 /*
6452  * Free a duplicate block record
6453  */
6454 static void block_dnode_free(dnode_t *node)
6455 {
6456         struct dup_block        *db;
6457         struct inode_el         *p, *next;
6458
6459         db = (struct dup_block *) dnode_get(node);
6460         for (p = db->inode_list; p; p = next) {
6461                 next = p->next;
6462                 free(p);
6463         }
6464         free(node);
6465 }
6466
6467
6468 /*
6469  * Main procedure for handling duplicate blocks
6470  */
6471 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6472 {
6473         ext2_filsys             fs = ctx->fs;
6474         struct problem_context  pctx;
6475
6476         clear_problem_context(&pctx);
6477
6478         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6479                       _("multiply claimed inode map"), &inode_dup_map);
6480         if (pctx.errcode) {
6481                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6482                 ctx->flags |= E2F_FLAG_ABORT;
6483                 return;
6484         }
6485
6486         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6487         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6488         dict_set_allocator(&ino_dict, inode_dnode_free);
6489         dict_set_allocator(&blk_dict, block_dnode_free);
6490
6491         pass1b(ctx, block_buf);
6492         pass1c(ctx, block_buf);
6493         pass1d(ctx, block_buf);
6494
6495         /*
6496          * Time to free all of the accumulated data structures that we
6497          * don't need anymore.
6498          */
6499         dict_free_nodes(&ino_dict);
6500         dict_free_nodes(&blk_dict);
6501 }
6502
6503 /*
6504  * Scan the inodes looking for inodes that contain duplicate blocks.
6505  */
6506 struct process_block_struct_1b {
6507         e2fsck_t        ctx;
6508         ext2_ino_t      ino;
6509         int             dup_blocks;
6510         struct ext2_inode *inode;
6511         struct problem_context *pctx;
6512 };
6513
6514 static void pass1b(e2fsck_t ctx, char *block_buf)
6515 {
6516         ext2_filsys fs = ctx->fs;
6517         ext2_ino_t ino;
6518         struct ext2_inode inode;
6519         ext2_inode_scan scan;
6520         struct process_block_struct_1b pb;
6521         struct problem_context pctx;
6522
6523         clear_problem_context(&pctx);
6524
6525         if (!(ctx->options & E2F_OPT_PREEN))
6526                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6527         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6528                                               &scan);
6529         if (pctx.errcode) {
6530                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6531                 ctx->flags |= E2F_FLAG_ABORT;
6532                 return;
6533         }
6534         ctx->stashed_inode = &inode;
6535         pb.ctx = ctx;
6536         pb.pctx = &pctx;
6537         pctx.str = "pass1b";
6538         while (1) {
6539                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6540                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6541                         continue;
6542                 if (pctx.errcode) {
6543                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6544                         ctx->flags |= E2F_FLAG_ABORT;
6545                         return;
6546                 }
6547                 if (!ino)
6548                         break;
6549                 pctx.ino = ctx->stashed_ino = ino;
6550                 if ((ino != EXT2_BAD_INO) &&
6551                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6552                         continue;
6553
6554                 pb.ino = ino;
6555                 pb.dup_blocks = 0;
6556                 pb.inode = &inode;
6557
6558                 if (ext2fs_inode_has_valid_blocks(&inode) ||
6559                     (ino == EXT2_BAD_INO))
6560                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
6561                                      0, block_buf, process_pass1b_block, &pb);
6562                 if (inode.i_file_acl)
6563                         process_pass1b_block(fs, &inode.i_file_acl,
6564                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6565                 if (pb.dup_blocks) {
6566                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
6567                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
6568                             ino == EXT2_ROOT_INO)
6569                                 dup_inode_count++;
6570                 }
6571                 if (pctx.errcode)
6572                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6573         }
6574         ext2fs_close_inode_scan(scan);
6575         e2fsck_use_inode_shortcuts(ctx, 0);
6576 }
6577
6578 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6579                                 blk_t   *block_nr,
6580                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6581                                 blk_t ref_blk FSCK_ATTR((unused)),
6582                                 int ref_offset FSCK_ATTR((unused)),
6583                                 void *priv_data)
6584 {
6585         struct process_block_struct_1b *p;
6586         e2fsck_t ctx;
6587
6588         if (HOLE_BLKADDR(*block_nr))
6589                 return 0;
6590         p = (struct process_block_struct_1b *) priv_data;
6591         ctx = p->ctx;
6592
6593         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6594                 return 0;
6595
6596         /* OK, this is a duplicate block */
6597         if (p->ino != EXT2_BAD_INO) {
6598                 p->pctx->blk = *block_nr;
6599                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6600         }
6601         p->dup_blocks++;
6602         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6603
6604         add_dupe(ctx, p->ino, *block_nr, p->inode);
6605
6606         return 0;
6607 }
6608
6609 /*
6610  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
6611  * is used so that we can print pathnames when prompting the user for
6612  * what to do.
6613  */
6614 struct search_dir_struct {
6615         int             count;
6616         ext2_ino_t      first_inode;
6617         ext2_ino_t      max_inode;
6618 };
6619
6620 static int search_dirent_proc(ext2_ino_t dir, int entry,
6621                               struct ext2_dir_entry *dirent,
6622                               int offset FSCK_ATTR((unused)),
6623                               int blocksize FSCK_ATTR((unused)),
6624                               char *buf FSCK_ATTR((unused)),
6625                               void *priv_data)
6626 {
6627         struct search_dir_struct *sd;
6628         struct dup_inode        *p;
6629         dnode_t                 *n;
6630
6631         sd = (struct search_dir_struct *) priv_data;
6632
6633         if (dirent->inode > sd->max_inode)
6634                 /* Should abort this inode, but not everything */
6635                 return 0;
6636
6637         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6638             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6639                 return 0;
6640
6641         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6642         if (!n)
6643                 return 0;
6644         p = (struct dup_inode *) dnode_get(n);
6645         p->dir = dir;
6646         sd->count--;
6647
6648         return(sd->count ? 0 : DIRENT_ABORT);
6649 }
6650
6651
6652 static void pass1c(e2fsck_t ctx, char *block_buf)
6653 {
6654         ext2_filsys fs = ctx->fs;
6655         struct search_dir_struct sd;
6656         struct problem_context pctx;
6657
6658         clear_problem_context(&pctx);
6659
6660         if (!(ctx->options & E2F_OPT_PREEN))
6661                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6662
6663         /*
6664          * Search through all directories to translate inodes to names
6665          * (by searching for the containing directory for that inode.)
6666          */
6667         sd.count = dup_inode_count;
6668         sd.first_inode = EXT2_FIRST_INODE(fs->super);
6669         sd.max_inode = fs->super->s_inodes_count;
6670         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6671                                   search_dirent_proc, &sd);
6672 }
6673
6674 static void pass1d(e2fsck_t ctx, char *block_buf)
6675 {
6676         ext2_filsys fs = ctx->fs;
6677         struct dup_inode        *p, *t;
6678         struct dup_block        *q;
6679         ext2_ino_t              *shared, ino;
6680         int     shared_len;
6681         int     i;
6682         int     file_ok;
6683         int     meta_data = 0;
6684         struct problem_context pctx;
6685         dnode_t *n, *m;
6686         struct block_el *s;
6687         struct inode_el *r;
6688
6689         clear_problem_context(&pctx);
6690
6691         if (!(ctx->options & E2F_OPT_PREEN))
6692                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6693         e2fsck_read_bitmaps(ctx);
6694
6695         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6696         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6697         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6698                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6699                                 "Shared inode list");
6700         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6701                 p = (struct dup_inode *) dnode_get(n);
6702                 shared_len = 0;
6703                 file_ok = 1;
6704                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6705                 if (ino == EXT2_BAD_INO)
6706                         continue;
6707
6708                 /*
6709                  * Find all of the inodes which share blocks with this
6710                  * one.  First we find all of the duplicate blocks
6711                  * belonging to this inode, and then search each block
6712                  * get the list of inodes, and merge them together.
6713                  */
6714                 for (s = p->block_list; s; s = s->next) {
6715                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6716                         if (!m)
6717                                 continue; /* Should never happen... */
6718                         q = (struct dup_block *) dnode_get(m);
6719                         if (q->num_bad > 1)
6720                                 file_ok = 0;
6721                         if (check_if_fs_block(ctx, s->block)) {
6722                                 file_ok = 0;
6723                                 meta_data = 1;
6724                         }
6725
6726                         /*
6727                          * Add all inodes used by this block to the
6728                          * shared[] --- which is a unique list, so
6729                          * if an inode is already in shared[], don't
6730                          * add it again.
6731                          */
6732                         for (r = q->inode_list; r; r = r->next) {
6733                                 if (r->inode == ino)
6734                                         continue;
6735                                 for (i = 0; i < shared_len; i++)
6736                                         if (shared[i] == r->inode)
6737                                                 break;
6738                                 if (i == shared_len) {
6739                                         shared[shared_len++] = r->inode;
6740                                 }
6741                         }
6742                 }
6743
6744                 /*
6745                  * Report the inode that we are working on
6746                  */
6747                 pctx.inode = &p->inode;
6748                 pctx.ino = ino;
6749                 pctx.dir = p->dir;
6750                 pctx.blkcount = p->num_dupblocks;
6751                 pctx.num = meta_data ? shared_len+1 : shared_len;
6752                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6753                 pctx.blkcount = 0;
6754                 pctx.num = 0;
6755
6756                 if (meta_data)
6757                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6758
6759                 for (i = 0; i < shared_len; i++) {
6760                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6761                         if (!m)
6762                                 continue; /* should never happen */
6763                         t = (struct dup_inode *) dnode_get(m);
6764                         /*
6765                          * Report the inode that we are sharing with
6766                          */
6767                         pctx.inode = &t->inode;
6768                         pctx.ino = shared[i];
6769                         pctx.dir = t->dir;
6770                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6771                 }
6772                 if (file_ok) {
6773                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6774                         continue;
6775                 }
6776                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6777                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
6778                         if (pctx.errcode)
6779                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6780                         else
6781                                 continue;
6782                 }
6783                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6784                         delete_file(ctx, ino, p, block_buf);
6785                 else
6786                         ext2fs_unmark_valid(fs);
6787         }
6788         ext2fs_free_mem(&shared);
6789 }
6790
6791 /*
6792  * Drop the refcount on the dup_block structure, and clear the entry
6793  * in the block_dup_map if appropriate.
6794  */
6795 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6796 {
6797         p->num_bad--;
6798         if (p->num_bad <= 0 ||
6799             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6800                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6801 }
6802
6803 static int delete_file_block(ext2_filsys fs,
6804                              blk_t      *block_nr,
6805                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6806                              blk_t ref_block FSCK_ATTR((unused)),
6807                              int ref_offset FSCK_ATTR((unused)),
6808                              void *priv_data)
6809 {
6810         struct process_block_struct_1b *pb;
6811         struct dup_block *p;
6812         dnode_t *n;
6813         e2fsck_t ctx;
6814
6815         pb = (struct process_block_struct_1b *) priv_data;
6816         ctx = pb->ctx;
6817
6818         if (HOLE_BLKADDR(*block_nr))
6819                 return 0;
6820
6821         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6822                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6823                 if (n) {
6824                         p = (struct dup_block *) dnode_get(n);
6825                         decrement_badcount(ctx, *block_nr, p);
6826                 } else
6827                         com_err("delete_file_block", 0,
6828                             _("internal error; can't find dup_blk for %d\n"),
6829                                 *block_nr);
6830         } else {
6831                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6832                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6833         }
6834
6835         return 0;
6836 }
6837
6838 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6839                         struct dup_inode *dp, char* block_buf)
6840 {
6841         ext2_filsys fs = ctx->fs;
6842         struct process_block_struct_1b pb;
6843         struct ext2_inode       inode;
6844         struct problem_context  pctx;
6845         unsigned int            count;
6846
6847         clear_problem_context(&pctx);
6848         pctx.ino = pb.ino = ino;
6849         pb.dup_blocks = dp->num_dupblocks;
6850         pb.ctx = ctx;
6851         pctx.str = "delete_file";
6852
6853         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6854         if (ext2fs_inode_has_valid_blocks(&inode))
6855                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6856                                                      delete_file_block, &pb);
6857         if (pctx.errcode)
6858                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6859         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6860         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6861         if (ctx->inode_bad_map)
6862                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6863         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6864
6865         /* Inode may have changed by block_iterate, so reread it */
6866         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6867         inode.i_links_count = 0;
6868         inode.i_dtime = time(0);
6869         if (inode.i_file_acl &&
6870             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6871                 count = 1;
6872                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6873                                                    block_buf, -1, &count);
6874                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6875                         pctx.errcode = 0;
6876                         count = 1;
6877                 }
6878                 if (pctx.errcode) {
6879                         pctx.blk = inode.i_file_acl;
6880                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6881                 }
6882                 /*
6883                  * If the count is zero, then arrange to have the
6884                  * block deleted.  If the block is in the block_dup_map,
6885                  * also call delete_file_block since it will take care
6886                  * of keeping the accounting straight.
6887                  */
6888                 if ((count == 0) ||
6889                     ext2fs_test_block_bitmap(ctx->block_dup_map,
6890                                              inode.i_file_acl))
6891                         delete_file_block(fs, &inode.i_file_acl,
6892                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6893         }
6894         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6895 }
6896
6897 struct clone_struct {
6898         errcode_t       errcode;
6899         ext2_ino_t      dir;
6900         char    *buf;
6901         e2fsck_t ctx;
6902 };
6903
6904 static int clone_file_block(ext2_filsys fs,
6905                             blk_t       *block_nr,
6906                             e2_blkcnt_t blockcnt,
6907                             blk_t ref_block FSCK_ATTR((unused)),
6908                             int ref_offset FSCK_ATTR((unused)),
6909                             void *priv_data)
6910 {
6911         struct dup_block *p;
6912         blk_t   new_block;
6913         errcode_t       retval;
6914         struct clone_struct *cs = (struct clone_struct *) priv_data;
6915         dnode_t *n;
6916         e2fsck_t ctx;
6917
6918         ctx = cs->ctx;
6919
6920         if (HOLE_BLKADDR(*block_nr))
6921                 return 0;
6922
6923         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6924                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6925                 if (n) {
6926                         p = (struct dup_block *) dnode_get(n);
6927                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6928                                                   &new_block);
6929                         if (retval) {
6930                                 cs->errcode = retval;
6931                                 return BLOCK_ABORT;
6932                         }
6933                         if (cs->dir && (blockcnt >= 0)) {
6934                                 retval = ext2fs_set_dir_block(fs->dblist,
6935                                       cs->dir, new_block, blockcnt);
6936                                 if (retval) {
6937                                         cs->errcode = retval;
6938                                         return BLOCK_ABORT;
6939                                 }
6940                         }
6941 #if 0
6942                         printf("Cloning block %u to %u\n", *block_nr,
6943                                new_block);
6944 #endif
6945                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
6946                                                      cs->buf);
6947                         if (retval) {
6948                                 cs->errcode = retval;
6949                                 return BLOCK_ABORT;
6950                         }
6951                         retval = io_channel_write_blk(fs->io, new_block, 1,
6952                                                       cs->buf);
6953                         if (retval) {
6954                                 cs->errcode = retval;
6955                                 return BLOCK_ABORT;
6956                         }
6957                         decrement_badcount(ctx, *block_nr, p);
6958                         *block_nr = new_block;
6959                         ext2fs_mark_block_bitmap(ctx->block_found_map,
6960                                                  new_block);
6961                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
6962                         return BLOCK_CHANGED;
6963                 } else
6964                         com_err("clone_file_block", 0,
6965                             _("internal error; can't find dup_blk for %d\n"),
6966                                 *block_nr);
6967         }
6968         return 0;
6969 }
6970
6971 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6972                       struct dup_inode *dp, char* block_buf)
6973 {
6974         ext2_filsys fs = ctx->fs;
6975         errcode_t       retval;
6976         struct clone_struct cs;
6977         struct problem_context  pctx;
6978         blk_t           blk;
6979         dnode_t         *n;
6980         struct inode_el *ino_el;
6981         struct dup_block        *db;
6982         struct dup_inode        *di;
6983
6984         clear_problem_context(&pctx);
6985         cs.errcode = 0;
6986         cs.dir = 0;
6987         cs.ctx = ctx;
6988         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
6989         if (retval)
6990                 return retval;
6991
6992         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
6993                 cs.dir = ino;
6994
6995         pctx.ino = ino;
6996         pctx.str = "clone_file";
6997         if (ext2fs_inode_has_valid_blocks(&dp->inode))
6998                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6999                                                      clone_file_block, &cs);
7000         ext2fs_mark_bb_dirty(fs);
7001         if (pctx.errcode) {
7002                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7003                 retval = pctx.errcode;
7004                 goto errout;
7005         }
7006         if (cs.errcode) {
7007                 com_err("clone_file", cs.errcode,
7008                         _("returned from clone_file_block"));
7009                 retval = cs.errcode;
7010                 goto errout;
7011         }
7012         /* The inode may have changed on disk, so we have to re-read it */
7013         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7014         blk = dp->inode.i_file_acl;
7015         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7016                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7017                     BLOCK_CHANGED)) {
7018                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7019                 /*
7020                  * If we cloned the EA block, find all other inodes
7021                  * which refered to that EA block, and modify
7022                  * them to point to the new EA block.
7023                  */
7024                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7025                 db = (struct dup_block *) dnode_get(n);
7026                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7027                         if (ino_el->inode == ino)
7028                                 continue;
7029                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7030                         di = (struct dup_inode *) dnode_get(n);
7031                         if (di->inode.i_file_acl == blk) {
7032                                 di->inode.i_file_acl = dp->inode.i_file_acl;
7033                                 e2fsck_write_inode(ctx, ino_el->inode,
7034                                            &di->inode, "clone file EA");
7035                                 decrement_badcount(ctx, blk, db);
7036                         }
7037                 }
7038         }
7039         retval = 0;
7040 errout:
7041         ext2fs_free_mem(&cs.buf);
7042         return retval;
7043 }
7044
7045 /*
7046  * This routine returns 1 if a block overlaps with one of the superblocks,
7047  * group descriptors, inode bitmaps, or block bitmaps.
7048  */
7049 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7050 {
7051         ext2_filsys fs = ctx->fs;
7052         blk_t   block;
7053         dgrp_t  i;
7054
7055         block = fs->super->s_first_data_block;
7056         for (i = 0; i < fs->group_desc_count; i++) {
7057
7058                 /* Check superblocks/block group descriptros */
7059                 if (ext2fs_bg_has_super(fs, i)) {
7060                         if (test_block >= block &&
7061                             (test_block <= block + fs->desc_blocks))
7062                                 return 1;
7063                 }
7064
7065                 /* Check the inode table */
7066                 if ((fs->group_desc[i].bg_inode_table) &&
7067                     (test_block >= fs->group_desc[i].bg_inode_table) &&
7068                     (test_block < (fs->group_desc[i].bg_inode_table +
7069                                    fs->inode_blocks_per_group)))
7070                         return 1;
7071
7072                 /* Check the bitmap blocks */
7073                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7074                     (test_block == fs->group_desc[i].bg_inode_bitmap))
7075                         return 1;
7076
7077                 block += fs->super->s_blocks_per_group;
7078         }
7079         return 0;
7080 }
7081 /*
7082  * pass2.c --- check directory structure
7083  *
7084  * Pass 2 of e2fsck iterates through all active directory inodes, and
7085  * applies to following tests to each directory entry in the directory
7086  * blocks in the inodes:
7087  *
7088  *      - The length of the directory entry (rec_len) should be at
7089  *              least 8 bytes, and no more than the remaining space
7090  *              left in the directory block.
7091  *      - The length of the name in the directory entry (name_len)
7092  *              should be less than (rec_len - 8).
7093  *      - The inode number in the directory entry should be within
7094  *              legal bounds.
7095  *      - The inode number should refer to a in-use inode.
7096  *      - The first entry should be '.', and its inode should be
7097  *              the inode of the directory.
7098  *      - The second entry should be '..'.
7099  *
7100  * To minimize disk seek time, the directory blocks are processed in
7101  * sorted order of block numbers.
7102  *
7103  * Pass 2 also collects the following information:
7104  *      - The inode numbers of the subdirectories for each directory.
7105  *
7106  * Pass 2 relies on the following information from previous passes:
7107  *      - The directory information collected in pass 1.
7108  *      - The inode_used_map bitmap
7109  *      - The inode_bad_map bitmap
7110  *      - The inode_dir_map bitmap
7111  *
7112  * Pass 2 frees the following data structures
7113  *      - The inode_bad_map bitmap
7114  *      - The inode_reg_map bitmap
7115  */
7116
7117 /* #define DX_DEBUG */
7118
7119 /*
7120  * Keeps track of how many times an inode is referenced.
7121  */
7122 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7123 static int check_dir_block(ext2_filsys fs,
7124                            struct ext2_db_entry *dir_blocks_info,
7125                            void *priv_data);
7126 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7127                               struct problem_context *pctx);
7128 static int update_dir_block(ext2_filsys fs,
7129                             blk_t       *block_nr,
7130                             e2_blkcnt_t blockcnt,
7131                             blk_t       ref_block,
7132                             int         ref_offset,
7133                             void        *priv_data);
7134 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7135 static int htree_depth(struct dx_dir_info *dx_dir,
7136                        struct dx_dirblock_info *dx_db);
7137 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7138
7139 struct check_dir_struct {
7140         char *buf;
7141         struct problem_context  pctx;
7142         int     count, max;
7143         e2fsck_t ctx;
7144 };
7145
7146 static void e2fsck_pass2(e2fsck_t ctx)
7147 {
7148         struct ext2_super_block *sb = ctx->fs->super;
7149         struct problem_context  pctx;
7150         ext2_filsys             fs = ctx->fs;
7151         char                    *buf;
7152 #ifdef RESOURCE_TRACK
7153         struct resource_track   rtrack;
7154 #endif
7155         struct dir_info         *dir;
7156         struct check_dir_struct cd;
7157         struct dx_dir_info      *dx_dir;
7158         struct dx_dirblock_info *dx_db, *dx_parent;
7159         int                     b;
7160         int                     i, depth;
7161         problem_t               code;
7162         int                     bad_dir;
7163
7164 #ifdef RESOURCE_TRACK
7165         init_resource_track(&rtrack);
7166 #endif
7167
7168         clear_problem_context(&cd.pctx);
7169
7170 #ifdef MTRACE
7171         mtrace_print("Pass 2");
7172 #endif
7173
7174         if (!(ctx->options & E2F_OPT_PREEN))
7175                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7176
7177         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7178                                                 0, ctx->inode_link_info,
7179                                                 &ctx->inode_count);
7180         if (cd.pctx.errcode) {
7181                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7182                 ctx->flags |= E2F_FLAG_ABORT;
7183                 return;
7184         }
7185         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7186                                               "directory scan buffer");
7187
7188         /*
7189          * Set up the parent pointer for the root directory, if
7190          * present.  (If the root directory is not present, we will
7191          * create it in pass 3.)
7192          */
7193         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7194         if (dir)
7195                 dir->parent = EXT2_ROOT_INO;
7196
7197         cd.buf = buf;
7198         cd.ctx = ctx;
7199         cd.count = 1;
7200         cd.max = ext2fs_dblist_count(fs->dblist);
7201
7202         if (ctx->progress)
7203                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7204
7205         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7206                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7207
7208         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7209                                                 &cd);
7210         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7211                 return;
7212         if (cd.pctx.errcode) {
7213                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7214                 ctx->flags |= E2F_FLAG_ABORT;
7215                 return;
7216         }
7217
7218 #ifdef ENABLE_HTREE
7219         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7220                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7221                         return;
7222                 if (dx_dir->numblocks == 0)
7223                         continue;
7224                 clear_problem_context(&pctx);
7225                 bad_dir = 0;
7226                 pctx.dir = dx_dir->ino;
7227                 dx_db = dx_dir->dx_block;
7228                 if (dx_db->flags & DX_FLAG_REFERENCED)
7229                         dx_db->flags |= DX_FLAG_DUP_REF;
7230                 else
7231                         dx_db->flags |= DX_FLAG_REFERENCED;
7232                 /*
7233                  * Find all of the first and last leaf blocks, and
7234                  * update their parent's min and max hash values
7235                  */
7236                 for (b=0, dx_db = dx_dir->dx_block;
7237                      b < dx_dir->numblocks;
7238                      b++, dx_db++) {
7239                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7240                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7241                                 continue;
7242                         dx_parent = &dx_dir->dx_block[dx_db->parent];
7243                         /*
7244                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7245                          */
7246                         if (dx_db->flags & DX_FLAG_FIRST)
7247                                 dx_parent->min_hash = dx_db->min_hash;
7248                         /*
7249                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7250                          */
7251                         if (dx_db->flags & DX_FLAG_LAST)
7252                                 dx_parent->max_hash = dx_db->max_hash;
7253                 }
7254
7255                 for (b=0, dx_db = dx_dir->dx_block;
7256                      b < dx_dir->numblocks;
7257                      b++, dx_db++) {
7258                         pctx.blkcount = b;
7259                         pctx.group = dx_db->parent;
7260                         code = 0;
7261                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
7262                             (dx_db->min_hash < dx_db->node_min_hash)) {
7263                                 pctx.blk = dx_db->min_hash;
7264                                 pctx.blk2 = dx_db->node_min_hash;
7265                                 code = PR_2_HTREE_MIN_HASH;
7266                                 fix_problem(ctx, code, &pctx);
7267                                 bad_dir++;
7268                         }
7269                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
7270                                 depth = htree_depth(dx_dir, dx_db);
7271                                 if (depth != dx_dir->depth) {
7272                                         code = PR_2_HTREE_BAD_DEPTH;
7273                                         fix_problem(ctx, code, &pctx);
7274                                         bad_dir++;
7275                                 }
7276                         }
7277                         /*
7278                          * This test doesn't apply for the root block
7279                          * at block #0
7280                          */
7281                         if (b &&
7282                             (dx_db->max_hash > dx_db->node_max_hash)) {
7283                                 pctx.blk = dx_db->max_hash;
7284                                 pctx.blk2 = dx_db->node_max_hash;
7285                                 code = PR_2_HTREE_MAX_HASH;
7286                                 fix_problem(ctx, code, &pctx);
7287                                 bad_dir++;
7288                         }
7289                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7290                                 code = PR_2_HTREE_NOTREF;
7291                                 fix_problem(ctx, code, &pctx);
7292                                 bad_dir++;
7293                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7294                                 code = PR_2_HTREE_DUPREF;
7295                                 fix_problem(ctx, code, &pctx);
7296                                 bad_dir++;
7297                         }
7298                         if (code == 0)
7299                                 continue;
7300                 }
7301                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7302                         clear_htree(ctx, dx_dir->ino);
7303                         dx_dir->numblocks = 0;
7304                 }
7305         }
7306 #endif
7307         ext2fs_free_mem(&buf);
7308         ext2fs_free_dblist(fs->dblist);
7309
7310         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7311         ctx->inode_bad_map = 0;
7312         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7313         ctx->inode_reg_map = 0;
7314
7315         clear_problem_context(&pctx);
7316         if (ctx->large_files) {
7317                 if (!(sb->s_feature_ro_compat &
7318                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7319                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7320                         sb->s_feature_ro_compat |=
7321                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7322                         ext2fs_mark_super_dirty(fs);
7323                 }
7324                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7325                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7326                         ext2fs_update_dynamic_rev(fs);
7327                         ext2fs_mark_super_dirty(fs);
7328                 }
7329         } else if (!ctx->large_files &&
7330             (sb->s_feature_ro_compat &
7331               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7332                 if (fs->flags & EXT2_FLAG_RW) {
7333                         sb->s_feature_ro_compat &=
7334                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7335                         ext2fs_mark_super_dirty(fs);
7336                 }
7337         }
7338
7339 #ifdef RESOURCE_TRACK
7340         if (ctx->options & E2F_OPT_TIME2) {
7341                 e2fsck_clear_progbar(ctx);
7342                 print_resource_track(_("Pass 2"), &rtrack);
7343         }
7344 #endif
7345 }
7346
7347 #define MAX_DEPTH 32000
7348 static int htree_depth(struct dx_dir_info *dx_dir,
7349                        struct dx_dirblock_info *dx_db)
7350 {
7351         int     depth = 0;
7352
7353         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7354                 dx_db = &dx_dir->dx_block[dx_db->parent];
7355                 depth++;
7356         }
7357         return depth;
7358 }
7359
7360 static int dict_de_cmp(const void *a, const void *b)
7361 {
7362         const struct ext2_dir_entry *de_a, *de_b;
7363         int     a_len, b_len;
7364
7365         de_a = (const struct ext2_dir_entry *) a;
7366         a_len = de_a->name_len & 0xFF;
7367         de_b = (const struct ext2_dir_entry *) b;
7368         b_len = de_b->name_len & 0xFF;
7369
7370         if (a_len != b_len)
7371                 return (a_len - b_len);
7372
7373         return strncmp(de_a->name, de_b->name, a_len);
7374 }
7375
7376 /*
7377  * This is special sort function that makes sure that directory blocks
7378  * with a dirblock of zero are sorted to the beginning of the list.
7379  * This guarantees that the root node of the htree directories are
7380  * processed first, so we know what hash version to use.
7381  */
7382 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7383 {
7384         const struct ext2_db_entry *db_a =
7385                 (const struct ext2_db_entry *) a;
7386         const struct ext2_db_entry *db_b =
7387                 (const struct ext2_db_entry *) b;
7388
7389         if (db_a->blockcnt && !db_b->blockcnt)
7390                 return 1;
7391
7392         if (!db_a->blockcnt && db_b->blockcnt)
7393                 return -1;
7394
7395         if (db_a->blk != db_b->blk)
7396                 return (int) (db_a->blk - db_b->blk);
7397
7398         if (db_a->ino != db_b->ino)
7399                 return (int) (db_a->ino - db_b->ino);
7400
7401         return (int) (db_a->blockcnt - db_b->blockcnt);
7402 }
7403
7404
7405 /*
7406  * Make sure the first entry in the directory is '.', and that the
7407  * directory entry is sane.
7408  */
7409 static int check_dot(e2fsck_t ctx,
7410                      struct ext2_dir_entry *dirent,
7411                      ext2_ino_t ino, struct problem_context *pctx)
7412 {
7413         struct ext2_dir_entry *nextdir;
7414         int     status = 0;
7415         int     created = 0;
7416         int     new_len;
7417         int     problem = 0;
7418
7419         if (!dirent->inode)
7420                 problem = PR_2_MISSING_DOT;
7421         else if (((dirent->name_len & 0xFF) != 1) ||
7422                  (dirent->name[0] != '.'))
7423                 problem = PR_2_1ST_NOT_DOT;
7424         else if (dirent->name[1] != '\0')
7425                 problem = PR_2_DOT_NULL_TERM;
7426
7427         if (problem) {
7428                 if (fix_problem(ctx, problem, pctx)) {
7429                         if (dirent->rec_len < 12)
7430                                 dirent->rec_len = 12;
7431                         dirent->inode = ino;
7432                         dirent->name_len = 1;
7433                         dirent->name[0] = '.';
7434                         dirent->name[1] = '\0';
7435                         status = 1;
7436                         created = 1;
7437                 }
7438         }
7439         if (dirent->inode != ino) {
7440                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7441                         dirent->inode = ino;
7442                         status = 1;
7443                 }
7444         }
7445         if (dirent->rec_len > 12) {
7446                 new_len = dirent->rec_len - 12;
7447                 if (new_len > 12) {
7448                         if (created ||
7449                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7450                                 nextdir = (struct ext2_dir_entry *)
7451                                         ((char *) dirent + 12);
7452                                 dirent->rec_len = 12;
7453                                 nextdir->rec_len = new_len;
7454                                 nextdir->inode = 0;
7455                                 nextdir->name_len = 0;
7456                                 status = 1;
7457                         }
7458                 }
7459         }
7460         return status;
7461 }
7462
7463 /*
7464  * Make sure the second entry in the directory is '..', and that the
7465  * directory entry is sane.  We do not check the inode number of '..'
7466  * here; this gets done in pass 3.
7467  */
7468 static int check_dotdot(e2fsck_t ctx,
7469                         struct ext2_dir_entry *dirent,
7470                         struct dir_info *dir, struct problem_context *pctx)
7471 {
7472         int             problem = 0;
7473
7474         if (!dirent->inode)
7475                 problem = PR_2_MISSING_DOT_DOT;
7476         else if (((dirent->name_len & 0xFF) != 2) ||
7477                  (dirent->name[0] != '.') ||
7478                  (dirent->name[1] != '.'))
7479                 problem = PR_2_2ND_NOT_DOT_DOT;
7480         else if (dirent->name[2] != '\0')
7481                 problem = PR_2_DOT_DOT_NULL_TERM;
7482
7483         if (problem) {
7484                 if (fix_problem(ctx, problem, pctx)) {
7485                         if (dirent->rec_len < 12)
7486                                 dirent->rec_len = 12;
7487                         /*
7488                          * Note: we don't have the parent inode just
7489                          * yet, so we will fill it in with the root
7490                          * inode.  This will get fixed in pass 3.
7491                          */
7492                         dirent->inode = EXT2_ROOT_INO;
7493                         dirent->name_len = 2;
7494                         dirent->name[0] = '.';
7495                         dirent->name[1] = '.';
7496                         dirent->name[2] = '\0';
7497                         return 1;
7498                 }
7499                 return 0;
7500         }
7501         dir->dotdot = dirent->inode;
7502         return 0;
7503 }
7504
7505 /*
7506  * Check to make sure a directory entry doesn't contain any illegal
7507  * characters.
7508  */
7509 static int check_name(e2fsck_t ctx,
7510                       struct ext2_dir_entry *dirent,
7511                       struct problem_context *pctx)
7512 {
7513         int     i;
7514         int     fixup = -1;
7515         int     ret = 0;
7516
7517         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7518                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7519                         if (fixup < 0) {
7520                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7521                         }
7522                         if (fixup) {
7523                                 dirent->name[i] = '.';
7524                                 ret = 1;
7525                         }
7526                 }
7527         }
7528         return ret;
7529 }
7530
7531 /*
7532  * Check the directory filetype (if present)
7533  */
7534
7535 /*
7536  * Given a mode, return the ext2 file type
7537  */
7538 static int ext2_file_type(unsigned int mode)
7539 {
7540         if (LINUX_S_ISREG(mode))
7541                 return EXT2_FT_REG_FILE;
7542
7543         if (LINUX_S_ISDIR(mode))
7544                 return EXT2_FT_DIR;
7545
7546         if (LINUX_S_ISCHR(mode))
7547                 return EXT2_FT_CHRDEV;
7548
7549         if (LINUX_S_ISBLK(mode))
7550                 return EXT2_FT_BLKDEV;
7551
7552         if (LINUX_S_ISLNK(mode))
7553                 return EXT2_FT_SYMLINK;
7554
7555         if (LINUX_S_ISFIFO(mode))
7556                 return EXT2_FT_FIFO;
7557
7558         if (LINUX_S_ISSOCK(mode))
7559                 return EXT2_FT_SOCK;
7560
7561         return 0;
7562 }
7563
7564 static _INLINE_ int check_filetype(e2fsck_t ctx,
7565                                    struct ext2_dir_entry *dirent,
7566                                    struct problem_context *pctx)
7567 {
7568         int     filetype = dirent->name_len >> 8;
7569         int     should_be = EXT2_FT_UNKNOWN;
7570         struct ext2_inode       inode;
7571
7572         if (!(ctx->fs->super->s_feature_incompat &
7573               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7574                 if (filetype == 0 ||
7575                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7576                         return 0;
7577                 dirent->name_len = dirent->name_len & 0xFF;
7578                 return 1;
7579         }
7580
7581         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7582                 should_be = EXT2_FT_DIR;
7583         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7584                                             dirent->inode)) {
7585                 should_be = EXT2_FT_REG_FILE;
7586         } else if (ctx->inode_bad_map &&
7587                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7588                                             dirent->inode))
7589                 should_be = 0;
7590         else {
7591                 e2fsck_read_inode(ctx, dirent->inode, &inode,
7592                                   "check_filetype");
7593                 should_be = ext2_file_type(inode.i_mode);
7594         }
7595         if (filetype == should_be)
7596                 return 0;
7597         pctx->num = should_be;
7598
7599         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7600                         pctx) == 0)
7601                 return 0;
7602
7603         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7604         return 1;
7605 }
7606
7607 #ifdef ENABLE_HTREE
7608 static void parse_int_node(ext2_filsys fs,
7609                            struct ext2_db_entry *db,
7610                            struct check_dir_struct *cd,
7611                            struct dx_dir_info   *dx_dir,
7612                            char *block_buf)
7613 {
7614         struct          ext2_dx_root_info  *root;
7615         struct          ext2_dx_entry *ent;
7616         struct          ext2_dx_countlimit *limit;
7617         struct dx_dirblock_info *dx_db;
7618         int             i, expect_limit, count;
7619         blk_t           blk;
7620         ext2_dirhash_t  min_hash = 0xffffffff;
7621         ext2_dirhash_t  max_hash = 0;
7622         ext2_dirhash_t  hash = 0, prev_hash;
7623
7624         if (db->blockcnt == 0) {
7625                 root = (struct ext2_dx_root_info *) (block_buf + 24);
7626
7627 #ifdef DX_DEBUG
7628                 printf("Root node dump:\n");
7629                 printf("\t Reserved zero: %d\n", root->reserved_zero);
7630                 printf("\t Hash Version: %d\n", root->hash_version);
7631                 printf("\t Info length: %d\n", root->info_length);
7632                 printf("\t Indirect levels: %d\n", root->indirect_levels);
7633                 printf("\t Flags: %d\n", root->unused_flags);
7634 #endif
7635
7636                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7637         } else {
7638                 ent = (struct ext2_dx_entry *) (block_buf+8);
7639         }
7640         limit = (struct ext2_dx_countlimit *) ent;
7641
7642 #ifdef DX_DEBUG
7643         printf("Number of entries (count): %d\n",
7644                ext2fs_le16_to_cpu(limit->count));
7645         printf("Number of entries (limit): %d\n",
7646                ext2fs_le16_to_cpu(limit->limit));
7647 #endif
7648
7649         count = ext2fs_le16_to_cpu(limit->count);
7650         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7651                 sizeof(struct ext2_dx_entry);
7652         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7653                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7654                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7655                         goto clear_and_exit;
7656         }
7657         if (count > expect_limit) {
7658                 cd->pctx.num = count;
7659                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7660                         goto clear_and_exit;
7661                 count = expect_limit;
7662         }
7663
7664         for (i=0; i < count; i++) {
7665                 prev_hash = hash;
7666                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7667 #ifdef DX_DEBUG
7668                 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7669                        hash, ext2fs_le32_to_cpu(ent[i].block));
7670 #endif
7671                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7672                 /* Check to make sure the block is valid */
7673                 if (blk > (blk_t) dx_dir->numblocks) {
7674                         cd->pctx.blk = blk;
7675                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7676                                         &cd->pctx))
7677                                 goto clear_and_exit;
7678                 }
7679                 if (hash < prev_hash &&
7680                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7681                         goto clear_and_exit;
7682                 dx_db = &dx_dir->dx_block[blk];
7683                 if (dx_db->flags & DX_FLAG_REFERENCED) {
7684                         dx_db->flags |= DX_FLAG_DUP_REF;
7685                 } else {
7686                         dx_db->flags |= DX_FLAG_REFERENCED;
7687                         dx_db->parent = db->blockcnt;
7688                 }
7689                 if (hash < min_hash)
7690                         min_hash = hash;
7691                 if (hash > max_hash)
7692                         max_hash = hash;
7693                 dx_db->node_min_hash = hash;
7694                 if ((i+1) < count)
7695                         dx_db->node_max_hash =
7696                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7697                 else {
7698                         dx_db->node_max_hash = 0xfffffffe;
7699                         dx_db->flags |= DX_FLAG_LAST;
7700                 }
7701                 if (i == 0)
7702                         dx_db->flags |= DX_FLAG_FIRST;
7703         }
7704 #ifdef DX_DEBUG
7705         printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7706                db->blockcnt, min_hash, max_hash);
7707 #endif
7708         dx_db = &dx_dir->dx_block[db->blockcnt];
7709         dx_db->min_hash = min_hash;
7710         dx_db->max_hash = max_hash;
7711         return;
7712
7713 clear_and_exit:
7714         clear_htree(cd->ctx, cd->pctx.ino);
7715         dx_dir->numblocks = 0;
7716 }
7717 #endif /* ENABLE_HTREE */
7718
7719 /*
7720  * Given a busted directory, try to salvage it somehow.
7721  *
7722  */
7723 static void salvage_directory(ext2_filsys fs,
7724                               struct ext2_dir_entry *dirent,
7725                               struct ext2_dir_entry *prev,
7726                               unsigned int *offset)
7727 {
7728         char    *cp = (char *) dirent;
7729         int left = fs->blocksize - *offset - dirent->rec_len;
7730         int name_len = dirent->name_len & 0xFF;
7731
7732         /*
7733          * Special case of directory entry of size 8: copy what's left
7734          * of the directory block up to cover up the invalid hole.
7735          */
7736         if ((left >= 12) && (dirent->rec_len == 8)) {
7737                 memmove(cp, cp+8, left);
7738                 memset(cp + left, 0, 8);
7739                 return;
7740         }
7741         /*
7742          * If the directory entry overruns the end of the directory
7743          * block, and the name is small enough to fit, then adjust the
7744          * record length.
7745          */
7746         if ((left < 0) &&
7747             (name_len + 8 <= dirent->rec_len + left) &&
7748             dirent->inode <= fs->super->s_inodes_count &&
7749             strnlen(dirent->name, name_len) == name_len) {
7750                 dirent->rec_len += left;
7751                 return;
7752         }
7753         /*
7754          * If the directory entry is a multiple of four, so it is
7755          * valid, let the previous directory entry absorb the invalid
7756          * one.
7757          */
7758         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7759                 prev->rec_len += dirent->rec_len;
7760                 *offset += dirent->rec_len;
7761                 return;
7762         }
7763         /*
7764          * Default salvage method --- kill all of the directory
7765          * entries for the rest of the block.  We will either try to
7766          * absorb it into the previous directory entry, or create a
7767          * new empty directory entry the rest of the directory block.
7768          */
7769         if (prev) {
7770                 prev->rec_len += fs->blocksize - *offset;
7771                 *offset = fs->blocksize;
7772         } else {
7773                 dirent->rec_len = fs->blocksize - *offset;
7774                 dirent->name_len = 0;
7775                 dirent->inode = 0;
7776         }
7777 }
7778
7779 static int check_dir_block(ext2_filsys fs,
7780                            struct ext2_db_entry *db,
7781                            void *priv_data)
7782 {
7783         struct dir_info         *subdir, *dir;
7784         struct dx_dir_info      *dx_dir;
7785 #ifdef ENABLE_HTREE
7786         struct dx_dirblock_info *dx_db = 0;
7787 #endif /* ENABLE_HTREE */
7788         struct ext2_dir_entry   *dirent, *prev;
7789         ext2_dirhash_t          hash;
7790         unsigned int            offset = 0;
7791         int                     dir_modified = 0;
7792         int                     dot_state;
7793         blk_t                   block_nr = db->blk;
7794         ext2_ino_t              ino = db->ino;
7795         __u16                   links;
7796         struct check_dir_struct *cd;
7797         char                    *buf;
7798         e2fsck_t                ctx;
7799         int                     problem;
7800         struct ext2_dx_root_info *root;
7801         struct ext2_dx_countlimit *limit;
7802         static dict_t de_dict;
7803         struct problem_context  pctx;
7804         int     dups_found = 0;
7805
7806         cd = (struct check_dir_struct *) priv_data;
7807         buf = cd->buf;
7808         ctx = cd->ctx;
7809
7810         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7811                 return DIRENT_ABORT;
7812
7813         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7814                 return DIRENT_ABORT;
7815
7816         /*
7817          * Make sure the inode is still in use (could have been
7818          * deleted in the duplicate/bad blocks pass.
7819          */
7820         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7821                 return 0;
7822
7823         cd->pctx.ino = ino;
7824         cd->pctx.blk = block_nr;
7825         cd->pctx.blkcount = db->blockcnt;
7826         cd->pctx.ino2 = 0;
7827         cd->pctx.dirent = 0;
7828         cd->pctx.num = 0;
7829
7830         if (db->blk == 0) {
7831                 if (allocate_dir_block(ctx, db, &cd->pctx))
7832                         return 0;
7833                 block_nr = db->blk;
7834         }
7835
7836         if (db->blockcnt)
7837                 dot_state = 2;
7838         else
7839                 dot_state = 0;
7840
7841         if (ctx->dirs_to_hash &&
7842             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7843                 dups_found++;
7844
7845 #if 0
7846         printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7847                db->blockcnt, ino);
7848 #endif
7849
7850         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7851         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7852                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7853         if (cd->pctx.errcode) {
7854                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7855                         ctx->flags |= E2F_FLAG_ABORT;
7856                         return DIRENT_ABORT;
7857                 }
7858                 memset(buf, 0, fs->blocksize);
7859         }
7860 #ifdef ENABLE_HTREE
7861         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7862         if (dx_dir && dx_dir->numblocks) {
7863                 if (db->blockcnt >= dx_dir->numblocks) {
7864                         printf("XXX should never happen!!!\n");
7865                         abort();
7866                 }
7867                 dx_db = &dx_dir->dx_block[db->blockcnt];
7868                 dx_db->type = DX_DIRBLOCK_LEAF;
7869                 dx_db->phys = block_nr;
7870                 dx_db->min_hash = ~0;
7871                 dx_db->max_hash = 0;
7872
7873                 dirent = (struct ext2_dir_entry *) buf;
7874                 limit = (struct ext2_dx_countlimit *) (buf+8);
7875                 if (db->blockcnt == 0) {
7876                         root = (struct ext2_dx_root_info *) (buf + 24);
7877                         dx_db->type = DX_DIRBLOCK_ROOT;
7878                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7879                         if ((root->reserved_zero ||
7880                              root->info_length < 8 ||
7881                              root->indirect_levels > 1) &&
7882                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7883                                 clear_htree(ctx, ino);
7884                                 dx_dir->numblocks = 0;
7885                                 dx_db = 0;
7886                         }
7887                         dx_dir->hashversion = root->hash_version;
7888                         dx_dir->depth = root->indirect_levels + 1;
7889                 } else if ((dirent->inode == 0) &&
7890                            (dirent->rec_len == fs->blocksize) &&
7891                            (dirent->name_len == 0) &&
7892                            (ext2fs_le16_to_cpu(limit->limit) ==
7893                             ((fs->blocksize-8) /
7894                              sizeof(struct ext2_dx_entry))))
7895                         dx_db->type = DX_DIRBLOCK_NODE;
7896         }
7897 #endif /* ENABLE_HTREE */
7898
7899         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7900         prev = 0;
7901         do {
7902                 problem = 0;
7903                 dirent = (struct ext2_dir_entry *) (buf + offset);
7904                 cd->pctx.dirent = dirent;
7905                 cd->pctx.num = offset;
7906                 if (((offset + dirent->rec_len) > fs->blocksize) ||
7907                     (dirent->rec_len < 12) ||
7908                     ((dirent->rec_len % 4) != 0) ||
7909                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7910                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7911                                 salvage_directory(fs, dirent, prev, &offset);
7912                                 dir_modified++;
7913                                 continue;
7914                         } else
7915                                 goto abort_free_dict;
7916                 }
7917                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7918                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7919                                 dirent->name_len = EXT2_NAME_LEN;
7920                                 dir_modified++;
7921                         }
7922                 }
7923
7924                 if (dot_state == 0) {
7925                         if (check_dot(ctx, dirent, ino, &cd->pctx))
7926                                 dir_modified++;
7927                 } else if (dot_state == 1) {
7928                         dir = e2fsck_get_dir_info(ctx, ino);
7929                         if (!dir) {
7930                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7931                                 goto abort_free_dict;
7932                         }
7933                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7934                                 dir_modified++;
7935                 } else if (dirent->inode == ino) {
7936                         problem = PR_2_LINK_DOT;
7937                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7938                                 dirent->inode = 0;
7939                                 dir_modified++;
7940                                 goto next;
7941                         }
7942                 }
7943                 if (!dirent->inode)
7944                         goto next;
7945
7946                 /*
7947                  * Make sure the inode listed is a legal one.
7948                  */
7949                 if (((dirent->inode != EXT2_ROOT_INO) &&
7950                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
7951                     (dirent->inode > fs->super->s_inodes_count)) {
7952                         problem = PR_2_BAD_INO;
7953                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
7954                                                dirent->inode))) {
7955                         /*
7956                          * If the inode is unused, offer to clear it.
7957                          */
7958                         problem = PR_2_UNUSED_INODE;
7959                 } else if (ctx->inode_bb_map &&
7960                            (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
7961                                                      dirent->inode))) {
7962                         /*
7963                          * If the inode is in a bad block, offer to
7964                          * clear it.
7965                          */
7966                         problem = PR_2_BB_INODE;
7967                 } else if ((dot_state > 1) &&
7968                            ((dirent->name_len & 0xFF) == 1) &&
7969                            (dirent->name[0] == '.')) {
7970                         /*
7971                          * If there's a '.' entry in anything other
7972                          * than the first directory entry, it's a
7973                          * duplicate entry that should be removed.
7974                          */
7975                         problem = PR_2_DUP_DOT;
7976                 } else if ((dot_state > 1) &&
7977                            ((dirent->name_len & 0xFF) == 2) &&
7978                            (dirent->name[0] == '.') &&
7979                            (dirent->name[1] == '.')) {
7980                         /*
7981                          * If there's a '..' entry in anything other
7982                          * than the second directory entry, it's a
7983                          * duplicate entry that should be removed.
7984                          */
7985                         problem = PR_2_DUP_DOT_DOT;
7986                 } else if ((dot_state > 1) &&
7987                            (dirent->inode == EXT2_ROOT_INO)) {
7988                         /*
7989                          * Don't allow links to the root directory.
7990                          * We check this specially to make sure we
7991                          * catch this error case even if the root
7992                          * directory hasn't been created yet.
7993                          */
7994                         problem = PR_2_LINK_ROOT;
7995                 } else if ((dot_state > 1) &&
7996                            (dirent->name_len & 0xFF) == 0) {
7997                         /*
7998                          * Don't allow zero-length directory names.
7999                          */
8000                         problem = PR_2_NULL_NAME;
8001                 }
8002
8003                 if (problem) {
8004                         if (fix_problem(ctx, problem, &cd->pctx)) {
8005                                 dirent->inode = 0;
8006                                 dir_modified++;
8007                                 goto next;
8008                         } else {
8009                                 ext2fs_unmark_valid(fs);
8010                                 if (problem == PR_2_BAD_INO)
8011                                         goto next;
8012                         }
8013                 }
8014
8015                 /*
8016                  * If the inode was marked as having bad fields in
8017                  * pass1, process it and offer to fix/clear it.
8018                  * (We wait until now so that we can display the
8019                  * pathname to the user.)
8020                  */
8021                 if (ctx->inode_bad_map &&
8022                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8023                                              dirent->inode)) {
8024                         if (e2fsck_process_bad_inode(ctx, ino,
8025                                                      dirent->inode,
8026                                                      buf + fs->blocksize)) {
8027                                 dirent->inode = 0;
8028                                 dir_modified++;
8029                                 goto next;
8030                         }
8031                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8032                                 return DIRENT_ABORT;
8033                 }
8034
8035                 if (check_name(ctx, dirent, &cd->pctx))
8036                         dir_modified++;
8037
8038                 if (check_filetype(ctx, dirent, &cd->pctx))
8039                         dir_modified++;
8040
8041 #ifdef ENABLE_HTREE
8042                 if (dx_db) {
8043                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8044                                        (dirent->name_len & 0xFF),
8045                                        fs->super->s_hash_seed, &hash, 0);
8046                         if (hash < dx_db->min_hash)
8047                                 dx_db->min_hash = hash;
8048                         if (hash > dx_db->max_hash)
8049                                 dx_db->max_hash = hash;
8050                 }
8051 #endif
8052
8053                 /*
8054                  * If this is a directory, then mark its parent in its
8055                  * dir_info structure.  If the parent field is already
8056                  * filled in, then this directory has more than one
8057                  * hard link.  We assume the first link is correct,
8058                  * and ask the user if he/she wants to clear this one.
8059                  */
8060                 if ((dot_state > 1) &&
8061                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8062                                               dirent->inode))) {
8063                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8064                         if (!subdir) {
8065                                 cd->pctx.ino = dirent->inode;
8066                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8067                                 goto abort_free_dict;
8068                         }
8069                         if (subdir->parent) {
8070                                 cd->pctx.ino2 = subdir->parent;
8071                                 if (fix_problem(ctx, PR_2_LINK_DIR,
8072                                                 &cd->pctx)) {
8073                                         dirent->inode = 0;
8074                                         dir_modified++;
8075                                         goto next;
8076                                 }
8077                                 cd->pctx.ino2 = 0;
8078                         } else
8079                                 subdir->parent = ino;
8080                 }
8081
8082                 if (dups_found) {
8083                         ;
8084                 } else if (dict_lookup(&de_dict, dirent)) {
8085                         clear_problem_context(&pctx);
8086                         pctx.ino = ino;
8087                         pctx.dirent = dirent;
8088                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8089                         if (!ctx->dirs_to_hash)
8090                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8091                         if (ctx->dirs_to_hash)
8092                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8093                         dups_found++;
8094                 } else
8095                         dict_alloc_insert(&de_dict, dirent, dirent);
8096
8097                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8098                                         &links);
8099                 if (links > 1)
8100                         ctx->fs_links_count++;
8101                 ctx->fs_total_count++;
8102         next:
8103                 prev = dirent;
8104                 offset += dirent->rec_len;
8105                 dot_state++;
8106         } while (offset < fs->blocksize);
8107 #if 0
8108         printf("\n");
8109 #endif
8110 #ifdef ENABLE_HTREE
8111         if (dx_db) {
8112 #ifdef DX_DEBUG
8113                 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8114                        db->blockcnt, dx_db->type,
8115                        dx_db->min_hash, dx_db->max_hash);
8116 #endif
8117                 cd->pctx.dir = cd->pctx.ino;
8118                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8119                     (dx_db->type == DX_DIRBLOCK_NODE))
8120                         parse_int_node(fs, db, cd, dx_dir, buf);
8121         }
8122 #endif /* ENABLE_HTREE */
8123         if (offset != fs->blocksize) {
8124                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8125                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8126                         dirent->rec_len = cd->pctx.num;
8127                         dir_modified++;
8128                 }
8129         }
8130         if (dir_modified) {
8131                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8132                 if (cd->pctx.errcode) {
8133                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8134                                          &cd->pctx))
8135                                 goto abort_free_dict;
8136                 }
8137                 ext2fs_mark_changed(fs);
8138         }
8139         dict_free_nodes(&de_dict);
8140         return 0;
8141 abort_free_dict:
8142         dict_free_nodes(&de_dict);
8143         ctx->flags |= E2F_FLAG_ABORT;
8144         return DIRENT_ABORT;
8145 }
8146
8147 /*
8148  * This function is called to deallocate a block, and is an interator
8149  * functioned called by deallocate inode via ext2fs_iterate_block().
8150  */
8151 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8152                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
8153                                   blk_t ref_block FSCK_ATTR((unused)),
8154                                   int ref_offset FSCK_ATTR((unused)),
8155                                   void *priv_data)
8156 {
8157         e2fsck_t        ctx = (e2fsck_t) priv_data;
8158
8159         if (HOLE_BLKADDR(*block_nr))
8160                 return 0;
8161         if ((*block_nr < fs->super->s_first_data_block) ||
8162             (*block_nr >= fs->super->s_blocks_count))
8163                 return 0;
8164         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8165         ext2fs_block_alloc_stats(fs, *block_nr, -1);
8166         return 0;
8167 }
8168
8169 /*
8170  * This fuction deallocates an inode
8171  */
8172 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8173 {
8174         ext2_filsys fs = ctx->fs;
8175         struct ext2_inode       inode;
8176         struct problem_context  pctx;
8177         __u32                   count;
8178
8179         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8180         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8181         inode.i_links_count = 0;
8182         inode.i_dtime = time(0);
8183         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8184         clear_problem_context(&pctx);
8185         pctx.ino = ino;
8186
8187         /*
8188          * Fix up the bitmaps...
8189          */
8190         e2fsck_read_bitmaps(ctx);
8191         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8192         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8193         if (ctx->inode_bad_map)
8194                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8195         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8196
8197         if (inode.i_file_acl &&
8198             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8199                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8200                                                    block_buf, -1, &count);
8201                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8202                         pctx.errcode = 0;
8203                         count = 1;
8204                 }
8205                 if (pctx.errcode) {
8206                         pctx.blk = inode.i_file_acl;
8207                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8208                         ctx->flags |= E2F_FLAG_ABORT;
8209                         return;
8210                 }
8211                 if (count == 0) {
8212                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
8213                                                    inode.i_file_acl);
8214                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8215                 }
8216                 inode.i_file_acl = 0;
8217         }
8218
8219         if (!ext2fs_inode_has_valid_blocks(&inode))
8220                 return;
8221
8222         if (LINUX_S_ISREG(inode.i_mode) &&
8223             (inode.i_size_high || inode.i_size & 0x80000000UL))
8224                 ctx->large_files--;
8225
8226         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8227                                             deallocate_inode_block, ctx);
8228         if (pctx.errcode) {
8229                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8230                 ctx->flags |= E2F_FLAG_ABORT;
8231                 return;
8232         }
8233 }
8234
8235 /*
8236  * This fuction clears the htree flag on an inode
8237  */
8238 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8239 {
8240         struct ext2_inode       inode;
8241
8242         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8243         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8244         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8245         if (ctx->dirs_to_hash)
8246                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8247 }
8248
8249
8250 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8251                                     ext2_ino_t ino, char *buf)
8252 {
8253         ext2_filsys fs = ctx->fs;
8254         struct ext2_inode       inode;
8255         int                     inode_modified = 0;
8256         int                     not_fixed = 0;
8257         unsigned char           *frag, *fsize;
8258         struct problem_context  pctx;
8259         int     problem = 0;
8260
8261         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8262
8263         clear_problem_context(&pctx);
8264         pctx.ino = ino;
8265         pctx.dir = dir;
8266         pctx.inode = &inode;
8267
8268         if (inode.i_file_acl &&
8269             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8270             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8271                 inode.i_file_acl = 0;
8272 #ifdef EXT2FS_ENABLE_SWAPFS
8273                 /*
8274                  * This is a special kludge to deal with long symlinks
8275                  * on big endian systems.  i_blocks had already been
8276                  * decremented earlier in pass 1, but since i_file_acl
8277                  * hadn't yet been cleared, ext2fs_read_inode()
8278                  * assumed that the file was short symlink and would
8279                  * not have byte swapped i_block[0].  Hence, we have
8280                  * to byte-swap it here.
8281                  */
8282                 if (LINUX_S_ISLNK(inode.i_mode) &&
8283                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8284                     (inode.i_blocks == fs->blocksize >> 9))
8285                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8286 #endif
8287                 inode_modified++;
8288         } else
8289                 not_fixed++;
8290
8291         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8292             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8293             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8294             !(LINUX_S_ISSOCK(inode.i_mode)))
8295                 problem = PR_2_BAD_MODE;
8296         else if (LINUX_S_ISCHR(inode.i_mode)
8297                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8298                 problem = PR_2_BAD_CHAR_DEV;
8299         else if (LINUX_S_ISBLK(inode.i_mode)
8300                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8301                 problem = PR_2_BAD_BLOCK_DEV;
8302         else if (LINUX_S_ISFIFO(inode.i_mode)
8303                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8304                 problem = PR_2_BAD_FIFO;
8305         else if (LINUX_S_ISSOCK(inode.i_mode)
8306                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8307                 problem = PR_2_BAD_SOCKET;
8308         else if (LINUX_S_ISLNK(inode.i_mode)
8309                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8310                 problem = PR_2_INVALID_SYMLINK;
8311         }
8312
8313         if (problem) {
8314                 if (fix_problem(ctx, problem, &pctx)) {
8315                         deallocate_inode(ctx, ino, 0);
8316                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8317                                 return 0;
8318                         return 1;
8319                 } else
8320                         not_fixed++;
8321                 problem = 0;
8322         }
8323
8324         if (inode.i_faddr) {
8325                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8326                         inode.i_faddr = 0;
8327                         inode_modified++;
8328                 } else
8329                         not_fixed++;
8330         }
8331
8332         switch (fs->super->s_creator_os) {
8333             case EXT2_OS_LINUX:
8334                 frag = &inode.osd2.linux2.l_i_frag;
8335                 fsize = &inode.osd2.linux2.l_i_fsize;
8336                 break;
8337             case EXT2_OS_HURD:
8338                 frag = &inode.osd2.hurd2.h_i_frag;
8339                 fsize = &inode.osd2.hurd2.h_i_fsize;
8340                 break;
8341             case EXT2_OS_MASIX:
8342                 frag = &inode.osd2.masix2.m_i_frag;
8343                 fsize = &inode.osd2.masix2.m_i_fsize;
8344                 break;
8345             default:
8346                 frag = fsize = 0;
8347         }
8348         if (frag && *frag) {
8349                 pctx.num = *frag;
8350                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8351                         *frag = 0;
8352                         inode_modified++;
8353                 } else
8354                         not_fixed++;
8355                 pctx.num = 0;
8356         }
8357         if (fsize && *fsize) {
8358                 pctx.num = *fsize;
8359                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8360                         *fsize = 0;
8361                         inode_modified++;
8362                 } else
8363                         not_fixed++;
8364                 pctx.num = 0;
8365         }
8366
8367         if (inode.i_file_acl &&
8368             ((inode.i_file_acl < fs->super->s_first_data_block) ||
8369              (inode.i_file_acl >= fs->super->s_blocks_count))) {
8370                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8371                         inode.i_file_acl = 0;
8372                         inode_modified++;
8373                 } else
8374                         not_fixed++;
8375         }
8376         if (inode.i_dir_acl &&
8377             LINUX_S_ISDIR(inode.i_mode)) {
8378                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8379                         inode.i_dir_acl = 0;
8380                         inode_modified++;
8381                 } else
8382                         not_fixed++;
8383         }
8384
8385         if (inode_modified)
8386                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8387         if (!not_fixed)
8388                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8389         return 0;
8390 }
8391
8392
8393 /*
8394  * allocate_dir_block --- this function allocates a new directory
8395  *      block for a particular inode; this is done if a directory has
8396  *      a "hole" in it, or if a directory has a illegal block number
8397  *      that was zeroed out and now needs to be replaced.
8398  */
8399 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8400                               struct problem_context *pctx)
8401 {
8402         ext2_filsys fs = ctx->fs;
8403         blk_t                   blk;
8404         char                    *block;
8405         struct ext2_inode       inode;
8406
8407         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8408                 return 1;
8409
8410         /*
8411          * Read the inode and block bitmaps in; we'll be messing with
8412          * them.
8413          */
8414         e2fsck_read_bitmaps(ctx);
8415
8416         /*
8417          * First, find a free block
8418          */
8419         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8420         if (pctx->errcode) {
8421                 pctx->str = "ext2fs_new_block";
8422                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8423                 return 1;
8424         }
8425         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8426         ext2fs_mark_block_bitmap(fs->block_map, blk);
8427         ext2fs_mark_bb_dirty(fs);
8428
8429         /*
8430          * Now let's create the actual data block for the inode
8431          */
8432         if (db->blockcnt)
8433                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8434         else
8435                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8436                                                      EXT2_ROOT_INO, &block);
8437
8438         if (pctx->errcode) {
8439                 pctx->str = "ext2fs_new_dir_block";
8440                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8441                 return 1;
8442         }
8443
8444         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8445         ext2fs_free_mem(&block);
8446         if (pctx->errcode) {
8447                 pctx->str = "ext2fs_write_dir_block";
8448                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8449                 return 1;
8450         }
8451
8452         /*
8453          * Update the inode block count
8454          */
8455         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8456         inode.i_blocks += fs->blocksize / 512;
8457         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8458                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8459         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8460
8461         /*
8462          * Finally, update the block pointers for the inode
8463          */
8464         db->blk = blk;
8465         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8466                                       0, update_dir_block, db);
8467         if (pctx->errcode) {
8468                 pctx->str = "ext2fs_block_iterate";
8469                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8470                 return 1;
8471         }
8472
8473         return 0;
8474 }
8475
8476 /*
8477  * This is a helper function for allocate_dir_block().
8478  */
8479 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8480                             blk_t       *block_nr,
8481                             e2_blkcnt_t blockcnt,
8482                             blk_t ref_block FSCK_ATTR((unused)),
8483                             int ref_offset FSCK_ATTR((unused)),
8484                             void *priv_data)
8485 {
8486         struct ext2_db_entry *db;
8487
8488         db = (struct ext2_db_entry *) priv_data;
8489         if (db->blockcnt == (int) blockcnt) {
8490                 *block_nr = db->blk;
8491                 return BLOCK_CHANGED;
8492         }
8493         return 0;
8494 }
8495
8496 /*
8497  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8498  *
8499  * Pass #3 assures that all directories are connected to the
8500  * filesystem tree, using the following algorithm:
8501  *
8502  * First, the root directory is checked to make sure it exists; if
8503  * not, e2fsck will offer to create a new one.  It is then marked as
8504  * "done".
8505  *
8506  * Then, pass3 interates over all directory inodes; for each directory
8507  * it attempts to trace up the filesystem tree, using dirinfo.parent
8508  * until it reaches a directory which has been marked "done".  If it
8509  * can not do so, then the directory must be disconnected, and e2fsck
8510  * will offer to reconnect it to /lost+found.  While it is chasing
8511  * parent pointers up the filesystem tree, if pass3 sees a directory
8512  * twice, then it has detected a filesystem loop, and it will again
8513  * offer to reconnect the directory to /lost+found in to break the
8514  * filesystem loop.
8515  *
8516  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8517  * reconnect inodes to /lost+found; this subroutine is also used by
8518  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
8519  * is responsible for creating /lost+found if it does not exist.
8520  *
8521  * Pass 3 frees the following data structures:
8522  *      - The dirinfo directory information cache.
8523  */
8524
8525 static void check_root(e2fsck_t ctx);
8526 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8527                            struct problem_context *pctx);
8528 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8529
8530 static ext2fs_inode_bitmap inode_loop_detect;
8531 static ext2fs_inode_bitmap inode_done_map;
8532
8533 static void e2fsck_pass3(e2fsck_t ctx)
8534 {
8535         ext2_filsys fs = ctx->fs;
8536         int             i;
8537 #ifdef RESOURCE_TRACK
8538         struct resource_track   rtrack;
8539 #endif
8540         struct problem_context  pctx;
8541         struct dir_info *dir;
8542         unsigned long maxdirs, count;
8543
8544 #ifdef RESOURCE_TRACK
8545         init_resource_track(&rtrack);
8546 #endif
8547
8548         clear_problem_context(&pctx);
8549
8550 #ifdef MTRACE
8551         mtrace_print("Pass 3");
8552 #endif
8553
8554         if (!(ctx->options & E2F_OPT_PREEN))
8555                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8556
8557         /*
8558          * Allocate some bitmaps to do loop detection.
8559          */
8560         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8561                                                     &inode_done_map);
8562         if (pctx.errcode) {
8563                 pctx.num = 2;
8564                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8565                 ctx->flags |= E2F_FLAG_ABORT;
8566                 goto abort_exit;
8567         }
8568 #ifdef RESOURCE_TRACK
8569         if (ctx->options & E2F_OPT_TIME) {
8570                 e2fsck_clear_progbar(ctx);
8571                 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8572         }
8573 #endif
8574
8575         check_root(ctx);
8576         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8577                 goto abort_exit;
8578
8579         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8580
8581         maxdirs = e2fsck_get_num_dirinfo(ctx);
8582         count = 1;
8583
8584         if (ctx->progress)
8585                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8586                         goto abort_exit;
8587
8588         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8589                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8590                         goto abort_exit;
8591                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8592                         goto abort_exit;
8593                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8594                         if (check_directory(ctx, dir, &pctx))
8595                                 goto abort_exit;
8596         }
8597
8598         /*
8599          * Force the creation of /lost+found if not present
8600          */
8601         if ((ctx->flags & E2F_OPT_READONLY) == 0)
8602                 e2fsck_get_lost_and_found(ctx, 1);
8603
8604         /*
8605          * If there are any directories that need to be indexed or
8606          * optimized, do it here.
8607          */
8608         e2fsck_rehash_directories(ctx);
8609
8610 abort_exit:
8611         e2fsck_free_dir_info(ctx);
8612         ext2fs_free_inode_bitmap(inode_loop_detect);
8613         inode_loop_detect = 0;
8614         ext2fs_free_inode_bitmap(inode_done_map);
8615         inode_done_map = 0;
8616
8617 #ifdef RESOURCE_TRACK
8618         if (ctx->options & E2F_OPT_TIME2) {
8619                 e2fsck_clear_progbar(ctx);
8620                 print_resource_track(_("Pass 3"), &rtrack);
8621         }
8622 #endif
8623 }
8624
8625 /*
8626  * This makes sure the root inode is present; if not, we ask if the
8627  * user wants us to create it.  Not creating it is a fatal error.
8628  */
8629 static void check_root(e2fsck_t ctx)
8630 {
8631         ext2_filsys fs = ctx->fs;
8632         blk_t                   blk;
8633         struct ext2_inode       inode;
8634         char *                  block;
8635         struct problem_context  pctx;
8636
8637         clear_problem_context(&pctx);
8638
8639         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8640                 /*
8641                  * If the root inode is not a directory, die here.  The
8642                  * user must have answered 'no' in pass1 when we
8643                  * offered to clear it.
8644                  */
8645                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8646                                                EXT2_ROOT_INO))) {
8647                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8648                         ctx->flags |= E2F_FLAG_ABORT;
8649                 }
8650                 return;
8651         }
8652
8653         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8654                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8655                 ctx->flags |= E2F_FLAG_ABORT;
8656                 return;
8657         }
8658
8659         e2fsck_read_bitmaps(ctx);
8660
8661         /*
8662          * First, find a free block
8663          */
8664         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8665         if (pctx.errcode) {
8666                 pctx.str = "ext2fs_new_block";
8667                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8668                 ctx->flags |= E2F_FLAG_ABORT;
8669                 return;
8670         }
8671         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8672         ext2fs_mark_block_bitmap(fs->block_map, blk);
8673         ext2fs_mark_bb_dirty(fs);
8674
8675         /*
8676          * Now let's create the actual data block for the inode
8677          */
8678         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8679                                             &block);
8680         if (pctx.errcode) {
8681                 pctx.str = "ext2fs_new_dir_block";
8682                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8683                 ctx->flags |= E2F_FLAG_ABORT;
8684                 return;
8685         }
8686
8687         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8688         if (pctx.errcode) {
8689                 pctx.str = "ext2fs_write_dir_block";
8690                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8691                 ctx->flags |= E2F_FLAG_ABORT;
8692                 return;
8693         }
8694         ext2fs_free_mem(&block);
8695
8696         /*
8697          * Set up the inode structure
8698          */
8699         memset(&inode, 0, sizeof(inode));
8700         inode.i_mode = 040755;
8701         inode.i_size = fs->blocksize;
8702         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8703         inode.i_links_count = 2;
8704         inode.i_blocks = fs->blocksize / 512;
8705         inode.i_block[0] = blk;
8706
8707         /*
8708          * Write out the inode.
8709          */
8710         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8711         if (pctx.errcode) {
8712                 pctx.str = "ext2fs_write_inode";
8713                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8714                 ctx->flags |= E2F_FLAG_ABORT;
8715                 return;
8716         }
8717
8718         /*
8719          * Miscellaneous bookkeeping...
8720          */
8721         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8722         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8723         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8724
8725         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8726         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8727         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8728         ext2fs_mark_ib_dirty(fs);
8729 }
8730
8731 /*
8732  * This subroutine is responsible for making sure that a particular
8733  * directory is connected to the root; if it isn't we trace it up as
8734  * far as we can go, and then offer to connect the resulting parent to
8735  * the lost+found.  We have to do loop detection; if we ever discover
8736  * a loop, we treat that as a disconnected directory and offer to
8737  * reparent it to lost+found.
8738  *
8739  * However, loop detection is expensive, because for very large
8740  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8741  * is non-trivial.  Loops in filesystems are also a rare error case,
8742  * and we shouldn't optimize for error cases.  So we try two passes of
8743  * the algorithm.  The first time, we ignore loop detection and merely
8744  * increment a counter; if the counter exceeds some extreme threshold,
8745  * then we try again with the loop detection bitmap enabled.
8746  */
8747 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8748                            struct problem_context *pctx)
8749 {
8750         ext2_filsys     fs = ctx->fs;
8751         struct dir_info *p = dir;
8752         int             loop_pass = 0, parent_count = 0;
8753
8754         if (!p)
8755                 return 0;
8756
8757         while (1) {
8758                 /*
8759                  * Mark this inode as being "done"; by the time we
8760                  * return from this function, the inode we either be
8761                  * verified as being connected to the directory tree,
8762                  * or we will have offered to reconnect this to
8763                  * lost+found.
8764                  *
8765                  * If it was marked done already, then we've reached a
8766                  * parent we've already checked.
8767                  */
8768                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8769                         break;
8770
8771                 /*
8772                  * If this directory doesn't have a parent, or we've
8773                  * seen the parent once already, then offer to
8774                  * reparent it to lost+found
8775                  */
8776                 if (!p->parent ||
8777                     (loop_pass &&
8778                      (ext2fs_test_inode_bitmap(inode_loop_detect,
8779                                               p->parent)))) {
8780                         pctx->ino = p->ino;
8781                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8782                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
8783                                         ext2fs_unmark_valid(fs);
8784                                 else {
8785                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
8786                                         p->parent = ctx->lost_and_found;
8787                                         fix_dotdot(ctx, p, ctx->lost_and_found);
8788                                 }
8789                         }
8790                         break;
8791                 }
8792                 p = e2fsck_get_dir_info(ctx, p->parent);
8793                 if (!p) {
8794                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8795                         return 0;
8796                 }
8797                 if (loop_pass) {
8798                         ext2fs_mark_inode_bitmap(inode_loop_detect,
8799                                                  p->ino);
8800                 } else if (parent_count++ > 2048) {
8801                         /*
8802                          * If we've run into a path depth that's
8803                          * greater than 2048, try again with the inode
8804                          * loop bitmap turned on and start from the
8805                          * top.
8806                          */
8807                         loop_pass = 1;
8808                         if (inode_loop_detect)
8809                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
8810                         else {
8811                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8812                                 if (pctx->errcode) {
8813                                         pctx->num = 1;
8814                                         fix_problem(ctx,
8815                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8816                                         ctx->flags |= E2F_FLAG_ABORT;
8817                                         return -1;
8818                                 }
8819                         }
8820                         p = dir;
8821                 }
8822         }
8823
8824         /*
8825          * Make sure that .. and the parent directory are the same;
8826          * offer to fix it if not.
8827          */
8828         if (dir->parent != dir->dotdot) {
8829                 pctx->ino = dir->ino;
8830                 pctx->ino2 = dir->dotdot;
8831                 pctx->dir = dir->parent;
8832                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8833                         fix_dotdot(ctx, dir, dir->parent);
8834         }
8835         return 0;
8836 }
8837
8838 /*
8839  * This routine gets the lost_and_found inode, making it a directory
8840  * if necessary
8841  */
8842 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8843 {
8844         ext2_filsys fs = ctx->fs;
8845         ext2_ino_t                      ino;
8846         blk_t                   blk;
8847         errcode_t               retval;
8848         struct ext2_inode       inode;
8849         char *                  block;
8850         static const char       name[] = "lost+found";
8851         struct  problem_context pctx;
8852         struct dir_info         *dirinfo;
8853
8854         if (ctx->lost_and_found)
8855                 return ctx->lost_and_found;
8856
8857         clear_problem_context(&pctx);
8858
8859         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8860                                sizeof(name)-1, 0, &ino);
8861         if (retval && !fix)
8862                 return 0;
8863         if (!retval) {
8864                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8865                         ctx->lost_and_found = ino;
8866                         return ino;
8867                 }
8868
8869                 /* Lost+found isn't a directory! */
8870                 if (!fix)
8871                         return 0;
8872                 pctx.ino = ino;
8873                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8874                         return 0;
8875
8876                 /* OK, unlink the old /lost+found file. */
8877                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8878                 if (pctx.errcode) {
8879                         pctx.str = "ext2fs_unlink";
8880                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8881                         return 0;
8882                 }
8883                 dirinfo = e2fsck_get_dir_info(ctx, ino);
8884                 if (dirinfo)
8885                         dirinfo->parent = 0;
8886                 e2fsck_adjust_inode_count(ctx, ino, -1);
8887         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8888                 pctx.errcode = retval;
8889                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8890         }
8891         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8892                 return 0;
8893
8894         /*
8895          * Read the inode and block bitmaps in; we'll be messing with
8896          * them.
8897          */
8898         e2fsck_read_bitmaps(ctx);
8899
8900         /*
8901          * First, find a free block
8902          */
8903         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8904         if (retval) {
8905                 pctx.errcode = retval;
8906                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8907                 return 0;
8908         }
8909         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8910         ext2fs_block_alloc_stats(fs, blk, +1);
8911
8912         /*
8913          * Next find a free inode.
8914          */
8915         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8916                                   ctx->inode_used_map, &ino);
8917         if (retval) {
8918                 pctx.errcode = retval;
8919                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8920                 return 0;
8921         }
8922         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8923         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8924         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8925
8926         /*
8927          * Now let's create the actual data block for the inode
8928          */
8929         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8930         if (retval) {
8931                 pctx.errcode = retval;
8932                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8933                 return 0;
8934         }
8935
8936         retval = ext2fs_write_dir_block(fs, blk, block);
8937         ext2fs_free_mem(&block);
8938         if (retval) {
8939                 pctx.errcode = retval;
8940                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
8941                 return 0;
8942         }
8943
8944         /*
8945          * Set up the inode structure
8946          */
8947         memset(&inode, 0, sizeof(inode));
8948         inode.i_mode = 040700;
8949         inode.i_size = fs->blocksize;
8950         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8951         inode.i_links_count = 2;
8952         inode.i_blocks = fs->blocksize / 512;
8953         inode.i_block[0] = blk;
8954
8955         /*
8956          * Next, write out the inode.
8957          */
8958         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
8959         if (pctx.errcode) {
8960                 pctx.str = "ext2fs_write_inode";
8961                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8962                 return 0;
8963         }
8964         /*
8965          * Finally, create the directory link
8966          */
8967         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
8968         if (pctx.errcode) {
8969                 pctx.str = "ext2fs_link";
8970                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8971                 return 0;
8972         }
8973
8974         /*
8975          * Miscellaneous bookkeeping that needs to be kept straight.
8976          */
8977         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
8978         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
8979         ext2fs_icount_store(ctx->inode_count, ino, 2);
8980         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
8981         ctx->lost_and_found = ino;
8982 #if 0
8983         printf("/lost+found created; inode #%lu\n", ino);
8984 #endif
8985         return ino;
8986 }
8987
8988 /*
8989  * This routine will connect a file to lost+found
8990  */
8991 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
8992 {
8993         ext2_filsys fs = ctx->fs;
8994         errcode_t       retval;
8995         char            name[80];
8996         struct problem_context  pctx;
8997         struct ext2_inode       inode;
8998         int             file_type = 0;
8999
9000         clear_problem_context(&pctx);
9001         pctx.ino = ino;
9002
9003         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9004                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9005                         ctx->bad_lost_and_found++;
9006         }
9007         if (ctx->bad_lost_and_found) {
9008                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9009                 return 1;
9010         }
9011
9012         sprintf(name, "#%u", ino);
9013         if (ext2fs_read_inode(fs, ino, &inode) == 0)
9014                 file_type = ext2_file_type(inode.i_mode);
9015         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9016         if (retval == EXT2_ET_DIR_NO_SPACE) {
9017                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9018                         return 1;
9019                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9020                                                  1, 0);
9021                 if (retval) {
9022                         pctx.errcode = retval;
9023                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9024                         return 1;
9025                 }
9026                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9027                                      ino, file_type);
9028         }
9029         if (retval) {
9030                 pctx.errcode = retval;
9031                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9032                 return 1;
9033         }
9034         e2fsck_adjust_inode_count(ctx, ino, 1);
9035
9036         return 0;
9037 }
9038
9039 /*
9040  * Utility routine to adjust the inode counts on an inode.
9041  */
9042 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9043 {
9044         ext2_filsys fs = ctx->fs;
9045         errcode_t               retval;
9046         struct ext2_inode       inode;
9047
9048         if (!ino)
9049                 return 0;
9050
9051         retval = ext2fs_read_inode(fs, ino, &inode);
9052         if (retval)
9053                 return retval;
9054
9055 #if 0
9056         printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9057                inode.i_links_count);
9058 #endif
9059
9060         if (adj == 1) {
9061                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9062                 if (inode.i_links_count == (__u16) ~0)
9063                         return 0;
9064                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9065                 inode.i_links_count++;
9066         } else if (adj == -1) {
9067                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9068                 if (inode.i_links_count == 0)
9069                         return 0;
9070                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9071                 inode.i_links_count--;
9072         }
9073
9074         retval = ext2fs_write_inode(fs, ino, &inode);
9075         if (retval)
9076                 return retval;
9077
9078         return 0;
9079 }
9080
9081 /*
9082  * Fix parent --- this routine fixes up the parent of a directory.
9083  */
9084 struct fix_dotdot_struct {
9085         ext2_filsys     fs;
9086         ext2_ino_t      parent;
9087         int             done;
9088         e2fsck_t        ctx;
9089 };
9090
9091 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9092                            int  offset FSCK_ATTR((unused)),
9093                            int  blocksize FSCK_ATTR((unused)),
9094                            char *buf FSCK_ATTR((unused)),
9095                            void *priv_data)
9096 {
9097         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9098         errcode_t       retval;
9099         struct problem_context pctx;
9100
9101         if ((dirent->name_len & 0xFF) != 2)
9102                 return 0;
9103         if (strncmp(dirent->name, "..", 2))
9104                 return 0;
9105
9106         clear_problem_context(&pctx);
9107
9108         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9109         if (retval) {
9110                 pctx.errcode = retval;
9111                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9112         }
9113         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9114         if (retval) {
9115                 pctx.errcode = retval;
9116                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9117         }
9118         dirent->inode = fp->parent;
9119
9120         fp->done++;
9121         return DIRENT_ABORT | DIRENT_CHANGED;
9122 }
9123
9124 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9125 {
9126         ext2_filsys fs = ctx->fs;
9127         errcode_t       retval;
9128         struct fix_dotdot_struct fp;
9129         struct problem_context pctx;
9130
9131         fp.fs = fs;
9132         fp.parent = parent;
9133         fp.done = 0;
9134         fp.ctx = ctx;
9135
9136 #if 0
9137         printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9138 #endif
9139
9140         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9141                                     0, fix_dotdot_proc, &fp);
9142         if (retval || !fp.done) {
9143                 clear_problem_context(&pctx);
9144                 pctx.ino = dir->ino;
9145                 pctx.errcode = retval;
9146                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9147                             PR_3_FIX_PARENT_NOFIND, &pctx);
9148                 ext2fs_unmark_valid(fs);
9149         }
9150         dir->dotdot = parent;
9151
9152         return;
9153 }
9154
9155 /*
9156  * These routines are responsible for expanding a /lost+found if it is
9157  * too small.
9158  */
9159
9160 struct expand_dir_struct {
9161         int                     num;
9162         int                     guaranteed_size;
9163         int                     newblocks;
9164         int                     last_block;
9165         errcode_t               err;
9166         e2fsck_t                ctx;
9167 };
9168
9169 static int expand_dir_proc(ext2_filsys fs,
9170                            blk_t        *blocknr,
9171                            e2_blkcnt_t  blockcnt,
9172                            blk_t ref_block FSCK_ATTR((unused)),
9173                            int ref_offset FSCK_ATTR((unused)),
9174                            void *priv_data)
9175 {
9176         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9177         blk_t   new_blk;
9178         static blk_t    last_blk = 0;
9179         char            *block;
9180         errcode_t       retval;
9181         e2fsck_t        ctx;
9182
9183         ctx = es->ctx;
9184
9185         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9186                 return BLOCK_ABORT;
9187
9188         if (blockcnt > 0)
9189                 es->last_block = blockcnt;
9190         if (*blocknr) {
9191                 last_blk = *blocknr;
9192                 return 0;
9193         }
9194         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9195                                   &new_blk);
9196         if (retval) {
9197                 es->err = retval;
9198                 return BLOCK_ABORT;
9199         }
9200         if (blockcnt > 0) {
9201                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9202                 if (retval) {
9203                         es->err = retval;
9204                         return BLOCK_ABORT;
9205                 }
9206                 es->num--;
9207                 retval = ext2fs_write_dir_block(fs, new_blk, block);
9208         } else {
9209                 retval = ext2fs_get_mem(fs->blocksize, &block);
9210                 if (retval) {
9211                         es->err = retval;
9212                         return BLOCK_ABORT;
9213                 }
9214                 memset(block, 0, fs->blocksize);
9215                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9216         }
9217         if (retval) {
9218                 es->err = retval;
9219                 return BLOCK_ABORT;
9220         }
9221         ext2fs_free_mem(&block);
9222         *blocknr = new_blk;
9223         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9224         ext2fs_block_alloc_stats(fs, new_blk, +1);
9225         es->newblocks++;
9226
9227         if (es->num == 0)
9228                 return (BLOCK_CHANGED | BLOCK_ABORT);
9229         else
9230                 return BLOCK_CHANGED;
9231 }
9232
9233 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9234                                   int num, int guaranteed_size)
9235 {
9236         ext2_filsys fs = ctx->fs;
9237         errcode_t       retval;
9238         struct expand_dir_struct es;
9239         struct ext2_inode       inode;
9240
9241         if (!(fs->flags & EXT2_FLAG_RW))
9242                 return EXT2_ET_RO_FILSYS;
9243
9244         /*
9245          * Read the inode and block bitmaps in; we'll be messing with
9246          * them.
9247          */
9248         e2fsck_read_bitmaps(ctx);
9249
9250         retval = ext2fs_check_directory(fs, dir);
9251         if (retval)
9252                 return retval;
9253
9254         es.num = num;
9255         es.guaranteed_size = guaranteed_size;
9256         es.last_block = 0;
9257         es.err = 0;
9258         es.newblocks = 0;
9259         es.ctx = ctx;
9260
9261         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9262                                        0, expand_dir_proc, &es);
9263
9264         if (es.err)
9265                 return es.err;
9266
9267         /*
9268          * Update the size and block count fields in the inode.
9269          */
9270         retval = ext2fs_read_inode(fs, dir, &inode);
9271         if (retval)
9272                 return retval;
9273
9274         inode.i_size = (es.last_block + 1) * fs->blocksize;
9275         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9276
9277         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9278
9279         return 0;
9280 }
9281
9282 /*
9283  * pass4.c -- pass #4 of e2fsck: Check reference counts
9284  *
9285  * Pass 4 frees the following data structures:
9286  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
9287  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
9288  */
9289
9290 /*
9291  * This routine is called when an inode is not connected to the
9292  * directory tree.
9293  *
9294  * This subroutine returns 1 then the caller shouldn't bother with the
9295  * rest of the pass 4 tests.
9296  */
9297 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9298 {
9299         ext2_filsys fs = ctx->fs;
9300         struct ext2_inode       inode;
9301         struct problem_context  pctx;
9302
9303         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9304         clear_problem_context(&pctx);
9305         pctx.ino = i;
9306         pctx.inode = &inode;
9307
9308         /*
9309          * Offer to delete any zero-length files that does not have
9310          * blocks.  If there is an EA block, it might have useful
9311          * information, so we won't prompt to delete it, but let it be
9312          * reconnected to lost+found.
9313          */
9314         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9315                                 LINUX_S_ISDIR(inode.i_mode))) {
9316                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9317                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
9318                         inode.i_links_count = 0;
9319                         inode.i_dtime = time(0);
9320                         e2fsck_write_inode(ctx, i, &inode,
9321                                            "disconnect_inode");
9322                         /*
9323                          * Fix up the bitmaps...
9324                          */
9325                         e2fsck_read_bitmaps(ctx);
9326                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9327                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9328                         ext2fs_inode_alloc_stats2(fs, i, -1,
9329                                                   LINUX_S_ISDIR(inode.i_mode));
9330                         return 0;
9331                 }
9332         }
9333
9334         /*
9335          * Prompt to reconnect.
9336          */
9337         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9338                 if (e2fsck_reconnect_file(ctx, i))
9339                         ext2fs_unmark_valid(fs);
9340         } else {
9341                 /*
9342                  * If we don't attach the inode, then skip the
9343                  * i_links_test since there's no point in trying to
9344                  * force i_links_count to zero.
9345                  */
9346                 ext2fs_unmark_valid(fs);
9347                 return 1;
9348         }
9349         return 0;
9350 }
9351
9352
9353 static void e2fsck_pass4(e2fsck_t ctx)
9354 {
9355         ext2_filsys fs = ctx->fs;
9356         ext2_ino_t      i;
9357         struct ext2_inode       inode;
9358 #ifdef RESOURCE_TRACK
9359         struct resource_track   rtrack;
9360 #endif
9361         struct problem_context  pctx;
9362         __u16   link_count, link_counted;
9363         char    *buf = 0;
9364         int     group, maxgroup;
9365
9366 #ifdef RESOURCE_TRACK
9367         init_resource_track(&rtrack);
9368 #endif
9369
9370 #ifdef MTRACE
9371         mtrace_print("Pass 4");
9372 #endif
9373
9374         clear_problem_context(&pctx);
9375
9376         if (!(ctx->options & E2F_OPT_PREEN))
9377                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9378
9379         group = 0;
9380         maxgroup = fs->group_desc_count;
9381         if (ctx->progress)
9382                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9383                         return;
9384
9385         for (i=1; i <= fs->super->s_inodes_count; i++) {
9386                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9387                         return;
9388                 if ((i % fs->super->s_inodes_per_group) == 0) {
9389                         group++;
9390                         if (ctx->progress)
9391                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
9392                                         return;
9393                 }
9394                 if (i == EXT2_BAD_INO ||
9395                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9396                         continue;
9397                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9398                     (ctx->inode_imagic_map &&
9399                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9400                     (ctx->inode_bb_map &&
9401                      ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9402                         continue;
9403                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9404                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9405                 if (link_counted == 0) {
9406                         if (!buf)
9407                                 buf = e2fsck_allocate_memory(ctx,
9408                                      fs->blocksize, "bad_inode buffer");
9409                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9410                                 continue;
9411                         if (disconnect_inode(ctx, i))
9412                                 continue;
9413                         ext2fs_icount_fetch(ctx->inode_link_info, i,
9414                                             &link_count);
9415                         ext2fs_icount_fetch(ctx->inode_count, i,
9416                                             &link_counted);
9417                 }
9418                 if (link_counted != link_count) {
9419                         e2fsck_read_inode(ctx, i, &inode, "pass4");
9420                         pctx.ino = i;
9421                         pctx.inode = &inode;
9422                         if (link_count != inode.i_links_count) {
9423                                 pctx.num = link_count;
9424                                 fix_problem(ctx,
9425                                             PR_4_INCONSISTENT_COUNT, &pctx);
9426                         }
9427                         pctx.num = link_counted;
9428                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9429                                 inode.i_links_count = link_counted;
9430                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
9431                         }
9432                 }
9433         }
9434         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9435         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9436         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9437         ctx->inode_bb_map = 0;
9438         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9439         ctx->inode_imagic_map = 0;
9440         ext2fs_free_mem(&buf);
9441 #ifdef RESOURCE_TRACK
9442         if (ctx->options & E2F_OPT_TIME2) {
9443                 e2fsck_clear_progbar(ctx);
9444                 print_resource_track(_("Pass 4"), &rtrack);
9445         }
9446 #endif
9447 }
9448
9449 /*
9450  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9451  */
9452
9453 #define NO_BLK ((blk_t) -1)
9454
9455 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9456                             struct problem_context *pctx)
9457 {
9458         switch (problem) {
9459         case PR_5_BLOCK_UNUSED:
9460                 if (pctx->blk == pctx->blk2)
9461                         pctx->blk2 = 0;
9462                 else
9463                         problem = PR_5_BLOCK_RANGE_UNUSED;
9464                 break;
9465         case PR_5_BLOCK_USED:
9466                 if (pctx->blk == pctx->blk2)
9467                         pctx->blk2 = 0;
9468                 else
9469                         problem = PR_5_BLOCK_RANGE_USED;
9470                 break;
9471         case PR_5_INODE_UNUSED:
9472                 if (pctx->ino == pctx->ino2)
9473                         pctx->ino2 = 0;
9474                 else
9475                         problem = PR_5_INODE_RANGE_UNUSED;
9476                 break;
9477         case PR_5_INODE_USED:
9478                 if (pctx->ino == pctx->ino2)
9479                         pctx->ino2 = 0;
9480                 else
9481                         problem = PR_5_INODE_RANGE_USED;
9482                 break;
9483         }
9484         fix_problem(ctx, problem, pctx);
9485         pctx->blk = pctx->blk2 = NO_BLK;
9486         pctx->ino = pctx->ino2 = 0;
9487 }
9488
9489 static void check_block_bitmaps(e2fsck_t ctx)
9490 {
9491         ext2_filsys fs = ctx->fs;
9492         blk_t   i;
9493         int     *free_array;
9494         int     group = 0;
9495         unsigned int    blocks = 0;
9496         unsigned int    free_blocks = 0;
9497         int     group_free = 0;
9498         int     actual, bitmap;
9499         struct problem_context  pctx;
9500         int     problem, save_problem, fixit, had_problem;
9501         errcode_t       retval;
9502
9503         clear_problem_context(&pctx);
9504         free_array = (int *) e2fsck_allocate_memory(ctx,
9505             fs->group_desc_count * sizeof(int), "free block count array");
9506
9507         if ((fs->super->s_first_data_block <
9508              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9509             (fs->super->s_blocks_count-1 >
9510              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9511                 pctx.num = 1;
9512                 pctx.blk = fs->super->s_first_data_block;
9513                 pctx.blk2 = fs->super->s_blocks_count -1;
9514                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9515                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9516                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9517
9518                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9519                 return;
9520         }
9521
9522         if ((fs->super->s_first_data_block <
9523              ext2fs_get_block_bitmap_start(fs->block_map)) ||
9524             (fs->super->s_blocks_count-1 >
9525              ext2fs_get_block_bitmap_end(fs->block_map))) {
9526                 pctx.num = 2;
9527                 pctx.blk = fs->super->s_first_data_block;
9528                 pctx.blk2 = fs->super->s_blocks_count -1;
9529                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9530                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9531                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9532
9533                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9534                 return;
9535         }
9536
9537 redo_counts:
9538         had_problem = 0;
9539         save_problem = 0;
9540         pctx.blk = pctx.blk2 = NO_BLK;
9541         for (i = fs->super->s_first_data_block;
9542              i < fs->super->s_blocks_count;
9543              i++) {
9544                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9545                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9546
9547                 if (actual == bitmap)
9548                         goto do_counts;
9549
9550                 if (!actual && bitmap) {
9551                         /*
9552                          * Block not used, but marked in use in the bitmap.
9553                          */
9554                         problem = PR_5_BLOCK_UNUSED;
9555                 } else {
9556                         /*
9557                          * Block used, but not marked in use in the bitmap.
9558                          */
9559                         problem = PR_5_BLOCK_USED;
9560                 }
9561                 if (pctx.blk == NO_BLK) {
9562                         pctx.blk = pctx.blk2 = i;
9563                         save_problem = problem;
9564                 } else {
9565                         if ((problem == save_problem) &&
9566                             (pctx.blk2 == i-1))
9567                                 pctx.blk2++;
9568                         else {
9569                                 print_bitmap_problem(ctx, save_problem, &pctx);
9570                                 pctx.blk = pctx.blk2 = i;
9571                                 save_problem = problem;
9572                         }
9573                 }
9574                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9575                 had_problem++;
9576
9577         do_counts:
9578                 if (!bitmap) {
9579                         group_free++;
9580                         free_blocks++;
9581                 }
9582                 blocks ++;
9583                 if ((blocks == fs->super->s_blocks_per_group) ||
9584                     (i == fs->super->s_blocks_count-1)) {
9585                         free_array[group] = group_free;
9586                         group ++;
9587                         blocks = 0;
9588                         group_free = 0;
9589                         if (ctx->progress)
9590                                 if ((ctx->progress)(ctx, 5, group,
9591                                                     fs->group_desc_count*2))
9592                                         return;
9593                 }
9594         }
9595         if (pctx.blk != NO_BLK)
9596                 print_bitmap_problem(ctx, save_problem, &pctx);
9597         if (had_problem)
9598                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9599         else
9600                 fixit = -1;
9601         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9602
9603         if (fixit == 1) {
9604                 ext2fs_free_block_bitmap(fs->block_map);
9605                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9606                                                   &fs->block_map);
9607                 if (retval) {
9608                         clear_problem_context(&pctx);
9609                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9610                         ctx->flags |= E2F_FLAG_ABORT;
9611                         return;
9612                 }
9613                 ext2fs_set_bitmap_padding(fs->block_map);
9614                 ext2fs_mark_bb_dirty(fs);
9615
9616                 /* Redo the counts */
9617                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9618                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9619                 goto redo_counts;
9620         } else if (fixit == 0)
9621                 ext2fs_unmark_valid(fs);
9622
9623         for (i = 0; i < fs->group_desc_count; i++) {
9624                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9625                         pctx.group = i;
9626                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9627                         pctx.blk2 = free_array[i];
9628
9629                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9630                                         &pctx)) {
9631                                 fs->group_desc[i].bg_free_blocks_count =
9632                                         free_array[i];
9633                                 ext2fs_mark_super_dirty(fs);
9634                         } else
9635                                 ext2fs_unmark_valid(fs);
9636                 }
9637         }
9638         if (free_blocks != fs->super->s_free_blocks_count) {
9639                 pctx.group = 0;
9640                 pctx.blk = fs->super->s_free_blocks_count;
9641                 pctx.blk2 = free_blocks;
9642
9643                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9644                         fs->super->s_free_blocks_count = free_blocks;
9645                         ext2fs_mark_super_dirty(fs);
9646                 } else
9647                         ext2fs_unmark_valid(fs);
9648         }
9649         ext2fs_free_mem(&free_array);
9650 }
9651
9652 static void check_inode_bitmaps(e2fsck_t ctx)
9653 {
9654         ext2_filsys fs = ctx->fs;
9655         ext2_ino_t      i;
9656         unsigned int    free_inodes = 0;
9657         int             group_free = 0;
9658         int             dirs_count = 0;
9659         int             group = 0;
9660         unsigned int    inodes = 0;
9661         int             *free_array;
9662         int             *dir_array;
9663         int             actual, bitmap;
9664         errcode_t       retval;
9665         struct problem_context  pctx;
9666         int             problem, save_problem, fixit, had_problem;
9667
9668         clear_problem_context(&pctx);
9669         free_array = (int *) e2fsck_allocate_memory(ctx,
9670             fs->group_desc_count * sizeof(int), "free inode count array");
9671
9672         dir_array = (int *) e2fsck_allocate_memory(ctx,
9673            fs->group_desc_count * sizeof(int), "directory count array");
9674
9675         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9676             (fs->super->s_inodes_count >
9677              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9678                 pctx.num = 3;
9679                 pctx.blk = 1;
9680                 pctx.blk2 = fs->super->s_inodes_count;
9681                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9682                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9683                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9684
9685                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9686                 return;
9687         }
9688         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9689             (fs->super->s_inodes_count >
9690              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9691                 pctx.num = 4;
9692                 pctx.blk = 1;
9693                 pctx.blk2 = fs->super->s_inodes_count;
9694                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9695                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9696                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9697
9698                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9699                 return;
9700         }
9701
9702 redo_counts:
9703         had_problem = 0;
9704         save_problem = 0;
9705         pctx.ino = pctx.ino2 = 0;
9706         for (i = 1; i <= fs->super->s_inodes_count; i++) {
9707                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9708                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9709
9710                 if (actual == bitmap)
9711                         goto do_counts;
9712
9713                 if (!actual && bitmap) {
9714                         /*
9715                          * Inode wasn't used, but marked in bitmap
9716                          */
9717                         problem = PR_5_INODE_UNUSED;
9718                 } else /* if (actual && !bitmap) */ {
9719                         /*
9720                          * Inode used, but not in bitmap
9721                          */
9722                         problem = PR_5_INODE_USED;
9723                 }
9724                 if (pctx.ino == 0) {
9725                         pctx.ino = pctx.ino2 = i;
9726                         save_problem = problem;
9727                 } else {
9728                         if ((problem == save_problem) &&
9729                             (pctx.ino2 == i-1))
9730                                 pctx.ino2++;
9731                         else {
9732                                 print_bitmap_problem(ctx, save_problem, &pctx);
9733                                 pctx.ino = pctx.ino2 = i;
9734                                 save_problem = problem;
9735                         }
9736                 }
9737                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9738                 had_problem++;
9739
9740 do_counts:
9741                 if (!bitmap) {
9742                         group_free++;
9743                         free_inodes++;
9744                 } else {
9745                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9746                                 dirs_count++;
9747                 }
9748                 inodes++;
9749                 if ((inodes == fs->super->s_inodes_per_group) ||
9750                     (i == fs->super->s_inodes_count)) {
9751                         free_array[group] = group_free;
9752                         dir_array[group] = dirs_count;
9753                         group ++;
9754                         inodes = 0;
9755                         group_free = 0;
9756                         dirs_count = 0;
9757                         if (ctx->progress)
9758                                 if ((ctx->progress)(ctx, 5,
9759                                             group + fs->group_desc_count,
9760                                             fs->group_desc_count*2))
9761                                         return;
9762                 }
9763         }
9764         if (pctx.ino)
9765                 print_bitmap_problem(ctx, save_problem, &pctx);
9766
9767         if (had_problem)
9768                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9769         else
9770                 fixit = -1;
9771         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9772
9773         if (fixit == 1) {
9774                 ext2fs_free_inode_bitmap(fs->inode_map);
9775                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9776                                                   &fs->inode_map);
9777                 if (retval) {
9778                         clear_problem_context(&pctx);
9779                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9780                         ctx->flags |= E2F_FLAG_ABORT;
9781                         return;
9782                 }
9783                 ext2fs_set_bitmap_padding(fs->inode_map);
9784                 ext2fs_mark_ib_dirty(fs);
9785
9786                 /* redo counts */
9787                 inodes = 0; free_inodes = 0; group_free = 0;
9788                 dirs_count = 0; group = 0;
9789                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9790                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9791                 goto redo_counts;
9792         } else if (fixit == 0)
9793                 ext2fs_unmark_valid(fs);
9794
9795         for (i = 0; i < fs->group_desc_count; i++) {
9796                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9797                         pctx.group = i;
9798                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9799                         pctx.ino2 = free_array[i];
9800                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9801                                         &pctx)) {
9802                                 fs->group_desc[i].bg_free_inodes_count =
9803                                         free_array[i];
9804                                 ext2fs_mark_super_dirty(fs);
9805                         } else
9806                                 ext2fs_unmark_valid(fs);
9807                 }
9808                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9809                         pctx.group = i;
9810                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9811                         pctx.ino2 = dir_array[i];
9812
9813                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9814                                         &pctx)) {
9815                                 fs->group_desc[i].bg_used_dirs_count =
9816                                         dir_array[i];
9817                                 ext2fs_mark_super_dirty(fs);
9818                         } else
9819                                 ext2fs_unmark_valid(fs);
9820                 }
9821         }
9822         if (free_inodes != fs->super->s_free_inodes_count) {
9823                 pctx.group = -1;
9824                 pctx.ino = fs->super->s_free_inodes_count;
9825                 pctx.ino2 = free_inodes;
9826
9827                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9828                         fs->super->s_free_inodes_count = free_inodes;
9829                         ext2fs_mark_super_dirty(fs);
9830                 } else
9831                         ext2fs_unmark_valid(fs);
9832         }
9833         ext2fs_free_mem(&free_array);
9834         ext2fs_free_mem(&dir_array);
9835 }
9836
9837 static void check_inode_end(e2fsck_t ctx)
9838 {
9839         ext2_filsys fs = ctx->fs;
9840         ext2_ino_t      end, save_inodes_count, i;
9841         struct problem_context  pctx;
9842
9843         clear_problem_context(&pctx);
9844
9845         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9846         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9847                                                      &save_inodes_count);
9848         if (pctx.errcode) {
9849                 pctx.num = 1;
9850                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9851                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9852                 return;
9853         }
9854         if (save_inodes_count == end)
9855                 return;
9856
9857         for (i = save_inodes_count + 1; i <= end; i++) {
9858                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9859                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9860                                 for (i = save_inodes_count + 1; i <= end; i++)
9861                                         ext2fs_mark_inode_bitmap(fs->inode_map,
9862                                                                  i);
9863                                 ext2fs_mark_ib_dirty(fs);
9864                         } else
9865                                 ext2fs_unmark_valid(fs);
9866                         break;
9867                 }
9868         }
9869
9870         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9871                                                      save_inodes_count, 0);
9872         if (pctx.errcode) {
9873                 pctx.num = 2;
9874                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9875                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9876                 return;
9877         }
9878 }
9879
9880 static void check_block_end(e2fsck_t ctx)
9881 {
9882         ext2_filsys fs = ctx->fs;
9883         blk_t   end, save_blocks_count, i;
9884         struct problem_context  pctx;
9885
9886         clear_problem_context(&pctx);
9887
9888         end = fs->block_map->start +
9889                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9890         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9891                                                      &save_blocks_count);
9892         if (pctx.errcode) {
9893                 pctx.num = 3;
9894                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9895                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9896                 return;
9897         }
9898         if (save_blocks_count == end)
9899                 return;
9900
9901         for (i = save_blocks_count + 1; i <= end; i++) {
9902                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9903                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9904                                 for (i = save_blocks_count + 1; i <= end; i++)
9905                                         ext2fs_mark_block_bitmap(fs->block_map,
9906                                                                  i);
9907                                 ext2fs_mark_bb_dirty(fs);
9908                         } else
9909                                 ext2fs_unmark_valid(fs);
9910                         break;
9911                 }
9912         }
9913
9914         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9915                                                      save_blocks_count, 0);
9916         if (pctx.errcode) {
9917                 pctx.num = 4;
9918                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9919                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9920                 return;
9921         }
9922 }
9923
9924 static void e2fsck_pass5(e2fsck_t ctx)
9925 {
9926 #ifdef RESOURCE_TRACK
9927         struct resource_track   rtrack;
9928 #endif
9929         struct problem_context  pctx;
9930
9931 #ifdef MTRACE
9932         mtrace_print("Pass 5");
9933 #endif
9934
9935 #ifdef RESOURCE_TRACK
9936         init_resource_track(&rtrack);
9937 #endif
9938
9939         clear_problem_context(&pctx);
9940
9941         if (!(ctx->options & E2F_OPT_PREEN))
9942                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9943
9944         if (ctx->progress)
9945                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9946                         return;
9947
9948         e2fsck_read_bitmaps(ctx);
9949
9950         check_block_bitmaps(ctx);
9951         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9952                 return;
9953         check_inode_bitmaps(ctx);
9954         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9955                 return;
9956         check_inode_end(ctx);
9957         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9958                 return;
9959         check_block_end(ctx);
9960         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9961                 return;
9962
9963         ext2fs_free_inode_bitmap(ctx->inode_used_map);
9964         ctx->inode_used_map = 0;
9965         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9966         ctx->inode_dir_map = 0;
9967         ext2fs_free_block_bitmap(ctx->block_found_map);
9968         ctx->block_found_map = 0;
9969
9970 #ifdef RESOURCE_TRACK
9971         if (ctx->options & E2F_OPT_TIME2) {
9972                 e2fsck_clear_progbar(ctx);
9973                 print_resource_track(_("Pass 5"), &rtrack);
9974         }
9975 #endif
9976 }
9977
9978 /*
9979  * problem.c --- report filesystem problems to the user
9980  */
9981
9982 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
9983 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
9984 #define PR_NO_DEFAULT   0x000004 /* Default to no */
9985 #define PR_MSG_ONLY     0x000008 /* Print message only */
9986
9987 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
9988
9989 #define PR_FATAL        0x001000 /* Fatal error */
9990 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
9991                                  /* ask another */
9992 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
9993 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
9994 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
9995 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
9996 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
9997
9998
9999 #define PROMPT_NONE     0
10000 #define PROMPT_FIX      1
10001 #define PROMPT_CLEAR    2
10002 #define PROMPT_RELOCATE 3
10003 #define PROMPT_ALLOCATE 4
10004 #define PROMPT_EXPAND   5
10005 #define PROMPT_CONNECT  6
10006 #define PROMPT_CREATE   7
10007 #define PROMPT_SALVAGE  8
10008 #define PROMPT_TRUNCATE 9
10009 #define PROMPT_CLEAR_INODE 10
10010 #define PROMPT_ABORT    11
10011 #define PROMPT_SPLIT    12
10012 #define PROMPT_CONTINUE 13
10013 #define PROMPT_CLONE    14
10014 #define PROMPT_DELETE   15
10015 #define PROMPT_SUPPRESS 16
10016 #define PROMPT_UNLINK   17
10017 #define PROMPT_CLEAR_HTREE 18
10018 #define PROMPT_RECREATE 19
10019 #define PROMPT_NULL     20
10020
10021 struct e2fsck_problem {
10022         problem_t       e2p_code;
10023         const char *    e2p_description;
10024         char            prompt;
10025         int             flags;
10026         problem_t       second_code;
10027 };
10028
10029 struct latch_descr {
10030         int             latch_code;
10031         problem_t       question;
10032         problem_t       end_message;
10033         int             flags;
10034 };
10035
10036 /*
10037  * These are the prompts which are used to ask the user if they want
10038  * to fix a problem.
10039  */
10040 static const char * const prompt[] = {
10041         N_("(no prompt)"),      /* 0 */
10042         N_("Fix"),              /* 1 */
10043         N_("Clear"),            /* 2 */
10044         N_("Relocate"),         /* 3 */
10045         N_("Allocate"),         /* 4 */
10046         N_("Expand"),           /* 5 */
10047         N_("Connect to /lost+found"), /* 6 */
10048         N_("Create"),           /* 7 */
10049         N_("Salvage"),          /* 8 */
10050         N_("Truncate"),         /* 9 */
10051         N_("Clear inode"),      /* 10 */
10052         N_("Abort"),            /* 11 */
10053         N_("Split"),            /* 12 */
10054         N_("Continue"),         /* 13 */
10055         N_("Clone duplicate/bad blocks"), /* 14 */
10056         N_("Delete file"),      /* 15 */
10057         N_("Suppress messages"),/* 16 */
10058         N_("Unlink"),           /* 17 */
10059         N_("Clear HTree index"),/* 18 */
10060         N_("Recreate"),         /* 19 */
10061         "",                     /* 20 */
10062 };
10063
10064 /*
10065  * These messages are printed when we are preen mode and we will be
10066  * automatically fixing the problem.
10067  */
10068 static const char * const preen_msg[] = {
10069         N_("(NONE)"),           /* 0 */
10070         N_("FIXED"),            /* 1 */
10071         N_("CLEARED"),          /* 2 */
10072         N_("RELOCATED"),        /* 3 */
10073         N_("ALLOCATED"),        /* 4 */
10074         N_("EXPANDED"),         /* 5 */
10075         N_("RECONNECTED"),      /* 6 */
10076         N_("CREATED"),          /* 7 */
10077         N_("SALVAGED"),         /* 8 */
10078         N_("TRUNCATED"),        /* 9 */
10079         N_("INODE CLEARED"),    /* 10 */
10080         N_("ABORTED"),          /* 11 */
10081         N_("SPLIT"),            /* 12 */
10082         N_("CONTINUING"),       /* 13 */
10083         N_("DUPLICATE/BAD BLOCKS CLONED"), /* 14 */
10084         N_("FILE DELETED"),     /* 15 */
10085         N_("SUPPRESSED"),       /* 16 */
10086         N_("UNLINKED"),         /* 17 */
10087         N_("HTREE INDEX CLEARED"),/* 18 */
10088         N_("WILL RECREATE"),    /* 19 */
10089         "",                     /* 20 */
10090 };
10091
10092 static const struct e2fsck_problem problem_table[] = {
10093
10094         /* Pre-Pass 1 errors */
10095
10096         /* Block bitmap not in group */
10097         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
10098           PROMPT_RELOCATE, PR_LATCH_RELOC },
10099
10100         /* Inode bitmap not in group */
10101         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
10102           PROMPT_RELOCATE, PR_LATCH_RELOC },
10103
10104         /* Inode table not in group */
10105         { PR_0_ITABLE_NOT_GROUP,
10106           N_("@i table for @g %g is not in @g.  (@b %b)\n"
10107           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10108           PROMPT_RELOCATE, PR_LATCH_RELOC },
10109
10110         /* Superblock corrupt */
10111         { PR_0_SB_CORRUPT,
10112           N_("\nThe @S could not be read or does not describe a correct ext2\n"
10113           "@f.  If the @v is valid and it really contains an ext2\n"
10114           "@f (and not swap or ufs or something else), then the @S\n"
10115           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10116           "    e2fsck -b %S <@v>\n\n"),
10117           PROMPT_NONE, PR_FATAL },
10118
10119         /* Filesystem size is wrong */
10120         { PR_0_FS_SIZE_WRONG,
10121           N_("The @f size (according to the @S) is %b @bs\n"
10122           "The physical size of the @v is %c @bs\n"
10123           "Either the @S or the partition table is likely to be corrupt!\n"),
10124           PROMPT_ABORT, 0 },
10125
10126         /* Fragments not supported */
10127         { PR_0_NO_FRAGMENTS,
10128           N_("@S @b_size = %b, fragsize = %c.\n"
10129           "This version of e2fsck does not support fragment sizes different\n"
10130           "from the @b size.\n"),
10131           PROMPT_NONE, PR_FATAL },
10132
10133           /* Bad blocks_per_group */
10134         { PR_0_BLOCKS_PER_GROUP,
10135           N_("@S @bs_per_group = %b, should have been %c\n"),
10136           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10137
10138         /* Bad first_data_block */
10139         { PR_0_FIRST_DATA_BLOCK,
10140           N_("@S first_data_@b = %b, should have been %c\n"),
10141           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10142
10143         /* Adding UUID to filesystem */
10144         { PR_0_ADD_UUID,
10145           N_("@f did not have a UUID; generating one.\n\n"),
10146           PROMPT_NONE, 0 },
10147
10148         /* Relocate hint */
10149         { PR_0_RELOCATE_HINT,
10150           N_("Note: if there is several inode or block bitmap blocks\n"
10151           "which require relocation, or one part of the inode table\n"
10152           "which must be moved, you may wish to try running e2fsck\n"
10153           "with the '-b %S' option first.  The problem may lie only\n"
10154           "with the primary block group descriptor, and the backup\n"
10155           "block group descriptor may be OK.\n\n"),
10156           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10157
10158         /* Miscellaneous superblock corruption */
10159         { PR_0_MISC_CORRUPT_SUPER,
10160           N_("Corruption found in @S.  (%s = %N).\n"),
10161           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10162
10163         /* Error determing physical device size of filesystem */
10164         { PR_0_GETSIZE_ERROR,
10165           N_("Error determining size of the physical @v: %m\n"),
10166           PROMPT_NONE, PR_FATAL },
10167
10168         /* Inode count in superblock is incorrect */
10169         { PR_0_INODE_COUNT_WRONG,
10170           N_("@i count in @S is %i, should be %j.\n"),
10171           PROMPT_FIX, 0 },
10172
10173         { PR_0_HURD_CLEAR_FILETYPE,
10174           N_("The Hurd does not support the filetype feature.\n"),
10175           PROMPT_CLEAR, 0 },
10176
10177         /* Journal inode is invalid */
10178         { PR_0_JOURNAL_BAD_INODE,
10179           N_("@S has a bad ext3 @j (@i %i).\n"),
10180           PROMPT_CLEAR, PR_PREEN_OK },
10181
10182         /* The external journal has (unsupported) multiple filesystems */
10183         { PR_0_JOURNAL_UNSUPP_MULTIFS,
10184           N_("External @j has multiple @f users (unsupported).\n"),
10185           PROMPT_NONE, PR_FATAL },
10186
10187         /* Can't find external journal */
10188         { PR_0_CANT_FIND_JOURNAL,
10189           N_("Can't find external @j\n"),
10190           PROMPT_NONE, PR_FATAL },
10191
10192         /* External journal has bad superblock */
10193         { PR_0_EXT_JOURNAL_BAD_SUPER,
10194           N_("External @j has bad @S\n"),
10195           PROMPT_NONE, PR_FATAL },
10196
10197         /* Superblock has a bad journal UUID */
10198         { PR_0_JOURNAL_BAD_UUID,
10199           N_("External @j does not support this @f\n"),
10200           PROMPT_NONE, PR_FATAL },
10201
10202         /* Journal has an unknown superblock type */
10203         { PR_0_JOURNAL_UNSUPP_SUPER,
10204           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10205              "It is likely that your copy of e2fsck is old and/or doesn't "
10206              "support this @j format.\n"
10207              "It is also possible the @j @S is corrupt.\n"),
10208           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10209
10210         /* Journal superblock is corrupt */
10211         { PR_0_JOURNAL_BAD_SUPER,
10212           N_("Ext3 @j @S is corrupt.\n"),
10213           PROMPT_FIX, PR_PREEN_OK },
10214
10215         /* Superblock flag should be cleared */
10216         { PR_0_JOURNAL_HAS_JOURNAL,
10217           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10218           PROMPT_CLEAR, PR_PREEN_OK },
10219
10220         /* Superblock flag is incorrect */
10221         { PR_0_JOURNAL_RECOVER_SET,
10222           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10223           PROMPT_CLEAR, PR_PREEN_OK },
10224
10225         /* Journal has data, but recovery flag is clear */
10226         { PR_0_JOURNAL_RECOVERY_CLEAR,
10227           N_("ext3 recovery flag clear, but @j has data.\n"),
10228           PROMPT_NONE, 0 },
10229
10230         /* Ask if we should clear the journal */
10231         { PR_0_JOURNAL_RESET_JOURNAL,
10232           N_("Clear @j"),
10233           PROMPT_NULL, PR_PREEN_NOMSG },
10234
10235         /* Ask if we should run the journal anyway */
10236         { PR_0_JOURNAL_RUN,
10237           N_("Run @j anyway"),
10238           PROMPT_NULL, 0 },
10239
10240         /* Run the journal by default */
10241         { PR_0_JOURNAL_RUN_DEFAULT,
10242           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10243           PROMPT_NONE, 0 },
10244
10245         /* Clearing orphan inode */
10246         { PR_0_ORPHAN_CLEAR_INODE,
10247           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10248           PROMPT_NONE, 0 },
10249
10250         /* Illegal block found in orphaned inode */
10251         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10252            N_("@I @b #%B (%b) found in @o @i %i.\n"),
10253           PROMPT_NONE, 0 },
10254
10255         /* Already cleared block found in orphaned inode */
10256         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10257            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10258           PROMPT_NONE, 0 },
10259
10260         /* Illegal orphan inode in superblock */
10261         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10262           N_("@I @o @i %i in @S.\n"),
10263           PROMPT_NONE, 0 },
10264
10265         /* Illegal inode in orphaned inode list */
10266         { PR_0_ORPHAN_ILLEGAL_INODE,
10267           N_("@I @i %i in @o @i list.\n"),
10268           PROMPT_NONE, 0 },
10269
10270         /* Filesystem revision is 0, but feature flags are set */
10271         { PR_0_FS_REV_LEVEL,
10272           "@f has feature flag(s) set, but is a revision 0 @f.  ",
10273           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10274
10275         /* Journal superblock has an unknown read-only feature flag set */
10276         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10277           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10278           PROMPT_ABORT, 0 },
10279
10280         /* Journal superblock has an unknown incompatible feature flag set */
10281         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10282           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10283           PROMPT_ABORT, 0 },
10284
10285         /* Journal has unsupported version number */
10286         { PR_0_JOURNAL_UNSUPP_VERSION,
10287           N_("@j version not supported by this e2fsck.\n"),
10288           PROMPT_ABORT, 0 },
10289
10290         /* Moving journal to hidden file */
10291         { PR_0_MOVE_JOURNAL,
10292           N_("Moving @j from /%s to hidden inode.\n\n"),
10293           PROMPT_NONE, 0 },
10294
10295         /* Error moving journal to hidden file */
10296         { PR_0_ERR_MOVE_JOURNAL,
10297           N_("Error moving @j: %m\n\n"),
10298           PROMPT_NONE, 0 },
10299
10300         /* Clearing V2 journal superblock */
10301         { PR_0_CLEAR_V2_JOURNAL,
10302           N_("Found invalid V2 @j @S fields (from V1 journal).\n"
10303              "Clearing fields beyond the V1 @j @S...\n\n"),
10304           PROMPT_NONE, 0 },
10305
10306         /* Backup journal inode blocks */
10307         { PR_0_BACKUP_JNL,
10308           N_("Backing up @j @i @b information.\n\n"),
10309           PROMPT_NONE, 0 },
10310
10311         /* Reserved blocks w/o resize_inode */
10312         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10313           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10314              "is %N; @s zero.  "),
10315           PROMPT_FIX, 0 },
10316
10317         /* Resize_inode not enabled, but resize inode is non-zero */
10318         { PR_0_CLEAR_RESIZE_INODE,
10319           N_("Resize_@i not enabled, but the resize inode is non-zero.  "),
10320           PROMPT_CLEAR, 0 },
10321
10322         /* Resize inode invalid */
10323         { PR_0_RESIZE_INODE_INVALID,
10324           N_("Resize @i not valid.  "),
10325           PROMPT_RECREATE, 0 },
10326
10327         /* Pass 1 errors */
10328
10329         /* Pass 1: Checking inodes, blocks, and sizes */
10330         { PR_1_PASS_HEADER,
10331           N_("Pass 1: Checking @is, @bs, and sizes\n"),
10332           PROMPT_NONE, 0 },
10333
10334         /* Root directory is not an inode */
10335         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
10336           PROMPT_CLEAR, 0 },
10337
10338         /* Root directory has dtime set */
10339         { PR_1_ROOT_DTIME,
10340           N_("@r has dtime set (probably due to old mke2fs).  "),
10341           PROMPT_FIX, PR_PREEN_OK },
10342
10343         /* Reserved inode has bad mode */
10344         { PR_1_RESERVED_BAD_MODE,
10345           N_("Reserved @i %i %Q has bad mode.  "),
10346           PROMPT_CLEAR, PR_PREEN_OK },
10347
10348         /* Deleted inode has zero dtime */
10349         { PR_1_ZERO_DTIME,
10350           N_("@D @i %i has zero dtime.  "),
10351           PROMPT_FIX, PR_PREEN_OK },
10352
10353         /* Inode in use, but dtime set */
10354         { PR_1_SET_DTIME,
10355           N_("@i %i is in use, but has dtime set.  "),
10356           PROMPT_FIX, PR_PREEN_OK },
10357
10358         /* Zero-length directory */
10359         { PR_1_ZERO_LENGTH_DIR,
10360           N_("@i %i is a @z @d.  "),
10361           PROMPT_CLEAR, PR_PREEN_OK },
10362
10363         /* Block bitmap conflicts with some other fs block */
10364         { PR_1_BB_CONFLICT,
10365           N_("@g %g's @b @B at %b @C.\n"),
10366           PROMPT_RELOCATE, 0 },
10367
10368         /* Inode bitmap conflicts with some other fs block */
10369         { PR_1_IB_CONFLICT,
10370           N_("@g %g's @i @B at %b @C.\n"),
10371           PROMPT_RELOCATE, 0 },
10372
10373         /* Inode table conflicts with some other fs block */
10374         { PR_1_ITABLE_CONFLICT,
10375           N_("@g %g's @i table at %b @C.\n"),
10376           PROMPT_RELOCATE, 0 },
10377
10378         /* Block bitmap is on a bad block */
10379         { PR_1_BB_BAD_BLOCK,
10380           N_("@g %g's @b @B (%b) is bad.  "),
10381           PROMPT_RELOCATE, 0 },
10382
10383         /* Inode bitmap is on a bad block */
10384         { PR_1_IB_BAD_BLOCK,
10385           N_("@g %g's @i @B (%b) is bad.  "),
10386           PROMPT_RELOCATE, 0 },
10387
10388         /* Inode has incorrect i_size */
10389         { PR_1_BAD_I_SIZE,
10390           N_("@i %i, i_size is %Is, @s %N.  "),
10391           PROMPT_FIX, PR_PREEN_OK },
10392
10393         /* Inode has incorrect i_blocks */
10394         { PR_1_BAD_I_BLOCKS,
10395           N_("@i %i, i_@bs is %Ib, @s %N.  "),
10396           PROMPT_FIX, PR_PREEN_OK },
10397
10398         /* Illegal blocknumber in inode */
10399         { PR_1_ILLEGAL_BLOCK_NUM,
10400           N_("@I @b #%B (%b) in @i %i.  "),
10401           PROMPT_CLEAR, PR_LATCH_BLOCK },
10402
10403         /* Block number overlaps fs metadata */
10404         { PR_1_BLOCK_OVERLAPS_METADATA,
10405           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
10406           PROMPT_CLEAR, PR_LATCH_BLOCK },
10407
10408         /* Inode has illegal blocks (latch question) */
10409         { PR_1_INODE_BLOCK_LATCH,
10410           N_("@i %i has illegal @b(s).  "),
10411           PROMPT_CLEAR, 0 },
10412
10413         /* Too many bad blocks in inode */
10414         { PR_1_TOO_MANY_BAD_BLOCKS,
10415           N_("Too many illegal @bs in @i %i.\n"),
10416           PROMPT_CLEAR_INODE, PR_NO_OK },
10417
10418         /* Illegal block number in bad block inode */
10419         { PR_1_BB_ILLEGAL_BLOCK_NUM,
10420           N_("@I @b #%B (%b) in bad @b @i.  "),
10421           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10422
10423         /* Bad block inode has illegal blocks (latch question) */
10424         { PR_1_INODE_BBLOCK_LATCH,
10425           N_("Bad @b @i has illegal @b(s).  "),
10426           PROMPT_CLEAR, 0 },
10427
10428         /* Duplicate or bad blocks in use! */
10429         { PR_1_DUP_BLOCKS_PREENSTOP,
10430           N_("Duplicate or bad @b in use!\n"),
10431           PROMPT_NONE, 0 },
10432
10433         /* Bad block used as bad block indirect block */
10434         { PR_1_BBINODE_BAD_METABLOCK,
10435           N_("Bad @b %b used as bad @b @i indirect @b.  "),
10436           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10437
10438         /* Inconsistency can't be fixed prompt */
10439         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10440           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
10441              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10442              "in the @f.\n"),
10443           PROMPT_CONTINUE, PR_PREEN_NOMSG },
10444
10445         /* Bad primary block */
10446         { PR_1_BAD_PRIMARY_BLOCK,
10447           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10448           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10449
10450         /* Bad primary block prompt */
10451         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10452           N_("You can clear the this @b (and hope for the best) from the\n"
10453           "bad @b list and hope that @b is really OK, but there are no\n"
10454           "guarantees.\n\n"),
10455           PROMPT_CLEAR, PR_PREEN_NOMSG },
10456
10457         /* Bad primary superblock */
10458         { PR_1_BAD_PRIMARY_SUPERBLOCK,
10459           N_("The primary @S (%b) is on the bad @b list.\n"),
10460           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10461
10462         /* Bad primary block group descriptors */
10463         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10464           N_("Block %b in the primary @g descriptors "
10465           "is on the bad @b list\n"),
10466           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10467
10468         /* Bad superblock in group */
10469         { PR_1_BAD_SUPERBLOCK,
10470           N_("Warning: Group %g's @S (%b) is bad.\n"),
10471           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10472
10473         /* Bad block group descriptors in group */
10474         { PR_1_BAD_GROUP_DESCRIPTORS,
10475           N_("Warning: Group %g's copy of the @g descriptors has a bad "
10476           "@b (%b).\n"),
10477           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10478
10479         /* Block claimed for no reason */
10480         { PR_1_PROGERR_CLAIMED_BLOCK,
10481           N_("Programming error?  @b #%b claimed for no reason in "
10482           "process_bad_@b.\n"),
10483           PROMPT_NONE, PR_PREEN_OK },
10484
10485         /* Error allocating blocks for relocating metadata */
10486         { PR_1_RELOC_BLOCK_ALLOCATE,
10487           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10488           PROMPT_NONE, PR_PREEN_OK },
10489
10490         /* Error allocating block buffer during relocation process */
10491         { PR_1_RELOC_MEMORY_ALLOCATE,
10492           N_("@A @b buffer for relocating %s\n"),
10493           PROMPT_NONE, PR_PREEN_OK },
10494
10495         /* Relocating metadata group information from X to Y */
10496         { PR_1_RELOC_FROM_TO,
10497           N_("Relocating @g %g's %s from %b to %c...\n"),
10498           PROMPT_NONE, PR_PREEN_OK },
10499
10500         /* Relocating metatdata group information to X */
10501         { PR_1_RELOC_TO,
10502           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10503           PROMPT_NONE, PR_PREEN_OK },
10504
10505         /* Block read error during relocation process */
10506         { PR_1_RELOC_READ_ERR,
10507           N_("Warning: could not read @b %b of %s: %m\n"),
10508           PROMPT_NONE, PR_PREEN_OK },
10509
10510         /* Block write error during relocation process */
10511         { PR_1_RELOC_WRITE_ERR,
10512           N_("Warning: could not write @b %b for %s: %m\n"),
10513           PROMPT_NONE, PR_PREEN_OK },
10514
10515         /* Error allocating inode bitmap */
10516         { PR_1_ALLOCATE_IBITMAP_ERROR,
10517           "@A @i @B (%N): %m\n",
10518           PROMPT_NONE, PR_FATAL },
10519
10520         /* Error allocating block bitmap */
10521         { PR_1_ALLOCATE_BBITMAP_ERROR,
10522           "@A @b @B (%N): %m\n",
10523           PROMPT_NONE, PR_FATAL },
10524
10525         /* Error allocating icount structure */
10526         { PR_1_ALLOCATE_ICOUNT,
10527           N_("@A icount link information: %m\n"),
10528           PROMPT_NONE, PR_FATAL },
10529
10530         /* Error allocating dbcount */
10531         { PR_1_ALLOCATE_DBCOUNT,
10532           N_("@A @d @b array: %m\n"),
10533           PROMPT_NONE, PR_FATAL },
10534
10535         /* Error while scanning inodes */
10536         { PR_1_ISCAN_ERROR,
10537           N_("Error while scanning @is (%i): %m\n"),
10538           PROMPT_NONE, PR_FATAL },
10539
10540         /* Error while iterating over blocks */
10541         { PR_1_BLOCK_ITERATE,
10542           N_("Error while iterating over @bs in @i %i: %m\n"),
10543           PROMPT_NONE, PR_FATAL },
10544
10545         /* Error while storing inode count information */
10546         { PR_1_ICOUNT_STORE,
10547           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10548           PROMPT_NONE, PR_FATAL },
10549
10550         /* Error while storing directory block information */
10551         { PR_1_ADD_DBLOCK,
10552           N_("Error storing @d @b information "
10553           "(@i=%i, @b=%b, num=%N): %m\n"),
10554           PROMPT_NONE, PR_FATAL },
10555
10556         /* Error while reading inode (for clearing) */
10557         { PR_1_READ_INODE,
10558           N_("Error reading @i %i: %m\n"),
10559           PROMPT_NONE, PR_FATAL },
10560
10561         /* Suppress messages prompt */
10562         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10563
10564         /* Imagic flag set on an inode when filesystem doesn't support it */
10565         { PR_1_SET_IMAGIC,
10566           N_("@i %i has imagic flag set.  "),
10567           PROMPT_CLEAR, 0 },
10568
10569         /* Immutable flag set on a device or socket inode */
10570         { PR_1_SET_IMMUTABLE,
10571           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10572              "or append-only flag set.  "),
10573           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10574
10575         /* Compression flag set on an inode when filesystem doesn't support it */
10576         { PR_1_COMPR_SET,
10577           N_("@i %i has @cion flag set on @f without @cion support.  "),
10578           PROMPT_CLEAR, 0 },
10579
10580         /* Non-zero size for device, fifo or socket inode */
10581         { PR_1_SET_NONZSIZE,
10582           "Special (@v/socket/fifo) @i %i has non-zero size.  ",
10583           PROMPT_FIX, PR_PREEN_OK },
10584
10585         /* Filesystem revision is 0, but feature flags are set */
10586         { PR_1_FS_REV_LEVEL,
10587           "@f has feature flag(s) set, but is a revision 0 @f.  ",
10588           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10589
10590         /* Journal inode is not in use, but contains data */
10591         { PR_1_JOURNAL_INODE_NOT_CLEAR,
10592           "@j @i is not in use, but contains data.  ",
10593           PROMPT_CLEAR, PR_PREEN_OK },
10594
10595         /* Journal has bad mode */
10596         { PR_1_JOURNAL_BAD_MODE,
10597           N_("@j is not regular file.  "),
10598           PROMPT_FIX, PR_PREEN_OK },
10599
10600         /* Deal with inodes that were part of orphan linked list */
10601         { PR_1_LOW_DTIME,
10602           N_("@i %i was part of the orphaned @i list.  "),
10603           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10604
10605         /* Deal with inodes that were part of corrupted orphan linked
10606            list (latch question) */
10607         { PR_1_ORPHAN_LIST_REFUGEES,
10608           N_("@is that were part of a corrupted orphan linked list found.  "),
10609           PROMPT_FIX, 0 },
10610
10611         /* Error allocating refcount structure */
10612         { PR_1_ALLOCATE_REFCOUNT,
10613           "@A refcount structure (%N): %m\n",
10614           PROMPT_NONE, PR_FATAL },
10615
10616         /* Error reading extended attribute block */
10617         { PR_1_READ_EA_BLOCK,
10618           N_("Error reading @a @b %b for @i %i.  "),
10619           PROMPT_CLEAR, 0 },
10620
10621         /* Invalid extended attribute block */
10622         { PR_1_BAD_EA_BLOCK,
10623           N_("@i %i has a bad @a @b %b.  "),
10624           PROMPT_CLEAR, 0 },
10625
10626         /* Error reading Extended Attribute block while fixing refcount */
10627         { PR_1_EXTATTR_READ_ABORT,
10628           N_("Error reading @a @b %b (%m).  "),
10629           PROMPT_ABORT, 0 },
10630
10631         /* Extended attribute reference count incorrect */
10632         { PR_1_EXTATTR_REFCOUNT,
10633           N_("@a @b %b has reference count %B, should be %N.  "),
10634           PROMPT_FIX, 0 },
10635
10636         /* Error writing Extended Attribute block while fixing refcount */
10637         { PR_1_EXTATTR_WRITE,
10638           N_("Error writing @a @b %b (%m).  "),
10639           PROMPT_ABORT, 0 },
10640
10641         /* Multiple EA blocks not supported */
10642         { PR_1_EA_MULTI_BLOCK,
10643           N_("@a @b %b has h_blocks > 1.  "),
10644           PROMPT_CLEAR, 0},
10645
10646         /* Error allocating EA region allocation structure */
10647         { PR_1_EA_ALLOC_REGION,
10648           N_("Error allocating @a @b %b.  "),
10649           PROMPT_ABORT, 0},
10650
10651         /* Error EA allocation collision */
10652         { PR_1_EA_ALLOC_COLLISION,
10653           N_("@a @b %b is corrupt (allocation collision).  "),
10654           PROMPT_CLEAR, 0},
10655
10656         /* Bad extended attribute name */
10657         { PR_1_EA_BAD_NAME,
10658           N_("@a @b %b is corrupt (invalid name).  "),
10659           PROMPT_CLEAR, 0},
10660
10661         /* Bad extended attribute value */
10662         { PR_1_EA_BAD_VALUE,
10663           N_("@a @b %b is corrupt (invalid value).  "),
10664           PROMPT_CLEAR, 0},
10665
10666         /* Inode too big (latch question) */
10667         { PR_1_INODE_TOOBIG,
10668           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
10669
10670         /* Directory too big */
10671         { PR_1_TOOBIG_DIR,
10672           N_("@b #%B (%b) causes @d to be too big.  "),
10673           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10674
10675         /* Regular file too big */
10676         { PR_1_TOOBIG_REG,
10677           N_("@b #%B (%b) causes file to be too big.  "),
10678           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10679
10680         /* Symlink too big */
10681         { PR_1_TOOBIG_SYMLINK,
10682           N_("@b #%B (%b) causes symlink to be too big.  "),
10683           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10684
10685         /* INDEX_FL flag set on a non-HTREE filesystem */
10686         { PR_1_HTREE_SET,
10687           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10688           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10689
10690         /* INDEX_FL flag set on a non-directory */
10691         { PR_1_HTREE_NODIR,
10692           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10693           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10694
10695         /* Invalid root node in HTREE directory */
10696         { PR_1_HTREE_BADROOT,
10697           N_("@h %i has an invalid root node.\n"),
10698           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10699
10700         /* Unsupported hash version in HTREE directory */
10701         { PR_1_HTREE_HASHV,
10702           N_("@h %i has an unsupported hash version (%N)\n"),
10703           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10704
10705         /* Incompatible flag in HTREE root node */
10706         { PR_1_HTREE_INCOMPAT,
10707           N_("@h %i uses an incompatible htree root node flag.\n"),
10708           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10709
10710         /* HTREE too deep */
10711         { PR_1_HTREE_DEPTH,
10712           N_("@h %i has a tree depth (%N) which is too big\n"),
10713           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10714
10715         /* Bad block has indirect block that conflicts with filesystem block */
10716         { PR_1_BB_FS_BLOCK,
10717           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10718              "@f metadata.  "),
10719           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10720
10721         /* Resize inode failed */
10722         { PR_1_RESIZE_INODE_CREATE,
10723           N_("Resize @i (re)creation failed: %m."),
10724           PROMPT_ABORT, 0 },
10725
10726         /* invalid inode->i_extra_isize */
10727         { PR_1_EXTRA_ISIZE,
10728           N_("@i %i has a extra size (%IS) which is invalid\n"),
10729           PROMPT_FIX, PR_PREEN_OK },
10730
10731         /* invalid ea entry->e_name_len */
10732         { PR_1_ATTR_NAME_LEN,
10733           N_("@a in @i %i has a namelen (%N) which is invalid\n"),
10734           PROMPT_CLEAR, PR_PREEN_OK },
10735
10736         /* invalid ea entry->e_value_size */
10737         { PR_1_ATTR_VALUE_SIZE,
10738           N_("@a in @i %i has a value size (%N) which is invalid\n"),
10739           PROMPT_CLEAR, PR_PREEN_OK },
10740
10741         /* invalid ea entry->e_value_offs */
10742         { PR_1_ATTR_VALUE_OFFSET,
10743           N_("@a in @i %i has a value offset (%N) which is invalid\n"),
10744           PROMPT_CLEAR, PR_PREEN_OK },
10745
10746         /* invalid ea entry->e_value_block */
10747         { PR_1_ATTR_VALUE_BLOCK,
10748           N_("@a in @i %i has a value block (%N) which is invalid (must be 0)\n"),
10749           PROMPT_CLEAR, PR_PREEN_OK },
10750
10751         /* invalid ea entry->e_hash */
10752         { PR_1_ATTR_HASH,
10753           N_("@a in @i %i has a hash (%N) which is invalid (must be 0)\n"),
10754           PROMPT_CLEAR, PR_PREEN_OK },
10755
10756         /* Pass 1b errors */
10757
10758         /* Pass 1B: Rescan for duplicate/bad blocks */
10759         { PR_1B_PASS_HEADER,
10760           N_("Duplicate @bs found... invoking duplicate @b passes.\n"
10761           "Pass 1B: Rescan for duplicate/bad @bs\n"),
10762           PROMPT_NONE, 0 },
10763
10764         /* Duplicate/bad block(s) header */
10765         { PR_1B_DUP_BLOCK_HEADER,
10766           N_("Duplicate/bad @b(s) in @i %i:"),
10767           PROMPT_NONE, 0 },
10768
10769         /* Duplicate/bad block(s) in inode */
10770         { PR_1B_DUP_BLOCK,
10771           " %b",
10772           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10773
10774         /* Duplicate/bad block(s) end */
10775         { PR_1B_DUP_BLOCK_END,
10776           "\n",
10777           PROMPT_NONE, PR_PREEN_NOHDR },
10778
10779         /* Error while scanning inodes */
10780         { PR_1B_ISCAN_ERROR,
10781           N_("Error while scanning inodes (%i): %m\n"),
10782           PROMPT_NONE, PR_FATAL },
10783
10784         /* Error allocating inode bitmap */
10785         { PR_1B_ALLOCATE_IBITMAP_ERROR,
10786           N_("@A @i @B (inode_dup_map): %m\n"),
10787           PROMPT_NONE, PR_FATAL },
10788
10789         /* Error while iterating over blocks */
10790         { PR_1B_BLOCK_ITERATE,
10791           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10792           PROMPT_NONE, 0 },
10793
10794         /* Error adjusting EA refcount */
10795         { PR_1B_ADJ_EA_REFCOUNT,
10796           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
10797           PROMPT_NONE, 0 },
10798
10799
10800         /* Pass 1C: Scan directories for inodes with dup blocks. */
10801         { PR_1C_PASS_HEADER,
10802           N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
10803           PROMPT_NONE, 0 },
10804
10805
10806         /* Pass 1D: Reconciling duplicate blocks */
10807         { PR_1D_PASS_HEADER,
10808           N_("Pass 1D: Reconciling duplicate @bs\n"),
10809           PROMPT_NONE, 0 },
10810
10811         /* File has duplicate blocks */
10812         { PR_1D_DUP_FILE,
10813           N_("File %Q (@i #%i, mod time %IM) \n"
10814           "  has %B duplicate @b(s), shared with %N file(s):\n"),
10815           PROMPT_NONE, 0 },
10816
10817         /* List of files sharing duplicate blocks */
10818         { PR_1D_DUP_FILE_LIST,
10819           N_("\t%Q (@i #%i, mod time %IM)\n"),
10820           PROMPT_NONE, 0 },
10821
10822         /* File sharing blocks with filesystem metadata  */
10823         { PR_1D_SHARE_METADATA,
10824           N_("\t<@f metadata>\n"),
10825           PROMPT_NONE, 0 },
10826
10827         /* Report of how many duplicate/bad inodes */
10828         { PR_1D_NUM_DUP_INODES,
10829           N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
10830           PROMPT_NONE, 0 },
10831
10832         /* Duplicated blocks already reassigned or cloned. */
10833         { PR_1D_DUP_BLOCKS_DEALT,
10834           N_("Duplicated @bs already reassigned or cloned.\n\n"),
10835           PROMPT_NONE, 0 },
10836
10837         /* Clone duplicate/bad blocks? */
10838         { PR_1D_CLONE_QUESTION,
10839           "", PROMPT_CLONE, PR_NO_OK },
10840
10841         /* Delete file? */
10842         { PR_1D_DELETE_QUESTION,
10843           "", PROMPT_DELETE, 0 },
10844
10845         /* Couldn't clone file (error) */
10846         { PR_1D_CLONE_ERROR,
10847           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10848
10849         /* Pass 2 errors */
10850
10851         /* Pass 2: Checking directory structure */
10852         { PR_2_PASS_HEADER,
10853           N_("Pass 2: Checking @d structure\n"),
10854           PROMPT_NONE, 0 },
10855
10856         /* Bad inode number for '.' */
10857         { PR_2_BAD_INODE_DOT,
10858           N_("Bad @i number for '.' in @d @i %i.\n"),
10859           PROMPT_FIX, 0 },
10860
10861         /* Directory entry has bad inode number */
10862         { PR_2_BAD_INO,
10863           N_("@E has bad @i #: %Di.\n"),
10864           PROMPT_CLEAR, 0 },
10865
10866         /* Directory entry has deleted or unused inode */
10867         { PR_2_UNUSED_INODE,
10868           N_("@E has @D/unused @i %Di.  "),
10869           PROMPT_CLEAR, PR_PREEN_OK },
10870
10871         /* Directry entry is link to '.' */
10872         { PR_2_LINK_DOT,
10873           N_("@E @L to '.'  "),
10874           PROMPT_CLEAR, 0 },
10875
10876         /* Directory entry points to inode now located in a bad block */
10877         { PR_2_BB_INODE,
10878           N_("@E points to @i (%Di) located in a bad @b.\n"),
10879           PROMPT_CLEAR, 0 },
10880
10881         /* Directory entry contains a link to a directory */
10882         { PR_2_LINK_DIR,
10883           N_("@E @L to @d %P (%Di).\n"),
10884           PROMPT_CLEAR, 0 },
10885
10886         /* Directory entry contains a link to the root directry */
10887         { PR_2_LINK_ROOT,
10888           N_("@E @L to the @r.\n"),
10889           PROMPT_CLEAR, 0 },
10890
10891         /* Directory entry has illegal characters in its name */
10892         { PR_2_BAD_NAME,
10893           N_("@E has illegal characters in its name.\n"),
10894           PROMPT_FIX, 0 },
10895
10896         /* Missing '.' in directory inode */
10897         { PR_2_MISSING_DOT,
10898           N_("Missing '.' in @d @i %i.\n"),
10899           PROMPT_FIX, 0 },
10900
10901         /* Missing '..' in directory inode */
10902         { PR_2_MISSING_DOT_DOT,
10903           N_("Missing '..' in @d @i %i.\n"),
10904           PROMPT_FIX, 0 },
10905
10906         /* First entry in directory inode doesn't contain '.' */
10907         { PR_2_1ST_NOT_DOT,
10908           N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
10909           PROMPT_FIX, 0 },
10910
10911         /* Second entry in directory inode doesn't contain '..' */
10912         { PR_2_2ND_NOT_DOT_DOT,
10913           N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
10914           PROMPT_FIX, 0 },
10915
10916         /* i_faddr should be zero */
10917         { PR_2_FADDR_ZERO,
10918           N_("i_faddr @F %IF, @s zero.\n"),
10919           PROMPT_CLEAR, 0 },
10920
10921         /* i_file_acl should be zero */
10922         { PR_2_FILE_ACL_ZERO,
10923           N_("i_file_acl @F %If, @s zero.\n"),
10924           PROMPT_CLEAR, 0 },
10925
10926         /* i_dir_acl should be zero */
10927         { PR_2_DIR_ACL_ZERO,
10928           N_("i_dir_acl @F %Id, @s zero.\n"),
10929           PROMPT_CLEAR, 0 },
10930
10931         /* i_frag should be zero */
10932         { PR_2_FRAG_ZERO,
10933           N_("i_frag @F %N, @s zero.\n"),
10934           PROMPT_CLEAR, 0 },
10935
10936         /* i_fsize should be zero */
10937         { PR_2_FSIZE_ZERO,
10938           N_("i_fsize @F %N, @s zero.\n"),
10939           PROMPT_CLEAR, 0 },
10940
10941         /* inode has bad mode */
10942         { PR_2_BAD_MODE,
10943           N_("@i %i (%Q) has a bad mode (%Im).\n"),
10944           PROMPT_CLEAR, 0 },
10945
10946         /* directory corrupted */
10947         { PR_2_DIR_CORRUPTED,
10948           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
10949           PROMPT_SALVAGE, 0 },
10950
10951         /* filename too long */
10952         { PR_2_FILENAME_LONG,
10953           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
10954           PROMPT_TRUNCATE, 0 },
10955
10956         /* Directory inode has a missing block (hole) */
10957         { PR_2_DIRECTORY_HOLE,
10958           N_("@d @i %i has an unallocated @b #%B.  "),
10959           PROMPT_ALLOCATE, 0 },
10960
10961         /* '.' is not NULL terminated */
10962         { PR_2_DOT_NULL_TERM,
10963           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
10964           PROMPT_FIX, 0 },
10965
10966         /* '..' is not NULL terminated */
10967         { PR_2_DOT_DOT_NULL_TERM,
10968           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
10969           PROMPT_FIX, 0 },
10970
10971         /* Illegal character device inode */
10972         { PR_2_BAD_CHAR_DEV,
10973           N_("@i %i (%Q) is an @I character @v.\n"),
10974           PROMPT_CLEAR, 0 },
10975
10976         /* Illegal block device inode */
10977         { PR_2_BAD_BLOCK_DEV,
10978           N_("@i %i (%Q) is an @I @b @v.\n"),
10979           PROMPT_CLEAR, 0 },
10980
10981         /* Duplicate '.' entry */
10982         { PR_2_DUP_DOT,
10983           N_("@E is duplicate '.' @e.\n"),
10984           PROMPT_FIX, 0 },
10985
10986         /* Duplicate '..' entry */
10987         { PR_2_DUP_DOT_DOT,
10988           N_("@E is duplicate '..' @e.\n"),
10989           PROMPT_FIX, 0 },
10990
10991         /* Internal error: couldn't find dir_info */
10992         { PR_2_NO_DIRINFO,
10993           N_("Internal error: couldn't find dir_info for %i.\n"),
10994           PROMPT_NONE, PR_FATAL },
10995
10996         /* Final rec_len is wrong */
10997         { PR_2_FINAL_RECLEN,
10998           N_("@E has rec_len of %Dr, should be %N.\n"),
10999           PROMPT_FIX, 0 },
11000
11001         /* Error allocating icount structure */
11002         { PR_2_ALLOCATE_ICOUNT,
11003           N_("@A icount structure: %m\n"),
11004           PROMPT_NONE, PR_FATAL },
11005
11006         /* Error iterating over directory blocks */
11007         { PR_2_DBLIST_ITERATE,
11008           N_("Error iterating over @d @bs: %m\n"),
11009           PROMPT_NONE, PR_FATAL },
11010
11011         /* Error reading directory block */
11012         { PR_2_READ_DIRBLOCK,
11013           N_("Error reading @d @b %b (@i %i): %m\n"),
11014           PROMPT_CONTINUE, 0 },
11015
11016         /* Error writing directory block */
11017         { PR_2_WRITE_DIRBLOCK,
11018           N_("Error writing @d @b %b (@i %i): %m\n"),
11019           PROMPT_CONTINUE, 0 },
11020
11021         /* Error allocating new directory block */
11022         { PR_2_ALLOC_DIRBOCK,
11023           N_("@A new @d @b for @i %i (%s): %m\n"),
11024           PROMPT_NONE, 0 },
11025
11026         /* Error deallocating inode */
11027         { PR_2_DEALLOC_INODE,
11028           N_("Error deallocating @i %i: %m\n"),
11029           PROMPT_NONE, PR_FATAL },
11030
11031         /* Directory entry for '.' is big.  Split? */
11032         { PR_2_SPLIT_DOT,
11033           N_("@d @e for '.' is big.  "),
11034           PROMPT_SPLIT, PR_NO_OK },
11035
11036         /* Illegal FIFO inode */
11037         { PR_2_BAD_FIFO,
11038           N_("@i %i (%Q) is an @I FIFO.\n"),
11039           PROMPT_CLEAR, 0 },
11040
11041         /* Illegal socket inode */
11042         { PR_2_BAD_SOCKET,
11043           N_("@i %i (%Q) is an @I socket.\n"),
11044           PROMPT_CLEAR, 0 },
11045
11046         /* Directory filetype not set */
11047         { PR_2_SET_FILETYPE,
11048           N_("Setting filetype for @E to %N.\n"),
11049           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11050
11051         /* Directory filetype incorrect */
11052         { PR_2_BAD_FILETYPE,
11053           N_("@E has an incorrect filetype (was %Dt, should be %N).\n"),
11054           PROMPT_FIX, 0 },
11055
11056         /* Directory filetype set on filesystem */
11057         { PR_2_CLEAR_FILETYPE,
11058           N_("@E has filetype set.\n"),
11059           PROMPT_CLEAR, PR_PREEN_OK },
11060
11061         /* Directory filename is null */
11062         { PR_2_NULL_NAME,
11063           N_("@E has a zero-length name.\n"),
11064           PROMPT_CLEAR, 0 },
11065
11066         /* Invalid symlink */
11067         { PR_2_INVALID_SYMLINK,
11068           N_("Symlink %Q (@i #%i) is invalid.\n"),
11069           PROMPT_CLEAR, 0 },
11070
11071         /* i_file_acl (extended attribute block) is bad */
11072         { PR_2_FILE_ACL_BAD,
11073           N_("@a @b @F invalid (%If).\n"),
11074           PROMPT_CLEAR, 0 },
11075
11076         /* Filesystem contains large files, but has no such flag in sb */
11077         { PR_2_FEATURE_LARGE_FILES,
11078           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11079           PROMPT_FIX, 0 },
11080
11081         /* Node in HTREE directory not referenced */
11082         { PR_2_HTREE_NOTREF,
11083           N_("@p @h %d: node (%B) not referenced\n"),
11084           PROMPT_NONE, 0 },
11085
11086         /* Node in HTREE directory referenced twice */
11087         { PR_2_HTREE_DUPREF,
11088           N_("@p @h %d: node (%B) referenced twice\n"),
11089           PROMPT_NONE, 0 },
11090
11091         /* Node in HTREE directory has bad min hash */
11092         { PR_2_HTREE_MIN_HASH,
11093           N_("@p @h %d: node (%B) has bad min hash\n"),
11094           PROMPT_NONE, 0 },
11095
11096         /* Node in HTREE directory has bad max hash */
11097         { PR_2_HTREE_MAX_HASH,
11098           N_("@p @h %d: node (%B) has bad max hash\n"),
11099           PROMPT_NONE, 0 },
11100
11101         /* Clear invalid HTREE directory */
11102         { PR_2_HTREE_CLEAR,
11103           N_("Invalid @h %d (%q).  "), PROMPT_CLEAR, 0 },
11104
11105         /* Bad block in htree interior node */
11106         { PR_2_HTREE_BADBLK,
11107           N_("@p @h %d (%q): bad @b number %b.\n"),
11108           PROMPT_CLEAR_HTREE, 0 },
11109
11110         /* Error adjusting EA refcount */
11111         { PR_2_ADJ_EA_REFCOUNT,
11112           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
11113           PROMPT_NONE, PR_FATAL },
11114
11115         /* Invalid HTREE root node */
11116         { PR_2_HTREE_BAD_ROOT,
11117           N_("@p @h %d: root node is invalid\n"),
11118           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11119
11120         /* Invalid HTREE limit */
11121         { PR_2_HTREE_BAD_LIMIT,
11122           N_("@p @h %d: node (%B) has bad limit (%N)\n"),
11123           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11124
11125         /* Invalid HTREE count */
11126         { PR_2_HTREE_BAD_COUNT,
11127           N_("@p @h %d: node (%B) has bad count (%N)\n"),
11128           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11129
11130         /* HTREE interior node has out-of-order hashes in table */
11131         { PR_2_HTREE_HASH_ORDER,
11132           N_("@p @h %d: node (%B) has an unordered hash table\n"),
11133           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11134
11135         /* Node in HTREE directory has bad depth */
11136         { PR_2_HTREE_BAD_DEPTH,
11137           N_("@p @h %d: node (%B) has bad depth\n"),
11138           PROMPT_NONE, 0 },
11139
11140         /* Duplicate directory entry found */
11141         { PR_2_DUPLICATE_DIRENT,
11142           N_("Duplicate @E found.  "),
11143           PROMPT_CLEAR, 0 },
11144
11145         /* Non-unique filename found */
11146         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11147           N_("@E has a non-unique filename.\nRename to %s"),
11148           PROMPT_NULL, 0 },
11149
11150         /* Duplicate directory entry found */
11151         { PR_2_REPORT_DUP_DIRENT,
11152           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11153           PROMPT_NONE, 0 },
11154
11155         /* Pass 3 errors */
11156
11157         /* Pass 3: Checking directory connectivity */
11158         { PR_3_PASS_HEADER,
11159           N_("Pass 3: Checking @d connectivity\n"),
11160           PROMPT_NONE, 0 },
11161
11162         /* Root inode not allocated */
11163         { PR_3_NO_ROOT_INODE,
11164           N_("@r not allocated.  "),
11165           PROMPT_ALLOCATE, 0 },
11166
11167         /* No room in lost+found */
11168         { PR_3_EXPAND_LF_DIR,
11169           N_("No room in @l @d.  "),
11170           PROMPT_EXPAND, 0 },
11171
11172         /* Unconnected directory inode */
11173         { PR_3_UNCONNECTED_DIR,
11174           N_("Unconnected @d @i %i (%p)\n"),
11175           PROMPT_CONNECT, 0 },
11176
11177         /* /lost+found not found */
11178         { PR_3_NO_LF_DIR,
11179           N_("/@l not found.  "),
11180           PROMPT_CREATE, PR_PREEN_OK },
11181
11182         /* .. entry is incorrect */
11183         { PR_3_BAD_DOT_DOT,
11184           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11185           PROMPT_FIX, 0 },
11186
11187         /* Bad or non-existent /lost+found.  Cannot reconnect */
11188         { PR_3_NO_LPF,
11189           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
11190           PROMPT_NONE, 0 },
11191
11192         /* Could not expand /lost+found */
11193         { PR_3_CANT_EXPAND_LPF,
11194           N_("Could not expand /@l: %m\n"),
11195           PROMPT_NONE, 0 },
11196
11197         /* Could not reconnect inode */
11198         { PR_3_CANT_RECONNECT,
11199           N_("Could not reconnect %i: %m\n"),
11200           PROMPT_NONE, 0 },
11201
11202         /* Error while trying to find /lost+found */
11203         { PR_3_ERR_FIND_LPF,
11204           N_("Error while trying to find /@l: %m\n"),
11205           PROMPT_NONE, 0 },
11206
11207         /* Error in ext2fs_new_block while creating /lost+found */
11208         { PR_3_ERR_LPF_NEW_BLOCK,
11209           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11210           PROMPT_NONE, 0 },
11211
11212         /* Error in ext2fs_new_inode while creating /lost+found */
11213         { PR_3_ERR_LPF_NEW_INODE,
11214           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11215           PROMPT_NONE, 0 },
11216
11217         /* Error in ext2fs_new_dir_block while creating /lost+found */
11218         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11219           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11220           PROMPT_NONE, 0 },
11221
11222         /* Error while writing directory block for /lost+found */
11223         { PR_3_ERR_LPF_WRITE_BLOCK,
11224           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11225           PROMPT_NONE, 0 },
11226
11227         /* Error while adjusting inode count */
11228         { PR_3_ADJUST_INODE,
11229           N_("Error while adjusting @i count on @i %i\n"),
11230           PROMPT_NONE, 0 },
11231
11232         /* Couldn't fix parent directory -- error */
11233         { PR_3_FIX_PARENT_ERR,
11234           N_("Couldn't fix parent of @i %i: %m\n\n"),
11235           PROMPT_NONE, 0 },
11236
11237         /* Couldn't fix parent directory -- couldn't find it */
11238         { PR_3_FIX_PARENT_NOFIND,
11239           N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
11240           PROMPT_NONE, 0 },
11241
11242         /* Error allocating inode bitmap */
11243         { PR_3_ALLOCATE_IBITMAP_ERROR,
11244           N_("@A @i @B (%N): %m\n"),
11245           PROMPT_NONE, PR_FATAL },
11246
11247         /* Error creating root directory */
11248         { PR_3_CREATE_ROOT_ERROR,
11249           N_("Error creating root @d (%s): %m\n"),
11250           PROMPT_NONE, PR_FATAL },
11251
11252         /* Error creating lost and found directory */
11253         { PR_3_CREATE_LPF_ERROR,
11254           N_("Error creating /@l @d (%s): %m\n"),
11255           PROMPT_NONE, PR_FATAL },
11256
11257         /* Root inode is not directory; aborting */
11258         { PR_3_ROOT_NOT_DIR_ABORT,
11259           N_("@r is not a @d; aborting.\n"),
11260           PROMPT_NONE, PR_FATAL },
11261
11262         /* Cannot proceed without a root inode. */
11263         { PR_3_NO_ROOT_INODE_ABORT,
11264           N_("Cannot proceed without a @r.\n"),
11265           PROMPT_NONE, PR_FATAL },
11266
11267         /* Internal error: couldn't find dir_info */
11268         { PR_3_NO_DIRINFO,
11269           N_("Internal error: couldn't find dir_info for %i.\n"),
11270           PROMPT_NONE, PR_FATAL },
11271
11272         /* Lost+found not a directory */
11273         { PR_3_LPF_NOTDIR,
11274           N_("/@l is not a @d (ino=%i)\n"),
11275           PROMPT_UNLINK, 0 },
11276
11277         /* Pass 3A Directory Optimization       */
11278
11279         /* Pass 3A: Optimizing directories */
11280         { PR_3A_PASS_HEADER,
11281           N_("Pass 3A: Optimizing directories\n"),
11282           PROMPT_NONE, PR_PREEN_NOMSG },
11283
11284         /* Error iterating over directories */
11285         { PR_3A_OPTIMIZE_ITER,
11286           N_("Failed to create dirs_to_hash iterator: %m"),
11287           PROMPT_NONE, 0 },
11288
11289         /* Error rehash directory */
11290         { PR_3A_OPTIMIZE_DIR_ERR,
11291           N_("Failed to optimize directory %q (%d): %m"),
11292           PROMPT_NONE, 0 },
11293
11294         /* Rehashing dir header */
11295         { PR_3A_OPTIMIZE_DIR_HEADER,
11296           N_("Optimizing directories: "),
11297           PROMPT_NONE, PR_MSG_ONLY },
11298
11299         /* Rehashing directory %d */
11300         { PR_3A_OPTIMIZE_DIR,
11301           " %d",
11302           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11303
11304         /* Rehashing dir end */
11305         { PR_3A_OPTIMIZE_DIR_END,
11306           "\n",
11307           PROMPT_NONE, PR_PREEN_NOHDR },
11308
11309         /* Pass 4 errors */
11310
11311         /* Pass 4: Checking reference counts */
11312         { PR_4_PASS_HEADER,
11313           N_("Pass 4: Checking reference counts\n"),
11314           PROMPT_NONE, 0 },
11315
11316         /* Unattached zero-length inode */
11317         { PR_4_ZERO_LEN_INODE,
11318           "@u @z @i %i.  ",
11319           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11320
11321         /* Unattached inode */
11322         { PR_4_UNATTACHED_INODE,
11323           "@u @i %i\n",
11324           PROMPT_CONNECT, 0 },
11325
11326         /* Inode ref count wrong */
11327         { PR_4_BAD_REF_COUNT,
11328           N_("@i %i ref count is %Il, @s %N.  "),
11329           PROMPT_FIX, PR_PREEN_OK },
11330
11331         { PR_4_INCONSISTENT_COUNT,
11332           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11333           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11334           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
11335           "They should be the same!\n"),
11336           PROMPT_NONE, 0 },
11337
11338         /* Pass 5 errors */
11339
11340         /* Pass 5: Checking group summary information */
11341         { PR_5_PASS_HEADER,
11342           N_("Pass 5: Checking @g summary information\n"),
11343           PROMPT_NONE, 0 },
11344
11345         /* Padding at end of inode bitmap is not set. */
11346         { PR_5_INODE_BMAP_PADDING,
11347           N_("Padding at end of @i @B is not set. "),
11348           PROMPT_FIX, PR_PREEN_OK },
11349
11350         /* Padding at end of block bitmap is not set. */
11351         { PR_5_BLOCK_BMAP_PADDING,
11352           N_("Padding at end of @b @B is not set. "),
11353           PROMPT_FIX, PR_PREEN_OK },
11354
11355         /* Block bitmap differences header */
11356         { PR_5_BLOCK_BITMAP_HEADER,
11357           N_("@b @B differences: "),
11358           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11359
11360         /* Block not used, but marked in bitmap */
11361         { PR_5_BLOCK_UNUSED,
11362           " -%b",
11363           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11364
11365         /* Block used, but not marked used in bitmap */
11366         { PR_5_BLOCK_USED,
11367           " +%b",
11368           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11369
11370         /* Block bitmap differences end */
11371         { PR_5_BLOCK_BITMAP_END,
11372           "\n",
11373           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11374
11375         /* Inode bitmap differences header */
11376         { PR_5_INODE_BITMAP_HEADER,
11377           N_("@i @B differences: "),
11378           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11379
11380         /* Inode not used, but marked in bitmap */
11381         { PR_5_INODE_UNUSED,
11382           " -%i",
11383           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11384
11385         /* Inode used, but not marked used in bitmap */
11386         { PR_5_INODE_USED,
11387           " +%i",
11388           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11389
11390         /* Inode bitmap differences end */
11391         { PR_5_INODE_BITMAP_END,
11392           "\n",
11393           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11394
11395         /* Free inodes count for group wrong */
11396         { PR_5_FREE_INODE_COUNT_GROUP,
11397           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11398           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11399
11400         /* Directories count for group wrong */
11401         { PR_5_FREE_DIR_COUNT_GROUP,
11402           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11403           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11404
11405         /* Free inodes count wrong */
11406         { PR_5_FREE_INODE_COUNT,
11407           N_("Free @is count wrong (%i, counted=%j).\n"),
11408           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11409
11410         /* Free blocks count for group wrong */
11411         { PR_5_FREE_BLOCK_COUNT_GROUP,
11412           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11413           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11414
11415         /* Free blocks count wrong */
11416         { PR_5_FREE_BLOCK_COUNT,
11417           N_("Free @bs count wrong (%b, counted=%c).\n"),
11418           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11419
11420         /* Programming error: bitmap endpoints don't match */
11421         { PR_5_BMAP_ENDPOINTS,
11422           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11423           "match calculated @B endpoints (%i, %j)\n"),
11424           PROMPT_NONE, PR_FATAL },
11425
11426         /* Internal error: fudging end of bitmap */
11427         { PR_5_FUDGE_BITMAP_ERROR,
11428           N_("Internal error: fudging end of bitmap (%N)\n"),
11429           PROMPT_NONE, PR_FATAL },
11430
11431         /* Error copying in replacement inode bitmap */
11432         { PR_5_COPY_IBITMAP_ERROR,
11433           "Error copying in replacement @i @B: %m\n",
11434           PROMPT_NONE, PR_FATAL },
11435
11436         /* Error copying in replacement block bitmap */
11437         { PR_5_COPY_BBITMAP_ERROR,
11438           "Error copying in replacement @b @B: %m\n",
11439           PROMPT_NONE, PR_FATAL },
11440
11441         /* Block range not used, but marked in bitmap */
11442         { PR_5_BLOCK_RANGE_UNUSED,
11443           " -(%b--%c)",
11444           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11445
11446         /* Block range used, but not marked used in bitmap */
11447         { PR_5_BLOCK_RANGE_USED,
11448           " +(%b--%c)",
11449           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11450
11451         /* Inode range not used, but marked in bitmap */
11452         { PR_5_INODE_RANGE_UNUSED,
11453           " -(%i--%j)",
11454           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11455
11456         /* Inode range used, but not marked used in bitmap */
11457         { PR_5_INODE_RANGE_USED,
11458           " +(%i--%j)",
11459           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11460
11461         { 0 }
11462 };
11463
11464 /*
11465  * This is the latch flags register.  It allows several problems to be
11466  * "latched" together.  This means that the user has to answer but one
11467  * question for the set of problems, and all of the associated
11468  * problems will be either fixed or not fixed.
11469  */
11470 static struct latch_descr pr_latch_info[] = {
11471         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11472         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11473         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11474         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11475         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11476         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11477         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11478         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11479         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11480         { -1, 0, 0 },
11481 };
11482
11483 static const struct e2fsck_problem *find_problem(problem_t code)
11484 {
11485         int     i;
11486
11487         for (i=0; problem_table[i].e2p_code; i++) {
11488                 if (problem_table[i].e2p_code == code)
11489                         return &problem_table[i];
11490         }
11491         return 0;
11492 }
11493
11494 static struct latch_descr *find_latch(int code)
11495 {
11496         int     i;
11497
11498         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11499                 if (pr_latch_info[i].latch_code == code)
11500                         return &pr_latch_info[i];
11501         }
11502         return 0;
11503 }
11504
11505 int end_problem_latch(e2fsck_t ctx, int mask)
11506 {
11507         struct latch_descr *ldesc;
11508         struct problem_context pctx;
11509         int answer = -1;
11510
11511         ldesc = find_latch(mask);
11512         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11513                 clear_problem_context(&pctx);
11514                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11515         }
11516         ldesc->flags &= ~(PRL_VARIABLE);
11517         return answer;
11518 }
11519
11520 int set_latch_flags(int mask, int setflags, int clearflags)
11521 {
11522         struct latch_descr *ldesc;
11523
11524         ldesc = find_latch(mask);
11525         if (!ldesc)
11526                 return -1;
11527         ldesc->flags |= setflags;
11528         ldesc->flags &= ~clearflags;
11529         return 0;
11530 }
11531
11532 void clear_problem_context(struct problem_context *ctx)
11533 {
11534         memset(ctx, 0, sizeof(struct problem_context));
11535         ctx->blkcount = -1;
11536         ctx->group = -1;
11537 }
11538
11539 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11540 {
11541         ext2_filsys fs = ctx->fs;
11542         const struct e2fsck_problem *ptr;
11543         struct latch_descr *ldesc = 0;
11544         const char *message;
11545         int             def_yn, answer, ans;
11546         int             print_answer = 0;
11547         int             suppress = 0;
11548
11549         ptr = find_problem(code);
11550         if (!ptr) {
11551                 printf(_("Unhandled error code (0x%x)!\n"), code);
11552                 return 0;
11553         }
11554         def_yn = 1;
11555         if ((ptr->flags & PR_NO_DEFAULT) ||
11556             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11557             (ctx->options & E2F_OPT_NO))
11558                 def_yn= 0;
11559
11560         /*
11561          * Do special latch processing.  This is where we ask the
11562          * latch question, if it exists
11563          */
11564         if (ptr->flags & PR_LATCH_MASK) {
11565                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11566                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11567                         ans = fix_problem(ctx, ldesc->question, pctx);
11568                         if (ans == 1)
11569                                 ldesc->flags |= PRL_YES;
11570                         if (ans == 0)
11571                                 ldesc->flags |= PRL_NO;
11572                         ldesc->flags |= PRL_LATCHED;
11573                 }
11574                 if (ldesc->flags & PRL_SUPPRESS)
11575                         suppress++;
11576         }
11577         if ((ptr->flags & PR_PREEN_NOMSG) &&
11578             (ctx->options & E2F_OPT_PREEN))
11579                 suppress++;
11580         if ((ptr->flags & PR_NO_NOMSG) &&
11581             (ctx->options & E2F_OPT_NO))
11582                 suppress++;
11583         if (!suppress) {
11584                 message = ptr->e2p_description;
11585                 if ((ctx->options & E2F_OPT_PREEN) &&
11586                     !(ptr->flags & PR_PREEN_NOHDR)) {
11587                         printf("%s: ", ctx->device_name ?
11588                                ctx->device_name : ctx->filesystem_name);
11589                 }
11590                 if (*message)
11591                         print_e2fsck_message(ctx, _(message), pctx, 1);
11592         }
11593         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11594                 preenhalt(ctx);
11595
11596         if (ptr->flags & PR_FATAL)
11597                 fatal_error(ctx, 0);
11598
11599         if (ptr->prompt == PROMPT_NONE) {
11600                 if (ptr->flags & PR_NOCOLLATE)
11601                         answer = -1;
11602                 else
11603                         answer = def_yn;
11604         } else {
11605                 if (ctx->options & E2F_OPT_PREEN) {
11606                         answer = def_yn;
11607                         if (!(ptr->flags & PR_PREEN_NOMSG))
11608                                 print_answer = 1;
11609                 } else if ((ptr->flags & PR_LATCH_MASK) &&
11610                            (ldesc->flags & (PRL_YES | PRL_NO))) {
11611                         if (!suppress)
11612                                 print_answer = 1;
11613                         if (ldesc->flags & PRL_YES)
11614                                 answer = 1;
11615                         else
11616                                 answer = 0;
11617                 } else
11618                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11619                 if (!answer && !(ptr->flags & PR_NO_OK))
11620                         ext2fs_unmark_valid(fs);
11621
11622                 if (print_answer)
11623                         printf("%s.\n", answer ?
11624                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11625
11626         }
11627
11628         if ((ptr->prompt == PROMPT_ABORT) && answer)
11629                 fatal_error(ctx, 0);
11630
11631         if (ptr->flags & PR_AFTER_CODE)
11632                 answer = fix_problem(ctx, ptr->second_code, pctx);
11633
11634         return answer;
11635 }
11636
11637 /*
11638  * linux/fs/recovery.c
11639  *
11640  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11641  */
11642
11643 /*
11644  * Maintain information about the progress of the recovery job, so that
11645  * the different passes can carry information between them.
11646  */
11647 struct recovery_info
11648 {
11649         tid_t           start_transaction;
11650         tid_t           end_transaction;
11651
11652         int             nr_replays;
11653         int             nr_revokes;
11654         int             nr_revoke_hits;
11655 };
11656
11657 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11658 static int do_one_pass(journal_t *journal,
11659                                 struct recovery_info *info, enum passtype pass);
11660 static int scan_revoke_records(journal_t *, struct buffer_head *,
11661                                 tid_t, struct recovery_info *);
11662
11663 /*
11664  * Read a block from the journal
11665  */
11666
11667 static int jread(struct buffer_head **bhp, journal_t *journal,
11668                  unsigned int offset)
11669 {
11670         int err;
11671         unsigned long blocknr;
11672         struct buffer_head *bh;
11673
11674         *bhp = NULL;
11675
11676         J_ASSERT (offset < journal->j_maxlen);
11677
11678         err = journal_bmap(journal, offset, &blocknr);
11679
11680         if (err) {
11681                 printk (KERN_ERR "JBD: bad block at offset %u\n",
11682                         offset);
11683                 return err;
11684         }
11685
11686         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11687         if (!bh)
11688                 return -ENOMEM;
11689
11690         if (!buffer_uptodate(bh)) {
11691                 /* If this is a brand new buffer, start readahead.
11692                    Otherwise, we assume we are already reading it.  */
11693                 if (!buffer_req(bh))
11694                         do_readahead(journal, offset);
11695                 wait_on_buffer(bh);
11696         }
11697
11698         if (!buffer_uptodate(bh)) {
11699                 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11700                         offset);
11701                 brelse(bh);
11702                 return -EIO;
11703         }
11704
11705         *bhp = bh;
11706         return 0;
11707 }
11708
11709
11710 /*
11711  * Count the number of in-use tags in a journal descriptor block.
11712  */
11713
11714 static int count_tags(struct buffer_head *bh, int size)
11715 {
11716         char *                  tagp;
11717         journal_block_tag_t *   tag;
11718         int                     nr = 0;
11719
11720         tagp = &bh->b_data[sizeof(journal_header_t)];
11721
11722         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11723                 tag = (journal_block_tag_t *) tagp;
11724
11725                 nr++;
11726                 tagp += sizeof(journal_block_tag_t);
11727                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11728                         tagp += 16;
11729
11730                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11731                         break;
11732         }
11733
11734         return nr;
11735 }
11736
11737
11738 /* Make sure we wrap around the log correctly! */
11739 #define wrap(journal, var)                                            \
11740 do {                                                                \
11741         if (var >= (journal)->j_last)                                   \
11742                 var -= ((journal)->j_last - (journal)->j_first);        \
11743 } while (0)
11744
11745 /**
11746  * int journal_recover(journal_t *journal) - recovers a on-disk journal
11747  * @journal: the journal to recover
11748  *
11749  * The primary function for recovering the log contents when mounting a
11750  * journaled device.
11751  *
11752  * Recovery is done in three passes.  In the first pass, we look for the
11753  * end of the log.  In the second, we assemble the list of revoke
11754  * blocks.  In the third and final pass, we replay any un-revoked blocks
11755  * in the log.
11756  */
11757 int journal_recover(journal_t *journal)
11758 {
11759         int                     err;
11760         journal_superblock_t *  sb;
11761
11762         struct recovery_info    info;
11763
11764         memset(&info, 0, sizeof(info));
11765         sb = journal->j_superblock;
11766
11767         /*
11768          * The journal superblock's s_start field (the current log head)
11769          * is always zero if, and only if, the journal was cleanly
11770          * unmounted.
11771          */
11772
11773         if (!sb->s_start) {
11774                 jbd_debug(1, "No recovery required, last transaction %d\n",
11775                           ntohl(sb->s_sequence));
11776                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11777                 return 0;
11778         }
11779
11780         err = do_one_pass(journal, &info, PASS_SCAN);
11781         if (!err)
11782                 err = do_one_pass(journal, &info, PASS_REVOKE);
11783         if (!err)
11784                 err = do_one_pass(journal, &info, PASS_REPLAY);
11785
11786         jbd_debug(0, "JBD: recovery, exit status %d, "
11787                   "recovered transactions %u to %u\n",
11788                   err, info.start_transaction, info.end_transaction);
11789         jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11790                   info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11791
11792         /* Restart the log at the next transaction ID, thus invalidating
11793          * any existing commit records in the log. */
11794         journal->j_transaction_sequence = ++info.end_transaction;
11795
11796         journal_clear_revoke(journal);
11797         sync_blockdev(journal->j_fs_dev);
11798         return err;
11799 }
11800
11801 static int do_one_pass(journal_t *journal,
11802                         struct recovery_info *info, enum passtype pass)
11803 {
11804         unsigned int            first_commit_ID, next_commit_ID;
11805         unsigned long           next_log_block;
11806         int                     err, success = 0;
11807         journal_superblock_t *  sb;
11808         journal_header_t *      tmp;
11809         struct buffer_head *    bh;
11810         unsigned int            sequence;
11811         int                     blocktype;
11812
11813         /* Precompute the maximum metadata descriptors in a descriptor block */
11814         int                     MAX_BLOCKS_PER_DESC;
11815         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11816                                / sizeof(journal_block_tag_t));
11817
11818         /*
11819          * First thing is to establish what we expect to find in the log
11820          * (in terms of transaction IDs), and where (in terms of log
11821          * block offsets): query the superblock.
11822          */
11823
11824         sb = journal->j_superblock;
11825         next_commit_ID = ntohl(sb->s_sequence);
11826         next_log_block = ntohl(sb->s_start);
11827
11828         first_commit_ID = next_commit_ID;
11829         if (pass == PASS_SCAN)
11830                 info->start_transaction = first_commit_ID;
11831
11832         jbd_debug(1, "Starting recovery pass %d\n", pass);
11833
11834         /*
11835          * Now we walk through the log, transaction by transaction,
11836          * making sure that each transaction has a commit block in the
11837          * expected place.  Each complete transaction gets replayed back
11838          * into the main filesystem.
11839          */
11840
11841         while (1) {
11842                 int                     flags;
11843                 char *                  tagp;
11844                 journal_block_tag_t *   tag;
11845                 struct buffer_head *    obh;
11846                 struct buffer_head *    nbh;
11847
11848                 /* If we already know where to stop the log traversal,
11849                  * check right now that we haven't gone past the end of
11850                  * the log. */
11851
11852                 if (pass != PASS_SCAN)
11853                         if (tid_geq(next_commit_ID, info->end_transaction))
11854                                 break;
11855
11856                 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11857                           next_commit_ID, next_log_block, journal->j_last);
11858
11859                 /* Skip over each chunk of the transaction looking
11860                  * either the next descriptor block or the final commit
11861                  * record. */
11862
11863                 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11864                 err = jread(&bh, journal, next_log_block);
11865                 if (err)
11866                         goto failed;
11867
11868                 next_log_block++;
11869                 wrap(journal, next_log_block);
11870
11871                 /* What kind of buffer is it?
11872                  *
11873                  * If it is a descriptor block, check that it has the
11874                  * expected sequence number.  Otherwise, we're all done
11875                  * here. */
11876
11877                 tmp = (journal_header_t *)bh->b_data;
11878
11879                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11880                         brelse(bh);
11881                         break;
11882                 }
11883
11884                 blocktype = ntohl(tmp->h_blocktype);
11885                 sequence = ntohl(tmp->h_sequence);
11886                 jbd_debug(3, "Found magic %d, sequence %d\n",
11887                           blocktype, sequence);
11888
11889                 if (sequence != next_commit_ID) {
11890                         brelse(bh);
11891                         break;
11892                 }
11893
11894                 /* OK, we have a valid descriptor block which matches
11895                  * all of the sequence number checks.  What are we going
11896                  * to do with it?  That depends on the pass... */
11897
11898                 switch(blocktype) {
11899                 case JFS_DESCRIPTOR_BLOCK:
11900                         /* If it is a valid descriptor block, replay it
11901                          * in pass REPLAY; otherwise, just skip over the
11902                          * blocks it describes. */
11903                         if (pass != PASS_REPLAY) {
11904                                 next_log_block +=
11905                                         count_tags(bh, journal->j_blocksize);
11906                                 wrap(journal, next_log_block);
11907                                 brelse(bh);
11908                                 continue;
11909                         }
11910
11911                         /* A descriptor block: we can now write all of
11912                          * the data blocks.  Yay, useful work is finally
11913                          * getting done here! */
11914
11915                         tagp = &bh->b_data[sizeof(journal_header_t)];
11916                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11917                                <= journal->j_blocksize) {
11918                                 unsigned long io_block;
11919
11920                                 tag = (journal_block_tag_t *) tagp;
11921                                 flags = ntohl(tag->t_flags);
11922
11923                                 io_block = next_log_block++;
11924                                 wrap(journal, next_log_block);
11925                                 err = jread(&obh, journal, io_block);
11926                                 if (err) {
11927                                         /* Recover what we can, but
11928                                          * report failure at the end. */
11929                                         success = err;
11930                                         printk (KERN_ERR
11931                                                 "JBD: IO error %d recovering "
11932                                                 "block %ld in log\n",
11933                                                 err, io_block);
11934                                 } else {
11935                                         unsigned long blocknr;
11936
11937                                         J_ASSERT(obh != NULL);
11938                                         blocknr = ntohl(tag->t_blocknr);
11939
11940                                         /* If the block has been
11941                                          * revoked, then we're all done
11942                                          * here. */
11943                                         if (journal_test_revoke
11944                                             (journal, blocknr,
11945                                              next_commit_ID)) {
11946                                                 brelse(obh);
11947                                                 ++info->nr_revoke_hits;
11948                                                 goto skip_write;
11949                                         }
11950
11951                                         /* Find a buffer for the new
11952                                          * data being restored */
11953                                         nbh = getblk(journal->j_fs_dev,
11954                                                        blocknr,
11955                                                      journal->j_blocksize);
11956                                         if (nbh == NULL) {
11957                                                 printk(KERN_ERR
11958                                                        "JBD: Out of memory "
11959                                                        "during recovery.\n");
11960                                                 err = -ENOMEM;
11961                                                 brelse(bh);
11962                                                 brelse(obh);
11963                                                 goto failed;
11964                                         }
11965
11966                                         lock_buffer(nbh);
11967                                         memcpy(nbh->b_data, obh->b_data,
11968                                                         journal->j_blocksize);
11969                                         if (flags & JFS_FLAG_ESCAPE) {
11970                                                 *((unsigned int *)bh->b_data) =
11971                                                         htonl(JFS_MAGIC_NUMBER);
11972                                         }
11973
11974                                         BUFFER_TRACE(nbh, "marking dirty");
11975                                         mark_buffer_uptodate(nbh, 1);
11976                                         mark_buffer_dirty(nbh);
11977                                         BUFFER_TRACE(nbh, "marking uptodate");
11978                                         ++info->nr_replays;
11979                                         /* ll_rw_block(WRITE, 1, &nbh); */
11980                                         unlock_buffer(nbh);
11981                                         brelse(obh);
11982                                         brelse(nbh);
11983                                 }
11984
11985                         skip_write:
11986                                 tagp += sizeof(journal_block_tag_t);
11987                                 if (!(flags & JFS_FLAG_SAME_UUID))
11988                                         tagp += 16;
11989
11990                                 if (flags & JFS_FLAG_LAST_TAG)
11991                                         break;
11992                         }
11993
11994                         brelse(bh);
11995                         continue;
11996
11997                 case JFS_COMMIT_BLOCK:
11998                         /* Found an expected commit block: not much to
11999                          * do other than move on to the next sequence
12000                          * number. */
12001                         brelse(bh);
12002                         next_commit_ID++;
12003                         continue;
12004
12005                 case JFS_REVOKE_BLOCK:
12006                         /* If we aren't in the REVOKE pass, then we can
12007                          * just skip over this block. */
12008                         if (pass != PASS_REVOKE) {
12009                                 brelse(bh);
12010                                 continue;
12011                         }
12012
12013                         err = scan_revoke_records(journal, bh,
12014                                                   next_commit_ID, info);
12015                         brelse(bh);
12016                         if (err)
12017                                 goto failed;
12018                         continue;
12019
12020                 default:
12021                         jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12022                                   blocktype);
12023                         goto done;
12024                 }
12025         }
12026
12027  done:
12028         /*
12029          * We broke out of the log scan loop: either we came to the
12030          * known end of the log or we found an unexpected block in the
12031          * log.  If the latter happened, then we know that the "current"
12032          * transaction marks the end of the valid log.
12033          */
12034
12035         if (pass == PASS_SCAN)
12036                 info->end_transaction = next_commit_ID;
12037         else {
12038                 /* It's really bad news if different passes end up at
12039                  * different places (but possible due to IO errors). */
12040                 if (info->end_transaction != next_commit_ID) {
12041                         printk (KERN_ERR "JBD: recovery pass %d ended at "
12042                                 "transaction %u, expected %u\n",
12043                                 pass, next_commit_ID, info->end_transaction);
12044                         if (!success)
12045                                 success = -EIO;
12046                 }
12047         }
12048
12049         return success;
12050
12051  failed:
12052         return err;
12053 }
12054
12055
12056 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12057
12058 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12059                                tid_t sequence, struct recovery_info *info)
12060 {
12061         journal_revoke_header_t *header;
12062         int offset, max;
12063
12064         header = (journal_revoke_header_t *) bh->b_data;
12065         offset = sizeof(journal_revoke_header_t);
12066         max = ntohl(header->r_count);
12067
12068         while (offset < max) {
12069                 unsigned long blocknr;
12070                 int err;
12071
12072                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12073                 offset += 4;
12074                 err = journal_set_revoke(journal, blocknr, sequence);
12075                 if (err)
12076                         return err;
12077                 ++info->nr_revokes;
12078         }
12079         return 0;
12080 }
12081
12082
12083 /*
12084  * rehash.c --- rebuild hash tree directories
12085  *
12086  * This algorithm is designed for simplicity of implementation and to
12087  * pack the directory as much as possible.  It however requires twice
12088  * as much memory as the size of the directory.  The maximum size
12089  * directory supported using a 4k blocksize is roughly a gigabyte, and
12090  * so there may very well be problems with machines that don't have
12091  * virtual memory, and obscenely large directories.
12092  *
12093  * An alternate algorithm which is much more disk intensive could be
12094  * written, and probably will need to be written in the future.  The
12095  * design goals of such an algorithm are: (a) use (roughly) constant
12096  * amounts of memory, no matter how large the directory, (b) the
12097  * directory must be safe at all times, even if e2fsck is interrupted
12098  * in the middle, (c) we must use minimal amounts of extra disk
12099  * blocks.  This pretty much requires an incremental approach, where
12100  * we are reading from one part of the directory, and inserting into
12101  * the front half.  So the algorithm will have to keep track of a
12102  * moving block boundary between the new tree and the old tree, and
12103  * files will need to be moved from the old directory and inserted
12104  * into the new tree.  If the new directory requires space which isn't
12105  * yet available, blocks from the beginning part of the old directory
12106  * may need to be moved to the end of the directory to make room for
12107  * the new tree:
12108  *
12109  *    --------------------------------------------------------
12110  *    |  new tree   |        | old tree                      |
12111  *    --------------------------------------------------------
12112  *                  ^ ptr    ^ptr
12113  *                tail new   head old
12114  *
12115  * This is going to be a pain in the tuckus to implement, and will
12116  * require a lot more disk accesses.  So I'm going to skip it for now;
12117  * it's only really going to be an issue for really, really big
12118  * filesystems (when we reach the level of tens of millions of files
12119  * in a single directory).  It will probably be easier to simply
12120  * require that e2fsck use VM first.
12121  */
12122
12123 struct fill_dir_struct {
12124         char *buf;
12125         struct ext2_inode *inode;
12126         int err;
12127         e2fsck_t ctx;
12128         struct hash_entry *harray;
12129         int max_array, num_array;
12130         int dir_size;
12131         int compress;
12132         ino_t parent;
12133 };
12134
12135 struct hash_entry {
12136         ext2_dirhash_t  hash;
12137         ext2_dirhash_t  minor_hash;
12138         struct ext2_dir_entry   *dir;
12139 };
12140
12141 struct out_dir {
12142         int             num;
12143         int             max;
12144         char            *buf;
12145         ext2_dirhash_t  *hashes;
12146 };
12147
12148 static int fill_dir_block(ext2_filsys fs,
12149                           blk_t *block_nr,
12150                           e2_blkcnt_t blockcnt,
12151                           blk_t ref_block FSCK_ATTR((unused)),
12152                           int ref_offset FSCK_ATTR((unused)),
12153                           void *priv_data)
12154 {
12155         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
12156         struct hash_entry       *new_array, *ent;
12157         struct ext2_dir_entry   *dirent;
12158         char                    *dir;
12159         unsigned int            offset, dir_offset;
12160
12161         if (blockcnt < 0)
12162                 return 0;
12163
12164         offset = blockcnt * fs->blocksize;
12165         if (offset + fs->blocksize > fd->inode->i_size) {
12166                 fd->err = EXT2_ET_DIR_CORRUPTED;
12167                 return BLOCK_ABORT;
12168         }
12169         dir = (fd->buf+offset);
12170         if (HOLE_BLKADDR(*block_nr)) {
12171                 memset(dir, 0, fs->blocksize);
12172                 dirent = (struct ext2_dir_entry *) dir;
12173                 dirent->rec_len = fs->blocksize;
12174         } else {
12175                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12176                 if (fd->err)
12177                         return BLOCK_ABORT;
12178         }
12179         /* While the directory block is "hot", index it. */
12180         dir_offset = 0;
12181         while (dir_offset < fs->blocksize) {
12182                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12183                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12184                     (dirent->rec_len < 8) ||
12185                     ((dirent->rec_len % 4) != 0) ||
12186                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12187                         fd->err = EXT2_ET_DIR_CORRUPTED;
12188                         return BLOCK_ABORT;
12189                 }
12190                 dir_offset += dirent->rec_len;
12191                 if (dirent->inode == 0)
12192                         continue;
12193                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12194                     (dirent->name[0] == '.'))
12195                         continue;
12196                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12197                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12198                         fd->parent = dirent->inode;
12199                         continue;
12200                 }
12201                 if (fd->num_array >= fd->max_array) {
12202                         new_array = realloc(fd->harray,
12203                             sizeof(struct hash_entry) * (fd->max_array+500));
12204                         if (!new_array) {
12205                                 fd->err = ENOMEM;
12206                                 return BLOCK_ABORT;
12207                         }
12208                         fd->harray = new_array;
12209                         fd->max_array += 500;
12210                 }
12211                 ent = fd->harray + fd->num_array++;
12212                 ent->dir = dirent;
12213                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12214                 if (fd->compress)
12215                         ent->hash = ent->minor_hash = 0;
12216                 else {
12217                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12218                                                  dirent->name,
12219                                                  dirent->name_len & 0xFF,
12220                                                  fs->super->s_hash_seed,
12221                                                  &ent->hash, &ent->minor_hash);
12222                         if (fd->err)
12223                                 return BLOCK_ABORT;
12224                 }
12225         }
12226
12227         return 0;
12228 }
12229
12230 /* Used for sorting the hash entry */
12231 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12232 {
12233         const struct hash_entry *he_a = (const struct hash_entry *) a;
12234         const struct hash_entry *he_b = (const struct hash_entry *) b;
12235         int     ret;
12236         int     min_len;
12237
12238         min_len = he_a->dir->name_len;
12239         if (min_len > he_b->dir->name_len)
12240                 min_len = he_b->dir->name_len;
12241
12242         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12243         if (ret == 0) {
12244                 if (he_a->dir->name_len > he_b->dir->name_len)
12245                         ret = 1;
12246                 else if (he_a->dir->name_len < he_b->dir->name_len)
12247                         ret = -1;
12248                 else
12249                         ret = he_b->dir->inode - he_a->dir->inode;
12250         }
12251         return ret;
12252 }
12253
12254 /* Used for sorting the hash entry */
12255 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12256 {
12257         const struct hash_entry *he_a = (const struct hash_entry *) a;
12258         const struct hash_entry *he_b = (const struct hash_entry *) b;
12259         int     ret;
12260
12261         if (he_a->hash > he_b->hash)
12262                 ret = 1;
12263         else if (he_a->hash < he_b->hash)
12264                 ret = -1;
12265         else {
12266                 if (he_a->minor_hash > he_b->minor_hash)
12267                         ret = 1;
12268                 else if (he_a->minor_hash < he_b->minor_hash)
12269                         ret = -1;
12270                 else
12271                         ret = name_cmp(a, b);
12272         }
12273         return ret;
12274 }
12275
12276 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12277                                 int blocks)
12278 {
12279         void                    *new_mem;
12280
12281         if (outdir->max) {
12282                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12283                 if (!new_mem)
12284                         return ENOMEM;
12285                 outdir->buf = new_mem;
12286                 new_mem = realloc(outdir->hashes,
12287                                   blocks * sizeof(ext2_dirhash_t));
12288                 if (!new_mem)
12289                         return ENOMEM;
12290                 outdir->hashes = new_mem;
12291         } else {
12292                 outdir->buf = malloc(blocks * fs->blocksize);
12293                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12294                 outdir->num = 0;
12295         }
12296         outdir->max = blocks;
12297         return 0;
12298 }
12299
12300 static void free_out_dir(struct out_dir *outdir)
12301 {
12302         free(outdir->buf);
12303         free(outdir->hashes);
12304         outdir->max = 0;
12305         outdir->num =0;
12306 }
12307
12308 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12309                          char ** ret)
12310 {
12311         errcode_t       retval;
12312
12313         if (outdir->num >= outdir->max) {
12314                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12315                 if (retval)
12316                         return retval;
12317         }
12318         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12319         memset(*ret, 0, fs->blocksize);
12320         return 0;
12321 }
12322
12323 /*
12324  * This function is used to make a unique filename.  We do this by
12325  * appending ~0, and then incrementing the number.  However, we cannot
12326  * expand the length of the filename beyond the padding available in
12327  * the directory entry.
12328  */
12329 static void mutate_name(char *str, __u16 *len)
12330 {
12331         int     i;
12332         __u16   l = *len & 0xFF, h = *len & 0xff00;
12333
12334         /*
12335          * First check to see if it looks the name has been mutated
12336          * already
12337          */
12338         for (i = l-1; i > 0; i--) {
12339                 if (!isdigit(str[i]))
12340                         break;
12341         }
12342         if ((i == l-1) || (str[i] != '~')) {
12343                 if (((l-1) & 3) < 2)
12344                         l += 2;
12345                 else
12346                         l = (l+3) & ~3;
12347                 str[l-2] = '~';
12348                 str[l-1] = '0';
12349                 *len = l | h;
12350                 return;
12351         }
12352         for (i = l-1; i >= 0; i--) {
12353                 if (isdigit(str[i])) {
12354                         if (str[i] == '9')
12355                                 str[i] = '0';
12356                         else {
12357                                 str[i]++;
12358                                 return;
12359                         }
12360                         continue;
12361                 }
12362                 if (i == 1) {
12363                         if (str[0] == 'z')
12364                                 str[0] = 'A';
12365                         else if (str[0] == 'Z') {
12366                                 str[0] = '~';
12367                                 str[1] = '0';
12368                         } else
12369                                 str[0]++;
12370                 } else if (i > 0) {
12371                         str[i] = '1';
12372                         str[i-1] = '~';
12373                 } else {
12374                         if (str[0] == '~')
12375                                 str[0] = 'a';
12376                         else
12377                                 str[0]++;
12378                 }
12379                 break;
12380         }
12381 }
12382
12383 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12384                                     ext2_ino_t ino,
12385                                     struct fill_dir_struct *fd)
12386 {
12387         struct problem_context  pctx;
12388         struct hash_entry       *ent, *prev;
12389         int                     i, j;
12390         int                     fixed = 0;
12391         char                    new_name[256];
12392         __u16                   new_len;
12393
12394         clear_problem_context(&pctx);
12395         pctx.ino = ino;
12396
12397         for (i=1; i < fd->num_array; i++) {
12398                 ent = fd->harray + i;
12399                 prev = ent - 1;
12400                 if (!ent->dir->inode ||
12401                     ((ent->dir->name_len & 0xFF) !=
12402                      (prev->dir->name_len & 0xFF)) ||
12403                     (strncmp(ent->dir->name, prev->dir->name,
12404                              ent->dir->name_len & 0xFF)))
12405                         continue;
12406                 pctx.dirent = ent->dir;
12407                 if ((ent->dir->inode == prev->dir->inode) &&
12408                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12409                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12410                         ent->dir->inode = 0;
12411                         fixed++;
12412                         continue;
12413                 }
12414                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12415                 new_len = ent->dir->name_len;
12416                 mutate_name(new_name, &new_len);
12417                 for (j=0; j < fd->num_array; j++) {
12418                         if ((i==j) ||
12419                             ((ent->dir->name_len & 0xFF) !=
12420                              (fd->harray[j].dir->name_len & 0xFF)) ||
12421                             (strncmp(new_name, fd->harray[j].dir->name,
12422                                      new_len & 0xFF)))
12423                                 continue;
12424                         mutate_name(new_name, &new_len);
12425
12426                         j = -1;
12427                 }
12428                 new_name[new_len & 0xFF] = 0;
12429                 pctx.str = new_name;
12430                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12431                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
12432                         ent->dir->name_len = new_len;
12433                         ext2fs_dirhash(fs->super->s_def_hash_version,
12434                                        ent->dir->name,
12435                                        ent->dir->name_len & 0xFF,
12436                                        fs->super->s_hash_seed,
12437                                        &ent->hash, &ent->minor_hash);
12438                         fixed++;
12439                 }
12440         }
12441         return fixed;
12442 }
12443
12444
12445 static errcode_t copy_dir_entries(ext2_filsys fs,
12446                                   struct fill_dir_struct *fd,
12447                                   struct out_dir *outdir)
12448 {
12449         errcode_t               retval;
12450         char                    *block_start;
12451         struct hash_entry       *ent;
12452         struct ext2_dir_entry   *dirent;
12453         int                     i, rec_len, left;
12454         ext2_dirhash_t          prev_hash;
12455         int                     offset;
12456
12457         outdir->max = 0;
12458         retval = alloc_size_dir(fs, outdir,
12459                                 (fd->dir_size / fs->blocksize) + 2);
12460         if (retval)
12461                 return retval;
12462         outdir->num = fd->compress ? 0 : 1;
12463         offset = 0;
12464         outdir->hashes[0] = 0;
12465         prev_hash = 1;
12466         if ((retval = get_next_block(fs, outdir, &block_start)))
12467                 return retval;
12468         dirent = (struct ext2_dir_entry *) block_start;
12469         left = fs->blocksize;
12470         for (i=0; i < fd->num_array; i++) {
12471                 ent = fd->harray + i;
12472                 if (ent->dir->inode == 0)
12473                         continue;
12474                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12475                 if (rec_len > left) {
12476                         if (left)
12477                                 dirent->rec_len += left;
12478                         if ((retval = get_next_block(fs, outdir,
12479                                                       &block_start)))
12480                                 return retval;
12481                         offset = 0;
12482                 }
12483                 left = fs->blocksize - offset;
12484                 dirent = (struct ext2_dir_entry *) (block_start + offset);
12485                 if (offset == 0) {
12486                         if (ent->hash == prev_hash)
12487                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
12488                         else
12489                                 outdir->hashes[outdir->num-1] = ent->hash;
12490                 }
12491                 dirent->inode = ent->dir->inode;
12492                 dirent->name_len = ent->dir->name_len;
12493                 dirent->rec_len = rec_len;
12494                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12495                 offset += rec_len;
12496                 left -= rec_len;
12497                 if (left < 12) {
12498                         dirent->rec_len += left;
12499                         offset += left;
12500                         left = 0;
12501                 }
12502                 prev_hash = ent->hash;
12503         }
12504         if (left)
12505                 dirent->rec_len += left;
12506
12507         return 0;
12508 }
12509
12510
12511 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12512                                     ext2_ino_t ino, ext2_ino_t parent)
12513 {
12514         struct ext2_dir_entry           *dir;
12515         struct ext2_dx_root_info        *root;
12516         struct ext2_dx_countlimit       *limits;
12517         int                             filetype = 0;
12518
12519         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12520                 filetype = EXT2_FT_DIR << 8;
12521
12522         memset(buf, 0, fs->blocksize);
12523         dir = (struct ext2_dir_entry *) buf;
12524         dir->inode = ino;
12525         dir->name[0] = '.';
12526         dir->name_len = 1 | filetype;
12527         dir->rec_len = 12;
12528         dir = (struct ext2_dir_entry *) (buf + 12);
12529         dir->inode = parent;
12530         dir->name[0] = '.';
12531         dir->name[1] = '.';
12532         dir->name_len = 2 | filetype;
12533         dir->rec_len = fs->blocksize - 12;
12534
12535         root = (struct ext2_dx_root_info *) (buf+24);
12536         root->reserved_zero = 0;
12537         root->hash_version = fs->super->s_def_hash_version;
12538         root->info_length = 8;
12539         root->indirect_levels = 0;
12540         root->unused_flags = 0;
12541
12542         limits = (struct ext2_dx_countlimit *) (buf+32);
12543         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12544         limits->count = 0;
12545
12546         return root;
12547 }
12548
12549
12550 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12551 {
12552         struct ext2_dir_entry           *dir;
12553         struct ext2_dx_countlimit       *limits;
12554
12555         memset(buf, 0, fs->blocksize);
12556         dir = (struct ext2_dir_entry *) buf;
12557         dir->inode = 0;
12558         dir->rec_len = fs->blocksize;
12559
12560         limits = (struct ext2_dx_countlimit *) (buf+8);
12561         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12562         limits->count = 0;
12563
12564         return (struct ext2_dx_entry *) limits;
12565 }
12566
12567 /*
12568  * This function takes the leaf nodes which have been written in
12569  * outdir, and populates the root node and any necessary interior nodes.
12570  */
12571 static errcode_t calculate_tree(ext2_filsys fs,
12572                                 struct out_dir *outdir,
12573                                 ext2_ino_t ino,
12574                                 ext2_ino_t parent)
12575 {
12576         struct ext2_dx_root_info        *root_info;
12577         struct ext2_dx_entry            *root, *dx_ent = 0;
12578         struct ext2_dx_countlimit       *root_limit, *limit;
12579         errcode_t                       retval;
12580         char                            * block_start;
12581         int                             i, c1, c2, nblks;
12582         int                             limit_offset, root_offset;
12583
12584         root_info = set_root_node(fs, outdir->buf, ino, parent);
12585         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12586                 root_info->info_length;
12587         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12588         c1 = root_limit->limit;
12589         nblks = outdir->num;
12590
12591         /* Write out the pointer blocks */
12592         if (nblks-1 <= c1) {
12593                 /* Just write out the root block, and we're done */
12594                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12595                 for (i=1; i < nblks; i++) {
12596                         root->block = ext2fs_cpu_to_le32(i);
12597                         if (i != 1)
12598                                 root->hash =
12599                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12600                         root++;
12601                         c1--;
12602                 }
12603         } else {
12604                 c2 = 0;
12605                 limit = 0;
12606                 root_info->indirect_levels = 1;
12607                 for (i=1; i < nblks; i++) {
12608                         if (c1 == 0)
12609                                 return ENOSPC;
12610                         if (c2 == 0) {
12611                                 if (limit)
12612                                         limit->limit = limit->count =
12613                 ext2fs_cpu_to_le16(limit->limit);
12614                                 root = (struct ext2_dx_entry *)
12615                                         (outdir->buf + root_offset);
12616                                 root->block = ext2fs_cpu_to_le32(outdir->num);
12617                                 if (i != 1)
12618                                         root->hash =
12619                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12620                                 if ((retval =  get_next_block(fs, outdir,
12621                                                               &block_start)))
12622                                         return retval;
12623                                 dx_ent = set_int_node(fs, block_start);
12624                                 limit = (struct ext2_dx_countlimit *) dx_ent;
12625                                 c2 = limit->limit;
12626                                 root_offset += sizeof(struct ext2_dx_entry);
12627                                 c1--;
12628                         }
12629                         dx_ent->block = ext2fs_cpu_to_le32(i);
12630                         if (c2 != limit->limit)
12631                                 dx_ent->hash =
12632                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12633                         dx_ent++;
12634                         c2--;
12635                 }
12636                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12637                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12638         }
12639         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12640         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12641         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12642
12643         return 0;
12644 }
12645
12646 struct write_dir_struct {
12647         struct out_dir *outdir;
12648         errcode_t       err;
12649         e2fsck_t        ctx;
12650         int             cleared;
12651 };
12652
12653 /*
12654  * Helper function which writes out a directory block.
12655  */
12656 static int write_dir_block(ext2_filsys fs,
12657                            blk_t        *block_nr,
12658                            e2_blkcnt_t blockcnt,
12659                            blk_t ref_block FSCK_ATTR((unused)),
12660                            int ref_offset FSCK_ATTR((unused)),
12661                            void *priv_data)
12662 {
12663         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12664         blk_t   blk;
12665         char    *dir;
12666
12667         if (*block_nr == 0)
12668                 return 0;
12669         if (blockcnt >= wd->outdir->num) {
12670                 e2fsck_read_bitmaps(wd->ctx);
12671                 blk = *block_nr;
12672                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12673                 ext2fs_block_alloc_stats(fs, blk, -1);
12674                 *block_nr = 0;
12675                 wd->cleared++;
12676                 return BLOCK_CHANGED;
12677         }
12678         if (blockcnt < 0)
12679                 return 0;
12680
12681         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12682         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12683         if (wd->err)
12684                 return BLOCK_ABORT;
12685         return 0;
12686 }
12687
12688 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12689                                  struct out_dir *outdir,
12690                                  ext2_ino_t ino, int compress)
12691 {
12692         struct write_dir_struct wd;
12693         errcode_t       retval;
12694         struct ext2_inode       inode;
12695
12696         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12697         if (retval)
12698                 return retval;
12699
12700         wd.outdir = outdir;
12701         wd.err = 0;
12702         wd.ctx = ctx;
12703         wd.cleared = 0;
12704
12705         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12706                                        write_dir_block, &wd);
12707         if (retval)
12708                 return retval;
12709         if (wd.err)
12710                 return wd.err;
12711
12712         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12713         if (compress)
12714                 inode.i_flags &= ~EXT2_INDEX_FL;
12715         else
12716                 inode.i_flags |= EXT2_INDEX_FL;
12717         inode.i_size = outdir->num * fs->blocksize;
12718         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12719         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12720
12721         return 0;
12722 }
12723
12724 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12725 {
12726         ext2_filsys             fs = ctx->fs;
12727         errcode_t               retval;
12728         struct ext2_inode       inode;
12729         char                    *dir_buf = 0;
12730         struct fill_dir_struct  fd;
12731         struct out_dir          outdir;
12732
12733         outdir.max = outdir.num = 0;
12734         outdir.buf = 0;
12735         outdir.hashes = 0;
12736         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12737
12738         retval = ENOMEM;
12739         fd.harray = 0;
12740         dir_buf = malloc(inode.i_size);
12741         if (!dir_buf)
12742                 goto errout;
12743
12744         fd.max_array = inode.i_size / 32;
12745         fd.num_array = 0;
12746         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12747         if (!fd.harray)
12748                 goto errout;
12749
12750         fd.ctx = ctx;
12751         fd.buf = dir_buf;
12752         fd.inode = &inode;
12753         fd.err = 0;
12754         fd.dir_size = 0;
12755         fd.compress = 0;
12756         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12757             (inode.i_size / fs->blocksize) < 2)
12758                 fd.compress = 1;
12759         fd.parent = 0;
12760
12761         /* Read in the entire directory into memory */
12762         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12763                                        fill_dir_block, &fd);
12764         if (fd.err) {
12765                 retval = fd.err;
12766                 goto errout;
12767         }
12768
12769 #if 0
12770         printf("%d entries (%d bytes) found in inode %d\n",
12771                fd.num_array, fd.dir_size, ino);
12772 #endif
12773
12774         /* Sort the list */
12775 resort:
12776         if (fd.compress)
12777                 qsort(fd.harray+2, fd.num_array-2,
12778                       sizeof(struct hash_entry), name_cmp);
12779         else
12780                 qsort(fd.harray, fd.num_array,
12781                       sizeof(struct hash_entry), hash_cmp);
12782
12783         /*
12784          * Look for duplicates
12785          */
12786         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12787                 goto resort;
12788
12789         if (ctx->options & E2F_OPT_NO) {
12790                 retval = 0;
12791                 goto errout;
12792         }
12793
12794         /*
12795          * Copy the directory entries.  In a htree directory these
12796          * will become the leaf nodes.
12797          */
12798         retval = copy_dir_entries(fs, &fd, &outdir);
12799         if (retval)
12800                 goto errout;
12801
12802         free(dir_buf); dir_buf = 0;
12803
12804         if (!fd.compress) {
12805                 /* Calculate the interior nodes */
12806                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12807                 if (retval)
12808                         goto errout;
12809         }
12810
12811         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12812
12813 errout:
12814         free(dir_buf);
12815         free(fd.harray);
12816
12817         free_out_dir(&outdir);
12818         return retval;
12819 }
12820
12821 void e2fsck_rehash_directories(e2fsck_t ctx)
12822 {
12823         struct problem_context  pctx;
12824 #ifdef RESOURCE_TRACK
12825         struct resource_track   rtrack;
12826 #endif
12827         struct dir_info         *dir;
12828         ext2_u32_iterate        iter;
12829         ext2_ino_t              ino;
12830         errcode_t               retval;
12831         int                     i, cur, max, all_dirs, dir_index, first = 1;
12832
12833 #ifdef RESOURCE_TRACK
12834         init_resource_track(&rtrack);
12835 #endif
12836
12837         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12838
12839         if (!ctx->dirs_to_hash && !all_dirs)
12840                 return;
12841
12842         e2fsck_get_lost_and_found(ctx, 0);
12843
12844         clear_problem_context(&pctx);
12845
12846         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12847         cur = 0;
12848         if (all_dirs) {
12849                 i = 0;
12850                 max = e2fsck_get_num_dirinfo(ctx);
12851         } else {
12852                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12853                                                        &iter);
12854                 if (retval) {
12855                         pctx.errcode = retval;
12856                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12857                         return;
12858                 }
12859                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12860         }
12861         while (1) {
12862                 if (all_dirs) {
12863                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12864                                 break;
12865                         ino = dir->ino;
12866                 } else {
12867                         if (!ext2fs_u32_list_iterate(iter, &ino))
12868                                 break;
12869                 }
12870                 if (ino == ctx->lost_and_found)
12871                         continue;
12872                 pctx.dir = ino;
12873                 if (first) {
12874                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12875                         first = 0;
12876                 }
12877 #if 0
12878                 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12879 #endif
12880                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12881                 if (pctx.errcode) {
12882                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12883                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12884                 }
12885                 if (ctx->progress && !ctx->progress_fd)
12886                         e2fsck_simple_progress(ctx, "Rebuilding directory",
12887                                100.0 * (float) (++cur) / (float) max, ino);
12888         }
12889         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12890         if (!all_dirs)
12891                 ext2fs_u32_list_iterate_end(iter);
12892
12893         ext2fs_u32_list_free(ctx->dirs_to_hash);
12894         ctx->dirs_to_hash = 0;
12895
12896 #ifdef RESOURCE_TRACK
12897         if (ctx->options & E2F_OPT_TIME2) {
12898                 e2fsck_clear_progbar(ctx);
12899                 print_resource_track("Pass 3A", &rtrack);
12900         }
12901 #endif
12902 }
12903
12904 /*
12905  * linux/fs/revoke.c
12906  *
12907  * Journal revoke routines for the generic filesystem journaling code;
12908  * part of the ext2fs journaling system.
12909  *
12910  * Revoke is the mechanism used to prevent old log records for deleted
12911  * metadata from being replayed on top of newer data using the same
12912  * blocks.  The revoke mechanism is used in two separate places:
12913  *
12914  * + Commit: during commit we write the entire list of the current
12915  *   transaction's revoked blocks to the journal
12916  *
12917  * + Recovery: during recovery we record the transaction ID of all
12918  *   revoked blocks.  If there are multiple revoke records in the log
12919  *   for a single block, only the last one counts, and if there is a log
12920  *   entry for a block beyond the last revoke, then that log entry still
12921  *   gets replayed.
12922  *
12923  * We can get interactions between revokes and new log data within a
12924  * single transaction:
12925  *
12926  * Block is revoked and then journaled:
12927  *   The desired end result is the journaling of the new block, so we
12928  *   cancel the revoke before the transaction commits.
12929  *
12930  * Block is journaled and then revoked:
12931  *   The revoke must take precedence over the write of the block, so we
12932  *   need either to cancel the journal entry or to write the revoke
12933  *   later in the log than the log block.  In this case, we choose the
12934  *   latter: journaling a block cancels any revoke record for that block
12935  *   in the current transaction, so any revoke for that block in the
12936  *   transaction must have happened after the block was journaled and so
12937  *   the revoke must take precedence.
12938  *
12939  * Block is revoked and then written as data:
12940  *   The data write is allowed to succeed, but the revoke is _not_
12941  *   cancelled.  We still need to prevent old log records from
12942  *   overwriting the new data.  We don't even need to clear the revoke
12943  *   bit here.
12944  *
12945  * Revoke information on buffers is a tri-state value:
12946  *
12947  * RevokeValid clear:   no cached revoke status, need to look it up
12948  * RevokeValid set, Revoked clear:
12949  *                      buffer has not been revoked, and cancel_revoke
12950  *                      need do nothing.
12951  * RevokeValid set, Revoked set:
12952  *                      buffer has been revoked.
12953  */
12954
12955 static kmem_cache_t *revoke_record_cache;
12956 static kmem_cache_t *revoke_table_cache;
12957
12958 /* Each revoke record represents one single revoked block.  During
12959    journal replay, this involves recording the transaction ID of the
12960    last transaction to revoke this block. */
12961
12962 struct jbd_revoke_record_s
12963 {
12964         struct list_head  hash;
12965         tid_t             sequence;     /* Used for recovery only */
12966         unsigned long     blocknr;
12967 };
12968
12969
12970 /* The revoke table is just a simple hash table of revoke records. */
12971 struct jbd_revoke_table_s
12972 {
12973         /* It is conceivable that we might want a larger hash table
12974          * for recovery.  Must be a power of two. */
12975         int               hash_size;
12976         int               hash_shift;
12977         struct list_head *hash_table;
12978 };
12979
12980
12981 /* Utility functions to maintain the revoke table */
12982
12983 /* Borrowed from buffer.c: this is a tried and tested block hash function */
12984 static inline int hash(journal_t *journal, unsigned long block)
12985 {
12986         struct jbd_revoke_table_s *table = journal->j_revoke;
12987         int hash_shift = table->hash_shift;
12988
12989         return ((block << (hash_shift - 6)) ^
12990                 (block >> 13) ^
12991                 (block << (hash_shift - 12))) & (table->hash_size - 1);
12992 }
12993
12994 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
12995                               tid_t seq)
12996 {
12997         struct list_head *hash_list;
12998         struct jbd_revoke_record_s *record;
12999
13000         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13001         if (!record)
13002                 goto oom;
13003
13004         record->sequence = seq;
13005         record->blocknr = blocknr;
13006         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13007         list_add(&record->hash, hash_list);
13008         return 0;
13009
13010 oom:
13011         return -ENOMEM;
13012 }
13013
13014 /* Find a revoke record in the journal's hash table. */
13015
13016 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13017                                                       unsigned long blocknr)
13018 {
13019         struct list_head *hash_list;
13020         struct jbd_revoke_record_s *record;
13021
13022         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13023
13024         record = (struct jbd_revoke_record_s *) hash_list->next;
13025         while (&(record->hash) != hash_list) {
13026                 if (record->blocknr == blocknr)
13027                         return record;
13028                 record = (struct jbd_revoke_record_s *) record->hash.next;
13029         }
13030         return NULL;
13031 }
13032
13033 int journal_init_revoke_caches(void)
13034 {
13035         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13036         if (revoke_record_cache == 0)
13037                 return -ENOMEM;
13038
13039         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13040         if (revoke_table_cache == 0) {
13041                 do_cache_destroy(revoke_record_cache);
13042                 revoke_record_cache = NULL;
13043                 return -ENOMEM;
13044         }
13045         return 0;
13046 }
13047
13048 void journal_destroy_revoke_caches(void)
13049 {
13050         do_cache_destroy(revoke_record_cache);
13051         revoke_record_cache = 0;
13052         do_cache_destroy(revoke_table_cache);
13053         revoke_table_cache = 0;
13054 }
13055
13056 /* Initialise the revoke table for a given journal to a given size. */
13057
13058 int journal_init_revoke(journal_t *journal, int hash_size)
13059 {
13060         int shift, tmp;
13061
13062         J_ASSERT (journal->j_revoke == NULL);
13063
13064         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13065         if (!journal->j_revoke)
13066                 return -ENOMEM;
13067
13068         /* Check that the hash_size is a power of two */
13069         J_ASSERT ((hash_size & (hash_size-1)) == 0);
13070
13071         journal->j_revoke->hash_size = hash_size;
13072
13073         shift = 0;
13074         tmp = hash_size;
13075         while((tmp >>= 1UL) != 0UL)
13076                 shift++;
13077         journal->j_revoke->hash_shift = shift;
13078
13079         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13080         if (!journal->j_revoke->hash_table) {
13081                 free(journal->j_revoke);
13082                 journal->j_revoke = NULL;
13083                 return -ENOMEM;
13084         }
13085
13086         for (tmp = 0; tmp < hash_size; tmp++)
13087                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13088
13089         return 0;
13090 }
13091
13092 /* Destoy a journal's revoke table.  The table must already be empty! */
13093
13094 void journal_destroy_revoke(journal_t *journal)
13095 {
13096         struct jbd_revoke_table_s *table;
13097         struct list_head *hash_list;
13098         int i;
13099
13100         table = journal->j_revoke;
13101         if (!table)
13102                 return;
13103
13104         for (i=0; i<table->hash_size; i++) {
13105                 hash_list = &table->hash_table[i];
13106                 J_ASSERT (list_empty(hash_list));
13107         }
13108
13109         free(table->hash_table);
13110         free(table);
13111         journal->j_revoke = NULL;
13112 }
13113
13114 /*
13115  * Revoke support for recovery.
13116  *
13117  * Recovery needs to be able to:
13118  *
13119  *  record all revoke records, including the tid of the latest instance
13120  *  of each revoke in the journal
13121  *
13122  *  check whether a given block in a given transaction should be replayed
13123  *  (ie. has not been revoked by a revoke record in that or a subsequent
13124  *  transaction)
13125  *
13126  *  empty the revoke table after recovery.
13127  */
13128
13129 /*
13130  * First, setting revoke records.  We create a new revoke record for
13131  * every block ever revoked in the log as we scan it for recovery, and
13132  * we update the existing records if we find multiple revokes for a
13133  * single block.
13134  */
13135
13136 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13137                        tid_t sequence)
13138 {
13139         struct jbd_revoke_record_s *record;
13140
13141         record = find_revoke_record(journal, blocknr);
13142         if (record) {
13143                 /* If we have multiple occurences, only record the
13144                  * latest sequence number in the hashed record */
13145                 if (tid_gt(sequence, record->sequence))
13146                         record->sequence = sequence;
13147                 return 0;
13148         }
13149         return insert_revoke_hash(journal, blocknr, sequence);
13150 }
13151
13152 /*
13153  * Test revoke records.  For a given block referenced in the log, has
13154  * that block been revoked?  A revoke record with a given transaction
13155  * sequence number revokes all blocks in that transaction and earlier
13156  * ones, but later transactions still need replayed.
13157  */
13158
13159 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13160                         tid_t sequence)
13161 {
13162         struct jbd_revoke_record_s *record;
13163
13164         record = find_revoke_record(journal, blocknr);
13165         if (!record)
13166                 return 0;
13167         if (tid_gt(sequence, record->sequence))
13168                 return 0;
13169         return 1;
13170 }
13171
13172 /*
13173  * Finally, once recovery is over, we need to clear the revoke table so
13174  * that it can be reused by the running filesystem.
13175  */
13176
13177 void journal_clear_revoke(journal_t *journal)
13178 {
13179         int i;
13180         struct list_head *hash_list;
13181         struct jbd_revoke_record_s *record;
13182         struct jbd_revoke_table_s *revoke_var;
13183
13184         revoke_var = journal->j_revoke;
13185
13186         for (i = 0; i < revoke_var->hash_size; i++) {
13187                 hash_list = &revoke_var->hash_table[i];
13188                 while (!list_empty(hash_list)) {
13189                         record = (struct jbd_revoke_record_s*) hash_list->next;
13190                         list_del(&record->hash);
13191                         free(record);
13192                 }
13193         }
13194 }
13195
13196 /*
13197  * e2fsck.c - superblock checks
13198  */
13199
13200 #define MIN_CHECK 1
13201 #define MAX_CHECK 2
13202
13203 static void check_super_value(e2fsck_t ctx, const char *descr,
13204                               unsigned long value, int flags,
13205                               unsigned long min_val, unsigned long max_val)
13206 {
13207         struct          problem_context pctx;
13208
13209         if (((flags & MIN_CHECK) && (value < min_val)) ||
13210             ((flags & MAX_CHECK) && (value > max_val))) {
13211                 clear_problem_context(&pctx);
13212                 pctx.num = value;
13213                 pctx.str = descr;
13214                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13215                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13216         }
13217 }
13218
13219 /*
13220  * This routine may get stubbed out in special compilations of the
13221  * e2fsck code..
13222  */
13223 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13224 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13225 {
13226         return (ext2fs_get_device_size(ctx->filesystem_name,
13227                                        EXT2_BLOCK_SIZE(ctx->fs->super),
13228                                        &ctx->num_blocks));
13229 }
13230 #endif
13231
13232 /*
13233  * helper function to release an inode
13234  */
13235 struct process_block_struct {
13236         e2fsck_t        ctx;
13237         char            *buf;
13238         struct problem_context *pctx;
13239         int             truncating;
13240         int             truncate_offset;
13241         e2_blkcnt_t     truncate_block;
13242         int             truncated_blocks;
13243         int             abort;
13244         errcode_t       errcode;
13245 };
13246
13247 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13248                                e2_blkcnt_t blockcnt,
13249                                blk_t    ref_blk FSCK_ATTR((unused)),
13250                                int      ref_offset FSCK_ATTR((unused)),
13251                                void *priv_data)
13252 {
13253         struct process_block_struct *pb;
13254         e2fsck_t                ctx;
13255         struct problem_context  *pctx;
13256         blk_t                   blk = *block_nr;
13257         int                     retval = 0;
13258
13259         pb = (struct process_block_struct *) priv_data;
13260         ctx = pb->ctx;
13261         pctx = pb->pctx;
13262
13263         pctx->blk = blk;
13264         pctx->blkcount = blockcnt;
13265
13266         if (HOLE_BLKADDR(blk))
13267                 return 0;
13268
13269         if ((blk < fs->super->s_first_data_block) ||
13270             (blk >= fs->super->s_blocks_count)) {
13271                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13272         return_abort:
13273                 pb->abort = 1;
13274                 return BLOCK_ABORT;
13275         }
13276
13277         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13278                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13279                 goto return_abort;
13280         }
13281
13282         /*
13283          * If we are deleting an orphan, then we leave the fields alone.
13284          * If we are truncating an orphan, then update the inode fields
13285          * and clean up any partial block data.
13286          */
13287         if (pb->truncating) {
13288                 /*
13289                  * We only remove indirect blocks if they are
13290                  * completely empty.
13291                  */
13292                 if (blockcnt < 0) {
13293                         int     i, limit;
13294                         blk_t   *bp;
13295
13296                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13297                                                         pb->buf);
13298                         if (pb->errcode)
13299                                 goto return_abort;
13300
13301                         limit = fs->blocksize >> 2;
13302                         for (i = 0, bp = (blk_t *) pb->buf;
13303                              i < limit;  i++, bp++)
13304                                 if (*bp)
13305                                         return 0;
13306                 }
13307                 /*
13308                  * We don't remove direct blocks until we've reached
13309                  * the truncation block.
13310                  */
13311                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13312                         return 0;
13313                 /*
13314                  * If part of the last block needs truncating, we do
13315                  * it here.
13316                  */
13317                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13318                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13319                                                         pb->buf);
13320                         if (pb->errcode)
13321                                 goto return_abort;
13322                         memset(pb->buf + pb->truncate_offset, 0,
13323                                fs->blocksize - pb->truncate_offset);
13324                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13325                                                          pb->buf);
13326                         if (pb->errcode)
13327                                 goto return_abort;
13328                 }
13329                 pb->truncated_blocks++;
13330                 *block_nr = 0;
13331                 retval |= BLOCK_CHANGED;
13332         }
13333
13334         ext2fs_block_alloc_stats(fs, blk, -1);
13335         return retval;
13336 }
13337
13338 /*
13339  * This function releases an inode.  Returns 1 if an inconsistency was
13340  * found.  If the inode has a link count, then it is being truncated and
13341  * not deleted.
13342  */
13343 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13344                                 struct ext2_inode *inode, char *block_buf,
13345                                 struct problem_context *pctx)
13346 {
13347         struct process_block_struct     pb;
13348         ext2_filsys                     fs = ctx->fs;
13349         errcode_t                       retval;
13350         __u32                           count;
13351
13352         if (!ext2fs_inode_has_valid_blocks(inode))
13353                 return 0;
13354
13355         pb.buf = block_buf + 3 * ctx->fs->blocksize;
13356         pb.ctx = ctx;
13357         pb.abort = 0;
13358         pb.errcode = 0;
13359         pb.pctx = pctx;
13360         if (inode->i_links_count) {
13361                 pb.truncating = 1;
13362                 pb.truncate_block = (e2_blkcnt_t)
13363                         ((((long long)inode->i_size_high << 32) +
13364                           inode->i_size + fs->blocksize - 1) /
13365                          fs->blocksize);
13366                 pb.truncate_offset = inode->i_size % fs->blocksize;
13367         } else {
13368                 pb.truncating = 0;
13369                 pb.truncate_block = 0;
13370                 pb.truncate_offset = 0;
13371         }
13372         pb.truncated_blocks = 0;
13373         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13374                                       block_buf, release_inode_block, &pb);
13375         if (retval) {
13376                 com_err("release_inode_blocks", retval,
13377                         _("while calling ext2fs_block_iterate for inode %d"),
13378                         ino);
13379                 return 1;
13380         }
13381         if (pb.abort)
13382                 return 1;
13383
13384         /* Refresh the inode since ext2fs_block_iterate may have changed it */
13385         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13386
13387         if (pb.truncated_blocks)
13388                 inode->i_blocks -= pb.truncated_blocks *
13389                         (fs->blocksize / 512);
13390
13391         if (inode->i_file_acl) {
13392                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13393                                                    block_buf, -1, &count);
13394                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13395                         retval = 0;
13396                         count = 1;
13397                 }
13398                 if (retval) {
13399                         com_err("release_inode_blocks", retval,
13400                 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13401                                 ino);
13402                         return 1;
13403                 }
13404                 if (count == 0)
13405                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13406                 inode->i_file_acl = 0;
13407         }
13408         return 0;
13409 }
13410
13411 /*
13412  * This function releases all of the orphan inodes.  It returns 1 if
13413  * it hit some error, and 0 on success.
13414  */
13415 static int release_orphan_inodes(e2fsck_t ctx)
13416 {
13417         ext2_filsys fs = ctx->fs;
13418         ext2_ino_t      ino, next_ino;
13419         struct ext2_inode inode;
13420         struct problem_context pctx;
13421         char *block_buf;
13422
13423         if ((ino = fs->super->s_last_orphan) == 0)
13424                 return 0;
13425
13426         /*
13427          * Win or lose, we won't be using the head of the orphan inode
13428          * list again.
13429          */
13430         fs->super->s_last_orphan = 0;
13431         ext2fs_mark_super_dirty(fs);
13432
13433         /*
13434          * If the filesystem contains errors, don't run the orphan
13435          * list, since the orphan list can't be trusted; and we're
13436          * going to be running a full e2fsck run anyway...
13437          */
13438         if (fs->super->s_state & EXT2_ERROR_FS)
13439                 return 0;
13440
13441         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13442             (ino > fs->super->s_inodes_count)) {
13443                 clear_problem_context(&pctx);
13444                 pctx.ino = ino;
13445                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13446                 return 1;
13447         }
13448
13449         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13450                                                     "block iterate buffer");
13451         e2fsck_read_bitmaps(ctx);
13452
13453         while (ino) {
13454                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13455                 clear_problem_context(&pctx);
13456                 pctx.ino = ino;
13457                 pctx.inode = &inode;
13458                 pctx.str = inode.i_links_count ? _("Truncating") :
13459                         _("Clearing");
13460
13461                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13462
13463                 next_ino = inode.i_dtime;
13464                 if (next_ino &&
13465                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13466                      (next_ino > fs->super->s_inodes_count))) {
13467                         pctx.ino = next_ino;
13468                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13469                         goto return_abort;
13470                 }
13471
13472                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13473                         goto return_abort;
13474
13475                 if (!inode.i_links_count) {
13476                         ext2fs_inode_alloc_stats2(fs, ino, -1,
13477                                                   LINUX_S_ISDIR(inode.i_mode));
13478                         inode.i_dtime = time(0);
13479                 } else {
13480                         inode.i_dtime = 0;
13481                 }
13482                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13483                 ino = next_ino;
13484         }
13485         ext2fs_free_mem(&block_buf);
13486         return 0;
13487 return_abort:
13488         ext2fs_free_mem(&block_buf);
13489         return 1;
13490 }
13491
13492 /*
13493  * Check the resize inode to make sure it is sane.  We check both for
13494  * the case where on-line resizing is not enabled (in which case the
13495  * resize inode should be cleared) as well as the case where on-line
13496  * resizing is enabled.
13497  */
13498 static void check_resize_inode(e2fsck_t ctx)
13499 {
13500         ext2_filsys fs = ctx->fs;
13501         struct ext2_inode inode;
13502         struct problem_context  pctx;
13503         int             i, j, gdt_off, ind_off;
13504         blk_t           blk, pblk, expect;
13505         __u32           *dind_buf = 0, *ind_buf;
13506         errcode_t       retval;
13507
13508         clear_problem_context(&pctx);
13509
13510         /*
13511          * If the resize inode feature isn't set, then
13512          * s_reserved_gdt_blocks must be zero.
13513          */
13514         if (!(fs->super->s_feature_compat &
13515               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13516                 if (fs->super->s_reserved_gdt_blocks) {
13517                         pctx.num = fs->super->s_reserved_gdt_blocks;
13518                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13519                                         &pctx)) {
13520                                 fs->super->s_reserved_gdt_blocks = 0;
13521                                 ext2fs_mark_super_dirty(fs);
13522                         }
13523                 }
13524         }
13525
13526         /* Read the resizde inode */
13527         pctx.ino = EXT2_RESIZE_INO;
13528         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13529         if (retval) {
13530                 if (fs->super->s_feature_compat &
13531                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
13532                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13533                 return;
13534         }
13535
13536         /*
13537          * If the resize inode feature isn't set, check to make sure
13538          * the resize inode is cleared; then we're done.
13539          */
13540         if (!(fs->super->s_feature_compat &
13541               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13542                 for (i=0; i < EXT2_N_BLOCKS; i++) {
13543                         if (inode.i_block[i])
13544                                 break;
13545                 }
13546                 if ((i < EXT2_N_BLOCKS) &&
13547                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13548                         memset(&inode, 0, sizeof(inode));
13549                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13550                                            "clear_resize");
13551                 }
13552                 return;
13553         }
13554
13555         /*
13556          * The resize inode feature is enabled; check to make sure the
13557          * only block in use is the double indirect block
13558          */
13559         blk = inode.i_block[EXT2_DIND_BLOCK];
13560         for (i=0; i < EXT2_N_BLOCKS; i++) {
13561                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13562                         break;
13563         }
13564         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13565             !(inode.i_mode & LINUX_S_IFREG) ||
13566             (blk < fs->super->s_first_data_block ||
13567              blk >= fs->super->s_blocks_count)) {
13568         resize_inode_invalid:
13569                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13570                         memset(&inode, 0, sizeof(inode));
13571                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13572                                            "clear_resize");
13573                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13574                 }
13575                 if (!(ctx->options & E2F_OPT_READONLY)) {
13576                         fs->super->s_state &= ~EXT2_VALID_FS;
13577                         ext2fs_mark_super_dirty(fs);
13578                 }
13579                 goto cleanup;
13580         }
13581         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13582                                                     "resize dind buffer");
13583         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13584
13585         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13586         if (retval)
13587                 goto resize_inode_invalid;
13588
13589         gdt_off = fs->desc_blocks;
13590         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13591         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13592              i++, gdt_off++, pblk++) {
13593                 gdt_off %= fs->blocksize/4;
13594                 if (dind_buf[gdt_off] != pblk)
13595                         goto resize_inode_invalid;
13596                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13597                 if (retval)
13598                         goto resize_inode_invalid;
13599                 ind_off = 0;
13600                 for (j = 1; j < fs->group_desc_count; j++) {
13601                         if (!ext2fs_bg_has_super(fs, j))
13602                                 continue;
13603                         expect = pblk + (j * fs->super->s_blocks_per_group);
13604                         if (ind_buf[ind_off] != expect)
13605                                 goto resize_inode_invalid;
13606                         ind_off++;
13607                 }
13608         }
13609
13610 cleanup:
13611         ext2fs_free_mem(&dind_buf);
13612
13613  }
13614
13615 static void check_super_block(e2fsck_t ctx)
13616 {
13617         ext2_filsys fs = ctx->fs;
13618         blk_t   first_block, last_block;
13619         struct ext2_super_block *sb = fs->super;
13620         struct ext2_group_desc *gd;
13621         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
13622         blk_t   bpg_max;
13623         int     inodes_per_block;
13624         int     ipg_max;
13625         int     inode_size;
13626         dgrp_t  i;
13627         blk_t   should_be;
13628         struct problem_context  pctx;
13629         __u32   free_blocks = 0, free_inodes = 0;
13630
13631         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13632         ipg_max = inodes_per_block * (blocks_per_group - 4);
13633         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13634                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13635         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13636         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13637                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13638
13639         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13640                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13641         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13642                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13643         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13644                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13645
13646         clear_problem_context(&pctx);
13647
13648         /*
13649          * Verify the super block constants...
13650          */
13651         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13652                           MIN_CHECK, 1, 0);
13653         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13654                           MIN_CHECK, 1, 0);
13655         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13656                           MAX_CHECK, 0, sb->s_blocks_count);
13657         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13658                           MIN_CHECK | MAX_CHECK, 0,
13659                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13660         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13661                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13662         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13663                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13664                           bpg_max);
13665         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13666                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
13667         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13668                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13669         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13670                           MAX_CHECK, 0, sb->s_blocks_count / 2);
13671         check_super_value(ctx, "reserved_gdt_blocks",
13672                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13673                           fs->blocksize/4);
13674         inode_size = EXT2_INODE_SIZE(sb);
13675         check_super_value(ctx, "inode_size",
13676                           inode_size, MIN_CHECK | MAX_CHECK,
13677                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13678         if (inode_size & (inode_size - 1)) {
13679                 pctx.num = inode_size;
13680                 pctx.str = "inode_size";
13681                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13682                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13683                 return;
13684         }
13685
13686         if (!ctx->num_blocks) {
13687                 pctx.errcode = e2fsck_get_device_size(ctx);
13688                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13689                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13690                         ctx->flags |= E2F_FLAG_ABORT;
13691                         return;
13692                 }
13693                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13694                     (ctx->num_blocks < sb->s_blocks_count)) {
13695                         pctx.blk = sb->s_blocks_count;
13696                         pctx.blk2 = ctx->num_blocks;
13697                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13698                                 ctx->flags |= E2F_FLAG_ABORT;
13699                                 return;
13700                         }
13701                 }
13702         }
13703
13704         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13705                 pctx.blk = EXT2_BLOCK_SIZE(sb);
13706                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13707                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13708                 ctx->flags |= E2F_FLAG_ABORT;
13709                 return;
13710         }
13711
13712         should_be = sb->s_frags_per_group >>
13713                 (sb->s_log_block_size - sb->s_log_frag_size);
13714         if (sb->s_blocks_per_group != should_be) {
13715                 pctx.blk = sb->s_blocks_per_group;
13716                 pctx.blk2 = should_be;
13717                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13718                 ctx->flags |= E2F_FLAG_ABORT;
13719                 return;
13720         }
13721
13722         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13723         if (sb->s_first_data_block != should_be) {
13724                 pctx.blk = sb->s_first_data_block;
13725                 pctx.blk2 = should_be;
13726                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13727                 ctx->flags |= E2F_FLAG_ABORT;
13728                 return;
13729         }
13730
13731         should_be = sb->s_inodes_per_group * fs->group_desc_count;
13732         if (sb->s_inodes_count != should_be) {
13733                 pctx.ino = sb->s_inodes_count;
13734                 pctx.ino2 = should_be;
13735                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13736                         sb->s_inodes_count = should_be;
13737                         ext2fs_mark_super_dirty(fs);
13738                 }
13739         }
13740
13741         /*
13742          * Verify the group descriptors....
13743          */
13744         first_block =  sb->s_first_data_block;
13745         last_block = first_block + blocks_per_group;
13746
13747         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13748                 pctx.group = i;
13749
13750                 if (i == fs->group_desc_count - 1)
13751                         last_block = sb->s_blocks_count;
13752                 if ((gd->bg_block_bitmap < first_block) ||
13753                     (gd->bg_block_bitmap >= last_block)) {
13754                         pctx.blk = gd->bg_block_bitmap;
13755                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13756                                 gd->bg_block_bitmap = 0;
13757                 }
13758                 if (gd->bg_block_bitmap == 0) {
13759                         ctx->invalid_block_bitmap_flag[i]++;
13760                         ctx->invalid_bitmaps++;
13761                 }
13762                 if ((gd->bg_inode_bitmap < first_block) ||
13763                     (gd->bg_inode_bitmap >= last_block)) {
13764                         pctx.blk = gd->bg_inode_bitmap;
13765                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13766                                 gd->bg_inode_bitmap = 0;
13767                 }
13768                 if (gd->bg_inode_bitmap == 0) {
13769                         ctx->invalid_inode_bitmap_flag[i]++;
13770                         ctx->invalid_bitmaps++;
13771                 }
13772                 if ((gd->bg_inode_table < first_block) ||
13773                     ((gd->bg_inode_table +
13774                       fs->inode_blocks_per_group - 1) >= last_block)) {
13775                         pctx.blk = gd->bg_inode_table;
13776                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13777                                 gd->bg_inode_table = 0;
13778                 }
13779                 if (gd->bg_inode_table == 0) {
13780                         ctx->invalid_inode_table_flag[i]++;
13781                         ctx->invalid_bitmaps++;
13782                 }
13783                 free_blocks += gd->bg_free_blocks_count;
13784                 free_inodes += gd->bg_free_inodes_count;
13785                 first_block += sb->s_blocks_per_group;
13786                 last_block += sb->s_blocks_per_group;
13787
13788                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13789                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13790                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13791                         ext2fs_unmark_valid(fs);
13792
13793         }
13794
13795         /*
13796          * Update the global counts from the block group counts.  This
13797          * is needed for an experimental patch which eliminates
13798          * locking the entire filesystem when allocating blocks or
13799          * inodes; if the filesystem is not unmounted cleanly, the
13800          * global counts may not be accurate.
13801          */
13802         if ((free_blocks != sb->s_free_blocks_count) ||
13803             (free_inodes != sb->s_free_inodes_count)) {
13804                 if (ctx->options & E2F_OPT_READONLY)
13805                         ext2fs_unmark_valid(fs);
13806                 else {
13807                         sb->s_free_blocks_count = free_blocks;
13808                         sb->s_free_inodes_count = free_inodes;
13809                         ext2fs_mark_super_dirty(fs);
13810                 }
13811         }
13812
13813         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13814             (sb->s_free_inodes_count > sb->s_inodes_count))
13815                 ext2fs_unmark_valid(fs);
13816
13817
13818         /*
13819          * If we have invalid bitmaps, set the error state of the
13820          * filesystem.
13821          */
13822         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13823                 sb->s_state &= ~EXT2_VALID_FS;
13824                 ext2fs_mark_super_dirty(fs);
13825         }
13826
13827         clear_problem_context(&pctx);
13828
13829 #ifndef EXT2_SKIP_UUID
13830         /*
13831          * If the UUID field isn't assigned, assign it.
13832          */
13833         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13834                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13835                         uuid_generate(sb->s_uuid);
13836                         ext2fs_mark_super_dirty(fs);
13837                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13838                 }
13839         }
13840 #endif
13841
13842         /*
13843          * For the Hurd, check to see if the filetype option is set,
13844          * since it doesn't support it.
13845          */
13846         if (!(ctx->options & E2F_OPT_READONLY) &&
13847             fs->super->s_creator_os == EXT2_OS_HURD &&
13848             (fs->super->s_feature_incompat &
13849              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13850                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13851                         fs->super->s_feature_incompat &=
13852                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13853                         ext2fs_mark_super_dirty(fs);
13854
13855                 }
13856         }
13857
13858         /*
13859          * If we have any of the compatibility flags set, we need to have a
13860          * revision 1 filesystem.  Most kernels will not check the flags on
13861          * a rev 0 filesystem and we may have corruption issues because of
13862          * the incompatible changes to the filesystem.
13863          */
13864         if (!(ctx->options & E2F_OPT_READONLY) &&
13865             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13866             (fs->super->s_feature_compat ||
13867              fs->super->s_feature_ro_compat ||
13868              fs->super->s_feature_incompat) &&
13869             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13870                 ext2fs_update_dynamic_rev(fs);
13871                 ext2fs_mark_super_dirty(fs);
13872         }
13873
13874         check_resize_inode(ctx);
13875
13876         /*
13877          * Clean up any orphan inodes, if present.
13878          */
13879         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13880                 fs->super->s_state &= ~EXT2_VALID_FS;
13881                 ext2fs_mark_super_dirty(fs);
13882         }
13883
13884         /*
13885          * Move the ext3 journal file, if necessary.
13886          */
13887         e2fsck_move_ext3_journal(ctx);
13888         return;
13889 }
13890
13891 /*
13892  * swapfs.c --- byte-swap an ext2 filesystem
13893  */
13894
13895 #ifdef ENABLE_SWAPFS
13896
13897 struct swap_block_struct {
13898         ext2_ino_t      ino;
13899         int             isdir;
13900         errcode_t       errcode;
13901         char            *dir_buf;
13902         struct ext2_inode *inode;
13903 };
13904
13905 /*
13906  * This is a helper function for block_iterate.  We mark all of the
13907  * indirect and direct blocks as changed, so that block_iterate will
13908  * write them out.
13909  */
13910 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13911                       void *priv_data)
13912 {
13913         errcode_t       retval;
13914
13915         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13916
13917         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13918                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13919                 if (retval) {
13920                         sb->errcode = retval;
13921                         return BLOCK_ABORT;
13922                 }
13923                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13924                 if (retval) {
13925                         sb->errcode = retval;
13926                         return BLOCK_ABORT;
13927                 }
13928         }
13929         if (blockcnt >= 0) {
13930                 if (blockcnt < EXT2_NDIR_BLOCKS)
13931                         return 0;
13932                 return BLOCK_CHANGED;
13933         }
13934         if (blockcnt == BLOCK_COUNT_IND) {
13935                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
13936                         return 0;
13937                 return BLOCK_CHANGED;
13938         }
13939         if (blockcnt == BLOCK_COUNT_DIND) {
13940                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
13941                         return 0;
13942                 return BLOCK_CHANGED;
13943         }
13944         if (blockcnt == BLOCK_COUNT_TIND) {
13945                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
13946                         return 0;
13947                 return BLOCK_CHANGED;
13948         }
13949         return BLOCK_CHANGED;
13950 }
13951
13952 /*
13953  * This function is responsible for byte-swapping all of the indirect,
13954  * block pointers.  It is also responsible for byte-swapping directories.
13955  */
13956 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
13957                               struct ext2_inode *inode)
13958 {
13959         errcode_t                       retval;
13960         struct swap_block_struct        sb;
13961
13962         sb.ino = ino;
13963         sb.inode = inode;
13964         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
13965         sb.errcode = 0;
13966         sb.isdir = 0;
13967         if (LINUX_S_ISDIR(inode->i_mode))
13968                 sb.isdir = 1;
13969
13970         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
13971                                       swap_block, &sb);
13972         if (retval) {
13973                 com_err("swap_inode_blocks", retval,
13974                         _("while calling ext2fs_block_iterate"));
13975                 ctx->flags |= E2F_FLAG_ABORT;
13976                 return;
13977         }
13978         if (sb.errcode) {
13979                 com_err("swap_inode_blocks", sb.errcode,
13980                         _("while calling iterator function"));
13981                 ctx->flags |= E2F_FLAG_ABORT;
13982                 return;
13983         }
13984 }
13985
13986 static void swap_inodes(e2fsck_t ctx)
13987 {
13988         ext2_filsys fs = ctx->fs;
13989         dgrp_t                  group;
13990         unsigned int            i;
13991         ext2_ino_t              ino = 1;
13992         char                    *buf, *block_buf;
13993         errcode_t               retval;
13994         struct ext2_inode *     inode;
13995
13996         e2fsck_use_inode_shortcuts(ctx, 1);
13997
13998         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
13999                                 &buf);
14000         if (retval) {
14001                 com_err("swap_inodes", retval,
14002                         _("while allocating inode buffer"));
14003                 ctx->flags |= E2F_FLAG_ABORT;
14004                 return;
14005         }
14006         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14007                                                     "block interate buffer");
14008         for (group = 0; group < fs->group_desc_count; group++) {
14009                 retval = io_channel_read_blk(fs->io,
14010                       fs->group_desc[group].bg_inode_table,
14011                       fs->inode_blocks_per_group, buf);
14012                 if (retval) {
14013                         com_err("swap_inodes", retval,
14014                                 _("while reading inode table (group %d)"),
14015                                 group);
14016                         ctx->flags |= E2F_FLAG_ABORT;
14017                         return;
14018                 }
14019                 inode = (struct ext2_inode *) buf;
14020                 for (i=0; i < fs->super->s_inodes_per_group;
14021                      i++, ino++, inode++) {
14022                         ctx->stashed_ino = ino;
14023                         ctx->stashed_inode = inode;
14024
14025                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14026                                 ext2fs_swap_inode(fs, inode, inode, 0);
14027
14028                         /*
14029                          * Skip deleted files.
14030                          */
14031                         if (inode->i_links_count == 0)
14032                                 continue;
14033
14034                         if (LINUX_S_ISDIR(inode->i_mode) ||
14035                             ((inode->i_block[EXT2_IND_BLOCK] ||
14036                               inode->i_block[EXT2_DIND_BLOCK] ||
14037                               inode->i_block[EXT2_TIND_BLOCK]) &&
14038                              ext2fs_inode_has_valid_blocks(inode)))
14039                                 swap_inode_blocks(ctx, ino, block_buf, inode);
14040
14041                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14042                                 return;
14043
14044                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14045                                 ext2fs_swap_inode(fs, inode, inode, 1);
14046                 }
14047                 retval = io_channel_write_blk(fs->io,
14048                       fs->group_desc[group].bg_inode_table,
14049                       fs->inode_blocks_per_group, buf);
14050                 if (retval) {
14051                         com_err("swap_inodes", retval,
14052                                 _("while writing inode table (group %d)"),
14053                                 group);
14054                         ctx->flags |= E2F_FLAG_ABORT;
14055                         return;
14056                 }
14057         }
14058         ext2fs_free_mem(&buf);
14059         ext2fs_free_mem(&block_buf);
14060         e2fsck_use_inode_shortcuts(ctx, 0);
14061         ext2fs_flush_icache(fs);
14062 }
14063
14064 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14065 /*
14066  * On the PowerPC, the big-endian variant of the ext2 filesystem
14067  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14068  * of each word.  Thus a bitmap with only bit 0 set would be, as
14069  * a string of bytes, 00 00 00 01 00 ...
14070  * To cope with this, we byte-reverse each word of a bitmap if
14071  * we have a big-endian filesystem, that is, if we are *not*
14072  * byte-swapping other word-sized numbers.
14073  */
14074 #define EXT2_BIG_ENDIAN_BITMAPS
14075 #endif
14076
14077 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14078 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14079 {
14080         __u32 *p = (__u32 *) bmap->bitmap;
14081         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14082
14083         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14084                 *p = ext2fs_swab32(*p);
14085 }
14086 #endif
14087
14088
14089 #ifdef ENABLE_SWAPFS
14090 static void swap_filesys(e2fsck_t ctx)
14091 {
14092         ext2_filsys fs = ctx->fs;
14093 #ifdef RESOURCE_TRACK
14094         struct resource_track   rtrack;
14095
14096         init_resource_track(&rtrack);
14097 #endif
14098
14099         if (!(ctx->options & E2F_OPT_PREEN))
14100                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14101
14102 #ifdef MTRACE
14103         mtrace_print("Byte swap");
14104 #endif
14105
14106         if (fs->super->s_mnt_count) {
14107                 fprintf(stderr, _("%s: the filesystem must be freshly "
14108                         "checked using fsck\n"
14109                         "and not mounted before trying to "
14110                         "byte-swap it.\n"), ctx->device_name);
14111                 ctx->flags |= E2F_FLAG_ABORT;
14112                 return;
14113         }
14114         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14115                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14116                                EXT2_FLAG_SWAP_BYTES_WRITE);
14117                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14118         } else {
14119                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14120                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14121         }
14122         swap_inodes(ctx);
14123         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14124                 return;
14125         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14126                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14127         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14128                        EXT2_FLAG_SWAP_BYTES_WRITE);
14129
14130 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14131         e2fsck_read_bitmaps(ctx);
14132         ext2fs_swap_bitmap(fs->inode_map);
14133         ext2fs_swap_bitmap(fs->block_map);
14134         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14135 #endif
14136         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14137         ext2fs_flush(fs);
14138         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14139
14140 #ifdef RESOURCE_TRACK
14141         if (ctx->options & E2F_OPT_TIME2)
14142                 print_resource_track(_("Byte swap"), &rtrack);
14143 #endif
14144 }
14145 #endif  /* ENABLE_SWAPFS */
14146
14147 #endif
14148
14149 /*
14150  * util.c --- miscellaneous utilities
14151  */
14152
14153 #ifdef HAVE_CONIO_H
14154 #undef HAVE_TERMIOS_H
14155 #include <conio.h>
14156 #define read_a_char()   getch()
14157 #else
14158 #ifdef HAVE_TERMIOS_H
14159 #include <termios.h>
14160 #endif
14161 #endif
14162
14163 #if 0
14164 void fatal_error(e2fsck_t ctx, const char *msg)
14165 {
14166         if (msg)
14167                 fprintf (stderr, "e2fsck: %s\n", msg);
14168         if (ctx->fs && ctx->fs->io) {
14169                 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14170                         io_channel_flush(ctx->fs->io);
14171                 else
14172                         fprintf(stderr, "e2fsck: io manager magic bad!\n");
14173         }
14174         ctx->flags |= E2F_FLAG_ABORT;
14175         if (ctx->flags & E2F_FLAG_SETJMP_OK)
14176                 longjmp(ctx->abort_loc, 1);
14177         exit(EXIT_ERROR);
14178 }
14179 #endif
14180
14181 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14182                              const char *description)
14183 {
14184         void *ret;
14185         char buf[256];
14186
14187 #ifdef DEBUG_ALLOCATE_MEMORY
14188         printf("Allocating %d bytes for %s...\n", size, description);
14189 #endif
14190         ret = malloc(size);
14191         if (!ret) {
14192                 sprintf(buf, "Can't allocate %s\n", description);
14193                 fatal_error(ctx, buf);
14194         }
14195         memset(ret, 0, size);
14196         return ret;
14197 }
14198
14199 static char *string_copy(const char *str, int len)
14200 {
14201         char    *ret;
14202
14203         if (!str)
14204                 return NULL;
14205         if (!len)
14206                 len = strlen(str);
14207         ret = malloc(len+1);
14208         if (ret) {
14209                 strncpy(ret, str, len);
14210                 ret[len] = 0;
14211         }
14212         return ret;
14213 }
14214
14215 #ifndef HAVE_CONIO_H
14216 static int read_a_char(void)
14217 {
14218         char    c;
14219         int     r;
14220         int     fail = 0;
14221
14222         while(1) {
14223                 if (e2fsck_global_ctx &&
14224                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14225                         return 3;
14226                 }
14227                 r = read(0, &c, 1);
14228                 if (r == 1)
14229                         return c;
14230                 if (fail++ > 100)
14231                         break;
14232         }
14233         return EOF;
14234 }
14235 #endif
14236
14237 static int ask_yn(const char * string, int def)
14238 {
14239         int             c;
14240         const char      *defstr;
14241         static const char short_yes[] = "yY";
14242         static const char short_no[] = "nN";
14243
14244 #ifdef HAVE_TERMIOS_H
14245         struct termios  termios, tmp;
14246
14247         tcgetattr (0, &termios);
14248         tmp = termios;
14249         tmp.c_lflag &= ~(ICANON | ECHO);
14250         tmp.c_cc[VMIN] = 1;
14251         tmp.c_cc[VTIME] = 0;
14252         tcsetattr (0, TCSANOW, &tmp);
14253 #endif
14254
14255         if (def == 1)
14256                 defstr = "<y>";
14257         else if (def == 0)
14258                 defstr = "<n>";
14259         else
14260                 defstr = " (y/n)";
14261         printf("%s%s? ", string, defstr);
14262         while (1) {
14263                 fflush (stdout);
14264                 if ((c = read_a_char()) == EOF)
14265                         break;
14266                 if (c == 3) {
14267 #ifdef HAVE_TERMIOS_H
14268                         tcsetattr (0, TCSANOW, &termios);
14269 #endif
14270                         if (e2fsck_global_ctx &&
14271                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14272                                 puts("\n");
14273                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
14274                         }
14275                         puts(_("cancelled!\n"));
14276                         return 0;
14277                 }
14278                 if (strchr(short_yes, (char) c)) {
14279                         def = 1;
14280                         break;
14281                 }
14282                 else if (strchr(short_no, (char) c)) {
14283                         def = 0;
14284                         break;
14285                 }
14286                 else if ((c == ' ' || c == '\n') && (def != -1))
14287                         break;
14288         }
14289         if (def)
14290                 puts("yes\n");
14291         else
14292                 puts ("no\n");
14293 #ifdef HAVE_TERMIOS_H
14294         tcsetattr (0, TCSANOW, &termios);
14295 #endif
14296         return def;
14297 }
14298
14299 int ask (e2fsck_t ctx, const char * string, int def)
14300 {
14301         if (ctx->options & E2F_OPT_NO) {
14302                 printf (_("%s? no\n\n"), string);
14303                 return 0;
14304         }
14305         if (ctx->options & E2F_OPT_YES) {
14306                 printf (_("%s? yes\n\n"), string);
14307                 return 1;
14308         }
14309         if (ctx->options & E2F_OPT_PREEN) {
14310                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14311                 return def;
14312         }
14313         return ask_yn(string, def);
14314 }
14315
14316 void e2fsck_read_bitmaps(e2fsck_t ctx)
14317 {
14318         ext2_filsys fs = ctx->fs;
14319         errcode_t       retval;
14320
14321         if (ctx->invalid_bitmaps) {
14322                 com_err(ctx->program_name, 0,
14323                     _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14324                         ctx->device_name);
14325                 fatal_error(ctx, 0);
14326         }
14327
14328         ehandler_operation(_("reading inode and block bitmaps"));
14329         retval = ext2fs_read_bitmaps(fs);
14330         ehandler_operation(0);
14331         if (retval) {
14332                 com_err(ctx->program_name, retval,
14333                         _("while retrying to read bitmaps for %s"),
14334                         ctx->device_name);
14335                 fatal_error(ctx, 0);
14336         }
14337 }
14338
14339 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14340 {
14341         ext2_filsys fs = ctx->fs;
14342         errcode_t       retval;
14343
14344         if (ext2fs_test_bb_dirty(fs)) {
14345                 ehandler_operation(_("writing block bitmaps"));
14346                 retval = ext2fs_write_block_bitmap(fs);
14347                 ehandler_operation(0);
14348                 if (retval) {
14349                         com_err(ctx->program_name, retval,
14350                             _("while retrying to write block bitmaps for %s"),
14351                                 ctx->device_name);
14352                         fatal_error(ctx, 0);
14353                 }
14354         }
14355
14356         if (ext2fs_test_ib_dirty(fs)) {
14357                 ehandler_operation(_("writing inode bitmaps"));
14358                 retval = ext2fs_write_inode_bitmap(fs);
14359                 ehandler_operation(0);
14360                 if (retval) {
14361                         com_err(ctx->program_name, retval,
14362                             _("while retrying to write inode bitmaps for %s"),
14363                                 ctx->device_name);
14364                         fatal_error(ctx, 0);
14365                 }
14366         }
14367 }
14368
14369 void preenhalt(e2fsck_t ctx)
14370 {
14371         ext2_filsys fs = ctx->fs;
14372
14373         if (!(ctx->options & E2F_OPT_PREEN))
14374                 return;
14375         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14376                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14377                ctx->device_name);
14378         if (fs != NULL) {
14379                 fs->super->s_state |= EXT2_ERROR_FS;
14380                 ext2fs_mark_super_dirty(fs);
14381                 ext2fs_close(fs);
14382         }
14383         exit(EXIT_UNCORRECTED);
14384 }
14385
14386 #ifdef RESOURCE_TRACK
14387 void init_resource_track(struct resource_track *track)
14388 {
14389 #ifdef HAVE_GETRUSAGE
14390         struct rusage r;
14391 #endif
14392
14393         track->brk_start = sbrk(0);
14394         gettimeofday(&track->time_start, 0);
14395 #ifdef HAVE_GETRUSAGE
14396 #ifdef sun
14397         memset(&r, 0, sizeof(struct rusage));
14398 #endif
14399         getrusage(RUSAGE_SELF, &r);
14400         track->user_start = r.ru_utime;
14401         track->system_start = r.ru_stime;
14402 #else
14403         track->user_start.tv_sec = track->user_start.tv_usec = 0;
14404         track->system_start.tv_sec = track->system_start.tv_usec = 0;
14405 #endif
14406 }
14407
14408 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14409                                        struct timeval *tv2)
14410 {
14411         return ((tv1->tv_sec - tv2->tv_sec) +
14412                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14413 }
14414
14415 void print_resource_track(const char *desc, struct resource_track *track)
14416 {
14417 #ifdef HAVE_GETRUSAGE
14418         struct rusage r;
14419 #endif
14420 #ifdef HAVE_MALLINFO
14421         struct mallinfo malloc_info;
14422 #endif
14423         struct timeval time_end;
14424
14425         gettimeofday(&time_end, 0);
14426
14427         if (desc)
14428                 printf("%s: ", desc);
14429
14430 #ifdef HAVE_MALLINFO
14431 #define kbytes(x)       (((x) + 1023) / 1024)
14432
14433         malloc_info = mallinfo();
14434         printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14435                kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14436                kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14437 #else
14438         printf(_("Memory used: %d, "),
14439                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14440 #endif
14441 #ifdef HAVE_GETRUSAGE
14442         getrusage(RUSAGE_SELF, &r);
14443
14444         printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14445                timeval_subtract(&time_end, &track->time_start),
14446                timeval_subtract(&r.ru_utime, &track->user_start),
14447                timeval_subtract(&r.ru_stime, &track->system_start));
14448 #else
14449         printf(_("elapsed time: %6.3f\n"),
14450                timeval_subtract(&time_end, &track->time_start));
14451 #endif
14452 }
14453 #endif /* RESOURCE_TRACK */
14454
14455 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14456                               struct ext2_inode * inode, const char *proc)
14457 {
14458         int retval;
14459
14460         retval = ext2fs_read_inode(ctx->fs, ino, inode);
14461         if (retval) {
14462                 com_err("ext2fs_read_inode", retval,
14463                         _("while reading inode %ld in %s"), ino, proc);
14464                 fatal_error(ctx, 0);
14465         }
14466 }
14467
14468 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14469                                struct ext2_inode * inode, int bufsize,
14470                                const char *proc)
14471 {
14472         int retval;
14473
14474         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14475         if (retval) {
14476                 com_err("ext2fs_write_inode", retval,
14477                         _("while writing inode %ld in %s"), ino, proc);
14478                 fatal_error(ctx, 0);
14479         }
14480 }
14481
14482 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14483                                struct ext2_inode * inode, const char *proc)
14484 {
14485         int retval;
14486
14487         retval = ext2fs_write_inode(ctx->fs, ino, inode);
14488         if (retval) {
14489                 com_err("ext2fs_write_inode", retval,
14490                         _("while writing inode %ld in %s"), ino, proc);
14491                 fatal_error(ctx, 0);
14492         }
14493 }
14494
14495 #ifdef MTRACE
14496 void mtrace_print(char *mesg)
14497 {
14498         FILE    *malloc_get_mallstream();
14499         FILE    *f = malloc_get_mallstream();
14500
14501         if (f)
14502                 fprintf(f, "============= %s\n", mesg);
14503 }
14504 #endif
14505
14506 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14507                    io_manager manager)
14508 {
14509         struct ext2_super_block *sb;
14510         io_channel              io = NULL;
14511         void                    *buf = NULL;
14512         int                     blocksize;
14513         blk_t                   superblock, ret_sb = 8193;
14514
14515         if (fs && fs->super) {
14516                 ret_sb = (fs->super->s_blocks_per_group +
14517                           fs->super->s_first_data_block);
14518                 if (ctx) {
14519                         ctx->superblock = ret_sb;
14520                         ctx->blocksize = fs->blocksize;
14521                 }
14522                 return ret_sb;
14523         }
14524
14525         if (ctx) {
14526                 if (ctx->blocksize) {
14527                         ret_sb = ctx->blocksize * 8;
14528                         if (ctx->blocksize == 1024)
14529                                 ret_sb++;
14530                         ctx->superblock = ret_sb;
14531                         return ret_sb;
14532                 }
14533                 ctx->superblock = ret_sb;
14534                 ctx->blocksize = 1024;
14535         }
14536
14537         if (!name || !manager)
14538                 goto cleanup;
14539
14540         if (manager->open(name, 0, &io) != 0)
14541                 goto cleanup;
14542
14543         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14544                 goto cleanup;
14545         sb = (struct ext2_super_block *) buf;
14546
14547         for (blocksize = EXT2_MIN_BLOCK_SIZE;
14548              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14549                 superblock = blocksize*8;
14550                 if (blocksize == 1024)
14551                         superblock++;
14552                 io_channel_set_blksize(io, blocksize);
14553                 if (io_channel_read_blk(io, superblock,
14554                                         -SUPERBLOCK_SIZE, buf))
14555                         continue;
14556 #ifdef EXT2FS_ENABLE_SWAPFS
14557                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14558                         ext2fs_swap_super(sb);
14559 #endif
14560                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14561                         ret_sb = superblock;
14562                         if (ctx) {
14563                                 ctx->superblock = superblock;
14564                                 ctx->blocksize = blocksize;
14565                         }
14566                         break;
14567                 }
14568         }
14569
14570 cleanup:
14571         if (io)
14572                 io_channel_close(io);
14573         ext2fs_free_mem(&buf);
14574         return (ret_sb);
14575 }
14576
14577
14578 /*
14579  * This function runs through the e2fsck passes and calls them all,
14580  * returning restart, abort, or cancel as necessary...
14581  */
14582 typedef void (*pass_t)(e2fsck_t ctx);
14583
14584 static const pass_t e2fsck_passes[] = {
14585         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14586         e2fsck_pass5, 0 };
14587
14588 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14589
14590 static int e2fsck_run(e2fsck_t ctx)
14591 {
14592         int     i;
14593         pass_t  e2fsck_pass;
14594
14595         if (setjmp(ctx->abort_loc)) {
14596                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14597                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14598         }
14599         ctx->flags |= E2F_FLAG_SETJMP_OK;
14600
14601         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14602                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14603                         break;
14604                 e2fsck_pass(ctx);
14605                 if (ctx->progress)
14606                         (void) (ctx->progress)(ctx, 0, 0, 0);
14607         }
14608         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14609
14610         if (ctx->flags & E2F_FLAG_RUN_RETURN)
14611                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14612         return 0;
14613 }
14614
14615
14616 /*
14617  * unix.c - The unix-specific code for e2fsck
14618  */
14619
14620
14621 /* Command line options */
14622 static int swapfs;
14623 #ifdef ENABLE_SWAPFS
14624 static int normalize_swapfs;
14625 #endif
14626 static int cflag;               /* check disk */
14627 static int show_version_only;
14628 static int verbose;
14629
14630 static int replace_bad_blocks;
14631 static int keep_bad_blocks;
14632 static char *bad_blocks_file;
14633
14634 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
14635 int journal_enable_debug = -1;
14636 #endif
14637
14638 #if 0
14639 static void usage(e2fsck_t ctx)
14640 {
14641         fprintf(stderr,
14642                 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14643                 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14644                 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal]\n"
14645                 "\t\t[-E extended-options] device\n"),
14646                 ctx->program_name);
14647
14648         fprintf(stderr, _("\nEmergency help:\n"
14649                 " -p                   Automatic repair (no questions)\n"
14650                 " -n                   Make no changes to the filesystem\n"
14651                 " -y                   Assume \"yes\" to all questions\n"
14652                 " -c                   Check for bad blocks and add them to the badblock list\n"
14653                 " -f                   Force checking even if filesystem is marked clean\n"));
14654         fprintf(stderr, _(""
14655                 " -v                   Be verbose\n"
14656                 " -b superblock        Use alternative superblock\n"
14657                 " -B blocksize         Force blocksize when looking for superblock\n"
14658                 " -j external-journal  Set location of the external journal\n"
14659                 " -l bad_blocks_file   Add to badblocks list\n"
14660                 " -L bad_blocks_file   Set badblocks list\n"
14661                 ));
14662
14663         exit(EXIT_USAGE);
14664 }
14665 #endif
14666
14667 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
14668
14669 static void show_stats(e2fsck_t ctx)
14670 {
14671         ext2_filsys fs = ctx->fs;
14672         int inodes, inodes_used, blocks, blocks_used;
14673         int dir_links;
14674         int num_files, num_links;
14675         int frag_percent;
14676
14677         dir_links = 2 * ctx->fs_directory_count - 1;
14678         num_files = ctx->fs_total_count - dir_links;
14679         num_links = ctx->fs_links_count - dir_links;
14680         inodes = fs->super->s_inodes_count;
14681         inodes_used = (fs->super->s_inodes_count -
14682                        fs->super->s_free_inodes_count);
14683         blocks = fs->super->s_blocks_count;
14684         blocks_used = (fs->super->s_blocks_count -
14685                        fs->super->s_free_blocks_count);
14686
14687         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14688         frag_percent = (frag_percent + 5) / 10;
14689
14690         if (!verbose) {
14691                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14692                        ctx->device_name, inodes_used, inodes,
14693                        frag_percent / 10, frag_percent % 10,
14694                        blocks_used, blocks);
14695                 return;
14696         }
14697         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14698                 100 * inodes_used / inodes);
14699         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14700                 P_E2("", "s", ctx->fs_fragmented),
14701                 frag_percent / 10, frag_percent % 10);
14702         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14703                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14704         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14705                 (int) ((long long) 100 * blocks_used / blocks));
14706         printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14707         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14708         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14709         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14710         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14711         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14712         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14713         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14714         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14715         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14716         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14717         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14718 }
14719
14720 static void check_mount(e2fsck_t ctx)
14721 {
14722         errcode_t       retval;
14723         int             cont;
14724
14725         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14726                                          &ctx->mount_flags);
14727         if (retval) {
14728                 com_err("ext2fs_check_if_mount", retval,
14729                         _("while determining whether %s is mounted."),
14730                         ctx->filesystem_name);
14731                 return;
14732         }
14733
14734         /*
14735          * If the filesystem isn't mounted, or it's the root filesystem
14736          * and it's mounted read-only, then everything's fine.
14737          */
14738         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14739             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14740              (ctx->mount_flags & EXT2_MF_READONLY)))
14741                 return;
14742
14743         if (ctx->options & E2F_OPT_READONLY) {
14744                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
14745                 return;
14746         }
14747
14748         printf(_("%s is mounted.  "), ctx->filesystem_name);
14749         if (!ctx->interactive)
14750                 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14751         printf(_("\n\n\007\007\007\007WARNING!!!  "
14752                "Running e2fsck on a mounted filesystem may cause\n"
14753                "SEVERE filesystem damage.\007\007\007\n\n"));
14754         cont = ask_yn(_("Do you really want to continue"), -1);
14755         if (!cont) {
14756                 printf (_("check aborted.\n"));
14757                 exit (0);
14758         }
14759         return;
14760 }
14761
14762 static int is_on_batt(void)
14763 {
14764         FILE    *f;
14765         DIR     *d;
14766         char    tmp[80], tmp2[80], fname[80];
14767         unsigned int    acflag;
14768         struct dirent*  de;
14769
14770         f = fopen("/proc/apm", "r");
14771         if (f) {
14772                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14773                         acflag = 1;
14774                 fclose(f);
14775                 return (acflag != 1);
14776         }
14777         d = opendir("/proc/acpi/ac_adapter");
14778         if (d) {
14779                 while ((de=readdir(d)) != NULL) {
14780                         if (!strncmp(".", de->d_name, 1))
14781                                 continue;
14782                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14783                                  de->d_name);
14784                         f = fopen(fname, "r");
14785                         if (!f)
14786                                 continue;
14787                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14788                                 tmp[0] = 0;
14789                         fclose(f);
14790                         if (strncmp(tmp, "off-line", 8) == 0) {
14791                                 closedir(d);
14792                                 return 1;
14793                         }
14794                 }
14795                 closedir(d);
14796         }
14797         return 0;
14798 }
14799
14800 /*
14801  * This routine checks to see if a filesystem can be skipped; if so,
14802  * it will exit with EXIT_OK.  Under some conditions it will print a
14803  * message explaining why a check is being forced.
14804  */
14805 static void check_if_skip(e2fsck_t ctx)
14806 {
14807         ext2_filsys fs = ctx->fs;
14808         const char *reason = NULL;
14809         unsigned int reason_arg = 0;
14810         long next_check;
14811         int batt = is_on_batt();
14812         time_t now = time(0);
14813
14814         if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14815             cflag || swapfs)
14816                 return;
14817
14818         if ((fs->super->s_state & EXT2_ERROR_FS) ||
14819             !ext2fs_test_valid(fs))
14820                 reason = _(" contains a file system with errors");
14821         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14822                 reason = _(" was not cleanly unmounted");
14823         else if ((fs->super->s_max_mnt_count > 0) &&
14824                  (fs->super->s_mnt_count >=
14825                   (unsigned) fs->super->s_max_mnt_count)) {
14826                 reason = _(" has been mounted %u times without being checked");
14827                 reason_arg = fs->super->s_mnt_count;
14828                 if (batt && (fs->super->s_mnt_count <
14829                              (unsigned) fs->super->s_max_mnt_count*2))
14830                         reason = 0;
14831         } else if (fs->super->s_checkinterval &&
14832                    ((now - fs->super->s_lastcheck) >=
14833                     fs->super->s_checkinterval)) {
14834                 reason = _(" has gone %u days without being checked");
14835                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14836                 if (batt && ((now - fs->super->s_lastcheck) <
14837                              fs->super->s_checkinterval*2))
14838                         reason = 0;
14839         }
14840         if (reason) {
14841                 fputs(ctx->device_name, stdout);
14842                 printf(reason, reason_arg);
14843                 fputs(_(", check forced.\n"), stdout);
14844                 return;
14845         }
14846         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14847                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14848                fs->super->s_inodes_count,
14849                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14850                fs->super->s_blocks_count);
14851         next_check = 100000;
14852         if (fs->super->s_max_mnt_count > 0) {
14853                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14854                 if (next_check <= 0)
14855                         next_check = 1;
14856         }
14857         if (fs->super->s_checkinterval &&
14858             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14859                 next_check = 1;
14860         if (next_check <= 5) {
14861                 if (next_check == 1)
14862                         fputs(_(" (check after next mount)"), stdout);
14863                 else
14864                         printf(_(" (check in %ld mounts)"), next_check);
14865         }
14866         fputc('\n', stdout);
14867         ext2fs_close(fs);
14868         ctx->fs = NULL;
14869         e2fsck_free_context(ctx);
14870         exit(EXIT_OK);
14871 }
14872
14873 /*
14874  * For completion notice
14875  */
14876 struct percent_tbl {
14877         int     max_pass;
14878         int     table[32];
14879 };
14880 static const struct percent_tbl e2fsck_tbl = {
14881         5, { 0, 70, 90, 92,  95, 100 }
14882 };
14883
14884 static char bar[128], spaces[128];
14885
14886 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14887                           int max)
14888 {
14889         float   percent;
14890
14891         if (pass <= 0)
14892                 return 0.0;
14893         if (pass > tbl->max_pass || max == 0)
14894                 return 100.0;
14895         percent = ((float) curr) / ((float) max);
14896         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14897                 + tbl->table[pass-1]);
14898 }
14899
14900 extern void e2fsck_clear_progbar(e2fsck_t ctx)
14901 {
14902         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14903                 return;
14904
14905         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14906                ctx->stop_meta);
14907         fflush(stdout);
14908         ctx->flags &= ~E2F_FLAG_PROG_BAR;
14909 }
14910
14911 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14912                            unsigned int dpynum)
14913 {
14914         static const char spinner[] = "\\|/-";
14915         int     i;
14916         unsigned int    tick;
14917         struct timeval  tv;
14918         int dpywidth;
14919         int fixed_percent;
14920
14921         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14922                 return 0;
14923
14924         /*
14925          * Calculate the new progress position.  If the
14926          * percentage hasn't changed, then we skip out right
14927          * away.
14928          */
14929         fixed_percent = (int) ((10 * percent) + 0.5);
14930         if (ctx->progress_last_percent == fixed_percent)
14931                 return 0;
14932         ctx->progress_last_percent = fixed_percent;
14933
14934         /*
14935          * If we've already updated the spinner once within
14936          * the last 1/8th of a second, no point doing it
14937          * again.
14938          */
14939         gettimeofday(&tv, NULL);
14940         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
14941         if ((tick == ctx->progress_last_time) &&
14942             (fixed_percent != 0) && (fixed_percent != 1000))
14943                 return 0;
14944         ctx->progress_last_time = tick;
14945
14946         /*
14947          * Advance the spinner, and note that the progress bar
14948          * will be on the screen
14949          */
14950         ctx->progress_pos = (ctx->progress_pos+1) & 3;
14951         ctx->flags |= E2F_FLAG_PROG_BAR;
14952
14953         dpywidth = 66 - strlen(label);
14954         dpywidth = 8 * (dpywidth / 8);
14955         if (dpynum)
14956                 dpywidth -= 8;
14957
14958         i = ((percent * dpywidth) + 50) / 100;
14959         printf("%s%s: |%s%s", ctx->start_meta, label,
14960                bar + (sizeof(bar) - (i+1)),
14961                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
14962         if (fixed_percent == 1000)
14963                 fputc('|', stdout);
14964         else
14965                 fputc(spinner[ctx->progress_pos & 3], stdout);
14966         printf(" %4.1f%%  ", percent);
14967         if (dpynum)
14968                 printf("%u\r", dpynum);
14969         else
14970                 fputs(" \r", stdout);
14971         fputs(ctx->stop_meta, stdout);
14972
14973         if (fixed_percent == 1000)
14974                 e2fsck_clear_progbar(ctx);
14975         fflush(stdout);
14976
14977         return 0;
14978 }
14979
14980 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
14981                                   unsigned long cur, unsigned long max)
14982 {
14983         char buf[80];
14984         float percent;
14985
14986         if (pass == 0)
14987                 return 0;
14988
14989         if (ctx->progress_fd) {
14990                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
14991                 write(ctx->progress_fd, buf, strlen(buf));
14992         } else {
14993                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
14994                 e2fsck_simple_progress(ctx, ctx->device_name,
14995                                        percent, 0);
14996         }
14997         return 0;
14998 }
14999
15000 static void reserve_stdio_fds(void)
15001 {
15002         int     fd;
15003
15004         while (1) {
15005                 fd = open(bb_dev_null, O_RDWR);
15006                 if (fd > 2)
15007                         break;
15008                 if (fd < 0) {
15009                         fprintf(stderr, _("ERROR: Couldn't open "
15010                                 "/dev/null (%s)\n"),
15011                                 strerror(errno));
15012                         break;
15013                 }
15014         }
15015         close(fd);
15016 }
15017
15018 static void signal_progress_on(int sig FSCK_ATTR((unused)))
15019 {
15020         e2fsck_t ctx = e2fsck_global_ctx;
15021
15022         if (!ctx)
15023                 return;
15024
15025         ctx->progress = e2fsck_update_progress;
15026         ctx->progress_fd = 0;
15027 }
15028
15029 static void signal_progress_off(int sig FSCK_ATTR((unused)))
15030 {
15031         e2fsck_t ctx = e2fsck_global_ctx;
15032
15033         if (!ctx)
15034                 return;
15035
15036         e2fsck_clear_progbar(ctx);
15037         ctx->progress = 0;
15038 }
15039
15040 static void signal_cancel(int sig FSCK_ATTR((unused)))
15041 {
15042         e2fsck_t ctx = e2fsck_global_ctx;
15043
15044         if (!ctx)
15045                 exit(FSCK_CANCELED);
15046
15047         ctx->flags |= E2F_FLAG_CANCEL;
15048 }
15049
15050 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15051 {
15052         char    *buf, *token, *next, *p, *arg;
15053         int     ea_ver;
15054         int     extended_usage = 0;
15055
15056         buf = string_copy(opts, 0);
15057         for (token = buf; token && *token; token = next) {
15058                 p = strchr(token, ',');
15059                 next = 0;
15060                 if (p) {
15061                         *p = 0;
15062                         next = p+1;
15063                 }
15064                 arg = strchr(token, '=');
15065                 if (arg) {
15066                         *arg = 0;
15067                         arg++;
15068                 }
15069                 if (strcmp(token, "ea_ver") == 0) {
15070                         if (!arg) {
15071                                 extended_usage++;
15072                                 continue;
15073                         }
15074                         ea_ver = strtoul(arg, &p, 0);
15075                         if (*p ||
15076                             ((ea_ver != 1) && (ea_ver != 2))) {
15077                                 fprintf(stderr,
15078                                         _("Invalid EA version.\n"));
15079                                 extended_usage++;
15080                                 continue;
15081                         }
15082                         ctx->ext_attr_ver = ea_ver;
15083                 } else
15084                         extended_usage++;
15085         }
15086         if (extended_usage) {
15087                 bb_error_msg_and_die(
15088                         "Extended options are separated by commas, "
15089                         "and may take an argument which\n"
15090                         "is set off by an equals ('=') sign.  "
15091                         "Valid raid options are:\n"
15092                         "\tea_ver=<ea_version (1 or 2)\n\n");
15093         }
15094 }
15095
15096
15097 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15098 {
15099         int             flush = 0;
15100         int             c, fd;
15101 #ifdef MTRACE
15102         extern void     *mallwatch;
15103 #endif
15104         e2fsck_t        ctx;
15105         errcode_t       retval;
15106         struct sigaction        sa;
15107         char            *extended_opts = 0;
15108
15109         retval = e2fsck_allocate_context(&ctx);
15110         if (retval)
15111                 return retval;
15112
15113         *ret_ctx = ctx;
15114
15115         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15116         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15117         if (isatty(0) && isatty(1)) {
15118                 ctx->interactive = 1;
15119         } else {
15120                 ctx->start_meta[0] = '\001';
15121                 ctx->stop_meta[0] = '\002';
15122         }
15123         memset(bar, '=', sizeof(bar)-1);
15124         memset(spaces, ' ', sizeof(spaces)-1);
15125         blkid_get_cache(&ctx->blkid, NULL);
15126
15127         if (argc && *argv)
15128                 ctx->program_name = *argv;
15129         else
15130                 ctx->program_name = "e2fsck";
15131         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15132                 switch (c) {
15133                 case 'C':
15134                         ctx->progress = e2fsck_update_progress;
15135                         ctx->progress_fd = atoi(optarg);
15136                         if (!ctx->progress_fd)
15137                                 break;
15138                         /* Validate the file descriptor to avoid disasters */
15139                         fd = dup(ctx->progress_fd);
15140                         if (fd < 0) {
15141                                 fprintf(stderr,
15142                                 _("Error validating file descriptor %d: %s\n"),
15143                                         ctx->progress_fd,
15144                                         error_message(errno));
15145                                 fatal_error(ctx,
15146                         _("Invalid completion information file descriptor"));
15147                         } else
15148                                 close(fd);
15149                         break;
15150                 case 'D':
15151                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
15152                         break;
15153                 case 'E':
15154                         extended_opts = optarg;
15155                         break;
15156                 case 'p':
15157                 case 'a':
15158                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15159                         conflict_opt:
15160                                 fatal_error(ctx,
15161         _("Only one the options -p/-a, -n or -y may be specified."));
15162                         }
15163                         ctx->options |= E2F_OPT_PREEN;
15164                         break;
15165                 case 'n':
15166                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15167                                 goto conflict_opt;
15168                         ctx->options |= E2F_OPT_NO;
15169                         break;
15170                 case 'y':
15171                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15172                                 goto conflict_opt;
15173                         ctx->options |= E2F_OPT_YES;
15174                         break;
15175                 case 't':
15176 #ifdef RESOURCE_TRACK
15177                         if (ctx->options & E2F_OPT_TIME)
15178                                 ctx->options |= E2F_OPT_TIME2;
15179                         else
15180                                 ctx->options |= E2F_OPT_TIME;
15181 #else
15182                         fprintf(stderr, _("The -t option is not "
15183                                 "supported on this version of e2fsck.\n"));
15184 #endif
15185                         break;
15186                 case 'c':
15187                         if (cflag++)
15188                                 ctx->options |= E2F_OPT_WRITECHECK;
15189                         ctx->options |= E2F_OPT_CHECKBLOCKS;
15190                         break;
15191                 case 'r':
15192                         /* What we do by default, anyway! */
15193                         break;
15194                 case 'b':
15195                         ctx->use_superblock = atoi(optarg);
15196                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15197                         break;
15198                 case 'B':
15199                         ctx->blocksize = atoi(optarg);
15200                         break;
15201                 case 'I':
15202                         ctx->inode_buffer_blocks = atoi(optarg);
15203                         break;
15204                 case 'j':
15205                         ctx->journal_name = string_copy(optarg, 0);
15206                         break;
15207                 case 'P':
15208                         ctx->process_inode_size = atoi(optarg);
15209                         break;
15210                 case 'L':
15211                         replace_bad_blocks++;
15212                 case 'l':
15213                         bad_blocks_file = string_copy(optarg, 0);
15214                         break;
15215                 case 'd':
15216                         ctx->options |= E2F_OPT_DEBUG;
15217                         break;
15218                 case 'f':
15219                         ctx->options |= E2F_OPT_FORCE;
15220                         break;
15221                 case 'F':
15222                         flush = 1;
15223                         break;
15224                 case 'v':
15225                         verbose = 1;
15226                         break;
15227                 case 'V':
15228                         show_version_only = 1;
15229                         break;
15230 #ifdef MTRACE
15231                 case 'M':
15232                         mallwatch = (void *) strtol(optarg, NULL, 0);
15233                         break;
15234 #endif
15235                 case 'N':
15236                         ctx->device_name = optarg;
15237                         break;
15238 #ifdef ENABLE_SWAPFS
15239                 case 's':
15240                         normalize_swapfs = 1;
15241                 case 'S':
15242                         swapfs = 1;
15243                         break;
15244 #else
15245                 case 's':
15246                 case 'S':
15247                         fprintf(stderr, _("Byte-swapping filesystems "
15248                                           "not compiled in this version "
15249                                           "of e2fsck\n"));
15250                         exit(1);
15251 #endif
15252                 case 'k':
15253                         keep_bad_blocks++;
15254                         break;
15255                 default:
15256                         usage();
15257                 }
15258         if (show_version_only)
15259                 return 0;
15260         if (optind != argc - 1)
15261                 usage();
15262         if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15263             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15264                 ctx->options |= E2F_OPT_READONLY;
15265         ctx->io_options = strchr(argv[optind], '?');
15266         if (ctx->io_options)
15267                 *ctx->io_options++ = 0;
15268         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15269         if (!ctx->filesystem_name) {
15270                 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15271                         argv[optind]);
15272                 fatal_error(ctx, 0);
15273         }
15274         if (extended_opts)
15275                 parse_extended_opts(ctx, extended_opts);
15276
15277         if (flush) {
15278                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15279                 if (fd < 0) {
15280                         com_err("open", errno,
15281                                 _("while opening %s for flushing"),
15282                                 ctx->filesystem_name);
15283                         fatal_error(ctx, 0);
15284                 }
15285                 if ((retval = ext2fs_sync_device(fd, 1))) {
15286                         com_err("ext2fs_sync_device", retval,
15287                                 _("while trying to flush %s"),
15288                                 ctx->filesystem_name);
15289                         fatal_error(ctx, 0);
15290                 }
15291                 close(fd);
15292         }
15293 #ifdef ENABLE_SWAPFS
15294         if (swapfs) {
15295                 if (cflag || bad_blocks_file) {
15296                         fprintf(stderr, _("Incompatible options not "
15297                                           "allowed when byte-swapping.\n"));
15298                         exit(EXIT_USAGE);
15299                 }
15300         }
15301 #endif
15302         if (cflag && bad_blocks_file) {
15303                 fprintf(stderr, _("The -c and the -l/-L options may "
15304                                   "not be both used at the same time.\n"));
15305                 exit(EXIT_USAGE);
15306         }
15307         /*
15308          * Set up signal action
15309          */
15310         memset(&sa, 0, sizeof(struct sigaction));
15311         sa.sa_handler = signal_cancel;
15312         sigaction(SIGINT, &sa, 0);
15313         sigaction(SIGTERM, &sa, 0);
15314 #ifdef SA_RESTART
15315         sa.sa_flags = SA_RESTART;
15316 #endif
15317         e2fsck_global_ctx = ctx;
15318         sa.sa_handler = signal_progress_on;
15319         sigaction(SIGUSR1, &sa, 0);
15320         sa.sa_handler = signal_progress_off;
15321         sigaction(SIGUSR2, &sa, 0);
15322
15323         /* Update our PATH to include /sbin if we need to run badblocks  */
15324         if (cflag)
15325                 e2fs_set_sbin_path();
15326 #ifdef __CONFIG_JBD_DEBUG__E2FS
15327         if (getenv("E2FSCK_JBD_DEBUG"))
15328                 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15329 #endif
15330         return 0;
15331 }
15332
15333 static const char my_ver_string[] = E2FSPROGS_VERSION;
15334 static const char my_ver_date[] = E2FSPROGS_DATE;
15335
15336 int e2fsck_main (int argc, char *argv[])
15337 {
15338         errcode_t       retval;
15339         int             exit_value = EXIT_OK;
15340         ext2_filsys     fs = 0;
15341         io_manager      io_ptr;
15342         struct ext2_super_block *sb;
15343         const char      *lib_ver_date;
15344         int             my_ver, lib_ver;
15345         e2fsck_t        ctx;
15346         struct problem_context pctx;
15347         int flags, run_result;
15348
15349         clear_problem_context(&pctx);
15350 #ifdef MTRACE
15351         mtrace();
15352 #endif
15353 #ifdef MCHECK
15354         mcheck(0);
15355 #endif
15356 #ifdef ENABLE_NLS
15357         setlocale(LC_MESSAGES, "");
15358         setlocale(LC_CTYPE, "");
15359         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15360         textdomain(NLS_CAT_NAME);
15361 #endif
15362         my_ver = ext2fs_parse_version_string(my_ver_string);
15363         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15364         if (my_ver > lib_ver) {
15365                 fprintf( stderr, _("Error: ext2fs library version "
15366                         "out of date!\n"));
15367                 show_version_only++;
15368         }
15369
15370         retval = PRS(argc, argv, &ctx);
15371         if (retval) {
15372                 com_err("e2fsck", retval,
15373                         _("while trying to initialize program"));
15374                 exit(EXIT_ERROR);
15375         }
15376         reserve_stdio_fds();
15377
15378 #ifdef RESOURCE_TRACK
15379         init_resource_track(&ctx->global_rtrack);
15380 #endif
15381
15382         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15383                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15384                          my_ver_date);
15385
15386         if (show_version_only) {
15387                 fprintf(stderr, _("\tUsing %s, %s\n"),
15388                         error_message(EXT2_ET_BASE), lib_ver_date);
15389                 exit(EXIT_OK);
15390         }
15391
15392         check_mount(ctx);
15393
15394         if (!(ctx->options & E2F_OPT_PREEN) &&
15395             !(ctx->options & E2F_OPT_NO) &&
15396             !(ctx->options & E2F_OPT_YES)) {
15397                 if (!ctx->interactive)
15398                         fatal_error(ctx,
15399                                     _("need terminal for interactive repairs"));
15400         }
15401         ctx->superblock = ctx->use_superblock;
15402 restart:
15403 #ifdef CONFIG_TESTIO_DEBUG
15404         io_ptr = test_io_manager;
15405         test_io_backing_manager = unix_io_manager;
15406 #else
15407         io_ptr = unix_io_manager;
15408 #endif
15409         flags = 0;
15410         if ((ctx->options & E2F_OPT_READONLY) == 0)
15411                 flags |= EXT2_FLAG_RW;
15412
15413         if (ctx->superblock && ctx->blocksize) {
15414                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15415                                       flags, ctx->superblock, ctx->blocksize,
15416                                       io_ptr, &fs);
15417         } else if (ctx->superblock) {
15418                 int blocksize;
15419                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15420                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15421                         retval = ext2fs_open2(ctx->filesystem_name,
15422                                               ctx->io_options, flags,
15423                                               ctx->superblock, blocksize,
15424                                               io_ptr, &fs);
15425                         if (!retval)
15426                                 break;
15427                 }
15428         } else
15429                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15430                                       flags, 0, 0, io_ptr, &fs);
15431         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15432             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15433             ((retval == EXT2_ET_BAD_MAGIC) ||
15434              ((retval == 0) && ext2fs_check_desc(fs)))) {
15435                 if (!fs || (fs->group_desc_count > 1)) {
15436                         printf(_("%s trying backup blocks...\n"),
15437                                retval ? _("Couldn't find ext2 superblock,") :
15438                                _("Group descriptors look bad..."));
15439                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15440                         if (fs)
15441                                 ext2fs_close(fs);
15442                         goto restart;
15443                 }
15444         }
15445         if (retval) {
15446                 com_err(ctx->program_name, retval, _("while trying to open %s"),
15447                         ctx->filesystem_name);
15448                 if (retval == EXT2_ET_REV_TOO_HIGH) {
15449                         printf(_("The filesystem revision is apparently "
15450                                "too high for this version of e2fsck.\n"
15451                                "(Or the filesystem superblock "
15452                                "is corrupt)\n\n"));
15453                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15454                 } else if (retval == EXT2_ET_SHORT_READ)
15455                         printf(_("Could this be a zero-length partition?\n"));
15456                 else if ((retval == EPERM) || (retval == EACCES))
15457                         printf(_("You must have %s access to the "
15458                                "filesystem or be root\n"),
15459                                (ctx->options & E2F_OPT_READONLY) ?
15460                                "r/o" : "r/w");
15461                 else if (retval == ENXIO)
15462                         printf(_("Possibly non-existent or swap device?\n"));
15463 #ifdef EROFS
15464                 else if (retval == EROFS)
15465                         printf(_("Disk write-protected; use the -n option "
15466                                "to do a read-only\n"
15467                                "check of the device.\n"));
15468 #endif
15469                 else
15470                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15471                 fatal_error(ctx, 0);
15472         }
15473         ctx->fs = fs;
15474         fs->priv_data = ctx;
15475         sb = fs->super;
15476         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15477                 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15478                         _("while trying to open %s"),
15479                         ctx->filesystem_name);
15480         get_newer:
15481                 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15482         }
15483
15484         /*
15485          * Set the device name, which is used whenever we print error
15486          * or informational messages to the user.
15487          */
15488         if (ctx->device_name == 0 &&
15489             (sb->s_volume_name[0] != 0)) {
15490                 ctx->device_name = string_copy(sb->s_volume_name,
15491                                                sizeof(sb->s_volume_name));
15492         }
15493         if (ctx->device_name == 0)
15494                 ctx->device_name = ctx->filesystem_name;
15495
15496         /*
15497          * Make sure the ext3 superblock fields are consistent.
15498          */
15499         retval = e2fsck_check_ext3_journal(ctx);
15500         if (retval) {
15501                 com_err(ctx->program_name, retval,
15502                         _("while checking ext3 journal for %s"),
15503                         ctx->device_name);
15504                 fatal_error(ctx, 0);
15505         }
15506
15507         /*
15508          * Check to see if we need to do ext3-style recovery.  If so,
15509          * do it, and then restart the fsck.
15510          */
15511         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15512                 if (ctx->options & E2F_OPT_READONLY) {
15513                         printf(_("Warning: skipping journal recovery "
15514                                  "because doing a read-only filesystem "
15515                                  "check.\n"));
15516                         io_channel_flush(ctx->fs->io);
15517                 } else {
15518                         if (ctx->flags & E2F_FLAG_RESTARTED) {
15519                                 /*
15520                                  * Whoops, we attempted to run the
15521                                  * journal twice.  This should never
15522                                  * happen, unless the hardware or
15523                                  * device driver is being bogus.
15524                                  */
15525                                 com_err(ctx->program_name, 0,
15526                                         _("unable to set superblock flags on %s\n"), ctx->device_name);
15527                                 fatal_error(ctx, 0);
15528                         }
15529                         retval = e2fsck_run_ext3_journal(ctx);
15530                         if (retval) {
15531                                 com_err(ctx->program_name, retval,
15532                                 _("while recovering ext3 journal of %s"),
15533                                         ctx->device_name);
15534                                 fatal_error(ctx, 0);
15535                         }
15536                         ext2fs_close(ctx->fs);
15537                         ctx->fs = 0;
15538                         ctx->flags |= E2F_FLAG_RESTARTED;
15539                         goto restart;
15540                 }
15541         }
15542
15543         /*
15544          * Check for compatibility with the feature sets.  We need to
15545          * be more stringent than ext2fs_open().
15546          */
15547         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15548             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15549                 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15550                         "(%s)", ctx->device_name);
15551                 goto get_newer;
15552         }
15553         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15554                 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15555                         "(%s)", ctx->device_name);
15556                 goto get_newer;
15557         }
15558 #ifdef ENABLE_COMPRESSION
15559         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15560                 com_err(ctx->program_name, 0,
15561                         _("Warning: compression support is experimental.\n"));
15562 #endif
15563 #ifndef ENABLE_HTREE
15564         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15565                 com_err(ctx->program_name, 0,
15566                         _("E2fsck not compiled with HTREE support,\n\t"
15567                           "but filesystem %s has HTREE directories.\n"),
15568                         ctx->device_name);
15569                 goto get_newer;
15570         }
15571 #endif
15572
15573         /*
15574          * If the user specified a specific superblock, presumably the
15575          * master superblock has been trashed.  So we mark the
15576          * superblock as dirty, so it can be written out.
15577          */
15578         if (ctx->superblock &&
15579             !(ctx->options & E2F_OPT_READONLY))
15580                 ext2fs_mark_super_dirty(fs);
15581
15582         /*
15583          * We only update the master superblock because (a) paranoia;
15584          * we don't want to corrupt the backup superblocks, and (b) we
15585          * don't need to update the mount count and last checked
15586          * fields in the backup superblock (the kernel doesn't
15587          * update the backup superblocks anyway).
15588          */
15589         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15590
15591         ehandler_init(fs->io);
15592
15593         if (ctx->superblock)
15594                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15595         ext2fs_mark_valid(fs);
15596         check_super_block(ctx);
15597         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15598                 fatal_error(ctx, 0);
15599         check_if_skip(ctx);
15600         if (bad_blocks_file)
15601                 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15602         else if (cflag)
15603                 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15604         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15605                 fatal_error(ctx, 0);
15606 #ifdef ENABLE_SWAPFS
15607
15608 #ifdef WORDS_BIGENDIAN
15609 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
15610 #else
15611 #define NATIVE_FLAG 0
15612 #endif
15613
15614
15615         if (normalize_swapfs) {
15616                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
15617                         fprintf(stderr, _("%s: Filesystem byte order "
15618                                 "already normalized.\n"), ctx->device_name);
15619                         fatal_error(ctx, 0);
15620                 }
15621         }
15622         if (swapfs) {
15623                 swap_filesys(ctx);
15624                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15625                         fatal_error(ctx, 0);
15626         }
15627 #endif
15628
15629         /*
15630          * Mark the system as valid, 'til proven otherwise
15631          */
15632         ext2fs_mark_valid(fs);
15633
15634         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15635         if (retval) {
15636                 com_err(ctx->program_name, retval,
15637                         _("while reading bad blocks inode"));
15638                 preenhalt(ctx);
15639                 printf(_("This doesn't bode well,"
15640                          " but we'll try to go on...\n"));
15641         }
15642
15643         run_result = e2fsck_run(ctx);
15644         e2fsck_clear_progbar(ctx);
15645         if (run_result == E2F_FLAG_RESTART) {
15646                 printf(_("Restarting e2fsck from the beginning...\n"));
15647                 retval = e2fsck_reset_context(ctx);
15648                 if (retval) {
15649                         com_err(ctx->program_name, retval,
15650                                 _("while resetting context"));
15651                         fatal_error(ctx, 0);
15652                 }
15653                 ext2fs_close(fs);
15654                 goto restart;
15655         }
15656         if (run_result & E2F_FLAG_CANCEL) {
15657                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15658                        ctx->device_name : ctx->filesystem_name);
15659                 exit_value |= FSCK_CANCELED;
15660         }
15661         if (run_result & E2F_FLAG_ABORT)
15662                 fatal_error(ctx, _("aborted"));
15663
15664 #ifdef MTRACE
15665         mtrace_print("Cleanup");
15666 #endif
15667         if (ext2fs_test_changed(fs)) {
15668                 exit_value |= EXIT_NONDESTRUCT;
15669                 if (!(ctx->options & E2F_OPT_PREEN))
15670                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15671                                ctx->device_name);
15672                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15673                         printf(_("%s: ***** REBOOT LINUX *****\n"),
15674                                ctx->device_name);
15675                         exit_value |= EXIT_DESTRUCT;
15676                 }
15677         }
15678         if (!ext2fs_test_valid(fs)) {
15679                 printf(_("\n%s: ********** WARNING: Filesystem still has "
15680                          "errors **********\n\n"), ctx->device_name);
15681                 exit_value |= EXIT_UNCORRECTED;
15682                 exit_value &= ~EXIT_NONDESTRUCT;
15683         }
15684         if (exit_value & FSCK_CANCELED)
15685                 exit_value &= ~EXIT_NONDESTRUCT;
15686         else {
15687                 show_stats(ctx);
15688                 if (!(ctx->options & E2F_OPT_READONLY)) {
15689                         if (ext2fs_test_valid(fs)) {
15690                                 if (!(sb->s_state & EXT2_VALID_FS))
15691                                         exit_value |= EXIT_NONDESTRUCT;
15692                                 sb->s_state = EXT2_VALID_FS;
15693                         } else
15694                                 sb->s_state &= ~EXT2_VALID_FS;
15695                         sb->s_mnt_count = 0;
15696                         sb->s_lastcheck = time(NULL);
15697                         ext2fs_mark_super_dirty(fs);
15698                 }
15699         }
15700
15701         e2fsck_write_bitmaps(ctx);
15702
15703         ext2fs_close(fs);
15704         ctx->fs = NULL;
15705         free(ctx->filesystem_name);
15706         free(ctx->journal_name);
15707         e2fsck_free_context(ctx);
15708
15709 #ifdef RESOURCE_TRACK
15710         if (ctx->options & E2F_OPT_TIME)
15711                 print_resource_track(NULL, &ctx->global_rtrack);
15712 #endif
15713
15714         return exit_value;
15715 }